[libnet-ldns-perl] 02/05: Use system ldns library for compilation

Ondřej Surý ondrej at debian.org
Tue Sep 6 13:55:33 UTC 2016


This is an automated email from the git hooks/post-receive script.

ondrej pushed a commit to branch master
in repository libnet-ldns-perl.

commit ce5878439913bf2c0c57c356c694eeaf883f6542
Author: Ondřej Surý <ondrej at sury.org>
Date:   Tue Jun 28 12:36:34 2016 +0200

    Use system ldns library for compilation
---
 debian/control                                     |     2 +-
 ...1-Use-system-ldns-library-for-compilation.patch | 86155 +++++++++++++++++++
 debian/patches/series                              |     1 +
 3 files changed, 86157 insertions(+), 1 deletion(-)

diff --git a/debian/control b/debian/control
index 9e47b36..b3ba291 100644
--- a/debian/control
+++ b/debian/control
@@ -4,7 +4,7 @@ Priority: optional
 Maintainer: Ondřej Surý <ondrej at debian.org>
 Build-Depends: debhelper (>= 9.20120312~),
                libdevel-checklib-perl (>= 0.4),
-               libldns-dev,
+               libldns-dev (>= 1.6.17-9~),
                libtest-fatal-perl,
                perl (>= 5.17.4)
 Standards-Version: 3.9.8
diff --git a/debian/patches/0001-Use-system-ldns-library-for-compilation.patch b/debian/patches/0001-Use-system-ldns-library-for-compilation.patch
new file mode 100644
index 0000000..fe7041f
--- /dev/null
+++ b/debian/patches/0001-Use-system-ldns-library-for-compilation.patch
@@ -0,0 +1,86155 @@
+From: =?utf-8?q?Ond=C5=99ej_Sur=C3=BD?= <ondrej at sury.org>
+Date: Tue, 28 Jun 2016 12:36:19 +0200
+Subject: Use system ldns library for compilation
+
+---
+ MANIFEST                          |   99 +-
+ Makefile.PL                       |   19 +-
+ include/ldns/buffer.h             |  645 ---------
+ include/ldns/common.h             |   78 --
+ include/ldns/config.h             |  590 --------
+ include/ldns/dane.h               |  262 ----
+ include/ldns/dname.h              |  211 ---
+ include/ldns/dnssec.h             |  541 --------
+ include/ldns/dnssec_sign.h        |  383 ------
+ include/ldns/dnssec_verify.h      |  857 ------------
+ include/ldns/dnssec_zone.h        |  483 -------
+ include/ldns/duration.h           |  109 --
+ include/ldns/error.h              |  147 --
+ include/ldns/higher.h             |  113 --
+ include/ldns/host2str.h           |  891 ------------
+ include/ldns/host2wire.h          |  197 ---
+ include/ldns/keys.h               |  621 ---------
+ include/ldns/ldns.h               |  158 ---
+ include/ldns/net.h                |  207 ---
+ include/ldns/packet.h             |  891 ------------
+ include/ldns/parse.h              |  167 ---
+ include/ldns/radix.h              |  240 ----
+ include/ldns/rbtree.h             |  230 ----
+ include/ldns/rdata.h              |  451 -------
+ include/ldns/resolver.h           |  805 -----------
+ include/ldns/rr.h                 |  929 -------------
+ include/ldns/rr_functions.h       |  363 -----
+ include/ldns/sha1.h               |   38 -
+ include/ldns/sha2.h               |  149 --
+ include/ldns/str2host.h           |  319 -----
+ include/ldns/tsig.h               |  101 --
+ include/ldns/update.h             |  115 --
+ include/ldns/util.h               |  392 ------
+ include/ldns/wire2host.h          |  197 ---
+ include/ldns/zone.h               |  176 ---
+ ldns/include/ldns/buffer.h        |  645 +++++++++
+ ldns/include/ldns/common.h        |   78 ++
+ ldns/include/ldns/config.h        |  590 ++++++++
+ ldns/include/ldns/dane.h          |  262 ++++
+ ldns/include/ldns/dname.h         |  211 +++
+ ldns/include/ldns/dnssec.h        |  541 ++++++++
+ ldns/include/ldns/dnssec_sign.h   |  383 ++++++
+ ldns/include/ldns/dnssec_verify.h |  857 ++++++++++++
+ ldns/include/ldns/dnssec_zone.h   |  483 +++++++
+ ldns/include/ldns/duration.h      |  109 ++
+ ldns/include/ldns/error.h         |  147 ++
+ ldns/include/ldns/higher.h        |  113 ++
+ ldns/include/ldns/host2str.h      |  891 ++++++++++++
+ ldns/include/ldns/host2wire.h     |  197 +++
+ ldns/include/ldns/keys.h          |  621 +++++++++
+ ldns/include/ldns/ldns.h          |  158 +++
+ ldns/include/ldns/net.h           |  207 +++
+ ldns/include/ldns/packet.h        |  891 ++++++++++++
+ ldns/include/ldns/parse.h         |  167 +++
+ ldns/include/ldns/radix.h         |  240 ++++
+ ldns/include/ldns/rbtree.h        |  230 ++++
+ ldns/include/ldns/rdata.h         |  451 +++++++
+ ldns/include/ldns/resolver.h      |  805 +++++++++++
+ ldns/include/ldns/rr.h            |  929 +++++++++++++
+ ldns/include/ldns/rr_functions.h  |  363 +++++
+ ldns/include/ldns/sha1.h          |   38 +
+ ldns/include/ldns/sha2.h          |  149 ++
+ ldns/include/ldns/str2host.h      |  319 +++++
+ ldns/include/ldns/tsig.h          |  101 ++
+ ldns/include/ldns/update.h        |  115 ++
+ ldns/include/ldns/util.h          |  392 ++++++
+ ldns/include/ldns/wire2host.h     |  197 +++
+ ldns/include/ldns/zone.h          |  176 +++
+ ldns/src/buffer.c                 |  177 +++
+ ldns/src/compat/b64_ntop.c        |  185 +++
+ ldns/src/compat/b64_pton.c        |  244 ++++
+ ldns/src/compat/strlcpy.c         |   57 +
+ ldns/src/dane.c                   |  748 ++++++++++
+ ldns/src/dname.c                  |  598 ++++++++
+ ldns/src/dnssec.c                 | 1869 +++++++++++++++++++++++++
+ ldns/src/dnssec_sign.c            | 1456 ++++++++++++++++++++
+ ldns/src/dnssec_verify.c          | 2684 ++++++++++++++++++++++++++++++++++++
+ ldns/src/dnssec_zone.c            | 1192 ++++++++++++++++
+ ldns/src/duration.c               |  354 +++++
+ ldns/src/error.c                  |  160 +++
+ ldns/src/higher.c                 |  344 +++++
+ ldns/src/host2str.c               | 2635 ++++++++++++++++++++++++++++++++++++
+ ldns/src/host2wire.c              |  494 +++++++
+ ldns/src/keys.c                   | 1726 +++++++++++++++++++++++
+ ldns/src/net.c                    | 1002 ++++++++++++++
+ ldns/src/packet.c                 | 1159 ++++++++++++++++
+ ldns/src/parse.c                  |  434 ++++++
+ ldns/src/radix.c                  | 1590 ++++++++++++++++++++++
+ ldns/src/rbtree.c                 |  670 +++++++++
+ ldns/src/rdata.c                  |  757 +++++++++++
+ ldns/src/resolver.c               | 1603 ++++++++++++++++++++++
+ ldns/src/rr.c                     | 2705 +++++++++++++++++++++++++++++++++++++
+ ldns/src/rr_functions.c           |  419 ++++++
+ ldns/src/sha1.c                   |  177 +++
+ ldns/src/sha2.c                   |  991 ++++++++++++++
+ ldns/src/str2host.c               | 1604 ++++++++++++++++++++++
+ ldns/src/tsig.c                   |  470 +++++++
+ ldns/src/update.c                 |  325 +++++
+ ldns/src/util.c                   |  773 +++++++++++
+ ldns/src/wire2host.c              |  491 +++++++
+ ldns/src/zone.c                   |  318 +++++
+ src/ldns/buffer.c                 |  177 ---
+ src/ldns/compat/b64_ntop.c        |  185 ---
+ src/ldns/compat/b64_pton.c        |  244 ----
+ src/ldns/compat/strlcpy.c         |   57 -
+ src/ldns/dane.c                   |  748 ----------
+ src/ldns/dname.c                  |  598 --------
+ src/ldns/dnssec.c                 | 1869 -------------------------
+ src/ldns/dnssec_sign.c            | 1456 --------------------
+ src/ldns/dnssec_verify.c          | 2684 ------------------------------------
+ src/ldns/dnssec_zone.c            | 1192 ----------------
+ src/ldns/duration.c               |  354 -----
+ src/ldns/error.c                  |  160 ---
+ src/ldns/higher.c                 |  344 -----
+ src/ldns/host2str.c               | 2635 ------------------------------------
+ src/ldns/host2wire.c              |  494 -------
+ src/ldns/keys.c                   | 1726 -----------------------
+ src/ldns/net.c                    | 1002 --------------
+ src/ldns/packet.c                 | 1159 ----------------
+ src/ldns/parse.c                  |  434 ------
+ src/ldns/radix.c                  | 1590 ----------------------
+ src/ldns/rbtree.c                 |  670 ---------
+ src/ldns/rdata.c                  |  757 -----------
+ src/ldns/resolver.c               | 1603 ----------------------
+ src/ldns/rr.c                     | 2705 -------------------------------------
+ src/ldns/rr_functions.c           |  419 ------
+ src/ldns/sha1.c                   |  177 ---
+ src/ldns/sha2.c                   |  991 --------------
+ src/ldns/str2host.c               | 1604 ----------------------
+ src/ldns/tsig.c                   |  470 -------
+ src/ldns/update.c                 |  325 -----
+ src/ldns/util.c                   |  773 -----------
+ src/ldns/wire2host.c              |  491 -------
+ src/ldns/zone.c                   |  318 -----
+ 134 files changed, 42518 insertions(+), 42534 deletions(-)
+ delete mode 100644 include/ldns/buffer.h
+ delete mode 100644 include/ldns/common.h
+ delete mode 100644 include/ldns/config.h
+ delete mode 100644 include/ldns/dane.h
+ delete mode 100644 include/ldns/dname.h
+ delete mode 100644 include/ldns/dnssec.h
+ delete mode 100644 include/ldns/dnssec_sign.h
+ delete mode 100644 include/ldns/dnssec_verify.h
+ delete mode 100644 include/ldns/dnssec_zone.h
+ delete mode 100644 include/ldns/duration.h
+ delete mode 100644 include/ldns/error.h
+ delete mode 100644 include/ldns/higher.h
+ delete mode 100644 include/ldns/host2str.h
+ delete mode 100644 include/ldns/host2wire.h
+ delete mode 100644 include/ldns/keys.h
+ delete mode 100644 include/ldns/ldns.h
+ delete mode 100644 include/ldns/net.h
+ delete mode 100644 include/ldns/packet.h
+ delete mode 100644 include/ldns/parse.h
+ delete mode 100644 include/ldns/radix.h
+ delete mode 100644 include/ldns/rbtree.h
+ delete mode 100644 include/ldns/rdata.h
+ delete mode 100644 include/ldns/resolver.h
+ delete mode 100644 include/ldns/rr.h
+ delete mode 100644 include/ldns/rr_functions.h
+ delete mode 100644 include/ldns/sha1.h
+ delete mode 100644 include/ldns/sha2.h
+ delete mode 100644 include/ldns/str2host.h
+ delete mode 100644 include/ldns/tsig.h
+ delete mode 100644 include/ldns/update.h
+ delete mode 100644 include/ldns/util.h
+ delete mode 100644 include/ldns/wire2host.h
+ delete mode 100644 include/ldns/zone.h
+ create mode 100644 ldns/include/ldns/buffer.h
+ create mode 100644 ldns/include/ldns/common.h
+ create mode 100644 ldns/include/ldns/config.h
+ create mode 100644 ldns/include/ldns/dane.h
+ create mode 100644 ldns/include/ldns/dname.h
+ create mode 100644 ldns/include/ldns/dnssec.h
+ create mode 100644 ldns/include/ldns/dnssec_sign.h
+ create mode 100644 ldns/include/ldns/dnssec_verify.h
+ create mode 100644 ldns/include/ldns/dnssec_zone.h
+ create mode 100644 ldns/include/ldns/duration.h
+ create mode 100644 ldns/include/ldns/error.h
+ create mode 100644 ldns/include/ldns/higher.h
+ create mode 100644 ldns/include/ldns/host2str.h
+ create mode 100644 ldns/include/ldns/host2wire.h
+ create mode 100644 ldns/include/ldns/keys.h
+ create mode 100644 ldns/include/ldns/ldns.h
+ create mode 100644 ldns/include/ldns/net.h
+ create mode 100644 ldns/include/ldns/packet.h
+ create mode 100644 ldns/include/ldns/parse.h
+ create mode 100644 ldns/include/ldns/radix.h
+ create mode 100644 ldns/include/ldns/rbtree.h
+ create mode 100644 ldns/include/ldns/rdata.h
+ create mode 100644 ldns/include/ldns/resolver.h
+ create mode 100644 ldns/include/ldns/rr.h
+ create mode 100644 ldns/include/ldns/rr_functions.h
+ create mode 100644 ldns/include/ldns/sha1.h
+ create mode 100644 ldns/include/ldns/sha2.h
+ create mode 100644 ldns/include/ldns/str2host.h
+ create mode 100644 ldns/include/ldns/tsig.h
+ create mode 100644 ldns/include/ldns/update.h
+ create mode 100644 ldns/include/ldns/util.h
+ create mode 100644 ldns/include/ldns/wire2host.h
+ create mode 100644 ldns/include/ldns/zone.h
+ create mode 100644 ldns/src/buffer.c
+ create mode 100644 ldns/src/compat/b64_ntop.c
+ create mode 100644 ldns/src/compat/b64_pton.c
+ create mode 100644 ldns/src/compat/strlcpy.c
+ create mode 100644 ldns/src/dane.c
+ create mode 100644 ldns/src/dname.c
+ create mode 100644 ldns/src/dnssec.c
+ create mode 100644 ldns/src/dnssec_sign.c
+ create mode 100644 ldns/src/dnssec_verify.c
+ create mode 100644 ldns/src/dnssec_zone.c
+ create mode 100644 ldns/src/duration.c
+ create mode 100644 ldns/src/error.c
+ create mode 100644 ldns/src/higher.c
+ create mode 100644 ldns/src/host2str.c
+ create mode 100644 ldns/src/host2wire.c
+ create mode 100644 ldns/src/keys.c
+ create mode 100644 ldns/src/net.c
+ create mode 100644 ldns/src/packet.c
+ create mode 100644 ldns/src/parse.c
+ create mode 100644 ldns/src/radix.c
+ create mode 100644 ldns/src/rbtree.c
+ create mode 100644 ldns/src/rdata.c
+ create mode 100644 ldns/src/resolver.c
+ create mode 100644 ldns/src/rr.c
+ create mode 100644 ldns/src/rr_functions.c
+ create mode 100644 ldns/src/sha1.c
+ create mode 100644 ldns/src/sha2.c
+ create mode 100644 ldns/src/str2host.c
+ create mode 100644 ldns/src/tsig.c
+ create mode 100644 ldns/src/update.c
+ create mode 100644 ldns/src/util.c
+ create mode 100644 ldns/src/wire2host.c
+ create mode 100644 ldns/src/zone.c
+ delete mode 100644 src/ldns/buffer.c
+ delete mode 100644 src/ldns/compat/b64_ntop.c
+ delete mode 100644 src/ldns/compat/b64_pton.c
+ delete mode 100644 src/ldns/compat/strlcpy.c
+ delete mode 100644 src/ldns/dane.c
+ delete mode 100644 src/ldns/dname.c
+ delete mode 100644 src/ldns/dnssec.c
+ delete mode 100644 src/ldns/dnssec_sign.c
+ delete mode 100644 src/ldns/dnssec_verify.c
+ delete mode 100644 src/ldns/dnssec_zone.c
+ delete mode 100644 src/ldns/duration.c
+ delete mode 100644 src/ldns/error.c
+ delete mode 100644 src/ldns/higher.c
+ delete mode 100644 src/ldns/host2str.c
+ delete mode 100644 src/ldns/host2wire.c
+ delete mode 100644 src/ldns/keys.c
+ delete mode 100644 src/ldns/net.c
+ delete mode 100644 src/ldns/packet.c
+ delete mode 100644 src/ldns/parse.c
+ delete mode 100644 src/ldns/radix.c
+ delete mode 100644 src/ldns/rbtree.c
+ delete mode 100644 src/ldns/rdata.c
+ delete mode 100644 src/ldns/resolver.c
+ delete mode 100644 src/ldns/rr.c
+ delete mode 100644 src/ldns/rr_functions.c
+ delete mode 100644 src/ldns/sha1.c
+ delete mode 100644 src/ldns/sha2.c
+ delete mode 100644 src/ldns/str2host.c
+ delete mode 100644 src/ldns/tsig.c
+ delete mode 100644 src/ldns/update.c
+ delete mode 100644 src/ldns/util.c
+ delete mode 100644 src/ldns/wire2host.c
+ delete mode 100644 src/ldns/zone.c
+
+diff --git a/MANIFEST b/MANIFEST
+index 580f068..a8b2463 100644
+--- a/MANIFEST
++++ b/MANIFEST
+@@ -9,39 +9,6 @@ inc/Module/Install/Win32.pm
+ inc/Module/Install/WriteAll.pm
+ inc/Module/Install/XSUtil.pm
+ include/LDNS.h
+-include/ldns/buffer.h
+-include/ldns/common.h
+-include/ldns/config.h
+-include/ldns/dane.h
+-include/ldns/dname.h
+-include/ldns/dnssec.h
+-include/ldns/dnssec_sign.h
+-include/ldns/dnssec_verify.h
+-include/ldns/dnssec_zone.h
+-include/ldns/duration.h
+-include/ldns/error.h
+-include/ldns/higher.h
+-include/ldns/host2str.h
+-include/ldns/host2wire.h
+-include/ldns/keys.h
+-include/ldns/ldns.h
+-include/ldns/net.h
+-include/ldns/packet.h
+-include/ldns/parse.h
+-include/ldns/radix.h
+-include/ldns/rbtree.h
+-include/ldns/rdata.h
+-include/ldns/resolver.h
+-include/ldns/rr.h
+-include/ldns/rr_functions.h
+-include/ldns/sha1.h
+-include/ldns/sha2.h
+-include/ldns/str2host.h
+-include/ldns/tsig.h
+-include/ldns/update.h
+-include/ldns/util.h
+-include/ldns/wire2host.h
+-include/ldns/zone.h
+ lib/Net/LDNS.pm
+ lib/Net/LDNS/Packet.pm
+ lib/Net/LDNS/RR.pm
+@@ -128,39 +95,6 @@ ppport.h
+ README.md
+ src/assist.c
+ src/LDNS.xs
+-src/ldns/compat/b64_ntop.c
+-src/ldns/compat/b64_pton.c
+-src/ldns/buffer.c
+-src/ldns/compat/strlcpy.c
+-src/ldns/dane.c
+-src/ldns/dname.c
+-src/ldns/dnssec.c
+-src/ldns/dnssec_sign.c
+-src/ldns/dnssec_verify.c
+-src/ldns/dnssec_zone.c
+-src/ldns/duration.c
+-src/ldns/error.c
+-src/ldns/higher.c
+-src/ldns/host2str.c
+-src/ldns/host2wire.c
+-src/ldns/keys.c
+-src/ldns/net.c
+-src/ldns/packet.c
+-src/ldns/parse.c
+-src/ldns/radix.c
+-src/ldns/rbtree.c
+-src/ldns/rdata.c
+-src/ldns/resolver.c
+-src/ldns/rr.c
+-src/ldns/rr_functions.c
+-src/ldns/sha1.c
+-src/ldns/sha2.c
+-src/ldns/str2host.c
+-src/ldns/tsig.c
+-src/ldns/update.c
+-src/ldns/util.c
+-src/ldns/wire2host.c
+-src/ldns/zone.c
+ src/typemap
+ t/axfr.t
+ t/dnssec.t
+@@ -176,3 +110,36 @@ t/rrlist.t
+ t/serialize.t
+ t/threads.t
+ t/utils.t
++ldns/src/buffer.c
++ldns/src/compat/b64_ntop.c
++ldns/src/compat/b64_pton.c
++ldns/src/compat/strlcpy.c
++ldns/src/dane.c
++ldns/src/dname.c
++ldns/src/dnssec.c
++ldns/src/dnssec_sign.c
++ldns/src/dnssec_verify.c
++ldns/src/dnssec_zone.c
++ldns/src/duration.c
++ldns/src/error.c
++ldns/src/higher.c
++ldns/src/host2str.c
++ldns/src/host2wire.c
++ldns/src/keys.c
++ldns/src/net.c
++ldns/src/packet.c
++ldns/src/parse.c
++ldns/src/radix.c
++ldns/src/rbtree.c
++ldns/src/rdata.c
++ldns/src/resolver.c
++ldns/src/rr.c
++ldns/src/rr_functions.c
++ldns/src/sha1.c
++ldns/src/sha2.c
++ldns/src/str2host.c
++ldns/src/tsig.c
++ldns/src/update.c
++ldns/src/util.c
++ldns/src/wire2host.c
++ldns/src/zone.c
+diff --git a/Makefile.PL b/Makefile.PL
+index 35596f7..5ae48a9 100644
+--- a/Makefile.PL
++++ b/Makefile.PL
+@@ -75,6 +75,23 @@ else {
+ 
+ if (
+     check_lib(
++	lib      => 'ldns',
++	header   => 'ldns/ldns.h',
++	function => 'if (!ldns_resolver_clone(ldns_resolver_new())) return 1; else return 0;'
++    )
++  )
++{
++    print "Using system ldns library.\n";
++    cc_libs 'ldns';
++}
++else {
++    print "Using embedded ldns library.\n";
++    cc_include_paths 'ldns/include';
++    cc_src_paths 'ldns/src';
++}
++
++if (
++    check_lib(
+         lib      => 'idn',
+         header   => 'idna.h',
+         function => 'if(strcmp(IDNA_ACE_PREFIX,"xn--")==0) return 0; else return 1;'
+@@ -140,4 +157,4 @@ sub check_gost {
+ CODE
+ 
+     return check_lib(%args);
+-}
+\ No newline at end of file
++}
+diff --git a/include/ldns/buffer.h b/include/ldns/buffer.h
+deleted file mode 100644
+index 3b64198..0000000
+--- a/include/ldns/buffer.h
++++ /dev/null
+@@ -1,645 +0,0 @@
+-/*
+- * buffer.h -- generic memory buffer.
+- *
+- * Copyright (c) 2005-2008, NLnet Labs. All rights reserved.
+- *
+- * See LICENSE for the license.
+- *
+- *
+- * The buffer module implements a generic buffer.  The API is based on
+- * the java.nio.Buffer interface.
+- */
+-
+-#ifndef LDNS_BUFFER_H
+-#define LDNS_BUFFER_H
+-
+-#include <assert.h>
+-#include <stdarg.h>
+-#include <string.h>
+-
+-#include <ldns/error.h>
+-#include <ldns/common.h>
+-
+-#include "ldns/util.h"
+-
+-#ifdef __cplusplus
+-extern "C" {
+-#endif
+-
+-/**
+- * number of initial bytes in buffer of
+- * which we cannot tell the size before hand
+- */
+-#define LDNS_MIN_BUFLEN	512
+-
+-/**
+- * \file buffer.h
+- *
+- * This file contains the definition of ldns_buffer, and functions to manipulate those.
+- */
+-
+-/** 
+- * implementation of buffers to ease operations
+- *
+- * ldns_buffers can contain arbitrary information, per octet. You can write
+- * to the current end of a buffer, read from the current position, and
+- * access any data within it.
+- *
+- * Example use of buffers is in the source code of \ref host2str.c
+- */
+-struct ldns_struct_buffer
+-{
+-	/** The current position used for reading/writing */ 
+-	size_t   _position;
+-
+-	/** The read/write limit */
+-	size_t   _limit;
+-
+-	/** The amount of data the buffer can contain */
+-	size_t   _capacity;
+-
+-	/** The data contained in the buffer */
+-	uint8_t *_data;
+-
+-	/** If the buffer is fixed it cannot be resized */
+-	unsigned _fixed : 1;
+-
+-	/** The current state of the buffer. If writing to the buffer fails
+-	 * for any reason, this value is changed. This way, you can perform
+-	 * multiple writes in sequence and check for success afterwards. */
+-	ldns_status _status;
+-};
+-typedef struct ldns_struct_buffer ldns_buffer;
+-
+-
+-#ifdef NDEBUG
+-INLINE void
+-ldns_buffer_invariant(ldns_buffer *ATTR_UNUSED(buffer))
+-{
+-}
+-#else
+-INLINE void
+-ldns_buffer_invariant(ldns_buffer *buffer)
+-{
+-	assert(buffer != NULL);
+-	assert(buffer->_position <= buffer->_limit);
+-	assert(buffer->_limit <= buffer->_capacity);
+-	assert(buffer->_data != NULL);
+-}
+-#endif
+-
+-/**
+- * creates a new buffer with the specified capacity.
+- *
+- * \param[in] capacity the size (in bytes) to allocate for the buffer
+- * \return the created buffer
+- */
+-ldns_buffer *ldns_buffer_new(size_t capacity);
+-
+-/**
+- * creates a buffer with the specified data.  The data IS copied
+- * and MEMORY allocations are done.  The buffer is not fixed and can
+- * be resized using buffer_reserve().
+- *
+- * \param[in] buffer pointer to the buffer to put the data in
+- * \param[in] data the data to encapsulate in the buffer
+- * \param[in] size the size of the data
+- */
+-void ldns_buffer_new_frm_data(ldns_buffer *buffer, void *data, size_t size);
+-
+-/**
+- * clears the buffer and make it ready for writing.  The buffer's limit
+- * is set to the capacity and the position is set to 0.
+- * \param[in] buffer the buffer to clear
+- */
+-INLINE void ldns_buffer_clear(ldns_buffer *buffer)
+-{
+-	ldns_buffer_invariant(buffer);
+-
+-	/* reset status here? */
+-
+-	buffer->_position = 0;
+-	buffer->_limit = buffer->_capacity;
+-}
+-
+-/**
+- * makes the buffer ready for reading the data that has been written to
+- * the buffer.  The buffer's limit is set to the current position and
+- * the position is set to 0.
+- *
+- * \param[in] buffer the buffer to flip
+- * \return void
+- */
+-INLINE void ldns_buffer_flip(ldns_buffer *buffer)
+-{
+-	ldns_buffer_invariant(buffer);
+-
+-	buffer->_limit = buffer->_position;
+-	buffer->_position = 0;
+-}
+-
+-/**
+- * make the buffer ready for re-reading the data.  The buffer's
+- * position is reset to 0.
+- * \param[in] buffer the buffer to rewind
+- */
+-INLINE void ldns_buffer_rewind(ldns_buffer *buffer)
+-{
+-	ldns_buffer_invariant(buffer);
+-
+-	buffer->_position = 0;
+-}
+-
+-/**
+- * returns the current position in the buffer (as a number of bytes)
+- * \param[in] buffer the buffer
+- * \return the current position
+- */
+-INLINE size_t
+-ldns_buffer_position(ldns_buffer *buffer)
+-{
+-	return buffer->_position;
+-}
+-
+-/**
+- * sets the buffer's position to MARK.  The position must be less than
+- * or equal to the buffer's limit.
+- * \param[in] buffer the buffer
+- * \param[in] mark the mark to use
+- */
+-INLINE void
+-ldns_buffer_set_position(ldns_buffer *buffer, size_t mark)
+-{
+-	assert(mark <= buffer->_limit);
+-	buffer->_position = mark;
+-}
+-
+-/**
+- * changes the buffer's position by COUNT bytes.  The position must not
+- * be moved behind the buffer's limit or before the beginning of the
+- * buffer.
+- * \param[in] buffer the buffer
+- * \param[in] count the count to use
+- */
+-INLINE void
+-ldns_buffer_skip(ldns_buffer *buffer, ssize_t count)
+-{
+-	assert(buffer->_position + count <= buffer->_limit);
+-	buffer->_position += count;
+-}
+-
+-/**
+- * returns the maximum size of the buffer
+- * \param[in] buffer
+- * \return the size
+- */
+-INLINE size_t
+-ldns_buffer_limit(ldns_buffer *buffer)
+-{
+-	return buffer->_limit;
+-}
+-
+-/**
+- * changes the buffer's limit.  If the buffer's position is greater
+- * than the new limit the position is set to the limit.
+- * \param[in] buffer the buffer
+- * \param[in] limit the new limit
+- */
+-INLINE void
+-ldns_buffer_set_limit(ldns_buffer *buffer, size_t limit)
+-{
+-	assert(limit <= buffer->_capacity);
+-	buffer->_limit = limit;
+-	if (buffer->_position > buffer->_limit)
+-		buffer->_position = buffer->_limit;
+-}
+-
+-/**
+- * returns the number of bytes the buffer can hold.
+- * \param[in] buffer the buffer
+- * \return the number of bytes
+- */
+-INLINE size_t
+-ldns_buffer_capacity(ldns_buffer *buffer)
+-{
+-	return buffer->_capacity;
+-}
+-
+-/**
+- * changes the buffer's capacity.  The data is reallocated so any
+- * pointers to the data may become invalid.  The buffer's limit is set
+- * to the buffer's new capacity.
+- * \param[in] buffer the buffer
+- * \param[in] capacity the capacity to use
+- * \return whether this failed or succeeded
+- */
+-bool ldns_buffer_set_capacity(ldns_buffer *buffer, size_t capacity);
+-
+-/**
+- * ensures BUFFER can contain at least AMOUNT more bytes.  The buffer's
+- * capacity is increased if necessary using buffer_set_capacity().
+- *
+- * The buffer's limit is always set to the (possibly increased)
+- * capacity.
+- * \param[in] buffer the buffer
+- * \param[in] amount amount to use
+- * \return whether this failed or succeeded
+- */
+-bool ldns_buffer_reserve(ldns_buffer *buffer, size_t amount);
+-
+-/**
+- * returns a pointer to the data at the indicated position.
+- * \param[in] buffer the buffer
+- * \param[in] at position
+- * \return the pointer to the data
+- */
+-INLINE uint8_t *
+-ldns_buffer_at(const ldns_buffer *buffer, size_t at)
+-{
+-	assert(at <= buffer->_limit);
+-	return buffer->_data + at;
+-}
+-
+-/**
+- * returns a pointer to the beginning of the buffer (the data at
+- * position 0).
+- * \param[in] buffer the buffer
+- * \return the pointer
+- */
+-INLINE uint8_t *
+-ldns_buffer_begin(const ldns_buffer *buffer)
+-{
+-	return ldns_buffer_at(buffer, 0);
+-}
+-
+-/**
+- * returns a pointer to the end of the buffer (the data at the buffer's
+- * limit).
+- * \param[in] buffer the buffer
+- * \return the pointer
+- */
+-INLINE uint8_t *
+-ldns_buffer_end(ldns_buffer *buffer)
+-{
+-	return ldns_buffer_at(buffer, buffer->_limit);
+-}
+-
+-/**
+- * returns a pointer to the data at the buffer's current position.
+- * \param[in] buffer the buffer
+- * \return the pointer
+- */
+-INLINE uint8_t *
+-ldns_buffer_current(ldns_buffer *buffer)
+-{
+-	return ldns_buffer_at(buffer, buffer->_position);
+-}
+-
+-/**
+- * returns the number of bytes remaining between the indicated position and
+- * the limit.
+- * \param[in] buffer the buffer
+- * \param[in] at indicated position
+- * \return number of bytes
+- */
+-INLINE size_t
+-ldns_buffer_remaining_at(ldns_buffer *buffer, size_t at)
+-{
+-	ldns_buffer_invariant(buffer);
+-	assert(at <= buffer->_limit);
+-	return buffer->_limit - at;
+-}
+-
+-/**
+- * returns the number of bytes remaining between the buffer's position and
+- * limit.
+- * \param[in] buffer the buffer
+- * \return the number of bytes
+- */
+-INLINE size_t
+-ldns_buffer_remaining(ldns_buffer *buffer)
+-{
+-	return ldns_buffer_remaining_at(buffer, buffer->_position);
+-}
+-
+-/**
+- * checks if the buffer has at least COUNT more bytes available.
+- * Before reading or writing the caller needs to ensure enough space
+- * is available!
+- * \param[in] buffer the buffer
+- * \param[in] at indicated position
+- * \param[in] count how much is available
+- * \return true or false (as int?)
+- */
+-INLINE int
+-ldns_buffer_available_at(ldns_buffer *buffer, size_t at, size_t count)
+-{
+-	return count <= ldns_buffer_remaining_at(buffer, at);
+-}
+-
+-/**
+- * checks if the buffer has count bytes available at the current position
+- * \param[in] buffer the buffer
+- * \param[in] count how much is available
+- * \return true or false (as int?)
+- */
+-INLINE int
+-ldns_buffer_available(ldns_buffer *buffer, size_t count)
+-{
+-	return ldns_buffer_available_at(buffer, buffer->_position, count);
+-}
+-
+-/**
+- * writes the given data to the buffer at the specified position
+- * \param[in] buffer the buffer
+- * \param[in] at the position (in number of bytes) to write the data at
+- * \param[in] data pointer to the data to write to the buffer
+- * \param[in] count the number of bytes of data to write
+- */
+-INLINE void
+-ldns_buffer_write_at(ldns_buffer *buffer, size_t at, const void *data, size_t count)
+-{
+-	assert(ldns_buffer_available_at(buffer, at, count));
+-	memcpy(buffer->_data + at, data, count);
+-}
+-
+-/**
+- * writes count bytes of data to the current position of the buffer
+- * \param[in] buffer the buffer
+- * \param[in] data the data to write
+- * \param[in] count the lenght of the data to write
+- */
+-INLINE void
+-ldns_buffer_write(ldns_buffer *buffer, const void *data, size_t count)
+-{
+-	ldns_buffer_write_at(buffer, buffer->_position, data, count);
+-	buffer->_position += count;
+-}
+-
+-/**
+- * copies the given (null-delimited) string to the specified position at the buffer
+- * \param[in] buffer the buffer
+- * \param[in] at the position in the buffer
+- * \param[in] str the string to write
+- */
+-INLINE void
+-ldns_buffer_write_string_at(ldns_buffer *buffer, size_t at, const char *str)
+-{
+-	ldns_buffer_write_at(buffer, at, str, strlen(str));
+-}
+-
+-/**
+- * copies the given (null-delimited) string to the current position at the buffer
+- * \param[in] buffer the buffer
+- * \param[in] str the string to write
+- */
+-INLINE void
+-ldns_buffer_write_string(ldns_buffer *buffer, const char *str)
+-{
+-	ldns_buffer_write(buffer, str, strlen(str));
+-}
+-
+-/**
+- * writes the given byte of data at the given position in the buffer
+- * \param[in] buffer the buffer
+- * \param[in] at the position in the buffer
+- * \param[in] data the 8 bits to write
+- */
+-INLINE void
+-ldns_buffer_write_u8_at(ldns_buffer *buffer, size_t at, uint8_t data)
+-{
+-	assert(ldns_buffer_available_at(buffer, at, sizeof(data)));
+-	buffer->_data[at] = data;
+-}
+-
+-/**
+- * writes the given byte of data at the current position in the buffer
+- * \param[in] buffer the buffer
+- * \param[in] data the 8 bits to write
+- */
+-INLINE void
+-ldns_buffer_write_u8(ldns_buffer *buffer, uint8_t data)
+-{
+-	ldns_buffer_write_u8_at(buffer, buffer->_position, data);
+-	buffer->_position += sizeof(data);
+-}
+-
+-/**
+- * writes the given 2 byte integer at the given position in the buffer
+- * \param[in] buffer the buffer
+- * \param[in] at the position in the buffer
+- * \param[in] data the 16 bits to write
+- */
+-INLINE void
+-ldns_buffer_write_u16_at(ldns_buffer *buffer, size_t at, uint16_t data)
+-{
+-	assert(ldns_buffer_available_at(buffer, at, sizeof(data)));
+-	ldns_write_uint16(buffer->_data + at, data);
+-}
+-
+-/**
+- * writes the given 2 byte integer at the current position in the buffer
+- * \param[in] buffer the buffer
+- * \param[in] data the 16 bits to write
+- */
+-INLINE void
+-ldns_buffer_write_u16(ldns_buffer *buffer, uint16_t data)
+-{
+-	ldns_buffer_write_u16_at(buffer, buffer->_position, data);
+-	buffer->_position += sizeof(data);
+-}
+-
+-/**
+- * writes the given 4 byte integer at the given position in the buffer
+- * \param[in] buffer the buffer
+- * \param[in] at the position in the buffer
+- * \param[in] data the 32 bits to write
+- */
+-INLINE void
+-ldns_buffer_write_u32_at(ldns_buffer *buffer, size_t at, uint32_t data)
+-{
+-	assert(ldns_buffer_available_at(buffer, at, sizeof(data)));
+-	ldns_write_uint32(buffer->_data + at, data);
+-}
+-
+-/**
+- * writes the given 4 byte integer at the current position in the buffer
+- * \param[in] buffer the buffer
+- * \param[in] data the 32 bits to write
+- */
+-INLINE void
+-ldns_buffer_write_u32(ldns_buffer *buffer, uint32_t data)
+-{
+-	ldns_buffer_write_u32_at(buffer, buffer->_position, data);
+-	buffer->_position += sizeof(data);
+-}
+-
+-/**
+- * copies count bytes of data at the given position to the given data-array
+- * \param[in] buffer the buffer
+- * \param[in] at the position in the buffer to start
+- * \param[out] data buffer to copy to
+- * \param[in] count the length of the data to copy
+- */
+-INLINE void
+-ldns_buffer_read_at(ldns_buffer *buffer, size_t at, void *data, size_t count)
+-{
+-	assert(ldns_buffer_available_at(buffer, at, count));
+-	memcpy(data, buffer->_data + at, count);
+-}
+-
+-/**
+- * copies count bytes of data at the current position to the given data-array
+- * \param[in] buffer the buffer
+- * \param[out] data buffer to copy to
+- * \param[in] count the length of the data to copy
+- */
+-INLINE void
+-ldns_buffer_read(ldns_buffer *buffer, void *data, size_t count)
+-{
+-	ldns_buffer_read_at(buffer, buffer->_position, data, count);
+-	buffer->_position += count;
+-}
+-
+-/**
+- * returns the byte value at the given position in the buffer
+- * \param[in] buffer the buffer
+- * \param[in] at the position in the buffer
+- * \return 1 byte integer
+- */
+-INLINE uint8_t
+-ldns_buffer_read_u8_at(ldns_buffer *buffer, size_t at)
+-{
+-	assert(ldns_buffer_available_at(buffer, at, sizeof(uint8_t)));
+-	return buffer->_data[at];
+-}
+-
+-/**
+- * returns the byte value at the current position in the buffer
+- * \param[in] buffer the buffer
+- * \return 1 byte integer
+- */
+-INLINE uint8_t
+-ldns_buffer_read_u8(ldns_buffer *buffer)
+-{
+-	uint8_t result = ldns_buffer_read_u8_at(buffer, buffer->_position);
+-	buffer->_position += sizeof(uint8_t);
+-	return result;
+-}
+-
+-/**
+- * returns the 2-byte integer value at the given position in the buffer
+- * \param[in] buffer the buffer
+- * \param[in] at position in the buffer
+- * \return 2 byte integer
+- */
+-INLINE uint16_t
+-ldns_buffer_read_u16_at(ldns_buffer *buffer, size_t at)
+-{
+-	assert(ldns_buffer_available_at(buffer, at, sizeof(uint16_t)));
+-	return ldns_read_uint16(buffer->_data + at);
+-}
+-
+-/**
+- * returns the 2-byte integer value at the current position in the buffer
+- * \param[in] buffer the buffer
+- * \return 2 byte integer
+- */
+-INLINE uint16_t
+-ldns_buffer_read_u16(ldns_buffer *buffer)
+-{
+-	uint16_t result = ldns_buffer_read_u16_at(buffer, buffer->_position);
+-	buffer->_position += sizeof(uint16_t);
+-	return result;
+-}
+-
+-/**
+- * returns the 4-byte integer value at the given position in the buffer
+- * \param[in] buffer the buffer
+- * \param[in] at position in the buffer
+- * \return 4 byte integer
+- */
+-INLINE uint32_t
+-ldns_buffer_read_u32_at(ldns_buffer *buffer, size_t at)
+-{
+-	assert(ldns_buffer_available_at(buffer, at, sizeof(uint32_t)));
+-	return ldns_read_uint32(buffer->_data + at);
+-}
+-
+-/**
+- * returns the 4-byte integer value at the current position in the buffer
+- * \param[in] buffer the buffer
+- * \return 4 byte integer
+- */
+-INLINE uint32_t
+-ldns_buffer_read_u32(ldns_buffer *buffer)
+-{
+-	uint32_t result = ldns_buffer_read_u32_at(buffer, buffer->_position);
+-	buffer->_position += sizeof(uint32_t);
+-	return result;
+-}
+-
+-/**
+- * returns the status of the buffer
+- * \param[in] buffer
+- * \return the status
+- */
+-INLINE ldns_status
+-ldns_buffer_status(ldns_buffer *buffer)
+-{
+-	return buffer->_status;
+-}
+-
+-/**
+- * returns true if the status of the buffer is LDNS_STATUS_OK, false otherwise
+- * \param[in] buffer the buffer
+- * \return true or false
+- */
+-INLINE bool
+-ldns_buffer_status_ok(ldns_buffer *buffer)
+-{
+-	if (buffer) {
+-		return ldns_buffer_status(buffer) == LDNS_STATUS_OK;
+-	} else {
+-		return false;
+-	}
+-}
+-
+-/**
+- * prints to the buffer, increasing the capacity if required using
+- * buffer_reserve(). The buffer's position is set to the terminating '\\0'
+- * Returns the number of characters written (not including the
+- * terminating '\\0') or -1 on failure.
+- */
+-int ldns_buffer_printf(ldns_buffer *buffer, const char *format, ...);
+-/*	ATTR_FORMAT(printf, 2, 3);*/
+-
+-/**
+- * frees the buffer.
+- * \param[in] *buffer the buffer to be freed
+- * \return void
+- */
+-void ldns_buffer_free(ldns_buffer *buffer);
+-
+-/**
+- * Makes the buffer fixed and returns a pointer to the data.  The
+- * caller is responsible for free'ing the result.
+- * \param[in] *buffer the buffer to be exported
+- * \return void
+- */
+-void *ldns_buffer_export(ldns_buffer *buffer);
+-
+-/**
+- * Copy contents of the from buffer to the result buffer and then flips 
+- * the result buffer. Data will be silently truncated if the result buffer is
+- * too small.
+- * \param[out] *result resulting buffer which is copied to.
+- * \param[in] *from what to copy to result.
+- */
+-void ldns_buffer_copy(ldns_buffer* result, ldns_buffer* from);
+-
+-#ifdef __cplusplus
+-}
+-#endif
+-
+-#endif /* LDNS_BUFFER_H */
+diff --git a/include/ldns/common.h b/include/ldns/common.h
+deleted file mode 100644
+index 9abd9b9..0000000
+--- a/include/ldns/common.h
++++ /dev/null
+@@ -1,78 +0,0 @@
+-/**
+- * \file common.h
+- *
+- * Common definitions for LDNS
+- */
+-
+-/**
+- * a Net::DNS like library for C
+- *
+- * (c) NLnet Labs, 2004-2006
+- *
+- * See the file LICENSE for the license
+- */
+-
+-#ifndef LDNS_COMMON_H
+-#define LDNS_COMMON_H
+-
+-/*
+- * The build configuration that is used in the distributed headers,
+- * as detected and determined by the auto configure script.
+- */
+-#define LDNS_BUILD_CONFIG_HAVE_SSL         1
+-#define LDNS_BUILD_CONFIG_HAVE_INTTYPES_H  1
+-#define LDNS_BUILD_CONFIG_HAVE_ATTR_FORMAT 1
+-#define LDNS_BUILD_CONFIG_HAVE_ATTR_UNUSED 1
+-#define LDNS_BUILD_CONFIG_HAVE_SOCKLEN_T   1
+-#define LDNS_BUILD_CONFIG_USE_DANE         1
+-#define LDNS_BUILD_CONFIG_HAVE_B32_PTON    0
+-#define LDNS_BUILD_CONFIG_HAVE_B32_NTOP    0
+-
+-/*
+- * HAVE_STDBOOL_H is not available when distributed as a library, but no build 
+- * configuration variables may be used (like those above) because the header
+- * is sometimes only available when using special compiler flags to enable the
+- * c99 environment. Because we cannot force the usage of this flag, we have to
+- * provide a default type. Below what is suggested by the autoconf manual.
+- */
+-/*@ignore@*/
+-/* splint barfs on this construct */
+-#ifndef __bool_true_false_are_defined
+-# ifdef HAVE_STDBOOL_H
+-#  include <stdbool.h>
+-# else
+-#  ifndef HAVE__BOOL
+-#   ifdef __cplusplus
+-typedef bool _Bool;
+-#   else
+-#    define _Bool signed char
+-#   endif
+-#  endif
+-#  define bool _Bool
+-#  define false 0
+-#  define true 1
+-#  define __bool_true_false_are_defined 1
+-# endif
+-#endif
+-/*@end@*/
+-
+-#if LDNS_BUILD_CONFIG_HAVE_ATTR_FORMAT
+-#define ATTR_FORMAT(archetype, string_index, first_to_check) \
+-    __attribute__ ((format (archetype, string_index, first_to_check)))
+-#else /* !LDNS_BUILD_CONFIG_HAVE_ATTR_FORMAT */
+-#define ATTR_FORMAT(archetype, string_index, first_to_check) /* empty */
+-#endif /* !LDNS_BUILD_CONFIG_HAVE_ATTR_FORMAT */
+-
+-#if defined(__cplusplus)
+-#define ATTR_UNUSED(x)
+-#elif LDNS_BUILD_CONFIG_HAVE_ATTR_UNUSED
+-#define ATTR_UNUSED(x)  x __attribute__((unused))
+-#else /* !LDNS_BUILD_CONFIG_HAVE_ATTR_UNUSED */
+-#define ATTR_UNUSED(x)  x
+-#endif /* !LDNS_BUILD_CONFIG_HAVE_ATTR_UNUSED */
+-
+-#if !LDNS_BUILD_CONFIG_HAVE_SOCKLEN_T
+-typedef int socklen_t;
+-#endif
+-
+-#endif /* LDNS_COMMON_H */
+diff --git a/include/ldns/config.h b/include/ldns/config.h
+deleted file mode 100644
+index d77cc7f..0000000
+--- a/include/ldns/config.h
++++ /dev/null
+@@ -1,590 +0,0 @@
+-#include "EXTERN.h"
+-#include "perl.h"
+-
+-/* Define if building universal (internal helper macro) */
+-/* #undef AC_APPLE_UNIVERSAL_BUILD */
+-
+-/* Define to 1 if you have the <arpa/inet.h> header file. */
+-#define HAVE_ARPA_INET_H 1
+-
+-/* Whether the C compiler accepts the "format" attribute */
+-#define HAVE_ATTR_FORMAT 1
+-
+-/* Whether the C compiler accepts the "unused" attribute */
+-#define HAVE_ATTR_UNUSED 1
+-
+-/* Define to 1 if you have the `b32_ntop' function. */
+-/* #undef HAVE_B32_NTOP */
+-
+-/* Define to 1 if you have the `b32_pton' function. */
+-/* #undef HAVE_B32_PTON */
+-
+-/* Define to 1 if you have the `b64_ntop' function. */
+-/* #undef HAVE_B64_NTOP */
+-
+-/* Define to 1 if you have the `b64_pton' function. */
+-/* #undef HAVE_B64_PTON */
+-
+-/* Define to 1 if you have the `bzero' function. */
+-#define HAVE_BZERO 1
+-
+-/* Define to 1 if you have the `calloc' function. */
+-#define HAVE_CALLOC 1
+-
+-/* Define to 1 if you have the `ctime_r' function. */
+-#define HAVE_CTIME_R 1
+-
+-/* Is a CAFILE given at configure time */
+-#define HAVE_DANE_CA_FILE 0
+-
+-/* Is a CAPATH given at configure time */
+-#define HAVE_DANE_CA_PATH 0
+-
+-/* Define to 1 if you have the declaration of `NID_secp384r1', and to 0 if you
+-   don't. */
+-#define HAVE_DECL_NID_SECP384R1 1
+-
+-/* Define to 1 if you have the declaration of `NID_X9_62_prime256v1', and to 0
+-   if you don't. */
+-#define HAVE_DECL_NID_X9_62_PRIME256V1 1
+-
+-/* Define to 1 if you have the <dlfcn.h> header file. */
+-#define HAVE_DLFCN_H 1
+-
+-/* Define to 1 if you have the `endprotoent' function. */
+-#define HAVE_ENDPROTOENT 1
+-
+-/* Define to 1 if you have the `endservent' function. */
+-#define HAVE_ENDSERVENT 1
+-
+-/* Define to 1 if you have the `ENGINE_load_cryptodev' function. */
+-#define HAVE_ENGINE_LOAD_CRYPTODEV 1
+-
+-/* Define to 1 if you have the `EVP_sha256' function. */
+-#define HAVE_EVP_SHA256 1
+-
+-/* Define to 1 if you have the `fcntl' function. */
+-#define HAVE_FCNTL 1
+-
+-/* Define to 1 if you have the `fork' function. */
+-#define HAVE_FORK 1
+-
+-/* Whether getaddrinfo is available */
+-#define HAVE_GETADDRINFO 1
+-
+-/* Define to 1 if you have the <getopt.h> header file. */
+-#define HAVE_GETOPT_H 1
+-
+-/* Define to 1 if you have the `gmtime_r' function. */
+-#define HAVE_GMTIME_R 1
+-
+-/* If you have HMAC_CTX_init */
+-#define HAVE_HMAC_CTX_INIT 1
+-
+-/* Define to 1 if you have the `inet_aton' function. */
+-#define HAVE_INET_ATON 1
+-
+-/* Define to 1 if you have the `inet_ntop' function. */
+-#define HAVE_INET_NTOP 1
+-
+-/* Define to 1 if you have the `inet_pton' function. */
+-#define HAVE_INET_PTON 1
+-
+-/* define if you have inttypes.h */
+-#define HAVE_INTTYPES_H 1
+-
+-/* if the function 'ioctlsocket' is available */
+-/* #undef HAVE_IOCTLSOCKET */
+-
+-/* Define to 1 if you have the `isascii' function. */
+-#define HAVE_ISASCII 1
+-
+-/* Define to 1 if you have the `isblank' function. */
+-#define HAVE_ISBLANK 1
+-
+-/* Define to 1 if you have the `pcap' library (-lpcap). */
+-/* #undef HAVE_LIBPCAP */
+-
+-/* Define to 1 if you have the `localtime_r' function. */
+-#define HAVE_LOCALTIME_R 1
+-
+-/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
+-   to 0 otherwise. */
+-#define HAVE_MALLOC 1
+-
+-/* Define to 1 if you have the `memmove' function. */
+-#define HAVE_MEMMOVE 1
+-
+-/* Define to 1 if you have the <memory.h> header file. */
+-#define HAVE_MEMORY_H 1
+-
+-/* Define to 1 if you have the `memset' function. */
+-#define HAVE_MEMSET 1
+-
+-/* Define to 1 if you have the <netdb.h> header file. */
+-#define HAVE_NETDB_H 1
+-
+-/* Define to 1 if you have the <netinet/if_ether.h> header file. */
+-/* #undef HAVE_NETINET_IF_ETHER_H */
+-
+-/* Define to 1 if you have the <netinet/igmp.h> header file. */
+-/* #undef HAVE_NETINET_IGMP_H */
+-
+-/* Define to 1 if you have the <netinet/in.h> header file. */
+-#define HAVE_NETINET_IN_H 1
+-
+-/* Define to 1 if you have the <netinet/in_systm.h> header file. */
+-/* #undef HAVE_NETINET_IN_SYSTM_H */
+-
+-/* Define to 1 if you have the <netinet/ip6.h> header file. */
+-/* #undef HAVE_NETINET_IP6_H */
+-
+-/* Define to 1 if you have the <netinet/ip_compat.h> header file. */
+-/* #undef HAVE_NETINET_IP_COMPAT_H */
+-
+-/* Define to 1 if you have the <netinet/ip.h> header file. */
+-/* #undef HAVE_NETINET_IP_H */
+-
+-/* Define to 1 if you have the <netinet/udp.h> header file. */
+-/* #undef HAVE_NETINET_UDP_H */
+-
+-/* Define to 1 if you have the <net/ethernet.h> header file. */
+-/* #undef HAVE_NET_ETHERNET_H */
+-
+-/* Define to 1 if you have the <net/if.h> header file. */
+-/* #undef HAVE_NET_IF_H */
+-
+-/* Define to 1 if you have the <openssl/err.h> header file. */
+-#define HAVE_OPENSSL_ERR_H 1
+-
+-/* Define to 1 if you have the <openssl/rand.h> header file. */
+-#define HAVE_OPENSSL_RAND_H 1
+-
+-/* Define to 1 if you have the <openssl/ssl.h> header file. */
+-#define HAVE_OPENSSL_SSL_H 1
+-
+-/* Define to 1 if you have the <pcap.h> header file. */
+-/* #undef HAVE_PCAP_H */
+-
+-/* Define to 1 if you have the `random' function. */
+-#define HAVE_RANDOM 1
+-
+-/* Define to 1 if your system has a GNU libc compatible `realloc' function,
+-   and to 0 otherwise. */
+-#define HAVE_REALLOC 1
+-
+-/* Define to 1 if you have the `sleep' function. */
+-#define HAVE_SLEEP 1
+-
+-/* Define to 1 if you have the `snprintf' function. */
+-#define HAVE_SNPRINTF 1
+-
+-/* Define if you have the SSL libraries installed. */
+-#define HAVE_SSL /**/
+-
+-/* Define to 1 if you have the <stdarg.h> header file. */
+-#define HAVE_STDARG_H 1
+-
+-/* Define to 1 if stdbool.h conforms to C99. */
+-#define HAVE_STDBOOL_H 1
+-
+-/* Define to 1 if you have the <stdint.h> header file. */
+-#define HAVE_STDINT_H 1
+-
+-/* Define to 1 if you have the <stdlib.h> header file. */
+-#define HAVE_STDLIB_H 1
+-
+-/* Define to 1 if you have the <strings.h> header file. */
+-#define HAVE_STRINGS_H 1
+-
+-/* Define to 1 if you have the <string.h> header file. */
+-#define HAVE_STRING_H 1
+-
+-/* Define to 1 if you have the `strlcpy' function. */
+-#ifdef HAS_STRLCPY
+-#define HAVE_STRLCPY 1
+-#else
+-#undef HAVE_STRLCPY
+-#endif
+-
+-/* Define to 1 if you have the `strtoul' function. */
+-#define HAVE_STRTOUL 1
+-
+-/* Define to 1 if you have the <sys/mount.h> header file. */
+-#define HAVE_SYS_MOUNT_H 1
+-
+-/* Define to 1 if you have the <sys/param.h> header file. */
+-#define HAVE_SYS_PARAM_H 1
+-
+-/* define if you have sys/socket.h */
+-#define HAVE_SYS_SOCKET_H 1
+-
+-/* Define to 1 if you have the <sys/stat.h> header file. */
+-#define HAVE_SYS_STAT_H 1
+-
+-/* define if you have sys/types.h */
+-#define HAVE_SYS_TYPES_H 1
+-
+-/* Define to 1 if you have the `timegm' function. */
+-#define HAVE_TIMEGM 1
+-
+-/* Define to 1 if you have the <time.h> header file. */
+-#define HAVE_TIME_H 1
+-
+-/* define if you have unistd.h */
+-#define HAVE_UNISTD_H 1
+-
+-/* Define to 1 if you have the `vfork' function. */
+-#define HAVE_VFORK 1
+-
+-/* Define to 1 if you have the <vfork.h> header file. */
+-/* #undef HAVE_VFORK_H */
+-
+-/* Define to 1 if you have the <winsock2.h> header file. */
+-/* #undef HAVE_WINSOCK2_H */
+-
+-/* Define to 1 if `fork' works. */
+-#define HAVE_WORKING_FORK 1
+-
+-/* Define to 1 if `vfork' works. */
+-#define HAVE_WORKING_VFORK 1
+-
+-/* Define to 1 if you have the <ws2tcpip.h> header file. */
+-/* #undef HAVE_WS2TCPIP_H */
+-
+-/* Define to 1 if the system has the type `_Bool'. */
+-#define HAVE__BOOL 1
+-
+-/* Is a CAFILE given at configure time */
+-/* #undef LDNS_DANE_CA_FILE */
+-
+-/* Is a CAPATH given at configure time */
+-/* #undef LDNS_DANE_CA_PATH */
+-
+-/* Define to the sub-directory where libtool stores uninstalled libraries. */
+-#define LT_OBJDIR ".libs/"
+-
+-/* Define to the address where bug reports for this package should be sent. */
+-#define PACKAGE_BUGREPORT "libdns at nlnetlabs.nl"
+-
+-/* Define to the full name of this package. */
+-#define PACKAGE_NAME "ldns"
+-
+-/* Define to the full name and version of this package. */
+-#define PACKAGE_STRING "ldns 1.6.17"
+-
+-/* Define to the one symbol short name of this package. */
+-#define PACKAGE_TARNAME "libdns"
+-
+-/* Define to the home page for this package. */
+-#define PACKAGE_URL ""
+-
+-/* Define to the version of this package. */
+-#define PACKAGE_VERSION "1.6.17"
+-
+-/* Define this to enable RR type NINFO. */
+-/* #undef RRTYPE_NINFO */
+-
+-/* Define this to enable RR type OPENPGPKEY. */
+-/* #undef RRTYPE_OPENPGPKEY */
+-
+-/* Define this to enable RR type RKEY. */
+-/* #undef RRTYPE_RKEY */
+-
+-/* Define this to enable RR type TA. */
+-/* #undef RRTYPE_TA */
+-
+-/* Define this to enable RR type URI. */
+-/* #undef RRTYPE_URI */
+-
+-/* The size of `time_t', as computed by sizeof. */
+-#define SIZEOF_TIME_T 8
+-
+-/* Define to 1 if you have the ANSI C header files. */
+-#define STDC_HEADERS 1
+-
+-/* Define this to enable messages to stderr. */
+-/* #undef STDERR_MSGS */
+-
+-/* System configuration dir */
+-#define SYSCONFDIR sysconfdir
+-
+-/* Define this to enable DANE support. */
+-#define USE_DANE 1
+-
+-/* Define this to enable ECDSA support. */
+-#define USE_ECDSA 1
+-
+-/* Define this to enable GOST support. */
+-/* #define USE_GOST 1 */
+-
+-/* Define this to enable SHA256 and SHA512 support. */
+-#define USE_SHA2 1
+-
+-/* Enable extensions on AIX 3, Interix.  */
+-#ifndef _ALL_SOURCE
+-# define _ALL_SOURCE 1
+-#endif
+-/* Enable GNU extensions on systems that have them.  */
+-#ifndef _GNU_SOURCE
+-# define _GNU_SOURCE 1
+-#endif
+-/* Enable threading extensions on Solaris.  */
+-#ifndef _POSIX_PTHREAD_SEMANTICS
+-# define _POSIX_PTHREAD_SEMANTICS 1
+-#endif
+-/* Enable extensions on HP NonStop.  */
+-#ifndef _TANDEM_SOURCE
+-# define _TANDEM_SOURCE 1
+-#endif
+-/* Enable general extensions on Solaris.  */
+-#ifndef __EXTENSIONS__
+-# define __EXTENSIONS__ 1
+-#endif
+-
+-
+-/* Whether the windows socket API is used */
+-/* #undef USE_WINSOCK */
+-
+-/* the version of the windows API enabled */
+-#define WINVER 0x0502
+-
+-/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
+-   significant byte first (like Motorola and SPARC, unlike Intel). */
+-#if defined AC_APPLE_UNIVERSAL_BUILD
+-# if defined __BIG_ENDIAN__
+-#  define WORDS_BIGENDIAN 1
+-# endif
+-#else
+-# ifndef WORDS_BIGENDIAN
+-/* #  undef WORDS_BIGENDIAN */
+-# endif
+-#endif
+-
+-/* Define to 1 if on MINIX. */
+-/* #undef _MINIX */
+-
+-/* Enable for compile on Minix */
+-/* #undef _NETBSD_SOURCE */
+-
+-/* Define to 2 if the system does not provide POSIX.1 features except with
+-   this defined. */
+-/* #undef _POSIX_1_SOURCE */
+-
+-/* Define to 1 if you need to in order for `stat' and other things to work. */
+-/* #undef _POSIX_SOURCE */
+-
+-/* Define to empty if `const' does not conform to ANSI C. */
+-/* #undef const */
+-
+-/* in_addr_t */
+-/* #undef in_addr_t */
+-
+-/* in_port_t */
+-/* #undef in_port_t */
+-
+-/* Define to `__inline__' or `__inline' if that's what the C compiler
+-   calls it, or to nothing if 'inline' is not supported under any name.  */
+-#ifndef __cplusplus
+-/* #undef inline */
+-#endif
+-
+-/* Define to `short' if <sys/types.h> does not define. */
+-/* #undef int16_t */
+-
+-/* Define to `int' if <sys/types.h> does not define. */
+-/* #undef int32_t */
+-
+-/* Define to `long long' if <sys/types.h> does not define. */
+-/* #undef int64_t */
+-
+-/* Define to `char' if <sys/types.h> does not define. */
+-/* #undef int8_t */
+-
+-/* Define to `size_t' if <sys/types.h> does not define. */
+-/* #undef intptr_t */
+-
+-/* Define to rpl_malloc if the replacement function should be used. */
+-/* #undef malloc */
+-
+-/* Define to `int' if <sys/types.h> does not define. */
+-/* #undef pid_t */
+-
+-/* Define to rpl_realloc if the replacement function should be used. */
+-/* #undef realloc */
+-
+-/* Define to `unsigned int' if <sys/types.h> does not define. */
+-/* #undef size_t */
+-
+-/* Define to 'int' if not defined */
+-/* #undef socklen_t */
+-
+-/* Fallback member name for socket family in struct sockaddr_storage */
+-/* #undef ss_family */
+-
+-/* Define to `int' if <sys/types.h> does not define. */
+-/* #undef ssize_t */
+-
+-/* Define to `unsigned short' if <sys/types.h> does not define. */
+-/* #undef uint16_t */
+-
+-/* Define to `unsigned int' if <sys/types.h> does not define. */
+-/* #undef uint32_t */
+-
+-/* Define to `unsigned long long' if <sys/types.h> does not define. */
+-/* #undef uint64_t */
+-
+-/* Define to `unsigned char' if <sys/types.h> does not define. */
+-/* #undef uint8_t */
+-
+-/* Define as `fork' if `vfork' does not work. */
+-/* #undef vfork */
+-
+-
+-#include <stdio.h>
+-#include <string.h>
+-#include <unistd.h>
+-#include <assert.h>
+-
+-#ifndef LITTLE_ENDIAN
+-#define LITTLE_ENDIAN 1234
+-#endif
+-
+-#ifndef BIG_ENDIAN
+-#define BIG_ENDIAN 4321
+-#endif
+-
+-#ifndef BYTE_ORDER
+-#ifdef WORDS_BIGENDIAN
+-#define BYTE_ORDER BIG_ENDIAN
+-#else
+-#define BYTE_ORDER LITTLE_ENDIAN
+-#endif /* WORDS_BIGENDIAN */
+-#endif /* BYTE_ORDER */
+-
+-#if STDC_HEADERS
+-#include <stdlib.h>
+-#include <stddef.h>
+-#endif
+-
+-#ifdef HAVE_STDINT_H
+-#include <stdint.h>
+-#endif
+-
+-#ifdef HAVE_SYS_SOCKET_H
+-#include <sys/socket.h>
+-#endif
+-
+-#ifdef HAVE_NETINET_IN_H
+-#include <netinet/in.h>
+-#endif
+-
+-#ifdef HAVE_ARPA_INET_H
+-#include <arpa/inet.h>
+-#endif
+-
+-#ifdef HAVE_WINSOCK2_H
+-#include <winsock2.h>
+-#endif
+-
+-#ifdef HAVE_WS2TCPIP_H
+-#include <ws2tcpip.h>
+-#endif
+-
+-
+-/* detect if we need to cast to unsigned int for FD_SET to avoid warnings */
+-#ifdef HAVE_WINSOCK2_H
+-#define FD_SET_T (u_int)
+-#else
+-#define FD_SET_T 
+-#endif
+-
+-
+-
+-
+-#ifdef __cplusplus
+-extern "C" {
+-#endif
+-
+-int ldns_b64_ntop(uint8_t const *src, size_t srclength,
+-	 	  char *target, size_t targsize);
+-/**
+- * calculates the size needed to store the result of b64_ntop
+- */
+-/*@unused@*/
+-static inline size_t ldns_b64_ntop_calculate_size(size_t srcsize)
+-{
+-	return ((((srcsize + 2) / 3) * 4) + 1);
+-}
+-int ldns_b64_pton(char const *src, uint8_t *target, size_t targsize);
+-/**
+- * calculates the size needed to store the result of ldns_b64_pton
+- */
+-/*@unused@*/
+-static inline size_t ldns_b64_pton_calculate_size(size_t srcsize)
+-{
+-	return (((((srcsize + 3) / 4) * 3)) + 1);
+-}
+-
+-/**
+- * Given in dnssec_zone.c, also used in dnssec_sign.c:w
+-
+- */
+-int ldns_dname_compare_v(const void *a, const void *b);
+-
+-#ifndef HAVE_SLEEP
+-/* use windows sleep, in millisecs, instead */
+-#define sleep(x) Sleep((x)*1000)
+-#endif
+-
+-#ifndef HAVE_RANDOM
+-#define srandom(x) srand(x)
+-#define random(x) rand(x)
+-#endif
+-
+-#ifndef HAVE_TIMEGM
+-#include <time.h>
+-time_t timegm (struct tm *tm);
+-#endif /* !TIMEGM */
+-#ifndef HAVE_GMTIME_R
+-struct tm *gmtime_r(const time_t *timep, struct tm *result);
+-#endif
+-#ifndef HAVE_LOCALTIME_R
+-struct tm *localtime_r(const time_t *timep, struct tm *result);
+-#endif
+-#ifndef HAVE_ISBLANK
+-int isblank(int c);
+-#endif /* !HAVE_ISBLANK */
+-#ifndef HAVE_ISASCII
+-int isascii(int c);
+-#endif /* !HAVE_ISASCII */
+-#ifndef HAVE_SNPRINTF
+-#include <stdarg.h>
+-int snprintf (char *str, size_t count, const char *fmt, ...);
+-int vsnprintf (char *str, size_t count, const char *fmt, va_list arg);
+-#endif /* HAVE_SNPRINTF */
+-#ifndef HAVE_INET_PTON
+-int inet_pton(int af, const char* src, void* dst);
+-#endif /* HAVE_INET_PTON */
+-#ifndef HAVE_INET_NTOP
+-const char *inet_ntop(int af, const void *src, char *dst, size_t size);
+-#endif
+-#ifndef HAVE_INET_ATON
+-int inet_aton(const char *cp, struct in_addr *addr);
+-#endif
+-#ifndef HAVE_MEMMOVE
+-void *memmove(void *dest, const void *src, size_t n);
+-#endif
+-#ifndef HAVE_STRLCPY
+-size_t strlcpy(char *dst, const char *src, size_t siz);
+-#endif
+-#ifdef __cplusplus
+-}
+-#endif
+-#ifndef HAVE_GETADDRINFO
+-#include "compat/fake-rfc2553.h"
+-#endif
+-#ifndef HAVE_STRTOUL
+-#define strtoul (unsigned long)strtol
+-#endif
+-
+diff --git a/include/ldns/dane.h b/include/ldns/dane.h
+deleted file mode 100644
+index 8234eb7..0000000
+--- a/include/ldns/dane.h
++++ /dev/null
+@@ -1,262 +0,0 @@
+-/*
+- * dane.h -- defines for the DNS-Based Authentication of Named Entities (DANE)
+- *                           Transport Layer Security (TLS) Protocol: TLSA
+- *
+- * Copyright (c) 2012, NLnet Labs. All rights reserved.
+- *
+- * See LICENSE for the license.
+- *
+- */
+-
+-/**
+- * \file
+- *
+- * This module contains base functions for creating and verifying TLSA RR's
+- * with PKIX certificates, certificate chains and validation stores.
+- * (See RFC6394 and RFC6698).
+- * 
+- * Since those functions heavily rely op cryptographic operations,
+- * this module is dependent on openssl.
+- */
+- 
+-
+-#ifndef LDNS_DANE_H
+-#define LDNS_DANE_H
+-#if LDNS_BUILD_CONFIG_USE_DANE
+-
+-#include <ldns/common.h>
+-#include <ldns/rdata.h>
+-#include <ldns/rr.h>
+-#if LDNS_BUILD_CONFIG_HAVE_SSL
+-#include <openssl/ssl.h>
+-#include <openssl/err.h>
+-#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */
+-
+-#ifdef __cplusplus
+-extern "C" {
+-#endif
+-
+-/**
+- * The different "Certificate usage" rdata field values for a TLSA RR.
+- */
+-enum ldns_enum_tlsa_certificate_usage
+-{
+-	/** CA constraint */
+-	LDNS_TLSA_USAGE_PKIX_TA				=   0,
+-	LDNS_TLSA_USAGE_CA_CONSTRAINT			=   0,
+-	/** Sevice certificate constraint */
+-	LDNS_TLSA_USAGE_PKIX_EE				=   1,
+-	LDNS_TLSA_USAGE_SERVICE_CERTIFICATE_CONSTRAINT	=   1,
+-	/** Trust anchor assertion */
+-	LDNS_TLSA_USAGE_DANE_TA				=   2,
+-	LDNS_TLSA_USAGE_TRUST_ANCHOR_ASSERTION		=   2,
+-	/** Domain issued certificate */
+-	LDNS_TLSA_USAGE_DANE_EE				=   3,
+-	LDNS_TLSA_USAGE_DOMAIN_ISSUED_CERTIFICATE	=   3,
+-	/** Reserved for Private Use */
+-	LDNS_TLSA_USAGE_PRIVCERT			= 255
+-};
+-typedef enum ldns_enum_tlsa_certificate_usage ldns_tlsa_certificate_usage;
+-
+-/**
+- * The different "Selector" rdata field values for a TLSA RR.
+- */
+-enum ldns_enum_tlsa_selector
+-{
+-	/** 
+-	 * Full certificate: the Certificate binary structure
+-	 * as defined in [RFC5280]
+-	 */
+-	LDNS_TLSA_SELECTOR_CERT			=   0,
+-	LDNS_TLSA_SELECTOR_FULL_CERTIFICATE	=   0,
+-
+-	/** 
+-	 * SubjectPublicKeyInfo: DER-encoded binary structure
+-	 * as defined in [RFC5280]
+-	 */
+-	LDNS_TLSA_SELECTOR_SPKI			=   1,
+-	LDNS_TLSA_SELECTOR_SUBJECTPUBLICKEYINFO	=   1,
+-
+-	/** Reserved for Private Use */
+-	LDNS_TLSA_SELECTOR_PRIVSEL		= 255
+-};
+-typedef enum ldns_enum_tlsa_selector ldns_tlsa_selector;
+-
+-/**
+- * The different "Matching type" rdata field values for a TLSA RR.
+- */
+-enum ldns_enum_tlsa_matching_type
+-{
+-	/** Exact match on selected content */
+-	LDNS_TLSA_MATCHING_TYPE_FULL		=   0,
+-	LDNS_TLSA_MATCHING_TYPE_NO_HASH_USED	=   0,
+-	/** SHA-256 hash of selected content [RFC6234] */
+-	LDNS_TLSA_MATCHING_TYPE_SHA2_256	=   1,
+-	LDNS_TLSA_MATCHING_TYPE_SHA256		=   1,
+-	/** SHA-512 hash of selected content [RFC6234] */
+-	LDNS_TLSA_MATCHING_TYPE_SHA2_512	=   2,
+-	LDNS_TLSA_MATCHING_TYPE_SHA512		=   2,
+-	/** Reserved for Private Use */
+-	LDNS_TLSA_MATCHING_TYPE_PRIVMATCH	= 255
+-};
+-typedef enum ldns_enum_tlsa_matching_type ldns_tlsa_matching_type;
+-
+-/**
+- * Known transports to use with TLSA owner names.
+- */
+-enum ldns_enum_dane_transport
+-{
+-	/** TCP */
+-	LDNS_DANE_TRANSPORT_TCP  = 0,
+-	/** UDP */
+-	LDNS_DANE_TRANSPORT_UDP  = 1,
+-	/** SCTP */
+-	LDNS_DANE_TRANSPORT_SCTP = 2
+-};
+-typedef enum ldns_enum_dane_transport ldns_dane_transport;
+-
+-
+-/**
+- * Creates a dname consisting of the given name, prefixed by the service port
+- * and type of transport: _<EM>port</EM>._<EM>transport</EM>.<EM>name</EM>.
+- *
+- * \param[out] tlsa_owner The created dname.
+- * \param[in] name The dname that should be prefixed.
+- * \param[in] port The service port number for wich the name should be created.
+- * \param[in] transport The transport for wich the name should be created.
+- * \return LDNS_STATUS_OK on success or an error code otherwise.
+- */
+-ldns_status ldns_dane_create_tlsa_owner(ldns_rdf** tlsa_owner,
+-		const ldns_rdf* name, uint16_t port,
+-		ldns_dane_transport transport);
+-
+-
+-#if LDNS_BUILD_CONFIG_HAVE_SSL
+-/**
+- * Creates a LDNS_RDF_TYPE_HEX type rdf based on the binary data choosen by
+- * the selector and encoded using matching_type.
+- *
+- * \param[out] rdf The created created rdf of type LDNS_RDF_TYPE_HEX.
+- * \param[in] cert The certificate from which the data is selected
+- * \param[in] selector The full certificate or the public key
+- * \param[in] matching_type The full data or the SHA256 or SHA512 hash
+- *            of the selected data
+- * \return LDNS_STATUS_OK on success or an error code otherwise.
+- */
+-ldns_status ldns_dane_cert2rdf(ldns_rdf** rdf, X509* cert,
+-		ldns_tlsa_selector      selector,
+-		ldns_tlsa_matching_type matching_type);
+-
+-
+-/**
+- * Selects the certificate from cert, extra_certs or the pkix_validation_store
+- * based on the value of cert_usage and index.
+- *
+- * \param[out] selected_cert The selected cert.
+- * \param[in] cert The certificate to validate (or not)
+- * \param[in] extra_certs Intermediate certificates that might be necessary
+- *            during validation. May be NULL, except when the certificate 
+- *            usage is "Trust Anchor Assertion" because the trust anchor has
+- *            to be provided.(otherwise choose a "Domain issued certificate!"
+- * \param[in] pkix_validation_store Used when the certificate usage is 
+- *            "CA constraint" or "Service Certificate Constraint" to 
+- *            validate the certificate and, in case of "CA constraint",
+- *            select the CA.
+- *            When pkix_validation_store is NULL, validation is explicitely
+- *            turned off and the behaviour is then the same as for "Trust
+- *            anchor assertion" and "Domain issued certificate" respectively.
+- * \param[in] cert_usage Which certificate to use and how to validate.
+- * \param[in] index Used to select the trust anchor when certificate usage
+- *            is "Trust Anchor Assertion". 0 is the last certificate in the
+- *            validation chain. 1 the one but last, etc. When index is -1,
+- *            the last certificate is used that MUST be self-signed.
+- *            This can help to make sure that the intended (self signed)
+- *            trust anchor is actually present in extra_certs (which is a
+- *            DANE requirement).
+- *
+- * \return LDNS_STATUS_OK on success or an error code otherwise.
+- */
+-ldns_status ldns_dane_select_certificate(X509** selected_cert,
+-		X509* cert, STACK_OF(X509)* extra_certs,
+-		X509_STORE* pkix_validation_store,
+-		ldns_tlsa_certificate_usage cert_usage, int index);
+-
+-/**
+- * Creates a TLSA resource record from the certificate.
+- * No PKIX validation is performed! The given certificate is used as data
+- * regardless the value of certificate_usage.
+- *
+- * \param[out] tlsa The created TLSA resource record.
+- * \param[in] certificate_usage The value for the Certificate Usage field
+- * \param[in] selector The value for the Selector field
+- * \param[in] matching_type The value for the Matching Type field
+- * \param[in] cert The certificate which data will be represented
+- *
+- * \return LDNS_STATUS_OK on success or an error code otherwise.
+- */
+-ldns_status ldns_dane_create_tlsa_rr(ldns_rr** tlsa,
+-		ldns_tlsa_certificate_usage certificate_usage,
+-		ldns_tlsa_selector          selector,
+-		ldns_tlsa_matching_type     matching_type,
+-		X509* cert);
+-
+-/**
+- * Verify if the given TLSA resource record matches the given certificate.
+- * Reporting on a TLSA rr mismatch (LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH)
+- * is preferred over PKIX failure  (LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE).
+- * So when PKIX validation is required by the TLSA Certificate usage,
+- * but the TLSA data does not match, LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH
+- * is returned whether the PKIX validated or not.
+- *
+- * \param[in] tlsa_rr The resource record that specifies what and how to
+- *            match the certificate. With tlsa_rr == NULL, regular PKIX
+- *            validation is performed.
+- * \param[in] cert The certificate to match (and validate)
+- * \param[in] extra_certs Intermediate certificates that might be necessary
+- *            creating the validation chain.
+- * \param[in] pkix_validation_store Used when the certificate usage is 
+- *            "CA constraint" or "Service Certificate Constraint" to 
+- *            validate the certificate.
+- *
+- * \return LDNS_STATUS_OK on success,
+- *         LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH on TLSA data mismatch,
+- *         LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE when TLSA matched,
+- *         but the PKIX validation failed, or other ldns_status errors.
+- */
+-ldns_status ldns_dane_verify_rr(const ldns_rr* tlsa_rr,
+-		X509* cert, STACK_OF(X509)* extra_certs,
+-		X509_STORE* pkix_validation_store);
+-
+-/**
+- * Verify if any of the given TLSA resource records matches the given
+- * certificate.
+- *
+- * \param[in] tlsas The resource records that specify what and how to
+- *            match the certificate. One must match for this function
+- *            to succeed. With tlsas == NULL or the number of TLSA records
+- *            in tlsas == 0, regular PKIX validation is performed.
+- * \param[in] cert The certificate to match (and validate)
+- * \param[in] extra_certs Intermediate certificates that might be necessary
+- *            creating the validation chain.
+- * \param[in] pkix_validation_store Used when the certificate usage is 
+- *            "CA constraint" or "Service Certificate Constraint" to 
+- *            validate the certificate.
+- *
+- * \return LDNS_STATUS_OK on success,
+- *         LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE when one of the TLSA's
+- *         matched but the PKIX validation failed,
+- *         LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH when none of the TLSA's matched,
+- *         or other ldns_status errors.
+- */
+-ldns_status ldns_dane_verify(ldns_rr_list* tlsas,
+-		X509* cert, STACK_OF(X509)* extra_certs,
+-		X509_STORE* pkix_validation_store);
+-#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */
+-
+-#ifdef __cplusplus
+-}
+-#endif
+-
+-#endif /* LDNS_BUILD_CONFIG_USE_DANE */
+-#endif /* LDNS_DANE_H */
+-
+diff --git a/include/ldns/dname.h b/include/ldns/dname.h
+deleted file mode 100644
+index 291786b..0000000
+--- a/include/ldns/dname.h
++++ /dev/null
+@@ -1,211 +0,0 @@
+-/*
+- * dname.h
+- *
+- * dname definitions
+- *
+- * a Net::DNS like library for C
+- *
+- * (c) NLnet Labs, 2004-2006
+- *
+- * See the file LICENSE for the license
+- */
+-
+-/**
+- * \file dname.h
+- *
+- * dname contains function to read and manipulate domain names.
+- *
+- * Example domain names are "www.nlnetlabs.nl." and "." (the root)
+- *
+- * If a domain name ends with a dot ("."), it is called a Fully Qualified
+- * Domain Name (FQDN). In certain places (for instance when reading a zone
+- * file), an origin (which is just another domain name) non-FQDNs will be
+- * placed after the current. For instance, if i have a zone file where the
+- * origin has been set to "nl.", and my file contains the name
+- * "www.nlnetlabs", it will result in "www.nlnetlabs.nl.". Internally, dnames are
+- * always absolute (the dot is added when it is missing and there is no origin).
+- *
+- * An FQDN is also
+- * known as an absolute domain name, therefore the function to check this is
+- * called \ref ldns_dname_str_absolute
+- *
+- * Domain names are stored in \ref ldns_rdf structures, with the type
+- * \ref LDNS_RDF_TYPE_DNAME
+- *
+- * This module is *NOT* about the RR type called DNAME.
+- */
+-
+-
+-#ifndef LDNS_DNAME_H
+-#define LDNS_DNAME_H
+-
+-#include <ldns/common.h>
+-#include <ldns/rdata.h>
+-
+-#ifdef __cplusplus
+-extern "C" {
+-#endif
+-
+-#define LDNS_DNAME_NORMALIZE        tolower
+-
+-/**
+- * concatenates two dnames together
+- * \param[in] rd1 the leftside
+- * \param[in] rd2 the rightside
+- * \return a new rdf with leftside/rightside
+- */
+-ldns_rdf *ldns_dname_cat_clone(const ldns_rdf *rd1, const ldns_rdf *rd2);
+-
+-/**
+- * concatenates rd2 after rd1 (rd2 is copied, rd1 is modified)
+- * \param[in] rd1 the leftside
+- * \param[in] rd2 the rightside
+- * \return LDNS_STATUS_OK on success
+- */
+-ldns_status 	ldns_dname_cat(ldns_rdf *rd1, ldns_rdf *rd2);
+-
+-/**
+- * Returns a clone of the given dname with the labels
+- * reversed
+- * \param[in] d the dname to reverse
+- * \return clone of the dname with the labels reversed.
+- */
+-ldns_rdf *ldns_dname_reverse(const ldns_rdf *d);
+-
+-/**
+- * Clones the given dname from the nth label on
+- * \param[in] d The dname to clone
+- * \param[in] n the label nr to clone from, if this is 0, the complete
+- *              dname is cloned
+- * \return A newly allocated *rdf structure, containing the cloned dname,
+- *         or NULL if either d was NULL, not a dname, or if n >=
+- *         label_count
+- */
+-ldns_rdf *
+-ldns_dname_clone_from(const ldns_rdf *d, uint16_t n);
+-
+-/**
+- * chop one label off the left side of a dname. so
+- * wwww.nlnetlabs.nl, becomes nlnetlabs.nl
+- * This new name is a clone and must be freed with ldns_deep_free()
+- * \param[in] d the dname to chop
+- * \return the remaining dname
+- */
+-ldns_rdf *ldns_dname_left_chop(const ldns_rdf *d);
+-
+-/**
+- * count the number of labels inside a LDNS_RDF_DNAME type rdf.
+- * \param[in] *r the rdf
+- * \return the number of labels
+- */
+-uint8_t  ldns_dname_label_count(const ldns_rdf *r);
+-
+-/**
+- * creates a new dname rdf from a string.
+- * \param[in] str string to use
+- * \return ldns_rdf* or NULL in case of an error
+- */
+-ldns_rdf *ldns_dname_new_frm_str(const char *str);
+-
+-/**
+- * Create a new dname rdf from a string
+- * \param[in] s the size of the new dname
+- * \param[in] *data pointer to the actual data
+- *
+- * \return ldns_rdf*
+- */
+-ldns_rdf *ldns_dname_new(uint16_t s, void *data);
+-
+-/**
+- * Create a new dname rdf from data (the data is copied)
+- * \param[in] size the size of the data
+- * \param[in] *data pointer to the actual data
+- *
+- * \return ldns_rdf*
+- */
+-ldns_rdf *ldns_dname_new_frm_data(uint16_t size, const void *data);
+-
+-/**
+- * Put a dname into canonical fmt - ie. lowercase it
+- * \param[in] rdf the dname to lowercase
+- * \return void
+- */
+-void ldns_dname2canonical(const ldns_rdf *rdf);
+-
+-/**
+- * test wether the name sub falls under parent (i.e. is a subdomain
+- * of parent). This function will return false if the given dnames are
+- * equal.
+- * \param[in] sub the name to test
+- * \param[in] parent the parent's name
+- * \return true if sub falls under parent, otherwise false
+- */
+-bool ldns_dname_is_subdomain(const ldns_rdf *sub, const ldns_rdf *parent);
+-
+-/**
+- * Compares the two dname rdf's according to the algorithm for ordering
+- * in RFC4034 Section 6.
+- * \param[in] dname1 First dname rdf to compare
+- * \param[in] dname2 Second dname rdf to compare
+- * \return -1 if dname1 comes before dname2, 1 if dname1 comes after dname2, and 0 if they are equal.
+- */
+-int ldns_dname_compare(const ldns_rdf *dname1, const ldns_rdf *dname2);
+-int ldns_dname_compare_v(const void *, const void *);
+-
+-/**
+- * Checks whether the dname matches the given wildcard
+- * \param[in] dname The dname to check
+- * \param[in] wildcard The wildcard to check with
+- * \return 1 If the wildcard matches, OR if 'wildcard' is not a wildcard and
+- *           the names are *exactly* the same
+- *         0 If the wildcard does not match, or if it is not a wildcard and
+- *           the names are not the same
+- */
+-int ldns_dname_match_wildcard(const ldns_rdf *dname, const ldns_rdf *wildcard);
+-
+-/**
+- * check if middle lays in the interval defined by prev and next
+- * prev <= middle < next. This is usefull for nsec checking
+- * \param[in] prev the previous dname
+- * \param[in] middle the dname to check
+- * \param[in] next the next dname
+- * return 0 on error or unknown, -1 when middle is in the interval, +1 when not
+- */
+-int ldns_dname_interval(const ldns_rdf *prev, const ldns_rdf *middle, const ldns_rdf *next);
+-
+-/**
+- * Checks whether the given dname string is absolute (i.e. ends with a '.')
+- * \param[in] *dname_str a string representing the dname
+- * \return true or false
+- */
+-bool ldns_dname_str_absolute(const char *dname_str);
+-
+-/**
+- * Checks whether the given dname is absolute (i.e. ends with a '.')
+- * \param[in] *dname a rdf representing the dname
+- * \return true or false
+- */
+-bool ldns_dname_absolute(const ldns_rdf *dname);
+-
+-/**
+- * look inside the rdf and if it is an LDNS_RDF_TYPE_DNAME
+- * try and retrieve a specific label. The labels are numbered
+- * starting from 0 (left most).
+- * \param[in] rdf the rdf to look in
+- * \param[in] labelpos return the label with this number
+- * \return a ldns_rdf* with the label as name or NULL on error
+- */
+-ldns_rdf * ldns_dname_label(const ldns_rdf *rdf, uint8_t labelpos);
+-
+-/**
+- * Check if dname is a wildcard, starts with *.
+- * \param[in] dname: the rdf to look in
+- * \return true if a wildcard, false if not.
+- */
+-int ldns_dname_is_wildcard(const ldns_rdf* dname);
+-
+-#ifdef __cplusplus
+-}
+-#endif
+-
+-#endif	/* LDNS_DNAME_H */
+diff --git a/include/ldns/dnssec.h b/include/ldns/dnssec.h
+deleted file mode 100644
+index f4cdafb..0000000
+--- a/include/ldns/dnssec.h
++++ /dev/null
+@@ -1,541 +0,0 @@
+-/*
+- * dnssec.h -- defines for the Domain Name System (SEC) (DNSSEC)
+- *
+- * Copyright (c) 2005-2008, NLnet Labs. All rights reserved.
+- *
+- * See LICENSE for the license.
+- *
+- * A bunch of defines that are used in the DNS
+- */
+-
+-/**
+- * \file dnssec.h
+- *
+- * This module contains base functions for DNSSEC operations
+- * (RFC4033 t/m RFC4035).
+- * 
+- * Since those functions heavily rely op cryptographic operations,
+- * this module is dependent on openssl.
+- * 
+- */
+- 
+-
+-#ifndef LDNS_DNSSEC_H
+-#define LDNS_DNSSEC_H
+-
+-#include <ldns/common.h>
+-#if LDNS_BUILD_CONFIG_HAVE_SSL
+-#include <openssl/ssl.h>
+-#include <openssl/evp.h>
+-#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */
+-#include <ldns/packet.h>
+-#include <ldns/keys.h>
+-#include <ldns/zone.h>
+-#include <ldns/resolver.h>
+-#include <ldns/dnssec_zone.h>
+-
+-#ifdef __cplusplus
+-extern "C" {
+-#endif
+-
+-#define LDNS_MAX_KEYLEN		2048
+-#define LDNS_DNSSEC_KEYPROTO	3
+-/* default time before sigs expire */
+-#define LDNS_DEFAULT_EXP_TIME	2419200 /* 4 weeks */
+-
+-/** return values for the old-signature callback */
+-#define LDNS_SIGNATURE_LEAVE_ADD_NEW 0
+-#define LDNS_SIGNATURE_LEAVE_NO_ADD 1
+-#define LDNS_SIGNATURE_REMOVE_ADD_NEW 2
+-#define LDNS_SIGNATURE_REMOVE_NO_ADD 3
+-
+-/**
+- * Returns the first RRSIG rr that corresponds to the rrset 
+- * with the given name and type
+- * 
+- * \param[in] name The dname of the RRset covered by the RRSIG to find
+- * \param[in] type The type of the RRset covered by the RRSIG to find
+- * \param[in] rrs List of rrs to search in
+- * \returns Pointer to the first RRsig ldns_rr found, or NULL if it is
+- * not present
+- */
+-ldns_rr *ldns_dnssec_get_rrsig_for_name_and_type(const ldns_rdf *name,
+-									    const ldns_rr_type type,
+-									    const ldns_rr_list *rrs);
+-
+-/**
+- * Returns the DNSKEY that corresponds to the given RRSIG rr from the list, if
+- * any
+- *
+- * \param[in] rrsig The rrsig to find the DNSKEY for
+- * \param[in] rrs The rr list to find the key in
+- * \return The DNSKEY that corresponds to the given RRSIG, or NULL if it was
+- *         not found.
+- */
+-ldns_rr *ldns_dnssec_get_dnskey_for_rrsig(const ldns_rr *rrsig, const ldns_rr_list *rrs);
+-
+-/**
+- * Returns the rdata field that contains the bitmap of the covered types of
+- * the given NSEC record
+- *
+- * \param[in] nsec The nsec to get the covered type bitmap of
+- * \return An ldns_rdf containing the bitmap, or NULL on error
+- */
+-ldns_rdf *ldns_nsec_get_bitmap(ldns_rr *nsec);
+-
+-
+-#define LDNS_NSEC3_MAX_ITERATIONS 65535
+-
+-/**
+- * Returns the dname of the closest (provable) encloser
+- */
+-ldns_rdf *
+-ldns_dnssec_nsec3_closest_encloser(ldns_rdf *qname,
+-							ldns_rr_type qtype,
+-							ldns_rr_list *nsec3s);
+-
+-/**
+- * Checks whether the packet contains rrsigs
+- */
+-bool
+-ldns_dnssec_pkt_has_rrsigs(const ldns_pkt *pkt);
+-
+-/**
+- * Returns a ldns_rr_list containing the signatures covering the given name
+- * and type
+- */
+-ldns_rr_list *ldns_dnssec_pkt_get_rrsigs_for_name_and_type(const ldns_pkt *pkt, ldns_rdf *name, ldns_rr_type type);
+-
+-/**
+- * Returns a ldns_rr_list containing the signatures covering the given type
+- */
+-ldns_rr_list *ldns_dnssec_pkt_get_rrsigs_for_type(const ldns_pkt *pkt, ldns_rr_type type);
+-
+-/** 
+- * calculates a keytag of a key for use in DNSSEC.
+- *
+- * \param[in] key the key as an RR to use for the calc.
+- * \return the keytag
+- */
+-uint16_t ldns_calc_keytag(const ldns_rr *key);
+-
+-/**
+- * Calculates keytag of DNSSEC key, operates on wireformat rdata.
+- * \param[in] key the key as uncompressed wireformat rdata.
+- * \param[in] keysize length of key data.
+- * \return the keytag
+- */
+-uint16_t ldns_calc_keytag_raw(uint8_t* key, size_t keysize);
+-
+-#if LDNS_BUILD_CONFIG_HAVE_SSL
+-/**
+- * converts a buffer holding key material to a DSA key in openssl.
+- *
+- * \param[in] key the key to convert
+- * \return a DSA * structure with the key material
+- */
+-DSA *ldns_key_buf2dsa(ldns_buffer *key);
+-/**
+- * Like ldns_key_buf2dsa, but uses raw buffer.
+- * \param[in] key the uncompressed wireformat of the key.
+- * \param[in] len length of key data
+- * \return a DSA * structure with the key material
+- */
+-DSA *ldns_key_buf2dsa_raw(unsigned char* key, size_t len);
+-
+-/**
+- * Utility function to calculate hash using generic EVP_MD pointer.
+- * \param[in] data the data to hash.
+- * \param[in] len  length of data.
+- * \param[out] dest the destination of the hash, must be large enough.
+- * \param[in] md the message digest to use.
+- * \return true if worked, false on failure.
+- */
+-int ldns_digest_evp(unsigned char* data, unsigned int len, 
+-	unsigned char* dest, const EVP_MD* md);
+-
+-/**
+- * Converts a holding buffer with key material to EVP PKEY in openssl.
+- * Only available if ldns was compiled with GOST.
+- * \param[in] key data to convert
+- * \param[in] keylen length of the key data
+- * \return the key or NULL on error.
+- */
+-EVP_PKEY* ldns_gost2pkey_raw(unsigned char* key, size_t keylen);
+-
+-/**
+- * Converts a holding buffer with key material to EVP PKEY in openssl.
+- * Only available if ldns was compiled with ECDSA.
+- * \param[in] key data to convert
+- * \param[in] keylen length of the key data
+- * \param[in] algo precise algorithm to initialize ECC group values.
+- * \return the key or NULL on error.
+- */
+-EVP_PKEY* ldns_ecdsa2pkey_raw(unsigned char* key, size_t keylen, uint8_t algo);
+-
+-#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */
+-
+-#if LDNS_BUILD_CONFIG_HAVE_SSL
+-/**
+- * converts a buffer holding key material to a RSA key in openssl.
+- *
+- * \param[in] key the key to convert
+- * \return a RSA * structure with the key material
+- */
+-RSA *ldns_key_buf2rsa(ldns_buffer *key);
+-
+-/**
+- * Like ldns_key_buf2rsa, but uses raw buffer.
+- * \param[in] key the uncompressed wireformat of the key.
+- * \param[in] len length of key data
+- * \return a RSA * structure with the key material
+- */
+-RSA *ldns_key_buf2rsa_raw(unsigned char* key, size_t len);
+-#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */
+-
+-/** 
+- * returns a new DS rr that represents the given key rr.
+- *
+- * \param[in] *key the key to convert
+- * \param[in] h the hash to use LDNS_SHA1/LDNS_SHA256
+- *
+- * \return ldns_rr* a new rr pointer to a DS
+- */
+-ldns_rr *ldns_key_rr2ds(const ldns_rr *key, ldns_hash h);
+-
+-/**
+- * Create the type bitmap for an NSEC(3) record
+- */
+-ldns_rdf *
+-ldns_dnssec_create_nsec_bitmap(ldns_rr_type rr_type_list[],
+-						 size_t size,
+-						 ldns_rr_type nsec_type);
+-
+-/**
+- * returns whether a rrset of the given type is found in the rrsets.
+- *
+- * \param[in] rrsets the rrsets to be tested
+- * \param[in] type the type to test for
+- * \return int 1 if the type was found, 0 otherwise.
+- */
+-int
+-ldns_dnssec_rrsets_contains_type (ldns_dnssec_rrsets *rrsets, ldns_rr_type type);
+-
+-/**
+- * Creates NSEC
+- */
+-ldns_rr *
+-ldns_dnssec_create_nsec(ldns_dnssec_name *from,
+-				    ldns_dnssec_name *to,
+-				    ldns_rr_type nsec_type);
+-
+-
+-/**
+- * Creates NSEC3
+- */
+-ldns_rr *
+-ldns_dnssec_create_nsec3(ldns_dnssec_name *from,
+-					ldns_dnssec_name *to,
+-					ldns_rdf *zone_name,
+-					uint8_t algorithm,
+-					uint8_t flags,
+-					uint16_t iterations,
+-					uint8_t salt_length,
+-					uint8_t *salt);
+-
+-/**
+- * Create a NSEC record
+- * \param[in] cur_owner the current owner which should be taken as the starting point
+- * \param[in] next_owner the rrlist which the nsec rr should point to 
+- * \param[in] rrs all rrs from the zone, to find all RR types of cur_owner in
+- * \return a ldns_rr with the nsec record in it
+- */
+-ldns_rr * ldns_create_nsec(ldns_rdf *cur_owner, ldns_rdf *next_owner, ldns_rr_list *rrs);
+-
+-/**
+- * Calculates the hashed name using the given parameters
+- * \param[in] *name The owner name to calculate the hash for 
+- * \param[in] algorithm The hash algorithm to use
+- * \param[in] iterations The number of hash iterations to use
+- * \param[in] salt_length The length of the salt in bytes
+- * \param[in] salt The salt to use
+- * \return The hashed owner name rdf, without the domain name
+- */
+-ldns_rdf *ldns_nsec3_hash_name(ldns_rdf *name, uint8_t algorithm, uint16_t iterations, uint8_t salt_length, uint8_t *salt);
+-
+-/**
+- * Sets all the NSEC3 options. The rr to set them in must be initialized with _new() and
+- * type LDNS_RR_TYPE_NSEC3
+- * \param[in] *rr The RR to set the values in
+- * \param[in] algorithm The NSEC3 hash algorithm 
+- * \param[in] flags The flags field 
+- * \param[in] iterations The number of hash iterations
+- * \param[in] salt_length The length of the salt in bytes 
+- * \param[in] salt The salt bytes
+- */
+-void ldns_nsec3_add_param_rdfs(ldns_rr *rr,
+-						 uint8_t algorithm,
+-						 uint8_t flags,
+-						 uint16_t iterations,
+-						 uint8_t salt_length,
+-						 uint8_t *salt);
+-
+-/* this will NOT return the NSEC3  completed, you will have to run the
+-   finalize function on the rrlist later! */
+-ldns_rr *
+-ldns_create_nsec3(ldns_rdf *cur_owner,
+-                  ldns_rdf *cur_zone,
+-                  ldns_rr_list *rrs,
+-                  uint8_t algorithm,
+-                  uint8_t flags,
+-                  uint16_t iterations,
+-                  uint8_t salt_length,
+-                  uint8_t *salt,
+-                  bool emptynonterminal);
+-
+-/**
+- * Returns the hash algorithm used in the given NSEC3 RR
+- * \param[in] *nsec3_rr The RR to read from
+- * \return The algorithm identifier, or 0 on error
+- */
+-uint8_t ldns_nsec3_algorithm(const ldns_rr *nsec3_rr);
+-
+-/**
+- * Returns flags field
+- */
+-uint8_t
+-ldns_nsec3_flags(const ldns_rr *nsec3_rr);
+-
+-/**
+- * Returns true if the opt-out flag has been set in the given NSEC3 RR
+- * \param[in] *nsec3_rr The RR to read from
+- * \return true if the RR has type NSEC3 and the opt-out bit has been set, false otherwise
+- */
+-bool ldns_nsec3_optout(const ldns_rr *nsec3_rr);
+-
+-/**
+- * Returns the number of hash iterations used in the given NSEC3 RR
+- * \param[in] *nsec3_rr The RR to read from
+- * \return The number of iterations
+- */
+-uint16_t ldns_nsec3_iterations(const ldns_rr *nsec3_rr);
+-
+-/**
+- * Returns the salt used in the given NSEC3 RR
+- * \param[in] *nsec3_rr The RR to read from
+- * \return The salt rdf, or NULL on error
+- */
+-ldns_rdf *ldns_nsec3_salt(const ldns_rr *nsec3_rr);
+-
+-/**
+- * Returns the length of the salt used in the given NSEC3 RR
+- * \param[in] *nsec3_rr The RR to read from
+- * \return The length of the salt in bytes
+- */
+-uint8_t ldns_nsec3_salt_length(const ldns_rr *nsec3_rr);
+-
+-/**
+- * Returns the salt bytes used in the given NSEC3 RR
+- * \param[in] *nsec3_rr The RR to read from
+- * \return The salt in bytes, this is alloced, so you need to free it
+- */
+-uint8_t *ldns_nsec3_salt_data(const ldns_rr *nsec3_rr);
+-
+-/**
+- * Returns the first label of the next ownername in the NSEC3 chain (ie. without the domain)
+- * \param[in] nsec3_rr The RR to read from
+- * \return The first label of the next owner name in the NSEC3 chain, or NULL on error 
+- */
+-ldns_rdf *ldns_nsec3_next_owner(const ldns_rr *nsec3_rr);
+-
+-/**
+- * Returns the bitmap specifying the covered types of the given NSEC3 RR
+- * \param[in] *nsec3_rr The RR to read from
+- * \return The covered type bitmap rdf
+- */
+-ldns_rdf *ldns_nsec3_bitmap(const ldns_rr *nsec3_rr);
+-
+-/**
+- * Calculates the hashed name using the parameters of the given NSEC3 RR
+- * \param[in] *nsec The RR to use the parameters from
+- * \param[in] *name The owner name to calculate the hash for 
+- * \return The hashed owner name rdf, without the domain name
+- */
+-ldns_rdf *ldns_nsec3_hash_name_frm_nsec3(const ldns_rr *nsec, ldns_rdf *name);
+-
+-/**
+- * Check if RR type t is enumerated and set in the RR type bitmap rdf.
+- * \param[in] bitmap the RR type bitmap rdf to look in
+- * \param[in] type the type to check for
+- * \return true when t is found and set, otherwise return false
+- */
+-bool ldns_nsec_bitmap_covers_type(const ldns_rdf* bitmap, ldns_rr_type type);
+-
+-/**
+- * Checks if RR type t is enumerated in the type bitmap rdf and sets the bit.
+- * \param[in] bitmap the RR type bitmap rdf to look in
+- * \param[in] type the type to for which the bit to set
+- * \return LDNS_STATUS_OK on success. LDNS_STATUS_TYPE_NOT_IN_BITMAP is 
+- *         returned when the bitmap does not contain the bit to set.
+- */
+-ldns_status ldns_nsec_bitmap_set_type(ldns_rdf* bitmap, ldns_rr_type type);
+-
+-/**
+- * Checks if RR type t is enumerated in the type bitmap rdf and clears the bit.
+- * \param[in] bitmap the RR type bitmap rdf to look in
+- * \param[in] type the type to for which the bit to clear
+- * \return LDNS_STATUS_OK on success. LDNS_STATUS_TYPE_NOT_IN_BITMAP is 
+- *         returned when the bitmap does not contain the bit to clear.
+- */
+-ldns_status ldns_nsec_bitmap_clear_type(ldns_rdf* bitmap, ldns_rr_type type);
+-
+-/**
+- * Checks coverage of NSEC(3) RR name span
+- * Remember that nsec and name must both be in canonical form (ie use
+- * \ref ldns_rr2canonical and \ref ldns_dname2canonical prior to calling this
+- * function)
+- *
+- * \param[in] nsec The NSEC RR to check
+- * \param[in] name The owner dname to check, if the nsec record is a NSEC3 record, this should be the hashed name
+- * \return true if the NSEC RR covers the owner name
+- */
+-bool ldns_nsec_covers_name(const ldns_rr *nsec, const ldns_rdf *name);
+-
+-#if LDNS_BUILD_CONFIG_HAVE_SSL
+-/**
+- * verify a packet 
+- * \param[in] p the packet
+- * \param[in] t the rr set type to check
+- * \param[in] o the rr set name to check
+- * \param[in] k list of keys
+- * \param[in] s list of sigs (may be null)
+- * \param[out] good_keys keys which validated the packet
+- * \return status 
+- * 
+- */
+-ldns_status ldns_pkt_verify(ldns_pkt *p, ldns_rr_type t, ldns_rdf *o, ldns_rr_list *k, ldns_rr_list *s, ldns_rr_list *good_keys);
+-
+-/**
+- * verify a packet 
+- * \param[in] p the packet
+- * \param[in] t the rr set type to check
+- * \param[in] o the rr set name to check
+- * \param[in] k list of keys
+- * \param[in] s list of sigs (may be null)
+- * \param[in] check_time the time for which the validation is performed
+- * \param[out] good_keys keys which validated the packet
+- * \return status 
+- * 
+- */
+-ldns_status ldns_pkt_verify_time(ldns_pkt *p, ldns_rr_type t, ldns_rdf *o, ldns_rr_list *k, ldns_rr_list *s, time_t check_time, ldns_rr_list *good_keys);
+-
+-#endif
+-
+-/**
+- * chains nsec3 list
+- */
+-ldns_status
+-ldns_dnssec_chain_nsec3_list(ldns_rr_list *nsec3_rrs);
+-
+-/**
+- * compare for nsec3 sort
+- */
+-int
+-qsort_rr_compare_nsec3(const void *a, const void *b);
+-
+-/**
+- * sort nsec3 list
+- */
+-void
+-ldns_rr_list_sort_nsec3(ldns_rr_list *unsorted);
+-
+-/** 
+- * Default callback function to always leave present signatures, and
+- * add new ones
+- * \param[in] sig The signature to check for removal (unused)
+- * \param[in] n Optional argument (unused)
+- * \return LDNS_SIGNATURE_LEAVE_ADD_NEW
+- */
+-int ldns_dnssec_default_add_to_signatures(ldns_rr *sig, void *n);
+-/** 
+- * Default callback function to always leave present signatures, and
+- * add no new ones for the keys of these signatures
+- * \param[in] sig The signature to check for removal (unused)
+- * \param[in] n Optional argument (unused)
+- * \return LDNS_SIGNATURE_LEAVE_NO_ADD
+- */
+-int ldns_dnssec_default_leave_signatures(ldns_rr *sig, void *n);
+-/** 
+- * Default callback function to always remove present signatures, but
+- * add no new ones
+- * \param[in] sig The signature to check for removal (unused)
+- * \param[in] n Optional argument (unused)
+- * \return LDNS_SIGNATURE_REMOVE_NO_ADD
+- */
+-int ldns_dnssec_default_delete_signatures(ldns_rr *sig, void *n);
+-/** 
+- * Default callback function to always leave present signatures, and
+- * add new ones
+- * \param[in] sig The signature to check for removal (unused)
+- * \param[in] n Optional argument (unused)
+- * \return LDNS_SIGNATURE_REMOVE_ADD_NEW
+- */
+-int ldns_dnssec_default_replace_signatures(ldns_rr *sig, void *n);
+-
+-#if LDNS_BUILD_CONFIG_HAVE_SSL
+-/**
+- * Converts the DSA signature from ASN1 representation (RFC2459, as 
+- * used by OpenSSL) to raw signature data as used in DNS (rfc2536)
+- *
+- * \param[in] sig The signature in RFC2459 format
+- * \param[in] sig_len The length of the signature
+- * \return a new rdf with the signature
+- */
+-ldns_rdf *
+-ldns_convert_dsa_rrsig_asn12rdf(const ldns_buffer *sig,
+-						  const long sig_len);
+-
+-/**
+- * Converts the RRSIG signature RDF (in rfc2536 format) to a buffer
+- * with the signature in rfc2459 format
+- *
+- * \param[out] target_buffer buffer to place the signature data
+- * \param[in] sig_rdf The signature rdf to convert
+- * \return LDNS_STATUS_OK on success, error code otherwise
+- */
+-ldns_status
+-ldns_convert_dsa_rrsig_rdf2asn1(ldns_buffer *target_buffer,
+-						  const ldns_rdf *sig_rdf);
+-
+-/**
+- * Converts the ECDSA signature from ASN1 representation (as 
+- * used by OpenSSL) to raw signature data as used in DNS
+- * This routine is only present if ldns is compiled with ecdsa support.
+- *
+- * \param[in] sig The signature in ASN1 format
+- * \param[in] sig_len The length of the signature
+- * \return a new rdf with the signature
+- */
+-ldns_rdf *
+-ldns_convert_ecdsa_rrsig_asn12rdf(const ldns_buffer *sig, const long sig_len);
+-
+-/**
+- * Converts the RRSIG signature RDF (from DNS) to a buffer with the 
+- * signature in ASN1 format as openssl uses it.
+- * This routine is only present if ldns is compiled with ecdsa support.
+- *
+- * \param[out] target_buffer buffer to place the signature data in ASN1.
+- * \param[in] sig_rdf The signature rdf to convert
+- * \return LDNS_STATUS_OK on success, error code otherwise
+- */
+-ldns_status
+-ldns_convert_ecdsa_rrsig_rdf2asn1(ldns_buffer *target_buffer,
+-        const ldns_rdf *sig_rdf);
+-
+-#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */
+-
+-#ifdef __cplusplus
+-}
+-#endif
+-
+-#endif /* LDNS_DNSSEC_H */
+diff --git a/include/ldns/dnssec_sign.h b/include/ldns/dnssec_sign.h
+deleted file mode 100644
+index f51c7fb..0000000
+--- a/include/ldns/dnssec_sign.h
++++ /dev/null
+@@ -1,383 +0,0 @@
+-/** dnssec_verify */
+-
+-#ifndef LDNS_DNSSEC_SIGN_H
+-#define LDNS_DNSSEC_SIGN_H
+-
+-#include <ldns/dnssec.h>
+-
+-#ifdef __cplusplus
+-extern "C" {
+-#endif
+-
+-/* sign functions */
+-
+-/** Sign flag that makes DNSKEY type signed by all keys, not only by SEP keys*/
+-#define LDNS_SIGN_DNSKEY_WITH_ZSK 1
+-
+-/**
+- * Create an empty RRSIG RR (i.e. without the actual signature data)
+- * \param[in] rrset The RRset to create the signature for
+- * \param[in] key The key that will create the signature
+- * \return signature rr
+- */
+-ldns_rr *
+-ldns_create_empty_rrsig(ldns_rr_list *rrset,
+-                        ldns_key *key);
+-
+-/**
+- * Sign the buffer which contains the wiredata of an rrset, and the
+- * corresponding empty rrsig rr with the given key
+- * \param[in] sign_buf the buffer with data to sign
+- * \param[in] key the key to sign with
+- * \return an rdata field with the signature data
+- */
+-ldns_rdf *
+-ldns_sign_public_buffer(ldns_buffer *sign_buf, ldns_key *key);
+-
+-/**
+- * Sign an rrset
+- * \param[in] rrset the rrset
+- * \param[in] keys the keys to use
+- * \return a rr_list with the signatures
+- */
+-ldns_rr_list *ldns_sign_public(ldns_rr_list *rrset, ldns_key_list *keys);
+-
+-#if LDNS_BUILD_CONFIG_HAVE_SSL
+-/**
+- * Sign a buffer with the DSA key (hash with SHA1)
+- * \param[in] to_sign buffer with the data
+- * \param[in] key the key to use
+- * \return a ldns_rdf with the signed data
+- */
+-ldns_rdf *ldns_sign_public_dsa(ldns_buffer *to_sign, DSA *key);
+-
+-/**
+- * Sign data with EVP (general method for different algorithms)
+- *
+- * \param[in] to_sign The ldns_buffer containing raw data that is
+- *                    to be signed
+- * \param[in] key The EVP_PKEY key structure to sign with
+- * \param[in] digest_type The digest algorithm to use in the creation of
+- *                        the signature
+- * \return ldns_rdf for the RRSIG ldns_rr
+- */
+-ldns_rdf *ldns_sign_public_evp(ldns_buffer *to_sign,
+-						 EVP_PKEY *key,
+-						 const EVP_MD *digest_type);
+-
+-/**
+- * Sign a buffer with the RSA key (hash with SHA1)
+- * \param[in] to_sign buffer with the data
+- * \param[in] key the key to use
+- * \return a ldns_rdf with the signed data
+- */
+-ldns_rdf *ldns_sign_public_rsasha1(ldns_buffer *to_sign, RSA *key);
+-
+-/**
+- * Sign a buffer with the RSA key (hash with MD5)
+- * \param[in] to_sign buffer with the data
+- * \param[in] key the key to use
+- * \return a ldns_rdf with the signed data
+- */
+-ldns_rdf *ldns_sign_public_rsamd5(ldns_buffer *to_sign, RSA *key);
+-#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */
+-
+-/**
+- * Marks the names in the zone that are occluded. Those names will be skipped
+- * when walking the tree with the ldns_dnssec_name_node_next_nonglue()
+- * function. But watch out! Names that are partially occluded (like glue with
+- * the same name as the delegation) will not be marked and should specifically 
+- * be taken into account separately.
+- *
+- * When glue_list is given (not NULL), in the process of marking the names, all
+- * glue resource records will be pushed to that list, even glue at the delegation name.
+- *
+- * \param[in] zone the zone in which to mark the names
+- * \param[in] glue_list the list to which to push the glue rrs
+- * \return LDNS_STATUS_OK on success, an error code otherwise
+- */
+-ldns_status
+-ldns_dnssec_zone_mark_and_get_glue(
+-		ldns_dnssec_zone *zone, ldns_rr_list *glue_list);
+-
+-/**
+- * Marks the names in the zone that are occluded. Those names will be skipped
+- * when walking the tree with the ldns_dnssec_name_node_next_nonglue()
+- * function. But watch out! Names that are partially occluded (like glue with
+- * the same name as the delegation) will not be marked and should specifically 
+- * be taken into account separately.
+- *
+- * \param[in] zone the zone in which to mark the names
+- * \return LDNS_STATUS_OK on succesful completion
+- */
+-ldns_status
+-ldns_dnssec_zone_mark_glue(ldns_dnssec_zone *zone);
+-
+-/**
+- * Finds the first dnssec_name node in the rbtree that is not occluded.
+- * It *does* return names that are partially occluded.
+- *
+- * \param[in] node the first node to check
+- * \return the first node that has not been marked as glue, or NULL
+- * if not found (TODO: make that LDNS_RBTREE_NULL?)
+- */
+-ldns_rbnode_t *ldns_dnssec_name_node_next_nonglue(ldns_rbnode_t *node);
+-
+-/**
+- * Adds NSEC records to the given dnssec_zone
+- *
+- * \param[in] zone the zone to add the records to
+- * \param[in] new_rrs ldns_rr's created by this function are
+- *            added to this rr list, so the caller can free them later
+- * \return LDNS_STATUS_OK on success, an error code otherwise
+- */
+-ldns_status ldns_dnssec_zone_create_nsecs(ldns_dnssec_zone *zone,
+-								  ldns_rr_list *new_rrs);
+-
+-/**
+- * Adds NSEC3 records to the zone
+- */
+-ldns_status
+-ldns_dnssec_zone_create_nsec3s(ldns_dnssec_zone *zone,
+-						 ldns_rr_list *new_rrs,
+-						 uint8_t algorithm,
+-						 uint8_t flags,
+-						 uint16_t iterations,
+-						 uint8_t salt_length,
+-						 uint8_t *salt);
+-
+-/**
+- * remove signatures if callback function tells to
+- * 
+- * \param[in] signatures list of signatures to check, and
+- *            possibly remove, depending on the value of the
+- *            callback
+- * \param[in] key_list these are marked to be used or not,
+- *            on the return value of the callback
+- * \param[in] func this function is called to specify what to
+- *            do with each signature (and corresponding key)
+- * \param[in] arg Optional argument for the callback function
+- * \returns pointer to the new signatures rrs (the original
+- *          passed to this function may have been removed)
+- */
+-ldns_dnssec_rrs *ldns_dnssec_remove_signatures(ldns_dnssec_rrs *signatures,
+-									  ldns_key_list *key_list,
+-									  int (*func)(ldns_rr *, void *),
+-									  void *arg);
+-
+-/**
+- * Adds signatures to the zone
+- *
+- * \param[in] zone the zone to add RRSIG Resource Records to
+- * \param[in] new_rrs the RRSIG RRs that are created are also
+- *            added to this list, so the caller can free them
+- *            later
+- * \param[in] key_list list of keys to sign with.
+- * \param[in] func Callback function to decide what keys to
+- *            use and what to do with old signatures
+- * \param[in] arg Optional argument for the callback function
+- * \param[in] flags option flags for signing process. 0 makes DNSKEY
+- * RRset signed with the minimal key set, that is only SEP keys are used
+- * for signing. If there are no SEP keys available, non-SEP keys will
+- * be used. LDNS_SIGN_DNSKEY_WITH_ZSK makes DNSKEY type signed with all
+- * keys. 0 is the default.
+- * \return LDNS_STATUS_OK on success, error otherwise
+- */
+-ldns_status ldns_dnssec_zone_create_rrsigs_flg(ldns_dnssec_zone *zone,
+-					ldns_rr_list *new_rrs,
+-					ldns_key_list *key_list,
+-					int (*func)(ldns_rr *, void*),
+-					void *arg,
+-					int flags);
+-
+-/**
+- * Adds signatures to the zone
+- *
+- * \param[in] zone the zone to add RRSIG Resource Records to
+- * \param[in] new_rrs the RRSIG RRs that are created are also
+- *            added to this list, so the caller can free them
+- *            later
+- * \param[in] key_list list of keys to sign with.
+- * \param[in] func Callback function to decide what keys to
+- *            use and what to do with old signatures
+- * \param[in] arg Optional argument for the callback function
+- * \return LDNS_STATUS_OK on success, error otherwise
+- */
+-ldns_status ldns_dnssec_zone_create_rrsigs(ldns_dnssec_zone *zone,
+-								   ldns_rr_list *new_rrs,
+-								   ldns_key_list *key_list,
+-								   int (*func)(ldns_rr *, void*),
+-								   void *arg);
+-
+-/**
+- * signs the given zone with the given keys
+- * 
+- * \param[in] zone the zone to sign
+- * \param[in] key_list the list of keys to sign the zone with
+- * \param[in] new_rrs newly created resource records are added to this list, to free them later
+- * \param[in] func callback function that decides what to do with old signatures
+- *            This function takes an ldns_rr* and an optional void *arg argument, and returns one of four values:
+- * LDNS_SIGNATURE_LEAVE_ADD_NEW:
+- * leave the signature and add a new one for the corresponding key
+- * LDNS_SIGNATURE_REMOVE_ADD_NEW:
+- * remove the signature and replace is with a new one from the same key
+- * LDNS_SIGNATURE_LEAVE_NO_ADD:
+- * leave the signature and do not add a new one with the corresponding key
+- * LDNS_SIGNATURE_REMOVE_NO_ADD:
+- * remove the signature and do not replace 
+- *
+- * \param[in] arg optional argument for the callback function
+- * \param[in] flags option flags for signing process. 0 makes DNSKEY
+- * RRset signed with the minimal key set, that is only SEP keys are used
+- * for signing. If there are no SEP keys available, non-SEP keys will
+- * be used. LDNS_SIGN_DNSKEY_WITH_ZSK makes DNSKEY type signed with all
+- * keys. 0 is the default.
+- * \return LDNS_STATUS_OK on success, an error code otherwise
+- */
+-ldns_status ldns_dnssec_zone_sign_flg(ldns_dnssec_zone *zone,
+-					ldns_rr_list *new_rrs,
+-					ldns_key_list *key_list,
+-					int (*func)(ldns_rr *, void *),
+-					void *arg, 
+-					int flags);
+-
+-/**
+- * signs the given zone with the given new zone, with NSEC3
+- *
+- * \param[in] zone the zone to sign
+- * \param[in] key_list the list of keys to sign the zone with
+- * \param[in] new_rrs newly created resource records are added to this list, to free them later
+- * \param[in] func callback function that decides what to do with old signatures
+- * \param[in] arg optional argument for the callback function
+- * \param[in] algorithm the NSEC3 hashing algorithm to use
+- * \param[in] flags NSEC3 flags
+- * \param[in] iterations the number of NSEC3 hash iterations to use
+- * \param[in] salt_length the length (in octets) of the NSEC3 salt
+- * \param[in] salt the NSEC3 salt data
+- * \param[in] signflags option flags for signing process. 0 is the default.
+- * \return LDNS_STATUS_OK on success, an error code otherwise
+- */
+-ldns_status ldns_dnssec_zone_sign_nsec3_flg(ldns_dnssec_zone *zone,
+-				ldns_rr_list *new_rrs,
+-				ldns_key_list *key_list,
+-				int (*func)(ldns_rr *, void *),
+-				void *arg,
+-				uint8_t algorithm,
+-				uint8_t flags,
+-				uint16_t iterations,
+-				uint8_t salt_length,
+-				uint8_t *salt,
+-				int signflags);
+-
+-/**
+- * signs the given zone with the given new zone, with NSEC3
+- *
+- * \param[in] zone the zone to sign
+- * \param[in] key_list the list of keys to sign the zone with
+- * \param[in] new_rrs newly created resource records are added to this list, to free them later
+- * \param[in] func callback function that decides what to do with old signatures
+- * \param[in] arg optional argument for the callback function
+- * \param[in] algorithm the NSEC3 hashing algorithm to use
+- * \param[in] flags NSEC3 flags
+- * \param[in] iterations the number of NSEC3 hash iterations to use
+- * \param[in] salt_length the length (in octets) of the NSEC3 salt
+- * \param[in] salt the NSEC3 salt data
+- * \param[in] signflags option flags for signing process. 0 is the default.
+- * \param[out] map a referenced rbtree pointer variable. The newly created 
+- *                 rbtree will contain mappings from hashed owner names to the 
+- *                 unhashed name.
+- * \return LDNS_STATUS_OK on success, an error code otherwise
+- */
+-ldns_status ldns_dnssec_zone_sign_nsec3_flg_mkmap(ldns_dnssec_zone *zone,
+-				ldns_rr_list *new_rrs,
+-				ldns_key_list *key_list,
+-				int (*func)(ldns_rr *, void *),
+-				void *arg,
+-				uint8_t algorithm,
+-				uint8_t flags,
+-				uint16_t iterations,
+-				uint8_t salt_length,
+-				uint8_t *salt,
+-				int signflags,
+-				ldns_rbtree_t **map
+-				);
+-
+-
+-/**
+- * signs the given zone with the given keys
+- * 
+- * \param[in] zone the zone to sign
+- * \param[in] key_list the list of keys to sign the zone with
+- * \param[in] new_rrs newly created resource records are added to this list, to free them later
+- * \param[in] func callback function that decides what to do with old signatures
+- *            This function takes an ldns_rr* and an optional void *arg argument, and returns one of four values:
+- * LDNS_SIGNATURE_LEAVE_ADD_NEW:
+- * leave the signature and add a new one for the corresponding key
+- * LDNS_SIGNATURE_REMOVE_ADD_NEW:
+- * remove the signature and replace is with a new one from the same key
+- * LDNS_SIGNATURE_LEAVE_NO_ADD:
+- * leave the signature and do not add a new one with the corresponding key
+- * LDNS_SIGNATURE_REMOVE_NO_ADD:
+- * remove the signature and do not replace 
+- *
+- * \param[in] arg optional argument for the callback function
+- * \return LDNS_STATUS_OK on success, an error code otherwise
+- */
+-ldns_status ldns_dnssec_zone_sign(ldns_dnssec_zone *zone,
+-						    ldns_rr_list *new_rrs,
+-						    ldns_key_list *key_list,
+-						    int (*func)(ldns_rr *, void *),
+-						    void *arg);
+-
+-/**
+- * signs the given zone with the given new zone, with NSEC3
+- *
+- * \param[in] zone the zone to sign
+- * \param[in] key_list the list of keys to sign the zone with
+- * \param[in] new_rrs newly created resource records are added to this list, to free them later
+- * \param[in] func callback function that decides what to do with old signatures
+- * \param[in] arg optional argument for the callback function
+- * \param[in] algorithm the NSEC3 hashing algorithm to use
+- * \param[in] flags NSEC3 flags
+- * \param[in] iterations the number of NSEC3 hash iterations to use
+- * \param[in] salt_length the length (in octets) of the NSEC3 salt
+- * \param[in] salt the NSEC3 salt data
+- * \return LDNS_STATUS_OK on success, an error code otherwise
+- */
+-ldns_status ldns_dnssec_zone_sign_nsec3(ldns_dnssec_zone *zone,
+-								ldns_rr_list *new_rrs,
+-								ldns_key_list *key_list,
+-								int (*func)(ldns_rr *, void *),
+-								void *arg,
+-								uint8_t algorithm,
+-								uint8_t flags,
+-								uint16_t iterations,
+-								uint8_t salt_length,
+-								uint8_t *salt);
+-
+-/**
+- * Signs the zone, and returns a newly allocated signed zone
+- * \param[in] zone the zone to sign
+- * \param[in] key_list list of keys to sign with
+- * \return signed zone
+- */
+-ldns_zone *ldns_zone_sign(const ldns_zone *zone, ldns_key_list *key_list);
+-
+-/**
+- * Signs the zone with NSEC3, and returns a newly allocated signed zone
+- * \param[in] zone the zone to sign
+- * \param[in] key_list list of keys to sign with
+- * \param[in] algorithm the NSEC3 hashing algorithm to use
+- * \param[in] flags NSEC3 flags
+- * \param[in] iterations the number of NSEC3 hash iterations to use
+- * \param[in] salt_length the length (in octets) of the NSEC3 salt
+- * \param[in] salt the NSEC3 salt data
+- * \return signed zone
+- */
+-ldns_zone *ldns_zone_sign_nsec3(ldns_zone *zone, ldns_key_list *key_list, uint8_t algorithm, uint8_t flags, uint16_t iterations, uint8_t salt_length, uint8_t *salt);
+- 
+-#ifdef __cplusplus
+-}
+-#endif
+-
+-#endif
+diff --git a/include/ldns/dnssec_verify.h b/include/ldns/dnssec_verify.h
+deleted file mode 100644
+index e8b1a91..0000000
+--- a/include/ldns/dnssec_verify.h
++++ /dev/null
+@@ -1,857 +0,0 @@
+-/** dnssec_verify */
+-
+-#ifndef LDNS_DNSSEC_VERIFY_H
+-#define LDNS_DNSSEC_VERIFY_H
+-
+-#define LDNS_DNSSEC_TRUST_TREE_MAX_PARENTS 10
+-
+-#include <ldns/dnssec.h>
+-#include <ldns/host2str.h>
+-
+-#ifdef __cplusplus
+-extern "C" {
+-#endif
+-
+-/**
+- * Chain structure that contains all DNSSEC data needed to
+- * verify an rrset
+- */
+-typedef struct ldns_dnssec_data_chain_struct ldns_dnssec_data_chain;
+-struct ldns_dnssec_data_chain_struct
+-{
+-	ldns_rr_list *rrset;
+-	ldns_rr_list *signatures;
+-	ldns_rr_type parent_type;
+-	ldns_dnssec_data_chain *parent;
+-	ldns_pkt_rcode packet_rcode;
+-	ldns_rr_type packet_qtype;
+-	bool packet_nodata;
+-};
+-
+-/**
+- * Creates a new dnssec_chain structure
+- * \return ldns_dnssec_data_chain *
+- */
+-ldns_dnssec_data_chain *ldns_dnssec_data_chain_new(void);
+-
+-/**
+- * Frees a dnssec_data_chain structure
+- *
+- * \param[in] *chain The chain to free
+- */
+-void ldns_dnssec_data_chain_free(ldns_dnssec_data_chain *chain);
+-
+-/**
+- * Frees a dnssec_data_chain structure, and all data
+- * contained therein
+- *
+- * \param[in] *chain The dnssec_data_chain to free
+- */
+-void ldns_dnssec_data_chain_deep_free(ldns_dnssec_data_chain *chain);
+-
+-/**
+- * Prints the dnssec_data_chain to the given file stream
+- * 
+- * \param[in] *out The file stream to print to
+- * \param[in] *chain The dnssec_data_chain to print
+- */
+-void ldns_dnssec_data_chain_print(FILE *out, const ldns_dnssec_data_chain *chain);
+-
+-/**
+- * Prints the dnssec_data_chain to the given file stream
+- * 
+- * \param[in] *out The file stream to print to
+- * \param[in] *fmt The format of the textual representation
+- * \param[in] *chain The dnssec_data_chain to print
+- */
+-void ldns_dnssec_data_chain_print_fmt(FILE *out, 
+-		const ldns_output_format *fmt,
+-		const ldns_dnssec_data_chain *chain);
+-
+-/**
+- * Build an ldns_dnssec_data_chain, which contains all
+- * DNSSEC data that is needed to derive the trust tree later
+- *
+- * The data_set will be cloned
+- *
+- * \param[in] *res resolver structure for further needed queries
+- * \param[in] qflags resolution flags
+- * \param[in] *data_set The original rrset where the chain ends
+- * \param[in] *pkt optional, can contain the original packet
+- * (and hence the sigs and maybe the key)
+- * \param[in] *orig_rr The original Resource Record
+- *
+- * \return the DNSSEC data chain
+- */
+-ldns_dnssec_data_chain *ldns_dnssec_build_data_chain(ldns_resolver *res,
+-										   const uint16_t qflags,
+-										   const ldns_rr_list *data_set,
+-										   const ldns_pkt *pkt,
+-										   ldns_rr *orig_rr);
+-
+-/**
+- * Tree structure that contains the relation of DNSSEC data,
+- * and their cryptographic status.
+- *
+- * This tree is derived from a data_chain, and can be used
+- * to look whether there is a connection between an RRSET
+- * and a trusted key. The tree only contains pointers to the
+- * data_chain, and therefore one should *never* free() the
+- * data_chain when there is still a trust tree derived from
+- * that chain.
+- *
+- * Example tree:
+- *     key   key    key
+- *       \    |    /
+- *        \   |   /
+- *         \  |  /
+- *            ds
+- *            |
+- *           key
+- *            |
+- *           key
+- *            |
+- *            rr
+- *
+- * For each signature there is a parent; if the parent
+- * pointer is null, it couldn't be found and there was no
+- * denial; otherwise is a tree which contains either a
+- * DNSKEY, a DS, or a NSEC rr
+- */
+-typedef struct ldns_dnssec_trust_tree_struct ldns_dnssec_trust_tree;
+-struct ldns_dnssec_trust_tree_struct
+-{
+-	ldns_rr *rr;
+-	/* the complete rrset this rr was in */
+-	ldns_rr_list *rrset;
+-	ldns_dnssec_trust_tree *parents[LDNS_DNSSEC_TRUST_TREE_MAX_PARENTS];
+-	ldns_status parent_status[LDNS_DNSSEC_TRUST_TREE_MAX_PARENTS];
+-	/** for debugging, add signatures too (you might want
+-	    those if they contain errors) */
+-	ldns_rr *parent_signature[LDNS_DNSSEC_TRUST_TREE_MAX_PARENTS];
+-	size_t parent_count;
+-};
+-
+-/**
+- * Creates a new (empty) dnssec_trust_tree structure
+- *
+- * \return ldns_dnssec_trust_tree *
+- */
+-ldns_dnssec_trust_tree *ldns_dnssec_trust_tree_new(void);
+-
+-/**
+- * Frees the dnssec_trust_tree recursively
+- *
+- * There is no deep free; all data in the trust tree
+- * consists of pointers to a data_chain
+- *
+- * \param[in] tree The tree to free
+- */
+-void ldns_dnssec_trust_tree_free(ldns_dnssec_trust_tree *tree);
+-
+-/**
+- * returns the depth of the trust tree
+- *
+- * \param[in] tree tree to calculate the depth of
+- * \return The depth of the tree
+- */
+-size_t ldns_dnssec_trust_tree_depth(ldns_dnssec_trust_tree *tree);
+-
+-/**
+- * Prints the dnssec_trust_tree structure to the given file
+- * stream.
+- *
+- * If a link status is not LDNS_STATUS_OK; the status and
+- * relevant signatures are printed too
+- *
+- * \param[in] *out The file stream to print to
+- * \param[in] tree The trust tree to print
+- * \param[in] tabs Prepend each line with tabs*2 spaces
+- * \param[in] extended If true, add little explanation lines to the output
+- */
+-void ldns_dnssec_trust_tree_print(FILE *out,
+-	       	ldns_dnssec_trust_tree *tree,
+-		size_t tabs,
+-		bool extended);
+-
+-/**
+- * Prints the dnssec_trust_tree structure to the given file
+- * stream.
+- *
+- * If a link status is not LDNS_STATUS_OK; the status and
+- * relevant signatures are printed too
+- *
+- * \param[in] *out The file stream to print to
+- * \param[in] *fmt The format of the textual representation
+- * \param[in] tree The trust tree to print
+- * \param[in] tabs Prepend each line with tabs*2 spaces
+- * \param[in] extended If true, add little explanation lines to the output
+- */
+-void ldns_dnssec_trust_tree_print_fmt(FILE *out,
+-		const ldns_output_format *fmt,
+-	       	ldns_dnssec_trust_tree *tree,
+-		size_t tabs,
+-		bool extended);
+-
+-/**
+- * Adds a trust tree as a parent for the given trust tree
+- *
+- * \param[in] *tree The tree to add the parent to
+- * \param[in] *parent The parent tree to add
+- * \param[in] *parent_signature The RRSIG relevant to this parent/child
+- *                              connection
+- * \param[in] parent_status The DNSSEC status for this parent, child and RRSIG
+- * \return LDNS_STATUS_OK if the addition succeeds, error otherwise
+- */
+-ldns_status ldns_dnssec_trust_tree_add_parent(ldns_dnssec_trust_tree *tree,
+-									 const ldns_dnssec_trust_tree *parent,
+-									 const ldns_rr *parent_signature,
+-									 const ldns_status parent_status);
+-
+-/**
+- * Generates a dnssec_trust_tree for the given rr from the
+- * given data_chain
+- *
+- * This does not clone the actual data; Don't free the
+- * data_chain before you are done with this tree
+- *
+- * \param[in] *data_chain The chain to derive the trust tree from
+- * \param[in] *rr The RR this tree will be about
+- * \return ldns_dnssec_trust_tree *
+- */
+-ldns_dnssec_trust_tree *ldns_dnssec_derive_trust_tree(
+-                            ldns_dnssec_data_chain *data_chain,
+-					   ldns_rr *rr);
+-
+-/**
+- * Generates a dnssec_trust_tree for the given rr from the
+- * given data_chain
+- *
+- * This does not clone the actual data; Don't free the
+- * data_chain before you are done with this tree
+- *
+- * \param[in] *data_chain The chain to derive the trust tree from
+- * \param[in] *rr The RR this tree will be about
+- * \param[in] check_time the time for which the validation is performed
+- * \return ldns_dnssec_trust_tree *
+- */
+-ldns_dnssec_trust_tree *ldns_dnssec_derive_trust_tree_time(
+-		ldns_dnssec_data_chain *data_chain, 
+-		ldns_rr *rr, time_t check_time);
+-
+-/**
+- * Sub function for derive_trust_tree that is used for a 'normal' rrset
+- *
+- * \param[in] new_tree The trust tree that we are building
+- * \param[in] data_chain The data chain containing the data for the trust tree
+- * \param[in] cur_sig_rr The currently relevant signature
+- */
+-void ldns_dnssec_derive_trust_tree_normal_rrset(
+-         ldns_dnssec_trust_tree *new_tree,
+-	    ldns_dnssec_data_chain *data_chain,
+-	    ldns_rr *cur_sig_rr);
+-
+-/**
+- * Sub function for derive_trust_tree that is used for a 'normal' rrset
+- *
+- * \param[in] new_tree The trust tree that we are building
+- * \param[in] data_chain The data chain containing the data for the trust tree
+- * \param[in] cur_sig_rr The currently relevant signature
+- * \param[in] check_time the time for which the validation is performed
+- */
+-void ldns_dnssec_derive_trust_tree_normal_rrset_time(
+-         ldns_dnssec_trust_tree *new_tree,
+-	    ldns_dnssec_data_chain *data_chain,
+-	    ldns_rr *cur_sig_rr, time_t check_time);
+-
+-
+-/**
+- * Sub function for derive_trust_tree that is used for DNSKEY rrsets
+- *
+- * \param[in] new_tree The trust tree that we are building
+- * \param[in] data_chain The data chain containing the data for the trust tree
+- * \param[in] cur_rr The currently relevant DNSKEY RR
+- * \param[in] cur_sig_rr The currently relevant signature
+- */
+-void ldns_dnssec_derive_trust_tree_dnskey_rrset(
+-         ldns_dnssec_trust_tree *new_tree,
+-	    ldns_dnssec_data_chain *data_chain,
+-	    ldns_rr *cur_rr,
+-	    ldns_rr *cur_sig_rr);
+-
+-/**
+- * Sub function for derive_trust_tree that is used for DNSKEY rrsets
+- *
+- * \param[in] new_tree The trust tree that we are building
+- * \param[in] data_chain The data chain containing the data for the trust tree
+- * \param[in] cur_rr The currently relevant DNSKEY RR
+- * \param[in] cur_sig_rr The currently relevant signature
+- * \param[in] check_time the time for which the validation is performed
+- */
+-void ldns_dnssec_derive_trust_tree_dnskey_rrset_time(
+-         ldns_dnssec_trust_tree *new_tree,
+-	    ldns_dnssec_data_chain *data_chain,
+-	    ldns_rr *cur_rr, ldns_rr *cur_sig_rr,
+-	    time_t check_time);
+-
+-/**
+- * Sub function for derive_trust_tree that is used for DS rrsets
+- *
+- * \param[in] new_tree The trust tree that we are building
+- * \param[in] data_chain The data chain containing the data for the trust tree
+- * \param[in] cur_rr The currently relevant DS RR
+- */
+-void ldns_dnssec_derive_trust_tree_ds_rrset(
+-         ldns_dnssec_trust_tree *new_tree,
+-	    ldns_dnssec_data_chain *data_chain,
+-	    ldns_rr *cur_rr);
+-
+-/**
+- * Sub function for derive_trust_tree that is used for DS rrsets
+- *
+- * \param[in] new_tree The trust tree that we are building
+- * \param[in] data_chain The data chain containing the data for the trust tree
+- * \param[in] cur_rr The currently relevant DS RR
+- * \param[in] check_time the time for which the validation is performed
+- */
+-void ldns_dnssec_derive_trust_tree_ds_rrset_time(
+-         ldns_dnssec_trust_tree *new_tree,
+-	    ldns_dnssec_data_chain *data_chain,
+-	    ldns_rr *cur_rr, time_t check_time);
+-
+-/**
+- * Sub function for derive_trust_tree that is used when there are no
+- * signatures
+- *
+- * \param[in] new_tree The trust tree that we are building
+- * \param[in] data_chain The data chain containing the data for the trust tree
+- */
+-void ldns_dnssec_derive_trust_tree_no_sig(
+-         ldns_dnssec_trust_tree *new_tree,
+-	    ldns_dnssec_data_chain *data_chain);
+-
+-/**
+- * Sub function for derive_trust_tree that is used when there are no
+- * signatures
+- *
+- * \param[in] new_tree The trust tree that we are building
+- * \param[in] data_chain The data chain containing the data for the trust tree
+- * \param[in] check_time the time for which the validation is performed
+- */
+-void ldns_dnssec_derive_trust_tree_no_sig_time(
+-         ldns_dnssec_trust_tree *new_tree,
+-	    ldns_dnssec_data_chain *data_chain,
+-	    time_t check_time);
+-
+-
+-/**
+- * Returns OK if there is a trusted path in the tree to one of 
+- * the DNSKEY or DS RRs in the given list
+- *
+- * \param *tree The trust tree so search
+- * \param *keys A ldns_rr_list of DNSKEY and DS rrs to look for
+- *
+- * \return LDNS_STATUS_OK if there is a trusted path to one of
+- *                        the keys, or the *first* error encountered
+- *                        if there were no paths
+- */
+-ldns_status ldns_dnssec_trust_tree_contains_keys(
+-			 ldns_dnssec_trust_tree *tree,
+-			 ldns_rr_list *keys);
+-
+-/**
+- * Verifies a list of signatures for one rrset.
+- *
+- * \param[in] rrset the rrset to verify
+- * \param[in] rrsig a list of signatures to check
+- * \param[in] keys a list of keys to check with
+- * \param[out] good_keys  if this is a (initialized) list, the pointer to keys
+- *                        from keys that validate one of the signatures
+- *                        are added to it
+- * \return status LDNS_STATUS_OK if there is at least one correct key
+- */
+-ldns_status ldns_verify(ldns_rr_list *rrset,
+-				    ldns_rr_list *rrsig,
+-				    const ldns_rr_list *keys,
+-				    ldns_rr_list *good_keys);	
+-
+-/**
+- * Verifies a list of signatures for one rrset.
+- *
+- * \param[in] rrset the rrset to verify
+- * \param[in] rrsig a list of signatures to check
+- * \param[in] keys a list of keys to check with
+- * \param[in] check_time the time for which the validation is performed
+- * \param[out] good_keys  if this is a (initialized) list, the pointer to keys
+- *                        from keys that validate one of the signatures
+- *                        are added to it
+- * \return status LDNS_STATUS_OK if there is at least one correct key
+- */
+-ldns_status ldns_verify_time(ldns_rr_list *rrset,
+-				    ldns_rr_list *rrsig,
+-				    const ldns_rr_list *keys,
+-				    time_t check_time,
+-				    ldns_rr_list *good_keys);	
+-
+-
+-/**
+- * Verifies a list of signatures for one rrset, but disregard the time.
+- * Inception and Expiration are not checked.
+- *
+- * \param[in] rrset the rrset to verify
+- * \param[in] rrsig a list of signatures to check
+- * \param[in] keys a list of keys to check with
+- * \param[out] good_keys  if this is a (initialized) list, the pointer to keys
+- *                        from keys that validate one of the signatures
+- *                        are added to it
+- * \return status LDNS_STATUS_OK if there is at least one correct key
+- */
+-ldns_status ldns_verify_notime(ldns_rr_list *rrset,
+-				    ldns_rr_list *rrsig,
+-				    const ldns_rr_list *keys,
+-				    ldns_rr_list *good_keys);	
+-
+-/**
+- * Tries to build an authentication chain from the given 
+- * keys down to the queried domain.
+- *
+- * If we find a valid trust path, return the valid keys for the domain.
+- * 
+- * \param[in] res the current resolver
+- * \param[in] domain the domain we want valid keys for
+- * \param[in] keys the current set of trusted keys
+- * \param[out] status pointer to the status variable where the result
+- *                    code will be stored
+- * \return the set of trusted keys for the domain, or NULL if no 
+- *         trust path could be built.
+- */
+-ldns_rr_list *ldns_fetch_valid_domain_keys(const ldns_resolver * res,
+-								   const ldns_rdf * domain,
+-								   const ldns_rr_list * keys,
+-								   ldns_status *status);
+-
+-/**
+- * Tries to build an authentication chain from the given 
+- * keys down to the queried domain.
+- *
+- * If we find a valid trust path, return the valid keys for the domain.
+- * 
+- * \param[in] res the current resolver
+- * \param[in] domain the domain we want valid keys for
+- * \param[in] keys the current set of trusted keys
+- * \param[in] check_time the time for which the validation is performed
+- * \param[out] status pointer to the status variable where the result
+- *                    code will be stored
+- * \return the set of trusted keys for the domain, or NULL if no 
+- *         trust path could be built.
+- */
+-ldns_rr_list *ldns_fetch_valid_domain_keys_time(const ldns_resolver * res,
+-		const ldns_rdf * domain, const ldns_rr_list * keys,
+-		time_t check_time, ldns_status *status);
+-
+-
+-/**
+- * Validates the DNSKEY RRset for the given domain using the provided 
+- * trusted keys.
+- *
+- * \param[in] res the current resolver
+- * \param[in] domain the domain we want valid keys for
+- * \param[in] keys the current set of trusted keys
+- * \return the set of trusted keys for the domain, or NULL if the RRSET
+- *         could not be validated
+- */
+-ldns_rr_list *ldns_validate_domain_dnskey (const ldns_resolver *res,
+-								   const ldns_rdf *domain,
+-								   const ldns_rr_list *keys);
+-
+-/**
+- * Validates the DNSKEY RRset for the given domain using the provided 
+- * trusted keys.
+- *
+- * \param[in] res the current resolver
+- * \param[in] domain the domain we want valid keys for
+- * \param[in] keys the current set of trusted keys
+- * \param[in] check_time the time for which the validation is performed
+- * \return the set of trusted keys for the domain, or NULL if the RRSET
+- *         could not be validated
+- */
+-ldns_rr_list *ldns_validate_domain_dnskey_time(
+-		const ldns_resolver *res, const ldns_rdf *domain, 
+-		const ldns_rr_list *keys, time_t check_time);
+-
+-
+-/**
+- * Validates the DS RRset for the given domain using the provided trusted keys.
+- *
+- * \param[in] res the current resolver
+- * \param[in] domain the domain we want valid keys for
+- * \param[in] keys the current set of trusted keys
+- * \return the set of trusted keys for the domain, or NULL if the RRSET could not be validated
+- */
+-ldns_rr_list *ldns_validate_domain_ds(const ldns_resolver *res,
+-							   const ldns_rdf *
+-							   domain,
+-							   const ldns_rr_list * keys);
+-
+-/**
+- * Validates the DS RRset for the given domain using the provided trusted keys.
+- *
+- * \param[in] res the current resolver
+- * \param[in] domain the domain we want valid keys for
+- * \param[in] keys the current set of trusted keys
+- * \param[in] check_time the time for which the validation is performed
+- * \return the set of trusted keys for the domain, or NULL if the RRSET could not be validated
+- */
+-ldns_rr_list *ldns_validate_domain_ds_time(
+-		const ldns_resolver *res, const ldns_rdf *domain, 
+-		const ldns_rr_list * keys, time_t check_time);
+-
+-
+-/**
+- * Verifies a list of signatures for one RRset using a valid trust path.
+- *
+- * \param[in] res the current resolver
+- * \param[in] rrset the rrset to verify
+- * \param[in] rrsigs a list of signatures to check
+- * \param[out] validating_keys  if this is a (initialized) list, the
+- *                              keys from keys that validate one of
+- *                              the signatures are added to it
+- * \return status LDNS_STATUS_OK if there is at least one correct key
+- */
+-ldns_status ldns_verify_trusted(ldns_resolver *res,
+-						  ldns_rr_list *rrset,
+-						  ldns_rr_list *rrsigs,
+-						  ldns_rr_list *validating_keys);
+-
+-/**
+- * Verifies a list of signatures for one RRset using a valid trust path.
+- *
+- * \param[in] res the current resolver
+- * \param[in] rrset the rrset to verify
+- * \param[in] rrsigs a list of signatures to check
+- * \param[in] check_time the time for which the validation is performed
+- * \param[out] validating_keys  if this is a (initialized) list, the
+- *                              keys from keys that validate one of
+- *                              the signatures are added to it
+- * \return status LDNS_STATUS_OK if there is at least one correct key
+- */
+-ldns_status ldns_verify_trusted_time(
+-		ldns_resolver *res, ldns_rr_list *rrset, 
+-		ldns_rr_list *rrsigs, time_t check_time,
+-		ldns_rr_list *validating_keys);
+-
+-
+-/**
+- * denial is not just a river in egypt
+- *
+- * \param[in] rr The (query) RR to check the denial of existence for
+- * \param[in] nsecs The list of NSEC RRs that are supposed to deny the
+- *                  existence of the RR
+- * \param[in] rrsigs The RRSIG RR covering the NSEC RRs
+- * \return LDNS_STATUS_OK if the NSEC RRs deny the existence, error code
+- *                        containing the reason they do not otherwise
+- */
+-ldns_status ldns_dnssec_verify_denial(ldns_rr *rr,
+-							   ldns_rr_list *nsecs,
+-							   ldns_rr_list *rrsigs);
+-
+-/**
+- * Denial of existence using NSEC3 records
+- * Since NSEC3 is a bit more complicated than normal denial, some
+- * context arguments are needed
+- *
+- * \param[in] rr The (query) RR to check the denial of existence for
+- * \param[in] nsecs The list of NSEC3 RRs that are supposed to deny the
+- *                  existence of the RR
+- * \param[in] rrsigs The RRSIG rr covering the NSEC RRs
+- * \param[in] packet_rcode The RCODE value of the packet that provided the
+- *                         NSEC3 RRs
+- * \param[in] packet_qtype The original query RR type
+- * \param[in] packet_nodata True if the providing packet had an empty ANSWER
+- *                          section
+- * \return LDNS_STATUS_OK if the NSEC3 RRs deny the existence, error code
+- *                        containing the reason they do not otherwise
+- */
+-ldns_status ldns_dnssec_verify_denial_nsec3(ldns_rr *rr,
+-								    ldns_rr_list *nsecs,
+-								    ldns_rr_list *rrsigs,
+-								    ldns_pkt_rcode packet_rcode,
+-								    ldns_rr_type packet_qtype,
+-								    bool packet_nodata);
+-
+-/**
+- * Same as ldns_status ldns_dnssec_verify_denial_nsec3 but also returns
+- * the nsec rr that matched.
+- *
+- * \param[in] rr The (query) RR to check the denial of existence for
+- * \param[in] nsecs The list of NSEC3 RRs that are supposed to deny the
+- *                  existence of the RR
+- * \param[in] rrsigs The RRSIG rr covering the NSEC RRs
+- * \param[in] packet_rcode The RCODE value of the packet that provided the
+- *                         NSEC3 RRs
+- * \param[in] packet_qtype The original query RR type
+- * \param[in] packet_nodata True if the providing packet had an empty ANSWER
+- *                          section
+- * \param[in] match On match, the given (reference to a) pointer will be set 
+- *                  to point to the matching nsec resource record.
+- * \return LDNS_STATUS_OK if the NSEC3 RRs deny the existence, error code
+- *                        containing the reason they do not otherwise
+- */
+-ldns_status ldns_dnssec_verify_denial_nsec3_match(ldns_rr *rr,
+-						  ldns_rr_list *nsecs,
+-						  ldns_rr_list *rrsigs,
+-						  ldns_pkt_rcode packet_rcode,
+-						  ldns_rr_type packet_qtype,
+-						  bool packet_nodata,
+-						  ldns_rr **match);
+-/**
+- * Verifies the already processed data in the buffers
+- * This function should probably not be used directly.
+- *
+- * \param[in] rawsig_buf Buffer containing signature data to use
+- * \param[in] verify_buf Buffer containing data to verify
+- * \param[in] key_buf Buffer containing key data to use
+- * \param[in] algo Signing algorithm
+- * \return status LDNS_STATUS_OK if the data verifies. Error if not.
+- */
+-ldns_status ldns_verify_rrsig_buffers(ldns_buffer *rawsig_buf,
+-							   ldns_buffer *verify_buf,
+-							   ldns_buffer *key_buf,
+-							   uint8_t algo);
+-
+-/**
+- * Like ldns_verify_rrsig_buffers, but uses raw data.
+- *
+- * \param[in] sig signature data to use
+- * \param[in] siglen length of signature data to use
+- * \param[in] verify_buf Buffer containing data to verify
+- * \param[in] key key data to use
+- * \param[in] keylen length of key data to use
+- * \param[in] algo Signing algorithm
+- * \return status LDNS_STATUS_OK if the data verifies. Error if not.
+- */
+-ldns_status ldns_verify_rrsig_buffers_raw(unsigned char* sig,
+-								  size_t siglen, 
+-								  ldns_buffer *verify_buf,
+-								  unsigned char* key,
+-								  size_t keylen, 
+-								  uint8_t algo);
+-
+-/**
+- * Verifies an rrsig. All keys in the keyset are tried.
+- * \param[in] rrset the rrset to check
+- * \param[in] rrsig the signature of the rrset
+- * \param[in] keys the keys to try
+- * \param[out] good_keys  if this is a (initialized) list, the pointer to keys
+- *                        from keys that validate one of the signatures
+- *                        are added to it
+- * \return a list of keys which validate the rrsig + rrset. Returns
+- * status LDNS_STATUS_OK if at least one key matched. Else an error.
+- */
+-ldns_status ldns_verify_rrsig_keylist(ldns_rr_list *rrset,
+-							   ldns_rr *rrsig,
+-							   const ldns_rr_list *keys,
+-							   ldns_rr_list *good_keys);
+-
+-/**
+- * Verifies an rrsig. All keys in the keyset are tried.
+- * \param[in] rrset the rrset to check
+- * \param[in] rrsig the signature of the rrset
+- * \param[in] keys the keys to try
+- * \param[in] check_time the time for which the validation is performed
+- * \param[out] good_keys  if this is a (initialized) list, the pointer to keys
+- *                        from keys that validate one of the signatures
+- *                        are added to it
+- * \return a list of keys which validate the rrsig + rrset. Returns
+- * status LDNS_STATUS_OK if at least one key matched. Else an error.
+- */
+-ldns_status ldns_verify_rrsig_keylist_time(
+-		ldns_rr_list *rrset, ldns_rr *rrsig, 
+-		const ldns_rr_list *keys, time_t check_time,
+-	       	ldns_rr_list *good_keys);
+-
+-
+-/**
+- * Verifies an rrsig. All keys in the keyset are tried. Time is not checked.
+- * \param[in] rrset the rrset to check
+- * \param[in] rrsig the signature of the rrset
+- * \param[in] keys the keys to try
+- * \param[out] good_keys  if this is a (initialized) list, the pointer to keys
+- *                        from keys that validate one of the signatures
+- *                        are added to it
+- * \return a list of keys which validate the rrsig + rrset. Returns
+- * status LDNS_STATUS_OK if at least one key matched. Else an error.
+- */
+-ldns_status ldns_verify_rrsig_keylist_notime(ldns_rr_list *rrset,
+-							   ldns_rr *rrsig,
+-							   const ldns_rr_list *keys,
+-							   ldns_rr_list *good_keys);
+-
+-/**
+- * verify an rrsig with 1 key
+- * \param[in] rrset the rrset
+- * \param[in] rrsig the rrsig to verify
+- * \param[in] key the key to use
+- * \return status message wether verification succeeded.
+- */
+-ldns_status ldns_verify_rrsig(ldns_rr_list *rrset,
+-						ldns_rr *rrsig,
+-						ldns_rr *key);
+-
+-
+-/**
+- * verify an rrsig with 1 key
+- * \param[in] rrset the rrset
+- * \param[in] rrsig the rrsig to verify
+- * \param[in] key the key to use
+- * \param[in] check_time the time for which the validation is performed
+- * \return status message wether verification succeeded.
+- */
+-ldns_status ldns_verify_rrsig_time(
+-		ldns_rr_list *rrset, ldns_rr *rrsig, 
+-		ldns_rr *key, time_t check_time);
+-
+-
+-#if LDNS_BUILD_CONFIG_HAVE_SSL
+-/**
+- * verifies a buffer with signature data for a buffer with rrset data 
+- * with an EVP_PKEY
+- *
+- * \param[in] sig the signature data
+- * \param[in] rrset the rrset data, sorted and processed for verification
+- * \param[in] key the EVP key structure
+- * \param[in] digest_type The digest type of the signature
+- */
+-ldns_status ldns_verify_rrsig_evp(ldns_buffer *sig,
+-						    ldns_buffer *rrset,
+-						    EVP_PKEY *key,
+-						    const EVP_MD *digest_type);
+-
+-/**
+- * Like ldns_verify_rrsig_evp, but uses raw signature data.
+- * \param[in] sig the signature data, wireformat uncompressed
+- * \param[in] siglen length of the signature data
+- * \param[in] rrset the rrset data, sorted and processed for verification
+- * \param[in] key the EVP key structure
+- * \param[in] digest_type The digest type of the signature
+- */
+-ldns_status ldns_verify_rrsig_evp_raw(unsigned char *sig,
+-							   size_t siglen,
+-							   ldns_buffer *rrset,
+-							   EVP_PKEY *key,
+-							   const EVP_MD *digest_type);
+-#endif
+-
+-/**
+- * verifies a buffer with signature data (DSA) for a buffer with rrset data 
+- * with a buffer with key data.
+- *
+- * \param[in] sig the signature data
+- * \param[in] rrset the rrset data, sorted and processed for verification
+- * \param[in] key the key data
+- */
+-ldns_status ldns_verify_rrsig_dsa(ldns_buffer *sig,
+-						    ldns_buffer *rrset,
+-						    ldns_buffer *key);
+-
+-/**
+- * verifies a buffer with signature data (RSASHA1) for a buffer with rrset data 
+- * with a buffer with key data.
+- *
+- * \param[in] sig the signature data
+- * \param[in] rrset the rrset data, sorted and processed for verification
+- * \param[in] key the key data
+- */
+-ldns_status ldns_verify_rrsig_rsasha1(ldns_buffer *sig,
+-							   ldns_buffer *rrset,
+-							   ldns_buffer *key);
+-
+-/**
+- * verifies a buffer with signature data (RSAMD5) for a buffer with rrset data 
+- * with a buffer with key data.
+- *
+- * \param[in] sig the signature data
+- * \param[in] rrset the rrset data, sorted and processed for verification
+- * \param[in] key the key data
+- */
+-ldns_status ldns_verify_rrsig_rsamd5(ldns_buffer *sig,
+-							  ldns_buffer *rrset,
+-							  ldns_buffer *key);
+-
+-/**
+- * Like ldns_verify_rrsig_dsa, but uses raw signature and key data.
+- * \param[in] sig raw uncompressed wireformat signature data
+- * \param[in] siglen length of signature data
+- * \param[in] rrset ldns buffer with prepared rrset data.
+- * \param[in] key raw uncompressed wireformat key data
+- * \param[in] keylen length of key data
+- */
+-ldns_status ldns_verify_rrsig_dsa_raw(unsigned char* sig,
+-							   size_t siglen,
+-							   ldns_buffer* rrset,
+-							   unsigned char* key,
+-							   size_t keylen);
+-
+-/**
+- * Like ldns_verify_rrsig_rsasha1, but uses raw signature and key data.
+- * \param[in] sig raw uncompressed wireformat signature data
+- * \param[in] siglen length of signature data
+- * \param[in] rrset ldns buffer with prepared rrset data.
+- * \param[in] key raw uncompressed wireformat key data
+- * \param[in] keylen length of key data
+- */
+-ldns_status ldns_verify_rrsig_rsasha1_raw(unsigned char* sig,
+-								  size_t siglen,
+-								  ldns_buffer* rrset,
+-								  unsigned char* key,
+-								  size_t keylen);
+-
+-/**
+- * Like ldns_verify_rrsig_rsasha256, but uses raw signature and key data.
+- * \param[in] sig raw uncompressed wireformat signature data
+- * \param[in] siglen length of signature data
+- * \param[in] rrset ldns buffer with prepared rrset data.
+- * \param[in] key raw uncompressed wireformat key data
+- * \param[in] keylen length of key data
+- */
+-
+-ldns_status ldns_verify_rrsig_rsasha256_raw(unsigned char* sig,
+-								    size_t siglen,
+-								    ldns_buffer* rrset,
+-								    unsigned char* key,
+-								    size_t keylen);
+-
+-/**
+- * Like ldns_verify_rrsig_rsasha512, but uses raw signature and key data.
+- * \param[in] sig raw uncompressed wireformat signature data
+- * \param[in] siglen length of signature data
+- * \param[in] rrset ldns buffer with prepared rrset data.
+- * \param[in] key raw uncompressed wireformat key data
+- * \param[in] keylen length of key data
+- */
+-ldns_status ldns_verify_rrsig_rsasha512_raw(unsigned char* sig,
+-								    size_t siglen,
+-								    ldns_buffer* rrset,
+-								    unsigned char* key,
+-								    size_t keylen);
+-
+-/**
+- * Like ldns_verify_rrsig_rsamd5, but uses raw signature and key data.
+- * \param[in] sig raw uncompressed wireformat signature data
+- * \param[in] siglen length of signature data
+- * \param[in] rrset ldns buffer with prepared rrset data.
+- * \param[in] key raw uncompressed wireformat key data
+- * \param[in] keylen length of key data
+- */
+-ldns_status ldns_verify_rrsig_rsamd5_raw(unsigned char* sig,
+-								 size_t siglen,
+-								 ldns_buffer* rrset,
+-								 unsigned char* key,
+-								 size_t keylen);
+-
+-#ifdef __cplusplus
+-}
+-#endif
+-
+-#endif
+-
+diff --git a/include/ldns/dnssec_zone.h b/include/ldns/dnssec_zone.h
+deleted file mode 100644
+index b794f94..0000000
+--- a/include/ldns/dnssec_zone.h
++++ /dev/null
+@@ -1,483 +0,0 @@
+-/*
+- * special zone file structures and functions for better dnssec handling
+- *
+- * A zone contains a SOA dnssec_zone_rrset, and an AVL tree of 'normal'
+- * dnssec_zone_rrsets, indexed by name and type
+- */
+-
+-#ifndef LDNS_DNSSEC_ZONE_H
+-#define LDNS_DNSSEC_ZONE_H
+- 
+-#include <ldns/rbtree.h>
+-#include <ldns/host2str.h>
+-
+-#ifdef __cplusplus
+-extern "C" {
+-#endif
+-
+-/**
+- * Singly linked list of rrs
+- */
+-typedef struct ldns_struct_dnssec_rrs ldns_dnssec_rrs;
+-struct ldns_struct_dnssec_rrs
+-{
+-	ldns_rr *rr;
+-	ldns_dnssec_rrs *next;
+-};
+-
+-/**
+- * Singly linked list of RRsets
+- */
+-typedef struct ldns_struct_dnssec_rrsets ldns_dnssec_rrsets;
+-struct ldns_struct_dnssec_rrsets
+-{
+-	ldns_dnssec_rrs *rrs;
+-	ldns_rr_type type;
+-	ldns_dnssec_rrs *signatures;
+-	ldns_dnssec_rrsets *next;
+-};
+-
+-/**
+- * Structure containing all resource records for a domain name
+- * Including the derived NSEC3, if present
+- */
+-typedef struct ldns_struct_dnssec_name ldns_dnssec_name;
+-struct ldns_struct_dnssec_name
+-{
+-	/**
+-	 * pointer to a dname containing the name.
+-	 * Usually points to the owner name of the first RR of the first RRset
+-	 */
+-	ldns_rdf *name;
+-	/** 
+-	 * Usually, the name is a pointer to the owner name of the first rr for
+-	 * this name, but sometimes there is no actual data to point to, 
+-	 * for instance in
+-	 * names representing empty nonterminals. If so, set alloced to true to
+-	 * indicate that this data must also be freed when the name is freed
+-	 */
+-	bool name_alloced;
+-	/**
+-	 * The rrsets for this name
+-	 */
+-	ldns_dnssec_rrsets *rrsets;
+-	/**
+-	 * NSEC pointing to the next name (or NSEC3 pointing to the next NSEC3)
+-	 */
+-	ldns_rr *nsec;
+-	/**
+-	 * signatures for the NSEC record
+-	 */
+-	ldns_dnssec_rrs *nsec_signatures;
+-	/**
+-	 * Unlike what the name is_glue suggests, this field is set to true by
+-	 * ldns_dnssec_zone_mark_glue() or ldns_dnssec_zone_mark_and_get_glue()
+-	 * when the name, this dnssec_name struct represents, is occluded.
+-	 * Names that contain other occluded rrsets and records with glue on
+-	 * the delegation point will NOT have this bool set to true.
+-	 * This field should NOT be read directly, but only via the 
+-	 * ldns_dnssec_name_is_glue() function!
+-	 */
+-	bool is_glue;
+-	/**
+-	 * pointer to store the hashed name (only used when in an NSEC3 zone
+-	 */
+-	ldns_rdf *hashed_name;
+-};
+-
+-/**
+- * Structure containing a dnssec zone
+- */
+-struct ldns_struct_dnssec_zone {
+-	/** points to the name containing the SOA RR */
+-	ldns_dnssec_name *soa;
+-	/** tree of ldns_dnssec_names */
+-	ldns_rbtree_t *names;
+-	/** tree of ldns_dnssec_names by nsec3 hashes (when applicible) */
+-	ldns_rbtree_t *hashed_names;
+-	/** points to the first added NSEC3 rr whose parameters will be 
+-	 *  assumed for all subsequent NSEC3 rr's and which will be used
+-	 *  to calculate hashed names
+-	 */
+-	ldns_rr *_nsec3params;
+-};
+-typedef struct ldns_struct_dnssec_zone ldns_dnssec_zone;
+-
+-/**
+- * Creates a new entry for 1 pointer to an rr and 1 pointer to the next rrs
+- * \return the allocated data
+- */
+-ldns_dnssec_rrs *ldns_dnssec_rrs_new(void);
+-
+-/**
+- * Frees the list of rrs, but *not* the individual ldns_rr records
+- * contained in the list
+- * 
+- * \param[in] rrs the data structure to free
+- */
+-void ldns_dnssec_rrs_free(ldns_dnssec_rrs *rrs);
+-
+-/**
+- * Frees the list of rrs, and the individual ldns_rr records
+- * contained in the list
+- * 
+- * \param[in] rrs the data structure to free
+- */
+-void ldns_dnssec_rrs_deep_free(ldns_dnssec_rrs *rrs);
+-
+-/**
+- * Adds an RR to the list of RRs. The list will remain ordered.
+- * If an equal RR already exists, this RR will not be added.
+- *
+- * \param[in] rrs the list to add to
+- * \param[in] rr the RR to add
+- * \return LDNS_STATUS_OK on success
+- */
+-ldns_status ldns_dnssec_rrs_add_rr(ldns_dnssec_rrs *rrs, ldns_rr *rr);
+-
+-/**
+- * Prints the given rrs to the file descriptor
+- *
+- * \param[in] out the file descriptor to print to
+- * \param[in] rrs the list of RRs to print
+- */
+-void ldns_dnssec_rrs_print(FILE *out, ldns_dnssec_rrs *rrs);
+-
+-/**
+- * Prints the given rrs to the file descriptor
+- *
+- * \param[in] out the file descriptor to print to
+- * \param[in] fmt the format of the textual representation
+- * \param[in] rrs the list of RRs to print
+- */
+-void ldns_dnssec_rrs_print_fmt(FILE *out, 
+-		const ldns_output_format *fmt, ldns_dnssec_rrs *rrs);
+-
+-/**
+- * Creates a new list (entry) of RRsets
+- * \return the newly allocated structure
+- */
+-ldns_dnssec_rrsets *ldns_dnssec_rrsets_new(void);
+-
+-/**
+- * Frees the list of rrsets and their rrs, but *not* the ldns_rr
+- * records in the sets
+- *
+- * \param[in] rrsets the data structure to free
+- */
+-void ldns_dnssec_rrsets_free(ldns_dnssec_rrsets *rrsets);
+-
+-/**
+- * Frees the list of rrsets and their rrs, and the ldns_rr
+- * records in the sets
+- *
+- * \param[in] rrsets the data structure to free
+- */
+-void ldns_dnssec_rrsets_deep_free(ldns_dnssec_rrsets *rrsets);
+-
+-/**
+- * Returns the rr type of the rrset (that is head of the given list)
+- *
+- * \param[in] rrsets the rrset to get the type of
+- * \return the rr type
+- */
+-ldns_rr_type ldns_dnssec_rrsets_type(ldns_dnssec_rrsets *rrsets);
+-
+-/**
+- * Sets the RR type of the rrset (that is head of the given list)
+- *
+- * \param[in] rrsets the rrset to set the type of
+- * \param[in] type the type to set
+- * \return LDNS_STATUS_OK on success
+- */
+-ldns_status ldns_dnssec_rrsets_set_type(ldns_dnssec_rrsets *rrsets,
+-					   ldns_rr_type type);
+-
+-/**
+- * Add an ldns_rr to the corresponding RRset in the given list of RRsets.
+- * If it is not present, add it as a new RRset with 1 record.
+- *
+- * \param[in] rrsets the list of rrsets to add the RR to
+- * \param[in] rr the rr to add to the list of rrsets
+- * \return LDNS_STATUS_OK on success
+- */
+-ldns_status ldns_dnssec_rrsets_add_rr(ldns_dnssec_rrsets *rrsets, ldns_rr *rr);
+-
+-/**
+- * Print the given list of rrsets to the fiven file descriptor
+- * 
+- * \param[in] out the file descriptor to print to
+- * \param[in] rrsets the list of RRsets to print
+- * \param[in] follow if set to false, only print the first RRset
+- */ 
+-void ldns_dnssec_rrsets_print(FILE *out,
+-		ldns_dnssec_rrsets *rrsets,
+-		bool follow);
+-
+-/**
+- * Print the given list of rrsets to the fiven file descriptor
+- * 
+- * \param[in] out the file descriptor to print to
+- * \param[in] fmt the format of the textual representation
+- * \param[in] rrsets the list of RRsets to print
+- * \param[in] follow if set to false, only print the first RRset
+- */ 
+-void ldns_dnssec_rrsets_print_fmt(FILE *out,
+-		const ldns_output_format *fmt,
+-		ldns_dnssec_rrsets *rrsets,
+-		bool follow);
+-
+-
+-/**
+- * Create a new data structure for a dnssec name
+- * \return the allocated structure
+- */
+-ldns_dnssec_name *ldns_dnssec_name_new(void);
+-
+-/**
+- * Create a new data structure for a dnssec name for the given RR
+- *
+- * \param[in] rr the RR to derive properties from, and to add to the name
+- */
+-ldns_dnssec_name *ldns_dnssec_name_new_frm_rr(ldns_rr *rr);
+-
+-/**
+- * Frees the name structure and its rrs and rrsets.
+- * Individual ldns_rr records therein are not freed
+- *
+- * \param[in] name the structure to free
+- */
+-void ldns_dnssec_name_free(ldns_dnssec_name *name);
+-
+-/**
+- * Frees the name structure and its rrs and rrsets.
+- * Individual ldns_rr records contained in the name are also freed
+- *
+- * \param[in] name the structure to free
+- */
+-void ldns_dnssec_name_deep_free(ldns_dnssec_name *name);
+-
+-/**
+- * Returns the domain name of the given dnssec_name structure
+- *
+- * \param[in] name the dnssec name to get the domain name from
+- * \return the domain name
+- */
+-ldns_rdf *ldns_dnssec_name_name(ldns_dnssec_name *name);
+-
+-
+-/**
+- * Sets the domain name of the given dnssec_name structure
+- *
+- * \param[in] name the dnssec name to set the domain name of
+- * \param[in] dname the domain name to set it to. This data is *not* copied.
+- */
+-void ldns_dnssec_name_set_name(ldns_dnssec_name *name,
+-						 ldns_rdf *dname);
+-/**
+- * Returns if dnssec_name structure is marked as glue.
+- * The ldns_dnssec_zone_mark_glue() function has to be called on a zone before
+- * using this function.
+- * Only names that have only glue rrsets will be marked.
+- * Names that have other occluded rrsets and names containing glue on the 
+- * delegation point will NOT be marked!
+- *
+- * \param[in] name the dnssec name to get the domain name from
+- * \return true if the structure is marked as glue, false otherwise.
+- */
+-bool ldns_dnssec_name_is_glue(ldns_dnssec_name *name);
+-
+-/**
+- * Sets the NSEC(3) RR of the given dnssec_name structure
+- *
+- * \param[in] name the dnssec name to set the domain name of
+- * \param[in] nsec the nsec rr to set it to. This data is *not* copied.
+- */
+-void ldns_dnssec_name_set_nsec(ldns_dnssec_name *name, ldns_rr *nsec);
+-
+-/**
+- * Compares the domain names of the two arguments in their
+- * canonical ordening.
+- * 
+- * \param[in] a The first dnssec_name to compare
+- * \param[in] b The second dnssec_name to compare
+- * \return -1 if the domain name of a comes before that of b in canonical
+- *            ordening, 1 if it is the other way around, and 0 if they are
+- *            equal
+- */
+-int ldns_dnssec_name_cmp(const void *a, const void *b);
+-
+-/**
+- * Inserts the given rr at the right place in the current dnssec_name
+- * No checking is done whether the name matches
+- *
+- * \param[in] name The ldns_dnssec_name to add the RR to
+- * \param[in] rr The RR to add
+- * \return LDNS_STATUS_OK on success, error code otherwise
+- */
+-ldns_status ldns_dnssec_name_add_rr(ldns_dnssec_name *name,
+-							 ldns_rr *rr);
+-
+-/**
+- * Find the RRset with the given type in within this name structure
+- *
+- * \param[in] name the name to find the RRset in
+- * \param[in] type the type of the RRset to find
+- * \return the RRset, or NULL if not present
+- */
+-ldns_dnssec_rrsets *ldns_dnssec_name_find_rrset(ldns_dnssec_name *name,
+-									   ldns_rr_type type);
+-
+-/**
+- * Find the RRset with the given name and type in the zone
+- *
+- * \param[in] zone the zone structure to find the RRset in
+- * \param[in] dname the domain name of the RRset to find
+- * \param[in] type the type of the RRset to find
+- * \return the RRset, or NULL if not present
+- */
+-ldns_dnssec_rrsets *ldns_dnssec_zone_find_rrset(ldns_dnssec_zone *zone,
+-									   ldns_rdf *dname,
+-									   ldns_rr_type type);
+-
+-/**
+- * Prints the RRs in the  dnssec name structure to the given
+- * file descriptor
+- *
+- * \param[in] out the file descriptor to print to
+- * \param[in] name the name structure to print the contents of
+- */
+-void ldns_dnssec_name_print(FILE *out, ldns_dnssec_name *name);
+-
+-/**
+- * Prints the RRs in the  dnssec name structure to the given
+- * file descriptor
+- *
+- * \param[in] out the file descriptor to print to
+- * \param[in] fmt the format of the textual representation
+- * \param[in] name the name structure to print the contents of
+- */
+-void ldns_dnssec_name_print_fmt(FILE *out, 
+-		const ldns_output_format *fmt, ldns_dnssec_name *name);
+-
+-/**
+- * Creates a new dnssec_zone structure
+- * \return the allocated structure
+- */
+-ldns_dnssec_zone *ldns_dnssec_zone_new(void);
+-
+-/**
+- * Create a new dnssec zone from a file.
+- * \param[out] z the new zone
+- * \param[in] *fp the filepointer to use
+- * \param[in] *origin the zones' origin
+- * \param[in] c default class to use (IN)
+- * \param[in] ttl default ttl to use
+- *
+- * \return ldns_status mesg with an error or LDNS_STATUS_OK
+- */
+-ldns_status ldns_dnssec_zone_new_frm_fp(ldns_dnssec_zone** z, FILE* fp,
+-		ldns_rdf* origin, uint32_t ttl, ldns_rr_class c);
+-
+-/**
+- * Create a new dnssec zone from a file, keep track of the line numbering
+- * \param[out] z the new zone
+- * \param[in] *fp the filepointer to use
+- * \param[in] *origin the zones' origin
+- * \param[in] ttl default ttl to use
+- * \param[in] c default class to use (IN)
+- * \param[out] line_nr used for error msg, to get to the line number
+- *
+- * \return ldns_status mesg with an error or LDNS_STATUS_OK
+- */
+-ldns_status ldns_dnssec_zone_new_frm_fp_l(ldns_dnssec_zone** z, FILE* fp,
+-		ldns_rdf* origin, uint32_t ttl, ldns_rr_class c, int* line_nr);
+-
+-/**
+- * Frees the given zone structure, and its rbtree of dnssec_names
+- * Individual ldns_rr RRs within those names are *not* freed
+- * \param[in] *zone the zone to free
+- */ 
+-void ldns_dnssec_zone_free(ldns_dnssec_zone *zone);
+-
+-/**
+- * Frees the given zone structure, and its rbtree of dnssec_names
+- * Individual ldns_rr RRs within those names are also freed
+- * \param[in] *zone the zone to free
+- */ 
+-void ldns_dnssec_zone_deep_free(ldns_dnssec_zone *zone);
+-
+-/**
+- * Adds the given RR to the zone.
+- * It find whether there is a dnssec_name with that name present.
+- * If so, add it to that, if not create a new one. 
+- * Special handling of NSEC and RRSIG provided
+- *
+- * \param[in] zone the zone to add the RR to
+- * \param[in] rr The RR to add
+- * \return LDNS_STATUS_OK on success, an error code otherwise
+- */
+-ldns_status ldns_dnssec_zone_add_rr(ldns_dnssec_zone *zone,
+-							 ldns_rr *rr);
+-
+-/**
+- * Prints the rbtree of ldns_dnssec_name structures to the file descriptor
+- *
+- * \param[in] out the file descriptor to print the names to
+- * \param[in] tree the tree of ldns_dnssec_name structures to print
+- * \param[in] print_soa if true, print SOA records, if false, skip them
+- */
+-void ldns_dnssec_zone_names_print(FILE *out, ldns_rbtree_t *tree, bool print_soa);
+-
+-/**
+- * Prints the rbtree of ldns_dnssec_name structures to the file descriptor
+- *
+- * \param[in] out the file descriptor to print the names to
+- * \param[in] fmt the format of the textual representation
+- * \param[in] tree the tree of ldns_dnssec_name structures to print
+- * \param[in] print_soa if true, print SOA records, if false, skip them
+- */
+-void ldns_dnssec_zone_names_print_fmt(FILE *out, const ldns_output_format *fmt,
+-		ldns_rbtree_t *tree, bool print_soa);
+-
+-/**
+- * Prints the complete zone to the given file descriptor
+- *
+- * \param[in] out the file descriptor to print to
+- * \param[in] zone the dnssec_zone to print
+- */
+-void ldns_dnssec_zone_print(FILE *out, ldns_dnssec_zone *zone);
+-
+-/**
+- * Prints the complete zone to the given file descriptor
+- *
+- * \param[in] out the file descriptor to print to
+- * \param[in] fmt the format of the textual representation
+- * \param[in] zone the dnssec_zone to print
+- */
+-void ldns_dnssec_zone_print_fmt(FILE *out, 
+-		const ldns_output_format *fmt, ldns_dnssec_zone *zone);
+-
+-/**
+- * Adds explicit dnssec_name structures for the empty nonterminals
+- * in this zone. (this is needed for NSEC3 generation)
+- *
+- * \param[in] zone the zone to check for empty nonterminals
+- * return LDNS_STATUS_OK on success.
+- */
+-ldns_status ldns_dnssec_zone_add_empty_nonterminals(ldns_dnssec_zone *zone);
+-
+-/**
+- * If a NSEC3PARAM is available in the apex, walks the zone and returns true
+- * on the first optout nsec3.
+- *
+- * \param[in] zone the zone to check for nsec3 optout records
+- * return true when the zone has at least one nsec3 optout record.
+- */
+-bool ldns_dnssec_zone_is_nsec3_optout(ldns_dnssec_zone* zone);
+-
+-#ifdef __cplusplus
+-}
+-#endif
+-
+-#endif
+diff --git a/include/ldns/duration.h b/include/ldns/duration.h
+deleted file mode 100644
+index f12edc4..0000000
+--- a/include/ldns/duration.h
++++ /dev/null
+@@ -1,109 +0,0 @@
+-/*
+- * $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);
+-
+-/**
+- * Clean up duration.
+- * \param[in] duration duration to be cleaned up
+- *
+- */
+-void ldns_duration_cleanup(ldns_duration_type* duration);
+-
+-#endif /* LDNS_DURATION_H */
+diff --git a/include/ldns/error.h b/include/ldns/error.h
+deleted file mode 100644
+index cc11958..0000000
+--- a/include/ldns/error.h
++++ /dev/null
+@@ -1,147 +0,0 @@
+-/**
+- * \file error.h
+- *
+- * Defines error numbers and functions to translate those to a readable string.
+- *
+- */
+- 
+-/**
+- * a Net::DNS like library for C
+- *
+- * (c) NLnet Labs, 2005-2006
+- *
+- * See the file LICENSE for the license
+- */
+-
+-#ifndef LDNS_ERROR_H
+-#define LDNS_ERROR_H
+-
+-#include <ldns/util.h>
+-
+-#ifdef __cplusplus
+-extern "C" {
+-#endif
+-
+-enum ldns_enum_status {
+-	LDNS_STATUS_OK,	
+-	LDNS_STATUS_EMPTY_LABEL,
+-	LDNS_STATUS_LABEL_OVERFLOW,
+-	LDNS_STATUS_DOMAINNAME_OVERFLOW,
+-	LDNS_STATUS_DOMAINNAME_UNDERFLOW,
+-	LDNS_STATUS_DDD_OVERFLOW,
+-	LDNS_STATUS_PACKET_OVERFLOW,
+-	LDNS_STATUS_INVALID_POINTER,
+-	LDNS_STATUS_MEM_ERR,
+-	LDNS_STATUS_INTERNAL_ERR,
+-	LDNS_STATUS_SSL_ERR,
+-	LDNS_STATUS_ERR,
+-	LDNS_STATUS_INVALID_INT,
+-	LDNS_STATUS_INVALID_IP4,
+-	LDNS_STATUS_INVALID_IP6,
+-	LDNS_STATUS_INVALID_STR,
+-	LDNS_STATUS_INVALID_B32_EXT,
+-	LDNS_STATUS_INVALID_B64,
+-	LDNS_STATUS_INVALID_HEX,
+-	LDNS_STATUS_INVALID_TIME,
+-	LDNS_STATUS_NETWORK_ERR,
+-	LDNS_STATUS_ADDRESS_ERR,
+-	LDNS_STATUS_FILE_ERR,
+-	LDNS_STATUS_UNKNOWN_INET,
+-	LDNS_STATUS_NOT_IMPL,
+-	LDNS_STATUS_NULL,
+-	LDNS_STATUS_CRYPTO_UNKNOWN_ALGO, 
+-	LDNS_STATUS_CRYPTO_ALGO_NOT_IMPL, 	
+-	LDNS_STATUS_CRYPTO_NO_RRSIG,
+-	LDNS_STATUS_CRYPTO_NO_DNSKEY,
+-	LDNS_STATUS_CRYPTO_NO_TRUSTED_DNSKEY,
+-	LDNS_STATUS_CRYPTO_NO_DS,
+-	LDNS_STATUS_CRYPTO_NO_TRUSTED_DS,
+-	LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY,
+-	LDNS_STATUS_CRYPTO_VALIDATED,
+-	LDNS_STATUS_CRYPTO_BOGUS,
+-	LDNS_STATUS_CRYPTO_SIG_EXPIRED,
+-	LDNS_STATUS_CRYPTO_SIG_NOT_INCEPTED,
+-	LDNS_STATUS_CRYPTO_TSIG_BOGUS,
+-	LDNS_STATUS_CRYPTO_TSIG_ERR,
+-	LDNS_STATUS_CRYPTO_EXPIRATION_BEFORE_INCEPTION,
+-	LDNS_STATUS_CRYPTO_TYPE_COVERED_ERR,
+-	LDNS_STATUS_ENGINE_KEY_NOT_LOADED,
+-	LDNS_STATUS_NSEC3_ERR,
+-	LDNS_STATUS_RES_NO_NS,
+-	LDNS_STATUS_RES_QUERY,
+-	LDNS_STATUS_WIRE_INCOMPLETE_HEADER,
+-	LDNS_STATUS_WIRE_INCOMPLETE_QUESTION,
+-	LDNS_STATUS_WIRE_INCOMPLETE_ANSWER,
+-	LDNS_STATUS_WIRE_INCOMPLETE_AUTHORITY,
+-	LDNS_STATUS_WIRE_INCOMPLETE_ADDITIONAL,
+-	LDNS_STATUS_NO_DATA,
+-	LDNS_STATUS_CERT_BAD_ALGORITHM,
+-	LDNS_STATUS_SYNTAX_TYPE_ERR,
+-	LDNS_STATUS_SYNTAX_CLASS_ERR,
+-	LDNS_STATUS_SYNTAX_TTL_ERR,
+-	LDNS_STATUS_SYNTAX_INCLUDE_ERR_NOTIMPL,
+-	LDNS_STATUS_SYNTAX_RDATA_ERR,
+-	LDNS_STATUS_SYNTAX_DNAME_ERR,
+-	LDNS_STATUS_SYNTAX_VERSION_ERR,
+-	LDNS_STATUS_SYNTAX_ALG_ERR,
+-	LDNS_STATUS_SYNTAX_KEYWORD_ERR,
+-	LDNS_STATUS_SYNTAX_TTL,
+-	LDNS_STATUS_SYNTAX_ORIGIN,
+-	LDNS_STATUS_SYNTAX_INCLUDE,
+-	LDNS_STATUS_SYNTAX_EMPTY,
+-	LDNS_STATUS_SYNTAX_ITERATIONS_OVERFLOW,
+-	LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR,
+-	LDNS_STATUS_SYNTAX_INTEGER_OVERFLOW,
+-	LDNS_STATUS_SYNTAX_BAD_ESCAPE,
+-	LDNS_STATUS_SOCKET_ERROR,
+-	LDNS_STATUS_SYNTAX_ERR,
+-	LDNS_STATUS_DNSSEC_EXISTENCE_DENIED,
+-	LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED,
+-	LDNS_STATUS_DNSSEC_NSEC_WILDCARD_NOT_COVERED,
+-	LDNS_STATUS_DNSSEC_NSEC3_ORIGINAL_NOT_FOUND,
+-	LDNS_STATUS_MISSING_RDATA_FIELDS_RRSIG,
+-	LDNS_STATUS_MISSING_RDATA_FIELDS_KEY,
+-	LDNS_STATUS_CRYPTO_SIG_EXPIRED_WITHIN_MARGIN,
+-	LDNS_STATUS_CRYPTO_SIG_NOT_INCEPTED_WITHIN_MARGIN,
+-	LDNS_STATUS_DANE_STATUS_MESSAGES,
+-	LDNS_STATUS_DANE_UNKNOWN_CERTIFICATE_USAGE,
+-	LDNS_STATUS_DANE_UNKNOWN_SELECTOR,
+-	LDNS_STATUS_DANE_UNKNOWN_MATCHING_TYPE,
+-	LDNS_STATUS_DANE_UNKNOWN_PROTOCOL,
+-	LDNS_STATUS_DANE_UNKNOWN_TRANSPORT,
+-	LDNS_STATUS_DANE_MISSING_EXTRA_CERTS,
+-	LDNS_STATUS_DANE_EXTRA_CERTS_NOT_USED,
+-	LDNS_STATUS_DANE_OFFSET_OUT_OF_RANGE,
+-	LDNS_STATUS_DANE_INSECURE,
+-	LDNS_STATUS_DANE_BOGUS,
+-	LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH,
+-	LDNS_STATUS_DANE_NON_CA_CERTIFICATE,
+-	LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE,
+-	LDNS_STATUS_DANE_PKIX_NO_SELF_SIGNED_TRUST_ANCHOR,
+-	LDNS_STATUS_EXISTS_ERR,
+-	LDNS_STATUS_INVALID_ILNP64,
+-	LDNS_STATUS_INVALID_EUI48,
+-	LDNS_STATUS_INVALID_EUI64,
+-	LDNS_STATUS_WIRE_RDATA_ERR,
+-	LDNS_STATUS_INVALID_TAG,
+-	LDNS_STATUS_TYPE_NOT_IN_BITMAP,
+-	LDNS_STATUS_INVALID_RDF_TYPE,
+-	LDNS_STATUS_RDATA_OVERFLOW
+-};
+-typedef enum ldns_enum_status ldns_status;
+-
+-extern ldns_lookup_table ldns_error_str[];
+-
+-/**
+- * look up a descriptive text by each error. This function
+- * could use a better name
+- * \param[in] err ldns_status number
+- * \return the string for that error
+- */
+-const char *ldns_get_errorstr_by_id(ldns_status err);
+-
+-#ifdef __cplusplus
+-}
+-#endif
+-
+-#endif /* LDNS_ERROR_H */
+diff --git a/include/ldns/higher.h b/include/ldns/higher.h
+deleted file mode 100644
+index 597e134..0000000
+--- a/include/ldns/higher.h
++++ /dev/null
+@@ -1,113 +0,0 @@
+-/**
+- * \file higher.h
+- *
+- * Specifies some higher level functions that could
+- * be useful for certain applications
+- */
+-
+-/*
+- * a Net::DNS like library for C
+- *
+- * (c) NLnet Labs, 2005-2006
+- *
+- * See the file LICENSE for the license
+- */
+-
+-#ifndef LDNS_HIGHER_H
+-#define LDNS_HIGHER_H
+-
+-#include <ldns/resolver.h>
+-#include <ldns/rdata.h>
+-#include <ldns/rr.h>
+-#include <ldns/host2str.h>
+-#include <ldns/tsig.h>
+-
+-#ifdef __cplusplus
+-extern "C" {
+-#endif
+-
+-/**
+- * Ask the resolver about name
+- * and return all address records
+- * \param[in] r the resolver to use
+- * \param[in] name the name to look for
+- * \param[in] c the class to use
+- * \param[in] flags give some optional flags to the query
+- */
+-ldns_rr_list *ldns_get_rr_list_addr_by_name(ldns_resolver *r, ldns_rdf *name, ldns_rr_class c, uint16_t flags);
+-
+-/**
+- * ask the resolver about the address
+- * and return the name
+- * \param[in] r the resolver to use
+- * \param[in] addr the addr to look for
+- * \param[in] c the class to use
+- * \param[in] flags give some optional flags to the query
+- */
+-ldns_rr_list *ldns_get_rr_list_name_by_addr(ldns_resolver *r, ldns_rdf *addr, ldns_rr_class c, uint16_t flags);
+-
+-/**
+- * wade through fp (a /etc/hosts like file)
+- * and return a rr_list containing all the 
+- * defined hosts in there
+- * \param[in] fp the file pointer to use
+- * \return ldns_rr_list * with the names
+- */
+-ldns_rr_list *ldns_get_rr_list_hosts_frm_fp(FILE *fp);
+-
+-/**
+- * wade through fp (a /etc/hosts like file)
+- * and return a rr_list containing all the 
+- * defined hosts in there
+- * \param[in] fp the file pointer to use
+- * \param[in] line_nr pointer to an integer containing the current line number (for debugging purposes)
+- * \return ldns_rr_list * with the names
+- */
+-ldns_rr_list *ldns_get_rr_list_hosts_frm_fp_l(FILE *fp, int *line_nr);
+-
+-/**
+- * wade through fp (a /etc/hosts like file)
+- * and return a rr_list containing all the 
+- * defined hosts in there
+- * \param[in] filename the filename to use (NULL for /etc/hosts)
+- * \return ldns_rr_list * with the names
+- */
+-ldns_rr_list *ldns_get_rr_list_hosts_frm_file(char *filename);
+-
+-/**
+- * This function is a wrapper function for ldns_get_rr_list_name_by_addr
+- * and ldns_get_rr_list_addr_by_name. It's name is from the getaddrinfo() 
+- * library call. It tries to mimic that call, but without the lowlevel
+- * stuff.
+- * \param[in] res The resolver. If this value is NULL then a resolver will
+- * be created by ldns_getaddrinfo.
+- * \param[in] node the name or ip address to look up
+- * \param[in] c the class to look in
+- * \param[out] list put the found RR's in this list
+- * \return the number of RR found.
+- */
+-uint16_t ldns_getaddrinfo(ldns_resolver *res, ldns_rdf *node, ldns_rr_class c, ldns_rr_list **list);
+-
+-/**
+- * Check if t is enumerated in the nsec type rdata
+- * \param[in] nsec the NSEC Record to look in
+- * \param[in] t the type to check for
+- * \return true when t is found, otherwise return false
+- */
+-bool ldns_nsec_type_check(ldns_rr *nsec, ldns_rr_type t);
+-
+-/**
+- * Print a number of rdf's of the RR. The rdfnum-list must 
+- * be ended by -1, otherwise unpredictable things might happen.
+- * rdfs may be printed multiple times
+- * \param[in] fp FILE * to write to
+- * \param[in] r RR to write
+- * \param[in] rdfnum a list of rdf to print.
+- */
+-void ldns_print_rr_rdf(FILE *fp, ldns_rr *r, int rdfnum, ...);
+-
+-#ifdef __cplusplus
+-}
+-#endif
+-
+-#endif /* LDNS_HIGHER_H */
+diff --git a/include/ldns/host2str.h b/include/ldns/host2str.h
+deleted file mode 100644
+index e69389e..0000000
+--- a/include/ldns/host2str.h
++++ /dev/null
+@@ -1,891 +0,0 @@
+-/**
+- * host2str.h -  txt presentation of RRs
+- *
+- * a Net::DNS like library for C
+- *
+- * (c) NLnet Labs, 2005-2006
+- *
+- * See the file LICENSE for the license
+- */
+-
+-/**
+- * \file
+- *
+- * Contains functions to translate the main structures to their text
+- * representation, as well as functions to print them.
+- */
+-
+-#ifndef LDNS_HOST2STR_H
+-#define LDNS_HOST2STR_H
+-
+-#include <ldns/common.h>
+-#include <ldns/error.h>
+-#include <ldns/rr.h>
+-#include <ldns/rdata.h>
+-#include <ldns/packet.h>
+-#include <ldns/buffer.h>
+-#include <ldns/resolver.h>
+-#include <ldns/zone.h>
+-#include <ctype.h>
+-
+-#include "ldns/util.h"
+-
+-#ifdef __cplusplus
+-extern "C" {
+-#endif
+-
+-#define LDNS_APL_IP4            1
+-#define LDNS_APL_IP6            2
+-#define LDNS_APL_MASK           0x7f
+-#define LDNS_APL_NEGATION       0x80
+-
+-/** 
+- * Represent a NULL pointer (instead of a pointer to a ldns_rr as "; (null)" 
+- * as opposed to outputting nothing at all in such a case.
+- */
+-/*	Flag Name			Flag Nr.	Has data associated
+-	---------------------------------------------------------------------*/
+-#define LDNS_COMMENT_NULLS		(1 <<  0)
+-/** Show key id with DNSKEY RR's as comment */
+-#define LDNS_COMMENT_KEY_ID		(1 <<  1)
+-/** Show if a DNSKEY is a ZSK or KSK as comment */
+-#define LDNS_COMMENT_KEY_TYPE		(1 <<  2)
+-/** Show DNSKEY key size as comment */
+-#define LDNS_COMMENT_KEY_SIZE		(1 <<  3)
+-/** Provide bubblebabble representation for DS RR's as comment */
+-#define LDNS_COMMENT_BUBBLEBABBLE	(1 <<  4)
+-/** Show when a NSEC3 RR has the optout flag set as comment */
+-#define LDNS_COMMENT_FLAGS		(1 <<  5)
+-/** Show the unhashed owner and next owner names for NSEC3 RR's as comment */
+-#define LDNS_COMMENT_NSEC3_CHAIN	(1 <<  6)	/* yes */
+-/** Print mark up */
+-#define LDNS_COMMENT_LAYOUT		(1 <<  7)
+-/** Also comment KEY_ID with RRSIGS **/
+-#define LDNS_COMMENT_RRSIGS		(1 <<  8)
+-#define LDNS_FMT_ZEROIZE_RRSIGS		(1 <<  9)
+-#define LDNS_FMT_PAD_SOA_SERIAL		(1 << 10)
+-#define LDNS_FMT_RFC3597		(1 << 11)	/* yes */
+-
+-#define LDNS_FMT_FLAGS_WITH_DATA			    2
+-
+-/** Show key id, type and size as comment for DNSKEY RR's */
+-#define LDNS_COMMENT_KEY		(LDNS_COMMENT_KEY_ID  \
+-					|LDNS_COMMENT_KEY_TYPE\
+-					|LDNS_COMMENT_KEY_SIZE)
+-
+-/**
+- * Output format specifier
+- *
+- * Determines how Packets, Resource Records and Resource record data fiels are
+- * formatted when printing or converting to string.
+- * Currently it is only used to specify what aspects of a Resource Record are
+- * annotated in the comment section of the textual representation the record.
+- * This is speciefed with flags and potential exra data (such as for example
+- * a lookup map of hashes to real names for annotation NSEC3 records).
+- */
+-struct ldns_struct_output_format
+-{
+-	/** Specification of how RR's should be formatted in text */
+-	int   flags;
+-	/** Potential extra data to be used with formatting RR's in text */
+-	void *data;
+-};
+-typedef struct ldns_struct_output_format ldns_output_format;
+-
+-/**
+- * Output format struct with additional data for flags that use them.
+- * This struct may not be initialized directly. Use ldns_output_format_init
+- * to initialize.
+- */
+-struct ldns_struct_output_format_storage
+-{	int   flags;
+-	ldns_rbtree_t* hashmap;    /* for LDNS_COMMENT_NSEC3_CHAIN */
+-	ldns_rdf*      bitmap;     /* for LDNS_FMT_RFC3597     */
+-};
+-typedef struct ldns_struct_output_format_storage ldns_output_format_storage;
+-
+-/**
+- * Standard output format record that disables commenting in the textual 
+- * representation of Resource Records completely.
+- */
+-extern const ldns_output_format *ldns_output_format_nocomments;
+-/**
+- * Standard output format record that annotated only DNSKEY RR's with commenti
+- * text.
+- */
+-extern const ldns_output_format *ldns_output_format_onlykeyids;
+-/**
+- * The default output format record. Same as ldns_output_format_onlykeyids.
+- */
+-extern const ldns_output_format *ldns_output_format_default;
+-/**
+- * Standard output format record that shows all DNSKEY related information in
+- * the comment text, plus the optout flag when set with NSEC3's, plus the
+- * bubblebabble representation of DS RR's.
+- */
+-extern const ldns_output_format *ldns_output_format_bubblebabble;
+-
+-/**
+- * Initialize output format storage to the default value.
+- * \param[in] fmt A reference to an output_format_ storage struct
+- * \return The initialized storage struct typecasted to ldns_output_format
+- */
+-INLINE
+-ldns_output_format* ldns_output_format_init(ldns_output_format_storage* fmt) {
+-	fmt->flags   = ldns_output_format_default->flags;
+-	fmt->hashmap = NULL;
+-	fmt->bitmap  = NULL;
+-	return (ldns_output_format*)fmt;
+-}
+-
+-/**
+- * Set an ouput format flag.
+- */
+-INLINE void ldns_output_format_set(ldns_output_format* fmt, int flag) {
+-        fmt->flags |= flag;
+-}
+-
+-/**
+- * Clear an ouput format flag.
+- */
+-INLINE void ldns_output_format_clear(ldns_output_format* fmt, int flag) {
+-        fmt->flags &= !flag;
+-}
+-
+-/**
+- * Makes sure the LDNS_FMT_RFC3597 is set in the output format.
+- * Marks the type to be printed in RFC3597 format.
+- * /param[in] fmt the output format to update
+- * /param[in] the type to be printed in RFC3597 format
+- * /return LDNS_STATUS_OK on success
+- */
+-ldns_status
+-ldns_output_format_set_type(ldns_output_format* fmt, ldns_rr_type type);
+-
+-/**
+- * Makes sure the LDNS_FMT_RFC3597 is set in the output format.
+- * Marks the type to not be printed in RFC3597 format. When no other types
+- * have been marked before, all known types (except the given one) will be
+- * marked for printing in RFC3597 format.
+- * /param[in] fmt the output format to update
+- * /param[in] the type not to be printed in RFC3597 format
+- * /return LDNS_STATUS_OK on success
+- */
+-ldns_status
+-ldns_output_format_clear_type(ldns_output_format* fmt, ldns_rr_type type);
+-
+-/**
+- * Converts an ldns packet opcode value to its mnemonic, and adds that
+- * to the output buffer
+- * \param[in] *output the buffer to add the data to
+- * \param[in] opcode to find the string representation of
+- * \return LDNS_STATUS_OK on success, or a buffer failure mode on error
+- */
+-ldns_status
+-ldns_pkt_opcode2buffer_str(ldns_buffer *output, ldns_pkt_opcode opcode);
+-
+-/**
+- * Converts an ldns packet rcode value to its mnemonic, and adds that
+- * to the output buffer
+- * \param[in] *output the buffer to add the data to
+- * \param[in] rcode to find the string representation of
+- * \return LDNS_STATUS_OK on success, or a buffer failure mode on error
+- */
+-ldns_status
+-ldns_pkt_rcode2buffer_str(ldns_buffer *output, ldns_pkt_rcode rcode);
+-
+-/**
+- * Converts an ldns algorithm type to its mnemonic, and adds that
+- * to the output buffer
+- * \param[in] *output the buffer to add the data to
+- * \param[in] algorithm to find the string representation of
+- * \return LDNS_STATUS_OK on success, or a buffer failure mode on error
+- */
+-ldns_status
+-ldns_algorithm2buffer_str(ldns_buffer *output,
+-                          ldns_algorithm algorithm);
+-
+-/**
+- * Converts an ldns certificate algorithm type to its mnemonic, 
+- * and adds that to the output buffer
+- * \param[in] *output the buffer to add the data to
+- * \param[in] cert_algorithm to find the string representation of
+- * \return LDNS_STATUS_OK on success, or a buffer failure mode on error
+- */
+-ldns_status
+-ldns_cert_algorithm2buffer_str(ldns_buffer *output,
+-                               ldns_cert_algorithm cert_algorithm);
+-
+-
+-/**
+- * Converts a packet opcode to its mnemonic and returns that as
+- * an allocated null-terminated string.
+- * Remember to free it.
+- *
+- * \param[in] opcode the opcode to convert to text
+- * \return null terminated char * data, or NULL on error
+- */
+-char *ldns_pkt_opcode2str(ldns_pkt_opcode opcode);
+-
+-/**
+- * Converts a packet rcode to its mnemonic and returns that as
+- * an allocated null-terminated string.
+- * Remember to free it.
+- *
+- * \param[in] rcode the rcode to convert to text
+- * \return null terminated char * data, or NULL on error
+- */
+-char *ldns_pkt_rcode2str(ldns_pkt_rcode rcode);
+-
+-/**
+- * Converts a signing algorithms to its mnemonic and returns that as
+- * an allocated null-terminated string.
+- * Remember to free it.
+- *
+- * \param[in] algorithm the algorithm to convert to text
+- * \return null terminated char * data, or NULL on error
+- */
+-char *ldns_pkt_algorithm2str(ldns_algorithm algorithm);
+-
+-/**
+- * Converts a cert algorithm to its mnemonic and returns that as
+- * an allocated null-terminated string.
+- * Remember to free it.
+- *
+- * \param[in] cert_algorithm to convert to text
+- * \return null terminated char * data, or NULL on error
+- */
+-char *ldns_pkt_cert_algorithm2str(ldns_cert_algorithm cert_algorithm);
+-
+-/** 
+- * Converts an LDNS_RDF_TYPE_A rdata element to string format and adds it to the output buffer 
+- * \param[in] *rdf The rdata to convert
+- * \param[in] *output The buffer to add the data to
+- * \return LDNS_STATUS_OK on success, and error status on failure
+- */
+-ldns_status ldns_rdf2buffer_str_a(ldns_buffer *output, const ldns_rdf *rdf);
+-
+-/** 
+- * Converts an LDNS_RDF_TYPE_AAAA rdata element to string format and adds it to the output buffer 
+- * \param[in] *rdf The rdata to convert
+- * \param[in] *output The buffer to add the data to
+- * \return LDNS_STATUS_OK on success, and error status on failure
+- */
+-ldns_status ldns_rdf2buffer_str_aaaa(ldns_buffer *output, const ldns_rdf *rdf);
+-
+-/** 
+- * Converts an LDNS_RDF_TYPE_STR rdata element to string format and adds it to the output buffer 
+- * \param[in] *rdf The rdata to convert
+- * \param[in] *output The buffer to add the data to
+- * \return LDNS_STATUS_OK on success, and error status on failure
+- */
+-ldns_status ldns_rdf2buffer_str_str(ldns_buffer *output, const ldns_rdf *rdf);
+-
+-/** 
+- * Converts an LDNS_RDF_TYPE_B64 rdata element to string format and adds it to the output buffer 
+- * \param[in] *rdf The rdata to convert
+- * \param[in] *output The buffer to add the data to
+- * \return LDNS_STATUS_OK on success, and error status on failure
+- */
+-ldns_status ldns_rdf2buffer_str_b64(ldns_buffer *output, const ldns_rdf *rdf);
+-
+-/** 
+- * Converts an LDNS_RDF_TYPE_B32_EXT rdata element to string format and adds it to the output buffer 
+- * \param[in] *rdf The rdata to convert
+- * \param[in] *output The buffer to add the data to
+- * \return LDNS_STATUS_OK on success, and error status on failure
+- */
+-ldns_status ldns_rdf2buffer_str_b32_ext(ldns_buffer *output, const ldns_rdf *rdf);
+-
+-/** 
+- * Converts an LDNS_RDF_TYPE_HEX rdata element to string format and adds it to the output buffer 
+- * \param[in] *rdf The rdata to convert
+- * \param[in] *output The buffer to add the data to
+- * \return LDNS_STATUS_OK on success, and error status on failure
+- */
+-ldns_status ldns_rdf2buffer_str_hex(ldns_buffer *output, const ldns_rdf *rdf);
+-
+-/** 
+- * Converts an LDNS_RDF_TYPE_TYPE rdata element to string format and adds it to the output buffer 
+- * \param[in] *rdf The rdata to convert
+- * \param[in] *output The buffer to add the data to
+- * \return LDNS_STATUS_OK on success, and error status on failure
+- */
+-ldns_status ldns_rdf2buffer_str_type(ldns_buffer *output, const ldns_rdf *rdf);
+-
+-/** 
+- * Converts an LDNS_RDF_TYPE_CLASS rdata element to string format and adds it to the output buffer 
+- * \param[in] *rdf The rdata to convert
+- * \param[in] *output The buffer to add the data to
+- * \return LDNS_STATUS_OK on success, and error status on failure
+- */
+-ldns_status ldns_rdf2buffer_str_class(ldns_buffer *output, const ldns_rdf *rdf);
+-
+-/** 
+- * Converts an LDNS_RDF_TYPE_ALG rdata element to string format and adds it to the output buffer 
+- * \param[in] *rdf The rdata to convert
+- * \param[in] *output The buffer to add the data to
+- * \return LDNS_STATUS_OK on success, and error status on failure
+- */
+-ldns_status ldns_rdf2buffer_str_alg(ldns_buffer *output, const ldns_rdf *rdf);
+-
+-/**
+- * Converts an ldns_rr_type value to its string representation,
+- * and places it in the given buffer
+- * \param[in] *output The buffer to add the data to
+- * \param[in] type the ldns_rr_type to convert
+- * \return LDNS_STATUS_OK on success, and error status on failure
+- */
+-ldns_status ldns_rr_type2buffer_str(ldns_buffer *output,
+-                                    const ldns_rr_type type);
+-
+-/**
+- * Converts an ldns_rr_type value to its string representation,
+- * and returns that string. For unknown types, the string
+- * "TYPE<id>" is returned. This function allocates data that must be
+- * freed by the caller
+- * \param[in] type the ldns_rr_type to convert
+- * \return a newly allocated string
+- */
+-char *ldns_rr_type2str(const ldns_rr_type type);
+-
+-/**
+- * Converts an ldns_rr_class value to its string representation,
+- * and places it in the given buffer
+- * \param[in] *output The buffer to add the data to
+- * \param[in] klass the ldns_rr_class to convert
+- * \return LDNS_STATUS_OK on success, and error status on failure
+- */
+-ldns_status ldns_rr_class2buffer_str(ldns_buffer *output,
+-                                     const ldns_rr_class klass);
+-
+-/**
+- * Converts an ldns_rr_class value to its string representation,
+- * and returns that string. For unknown types, the string
+- * "CLASS<id>" is returned. This function allocates data that must be
+- * freed by the caller
+- * \param[in] klass the ldns_rr_class to convert
+- * \return a newly allocated string
+- */
+-char *ldns_rr_class2str(const ldns_rr_class klass);
+-
+-
+-/** 
+- * Converts an LDNS_RDF_TYPE_CERT rdata element to string format and adds it to the output buffer 
+- * \param[in] *rdf The rdata to convert
+- * \param[in] *output The buffer to add the data to
+- * \return LDNS_STATUS_OK on success, and error status on failure
+- */
+-ldns_status ldns_rdf2buffer_str_cert_alg(ldns_buffer *output, const ldns_rdf *rdf);
+-
+-/** 
+- * Converts an LDNS_RDF_TYPE_LOC rdata element to string format and adds it to the output buffer 
+- * \param[in] *rdf The rdata to convert
+- * \param[in] *output The buffer to add the data to
+- * \return LDNS_STATUS_OK on success, and error status on failure
+- */
+-ldns_status ldns_rdf2buffer_str_loc(ldns_buffer *output, const ldns_rdf *rdf);
+-
+-/** 
+- * Converts an LDNS_RDF_TYPE_UNKNOWN rdata element to string format and adds it to the output buffer 
+- * \param[in] *rdf The rdata to convert
+- * \param[in] *output The buffer to add the data to
+- * \return LDNS_STATUS_OK on success, and error status on failure
+- */
+-ldns_status ldns_rdf2buffer_str_unknown(ldns_buffer *output, const ldns_rdf *rdf);
+-
+-/** 
+- * Converts an LDNS_RDF_TYPE_NSAP rdata element to string format and adds it to the output buffer 
+- * \param[in] *rdf The rdata to convert
+- * \param[in] *output The buffer to add the data to
+- * \return LDNS_STATUS_OK on success, and error status on failure
+- */
+-ldns_status ldns_rdf2buffer_str_nsap(ldns_buffer *output, const ldns_rdf *rdf);
+-
+-/** 
+- * Converts an LDNS_RDF_TYPE_ATMA rdata element to string format and adds it to the output buffer 
+- * \param[in] *rdf The rdata to convert
+- * \param[in] *output The buffer to add the data to
+- * \return LDNS_STATUS_OK on success, and error status on failure
+- */
+-ldns_status ldns_rdf2buffer_str_atma(ldns_buffer *output, const ldns_rdf *rdf);
+-
+-/** 
+- * Converts an LDNS_RDF_TYPE_WKS rdata element to string format and adds it to the output buffer 
+- * \param[in] *rdf The rdata to convert
+- * \param[in] *output The buffer to add the data to
+- * \return LDNS_STATUS_OK on success, and error status on failure
+- */
+-ldns_status ldns_rdf2buffer_str_wks(ldns_buffer *output, const ldns_rdf *rdf);
+-
+-/** 
+- * Converts an LDNS_RDF_TYPE_NSEC rdata element to string format and adds it to the output buffer 
+- * \param[in] *rdf The rdata to convert
+- * \param[in] *output The buffer to add the data to
+- * \return LDNS_STATUS_OK on success, and error status on failure
+- */
+-ldns_status ldns_rdf2buffer_str_nsec(ldns_buffer *output, const ldns_rdf *rdf);
+-
+-/** 
+- * Converts an LDNS_RDF_TYPE_PERIOD rdata element to string format and adds it to the output buffer 
+- * \param[in] *rdf The rdata to convert
+- * \param[in] *output The buffer to add the data to
+- * \return LDNS_STATUS_OK on success, and error status on failure
+- */
+-ldns_status ldns_rdf2buffer_str_period(ldns_buffer *output, const ldns_rdf *rdf);
+-
+-/** 
+- * Converts an LDNS_RDF_TYPE_TSIGTIME rdata element to string format and adds it to the output buffer 
+- * \param[in] *rdf The rdata to convert
+- * \param[in] *output The buffer to add the data to
+- * \return LDNS_STATUS_OK on success, and error status on failure
+- */
+-ldns_status ldns_rdf2buffer_str_tsigtime(ldns_buffer *output, const ldns_rdf *rdf);
+-
+-/** 
+- * Converts an LDNS_RDF_TYPE_APL rdata element to string format and adds it to the output buffer 
+- * \param[in] *rdf The rdata to convert
+- * \param[in] *output The buffer to add the data to
+- * \return LDNS_STATUS_OK on success, and error status on failure
+- */
+-ldns_status ldns_rdf2buffer_str_apl(ldns_buffer *output, const ldns_rdf *rdf);
+-
+-/** 
+- * Converts an LDNS_RDF_TYPE_INT16_DATA rdata element to string format and adds it to the output buffer 
+- * \param[in] *rdf The rdata to convert
+- * \param[in] *output The buffer to add the data to
+- * \return LDNS_STATUS_OK on success, and error status on failure
+- */
+-ldns_status ldns_rdf2buffer_str_int16_data(ldns_buffer *output, const ldns_rdf *rdf);
+-
+-/** 
+- * Converts an LDNS_RDF_TYPE_IPSECKEY rdata element to string format and adds it to the output buffer 
+- * \param[in] *rdf The rdata to convert
+- * \param[in] *output The buffer to add the data to
+- * \return LDNS_STATUS_OK on success, and error status on failure
+- */
+-ldns_status ldns_rdf2buffer_str_ipseckey(ldns_buffer *output, const ldns_rdf *rdf);
+-
+-/**
+- * Converts the data in the rdata field to presentation
+- * format (as char *) and appends it to the given buffer
+- *
+- * \param[in] output pointer to the buffer to append the data to
+- * \param[in] rdf the pointer to the rdafa field containing the data
+- * \return status
+- */
+-ldns_status ldns_rdf2buffer_str(ldns_buffer *output, const ldns_rdf *rdf);
+-
+-/**
+- * Converts the data in the resource record to presentation
+- * format (as char *) and appends it to the given buffer.
+- * The presentation format of DNSKEY record is annotated with comments giving
+- * the id, type and size of the key.
+- *
+- * \param[in] output pointer to the buffer to append the data to
+- * \param[in] rr the pointer to the rr field to convert
+- * \return status
+- */
+-ldns_status ldns_rr2buffer_str(ldns_buffer *output, const ldns_rr *rr);
+-
+-/**
+- * Converts the data in the resource record to presentation
+- * format (as char *) and appends it to the given buffer.
+- * The presentation format is annotated with comments giving
+- * additional information on the record.
+- *
+- * \param[in] output pointer to the buffer to append the data to
+- * \param[in] fmt how to format the textual representation of the 
+- *            resource record.
+- * \param[in] rr the pointer to the rr field to convert
+- * \return status
+- */
+-ldns_status ldns_rr2buffer_str_fmt(ldns_buffer *output, 
+-		const ldns_output_format *fmt, const ldns_rr *rr);
+-
+-/**
+- * Converts the data in the DNS packet to presentation
+- * format (as char *) and appends it to the given buffer
+- *
+- * \param[in] output pointer to the buffer to append the data to
+- * \param[in] pkt the pointer to the packet to convert
+- * \return status
+- */
+-ldns_status ldns_pkt2buffer_str(ldns_buffer *output, const ldns_pkt *pkt);
+-
+-/**
+- * Converts the data in the DNS packet to presentation
+- * format (as char *) and appends it to the given buffer
+- *
+- * \param[in] output pointer to the buffer to append the data to
+- * \param[in] fmt how to format the textual representation of the packet
+- * \param[in] pkt the pointer to the packet to convert
+- * \return status
+- */
+-ldns_status ldns_pkt2buffer_str_fmt(ldns_buffer *output,
+-		const ldns_output_format *fmt, const ldns_pkt *pkt);
+-
+-/** 
+- * Converts an LDNS_RDF_TYPE_NSEC3_SALT rdata element to string format and adds it to the output buffer 
+- * \param[in] *rdf The rdata to convert
+- * \param[in] *output The buffer to add the data to
+- * \return LDNS_STATUS_OK on success, and error status on failure
+- */
+-ldns_status ldns_rdf2buffer_str_nsec3_salt(ldns_buffer *output, const ldns_rdf *rdf);
+-
+-
+-/**
+- * Converts the data in the DNS packet to presentation
+- * format (as char *) and appends it to the given buffer
+- *
+- * \param[in] output pointer to the buffer to append the data to
+- * \param[in] k the pointer to the private key to convert
+- * \return status
+- */
+-ldns_status ldns_key2buffer_str(ldns_buffer *output, const ldns_key *k);
+-
+-/**
+- * Converts an LDNS_RDF_TYPE_INT8 rdata element to string format and adds it to the output buffer
+- * \param[in] *rdf The rdata to convert
+- * \param[in] *output The buffer to add the data to
+- * \return LDNS_STATUS_OK on success, and error status on failure
+- */
+-ldns_status ldns_rdf2buffer_str_int8(ldns_buffer *output, const ldns_rdf *rdf);
+-
+-/**
+- * Converts an LDNS_RDF_TYPE_INT16 rdata element to string format and adds it to the output buffer
+- * \param[in] *rdf The rdata to convert
+- * \param[in] *output The buffer to add the data to
+- * \return LDNS_STATUS_OK on success, and error status on failure
+- */
+-ldns_status ldns_rdf2buffer_str_int16(ldns_buffer *output, const ldns_rdf *rdf);
+-
+-/**
+- * Converts an LDNS_RDF_TYPE_INT32 rdata element to string format and adds it to the output buffer
+- * \param[in] *rdf The rdata to convert
+- * \param[in] *output The buffer to add the data to
+- * \return LDNS_STATUS_OK on success, and error status on failure
+- */
+-ldns_status ldns_rdf2buffer_str_int32(ldns_buffer *output, const ldns_rdf *rdf);
+-
+-/**
+- * Converts an LDNS_RDF_TYPE_TIME rdata element to string format and adds it to the output buffer
+- * \param[in] *rdf The rdata to convert
+- * \param[in] *output The buffer to add the data to
+- * \return LDNS_STATUS_OK on success, and error status on failure
+- */
+-ldns_status ldns_rdf2buffer_str_time(ldns_buffer *output, const ldns_rdf *rdf);
+-
+-/** 
+- * Converts an LDNS_RDF_TYPE_ILNP64 rdata element to 4 hexadecimal numbers
+- * separated by colons and adds it to the output buffer 
+- * \param[in] *rdf The rdata to convert
+- * \param[in] *output The buffer to add the data to
+- * \return LDNS_STATUS_OK on success, and error status on failure
+- */
+-ldns_status ldns_rdf2buffer_str_ilnp64(ldns_buffer *output,
+-		const ldns_rdf *rdf);
+-
+-/** 
+- * Converts an LDNS_RDF_TYPE_EUI48 rdata element to 6 hexadecimal numbers
+- * separated by dashes and adds it to the output buffer 
+- * \param[in] *rdf The rdata to convert
+- * \param[in] *output The buffer to add the data to
+- * \return LDNS_STATUS_OK on success, and error status on failure
+- */
+-ldns_status ldns_rdf2buffer_str_eui48(ldns_buffer *output,
+-		const ldns_rdf *rdf);
+-
+-/** 
+- * Converts an LDNS_RDF_TYPE_EUI64 rdata element to 8 hexadecimal numbers
+- * separated by dashes and adds it to the output buffer 
+- * \param[in] *rdf The rdata to convert
+- * \param[in] *output The buffer to add the data to
+- * \return LDNS_STATUS_OK on success, and error status on failure
+- */
+-ldns_status ldns_rdf2buffer_str_eui64(ldns_buffer *output,
+-		const ldns_rdf *rdf);
+-
+-/** 
+- * Adds the LDNS_RDF_TYPE_TAG rdata to the output buffer,
+- * provided it contains only alphanumeric characters.
+- * \param[in] *rdf The rdata to convert
+- * \param[in] *output The buffer to add the data to
+- * \return LDNS_STATUS_OK on success, and error status on failure
+- */
+-ldns_status ldns_rdf2buffer_str_tag(ldns_buffer *output,
+-		const ldns_rdf *rdf);
+-
+-/** 
+- * Adds the LDNS_RDF_TYPE_LONG_STR rdata to the output buffer, in-between 
+- * double quotes and all non printable characters properly escaped.
+- * \param[in] *rdf The rdata to convert
+- * \param[in] *output The buffer to add the data to
+- * \return LDNS_STATUS_OK on success, and error status on failure
+- */
+-ldns_status ldns_rdf2buffer_str_long_str(ldns_buffer *output,
+-	       	const ldns_rdf *rdf);
+-
+-/** 
+- * Converts an LDNS_RDF_TYPE_HIP rdata element to presentation format for
+- * the algorithm, HIT and Public Key and adds it the output buffer .
+- * \param[in] *rdf The rdata to convert
+- * \param[in] *output The buffer to add the data to
+- * \return LDNS_STATUS_OK on success, and error status on failure
+- */
+-ldns_status ldns_rdf2buffer_str_hip(ldns_buffer *output,
+-		const ldns_rdf *rdf);
+-
+-/**
+- * Converts the data in the rdata field to presentation format and
+- * returns that as a char *.
+- * Remember to free it.
+- *
+- * \param[in] rdf The rdata field to convert
+- * \return null terminated char * data, or NULL on error
+- */
+-char *ldns_rdf2str(const ldns_rdf *rdf);
+-
+-/**
+- * Converts the data in the resource record to presentation format and
+- * returns that as a char *.
+- * Remember to free it.
+- *
+- * \param[in] rr The rdata field to convert
+- * \return null terminated char * data, or NULL on error
+- */
+-char *ldns_rr2str(const ldns_rr *rr);
+-
+-/**
+- * Converts the data in the resource record to presentation format and
+- * returns that as a char *.
+- * Remember to free it.
+- *
+- * \param[in] fmt how to format the resource record
+- * \param[in] rr The rdata field to convert
+- * \return null terminated char * data, or NULL on error
+- */
+-char *ldns_rr2str_fmt(const ldns_output_format *fmt, const ldns_rr *rr);
+-
+-/**
+- * Converts the data in the DNS packet to presentation format and
+- * returns that as a char *.
+- * Remember to free it.
+- *
+- * \param[in] pkt The rdata field to convert
+- * \return null terminated char * data, or NULL on error
+- */
+-char *ldns_pkt2str(const ldns_pkt *pkt);
+-
+-/**
+- * Converts the data in the DNS packet to presentation format and
+- * returns that as a char *.
+- * Remember to free it.
+- *
+- * \param[in] fmt how to format the packet
+- * \param[in] pkt The rdata field to convert
+- * \return null terminated char * data, or NULL on error
+- */
+-char *ldns_pkt2str_fmt(const ldns_output_format *fmt, const ldns_pkt *pkt);
+-
+-/**
+- * Converts a private key to the test presentation fmt and
+- * returns that as a char *.
+- * Remember to free it.
+- *
+- * \param[in] k the key to convert to text
+- * \return null terminated char * data, or NULL on error
+- */
+-char *ldns_key2str(const ldns_key *k);
+-
+-/**
+- * Converts a list of resource records to presentation format
+- * and returns that as a char *.
+- * Remember to free it.
+- *
+- * \param[in] rr_list the rr_list to convert to text
+- * \return null terminated char * data, or NULL on error
+- */
+-char *ldns_rr_list2str(const ldns_rr_list *rr_list);
+-
+-/**
+- * Converts a list of resource records to presentation format
+- * and returns that as a char *.
+- * Remember to free it.
+- *
+- * \param[in] fmt how to format the list of resource records
+- * \param[in] rr_list the rr_list to convert to text
+- * \return null terminated char * data, or NULL on error
+- */
+-char *ldns_rr_list2str_fmt(
+-		const ldns_output_format *fmt, const ldns_rr_list *rr_list);
+-
+-/**
+- * Returns a copy of the data in the buffer as a null terminated
+- * char * string. The returned string must be freed by the caller.
+- * The buffer must be in write modus and may thus not have been flipped.
+- *
+- * \param[in] buffer buffer containing char * data
+- * \return null terminated char * data, or NULL on error
+- */
+-char *ldns_buffer2str(ldns_buffer *buffer);
+-
+-/**
+- * Exports and returns the data in the buffer as a null terminated
+- * char * string. The returned string must be freed by the caller.
+- * The buffer must be in write modus and may thus not have been flipped.
+- * The buffer is fixed after this function returns.
+- *
+- * \param[in] buffer buffer containing char * data
+- * \return null terminated char * data, or NULL on error
+- */
+-char *ldns_buffer_export2str(ldns_buffer *buffer);
+-
+-/**
+- * Prints the data in the rdata field to the given file stream
+- * (in presentation format)
+- *
+- * \param[in] output the file stream to print to
+- * \param[in] rdf the rdata field to print
+- * \return void
+- */
+-void ldns_rdf_print(FILE *output, const ldns_rdf *rdf);
+-
+-/**
+- * Prints the data in the resource record to the given file stream
+- * (in presentation format)
+- *
+- * \param[in] output the file stream to print to
+- * \param[in] rr the resource record to print
+- * \return void
+- */
+-void ldns_rr_print(FILE *output, const ldns_rr *rr);
+-
+-/**
+- * Prints the data in the resource record to the given file stream
+- * (in presentation format)
+- *
+- * \param[in] output the file stream to print to
+- * \param[in] fmt format of the textual representation
+- * \param[in] rr the resource record to print
+- * \return void
+- */
+-void ldns_rr_print_fmt(FILE *output, 
+-		const ldns_output_format *fmt, const ldns_rr *rr);
+-
+-/**
+- * Prints the data in the DNS packet to the given file stream
+- * (in presentation format)
+- *
+- * \param[in] output the file stream to print to
+- * \param[in] pkt the packet to print
+- * \return void
+- */
+-void ldns_pkt_print(FILE *output, const ldns_pkt *pkt);
+-
+-/**
+- * Prints the data in the DNS packet to the given file stream
+- * (in presentation format)
+- *
+- * \param[in] output the file stream to print to
+- * \param[in] fmt format of the textual representation
+- * \param[in] pkt the packet to print
+- * \return void
+- */
+-void ldns_pkt_print_fmt(FILE *output, 
+-		const ldns_output_format *fmt, const ldns_pkt *pkt);
+-
+-/**
+- * Converts a rr_list to presentation format and appends it to
+- * the output buffer
+- * \param[in] output the buffer to append output to
+- * \param[in] list the ldns_rr_list to print
+- * \return ldns_status
+- */
+-ldns_status ldns_rr_list2buffer_str(ldns_buffer *output, const ldns_rr_list *list);
+-
+-/**
+- * Converts a rr_list to presentation format and appends it to
+- * the output buffer
+- * \param[in] output the buffer to append output to
+- * \param[in] fmt format of the textual representation
+- * \param[in] list the ldns_rr_list to print
+- * \return ldns_status
+- */
+-ldns_status ldns_rr_list2buffer_str_fmt(ldns_buffer *output, 
+-		const ldns_output_format *fmt, const ldns_rr_list *list);
+-
+-/**
+- * Converts the header of a packet to presentation format and appends it to
+- * the output buffer
+- * \param[in] output the buffer to append output to
+- * \param[in] pkt the packet to convert the header of
+- * \return ldns_status
+- */
+-ldns_status ldns_pktheader2buffer_str(ldns_buffer *output, const ldns_pkt *pkt);
+-
+-/**
+- * print a rr_list to output
+- * \param[in] output the fd to print to
+- * \param[in] list the rr_list to print
+- */
+-void ldns_rr_list_print(FILE *output, const ldns_rr_list *list);
+-
+-/**
+- * print a rr_list to output
+- * \param[in] output the fd to print to
+- * \param[in] fmt format of the textual representation
+- * \param[in] list the rr_list to print
+- */
+-void ldns_rr_list_print_fmt(FILE *output, 
+-		const ldns_output_format *fmt, const ldns_rr_list *list);
+-
+-/**
+- * Print a resolver (in sofar that is possible) state
+- * to output.
+- * \param[in] output the fd to print to
+- * \param[in] r the resolver to print
+- */
+-void ldns_resolver_print(FILE *output, const ldns_resolver *r);
+-
+-/**
+- * Print a resolver (in sofar that is possible) state
+- * to output.
+- * \param[in] output the fd to print to
+- * \param[in] fmt format of the textual representation
+- * \param[in] r the resolver to print
+- */
+-void ldns_resolver_print_fmt(FILE *output, 
+-		const ldns_output_format *fmt, const ldns_resolver *r);
+-
+-/**
+- * Print a zone structure * to output. Note the SOA record
+- * is included in this output
+- * \param[in] output the fd to print to
+- * \param[in] z the zone to print
+- */
+-void ldns_zone_print(FILE *output, const ldns_zone *z);
+-
+-/**
+- * Print a zone structure * to output. Note the SOA record
+- * is included in this output
+- * \param[in] output the fd to print to
+- * \param[in] fmt format of the textual representation
+- * \param[in] z the zone to print
+- */
+-void ldns_zone_print_fmt(FILE *output, 
+-		const ldns_output_format *fmt, const ldns_zone *z);
+-
+-/**
+- * Print the ldns_rdf containing a dname to the buffer
+- * \param[in] output the buffer to print to
+- * \param[in] dname the dname to print
+- * \return ldns_status message if the printing succeeded
+- */
+-ldns_status ldns_rdf2buffer_str_dname(ldns_buffer *output, const ldns_rdf *dname);
+-
+-#ifdef __cplusplus
+-}
+-#endif
+-
+-#endif /* LDNS_HOST2STR_H */
+diff --git a/include/ldns/host2wire.h b/include/ldns/host2wire.h
+deleted file mode 100644
+index 94693cd..0000000
+--- a/include/ldns/host2wire.h
++++ /dev/null
+@@ -1,197 +0,0 @@
+-/*
+- * host2wire.h - 2wire conversion routines
+- *
+- * a Net::DNS like library for C
+- *
+- * (c) NLnet Labs, 2005-2006
+- *
+- * See the file LICENSE for the license
+- */
+-
+-/**
+- * \file
+- *
+- * Contains all functions to translate the main structures to wire format
+- */
+-
+-#ifndef LDNS_HOST2WIRE_H
+-#define LDNS_HOST2WIRE_H
+-
+-#include <ldns/common.h>
+-#include <ldns/error.h>
+-#include <ldns/rr.h>
+-#include <ldns/rdata.h>
+-#include <ldns/packet.h>
+-#include <ldns/buffer.h>
+-#include <ctype.h>
+-
+-#include "ldns/util.h"
+-
+-#ifdef __cplusplus
+-extern "C" {
+-#endif
+-
+-/**
+- * Copies the dname data to the buffer in wire format
+- * \param[out] *buffer buffer to append the result to
+- * \param[in] *name rdata dname to convert
+- * \return ldns_status
+- */
+-ldns_status ldns_dname2buffer_wire(ldns_buffer *buffer, const ldns_rdf *name);
+-
+-/**
+- * Copies the dname data to the buffer in wire format
+- * \param[out] *buffer buffer to append the result to
+- * \param[in] *name rdata dname to convert
+- * \param[out] *compression_data data structure holding state for compression
+- * \return ldns_status
+- */
+-ldns_status ldns_dname2buffer_wire_compress(ldns_buffer *buffer, const ldns_rdf *name, ldns_rbtree_t *compression_data);
+-
+-/**
+- * Copies the rdata data to the buffer in wire format
+- * \param[out] *output buffer to append the result to
+- * \param[in] *rdf rdata to convert
+- * \return ldns_status
+- */
+-ldns_status ldns_rdf2buffer_wire(ldns_buffer *output, const ldns_rdf *rdf);
+-
+-/**
+- * Copies the rdata data to the buffer in wire format
+- * \param[out] *output buffer to append the result to
+- * \param[in] *rdf rdata to convert
+- * \param[out] *compression_data data structure holding state for compression
+- * \return ldns_status
+- */
+-ldns_status ldns_rdf2buffer_wire_compress(ldns_buffer *output, const ldns_rdf *rdf, ldns_rbtree_t *compression_data);
+-
+-/**
+- * Copies the rdata data to the buffer in wire format
+- * If the rdata is a dname, the letters will be lowercased
+- * during the conversion
+- * \param[out] *output buffer to append the result to
+- * \param[in] *rdf rdata to convert
+- * \return ldns_status
+- */
+-ldns_status ldns_rdf2buffer_wire_canonical(ldns_buffer *output,
+-								   const ldns_rdf *rdf);
+-
+-/**
+- * Copies the rr data to the buffer in wire format
+- * \param[out] *output buffer to append the result to
+- * \param[in] *rr resource record to convert
+- * \param[in] section the section in the packet this rr is supposed to be in
+- *            (to determine whether to add rdata or not)
+- * \return ldns_status
+- */
+-ldns_status ldns_rr2buffer_wire(ldns_buffer *output,
+-						  const ldns_rr *rr,
+-						  int section);
+-
+-/**
+- * Copies the rr data to the buffer in wire format while doing DNAME compression
+- * \param[out] *output buffer to append the result to
+- * \param[in] *rr resource record to convert
+- * \param[in] section the section in the packet this rr is supposed to be in
+- *            (to determine whether to add rdata or not)
+- * \param[out] *compression_data data structure holding state information for compression
+- * \return ldns_status
+- */
+-ldns_status ldns_rr2buffer_wire_compress(ldns_buffer *output,
+-						  const ldns_rr *rr,
+-						  int section,
+-						  ldns_rbtree_t *compression_data);
+-
+-/**
+- * Copies the rr data to the buffer in wire format, in canonical format
+- * according to RFC3597 (every dname in rdata fields of RR's mentioned in
+- * that RFC will be lowercased)
+- * \param[out] *output buffer to append the result to
+- * \param[in] *rr resource record to convert
+- * \param[in] section the section in the packet this rr is supposed to be in
+- *            (to determine whether to add rdata or not)
+- * \return ldns_status
+- */
+-ldns_status ldns_rr2buffer_wire_canonical(ldns_buffer *output,
+-								  const ldns_rr *rr,
+-								  int section);
+-
+-
+-/**
+- * Converts a rrsig to wireformat BUT EXCLUDE the rrsig rdata
+- * This is needed in DNSSEC verification
+- * \param[out] output buffer to append the result to
+- * \param[in] sigrr signature rr to operate on
+- * \return ldns_status
+- */
+-ldns_status ldns_rrsig2buffer_wire(ldns_buffer *output, const ldns_rr *sigrr);
+-
+-/**
+- * Converts an rr's rdata to wireformat, while excluding
+- * the ownername and all the stuff before the rdata.
+- * This is needed in DNSSEC keytag calculation, the ds
+- * calcalution from the key and maybe elsewhere.
+- *
+- * \param[out] *output buffer where to put the result
+- * \param[in] *rr rr to operate on
+- * \return ldns_status
+- */
+-ldns_status ldns_rr_rdata2buffer_wire(ldns_buffer *output, const ldns_rr *rr);
+-
+-/**
+- * Copies the packet data to the buffer in wire format
+- * \param[out] *output buffer to append the result to
+- * \param[in] *pkt packet to convert
+- * \return ldns_status
+- */
+-ldns_status ldns_pkt2buffer_wire(ldns_buffer *output, const ldns_pkt *pkt);
+-
+-/**
+- * Copies the rr_list data to the buffer in wire format
+- * \param[out] *output buffer to append the result to
+- * \param[in] *rrlist rr_list to to convert
+- * \return ldns_status
+- */
+-ldns_status ldns_rr_list2buffer_wire(ldns_buffer *output, const ldns_rr_list *rrlist);
+-
+-/**
+- * Allocates an array of uint8_t at dest, and puts the wireformat of the
+- * given rdf in that array. The result_size value contains the
+- * length of the array, if it succeeds, and 0 otherwise (in which case
+- * the function also returns NULL)
+- *
+- * \param[out] dest pointer to the array of bytes to be created
+- * \param[in] rdf the rdata field to convert
+- * \param[out] size the size of the converted result
+- */
+-ldns_status ldns_rdf2wire(uint8_t **dest, const ldns_rdf *rdf, size_t *size);
+-
+-/**
+- * Allocates an array of uint8_t at dest, and puts the wireformat of the
+- * given rr in that array. The result_size value contains the
+- * length of the array, if it succeeds, and 0 otherwise (in which case
+- * the function also returns NULL)
+- *
+- * If the section argument is LDNS_SECTION_QUESTION, data like ttl and rdata
+- * are not put into the result
+- *
+- * \param[out] dest pointer to the array of bytes to be created
+- * \param[in] rr the rr to convert
+- * \param[in] section the rr section, determines how the rr is written.
+- * \param[out] size the size of the converted result
+- */
+-ldns_status ldns_rr2wire(uint8_t **dest, const ldns_rr *rr, int section, size_t *size);
+-
+-/**
+- * Allocates an array of uint8_t at dest, and puts the wireformat of the
+- * given packet in that array. The result_size value contains the
+- * length of the array, if it succeeds, and 0 otherwise (in which case
+- * the function also returns NULL)
+- */
+-ldns_status ldns_pkt2wire(uint8_t **dest, const ldns_pkt *p, size_t *size);
+-
+-#ifdef __cplusplus
+-}
+-#endif
+-
+-#endif /* LDNS_HOST2WIRE_H */
+diff --git a/include/ldns/keys.h b/include/ldns/keys.h
+deleted file mode 100644
+index d3b4873..0000000
+--- a/include/ldns/keys.h
++++ /dev/null
+@@ -1,621 +0,0 @@
+-/*
+- * 
+- * keys.h
+- *
+- * priv key definitions
+- *
+- * a Net::DNS like library for C
+- *
+- * (c) NLnet Labs, 2005-2006
+- *
+- * See the file LICENSE for the license
+- */
+-
+-/**
+- * \file
+- *
+- * Addendum to \ref dnssec.h, this module contains key and algorithm definitions and functions.
+- */
+- 
+-
+-#ifndef LDNS_KEYS_H
+-#define LDNS_KEYS_H
+-
+-#include <ldns/common.h>
+-#if LDNS_BUILD_CONFIG_HAVE_SSL
+-#include <openssl/ssl.h>
+-#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */
+-#include <ldns/util.h>
+-#include <errno.h>
+-
+-#ifdef __cplusplus
+-extern "C" {
+-#endif
+-
+-extern ldns_lookup_table ldns_signing_algorithms[];
+-
+-#define LDNS_KEY_ZONE_KEY 0x0100   /* rfc 4034 */
+-#define LDNS_KEY_SEP_KEY 0x0001    /* rfc 4034 */
+-#define LDNS_KEY_REVOKE_KEY 0x0080 /* rfc 5011 */
+-
+-/**
+- * Algorithms used in dns
+- */
+-enum ldns_enum_algorithm
+-{
+-        LDNS_RSAMD5             = 1,   /* RFC 4034,4035 */
+-        LDNS_DH                 = 2,
+-        LDNS_DSA                = 3,
+-        LDNS_ECC                = 4,
+-        LDNS_RSASHA1            = 5,
+-        LDNS_DSA_NSEC3          = 6,
+-        LDNS_RSASHA1_NSEC3      = 7,
+-        LDNS_RSASHA256          = 8,   /* RFC 5702 */
+-        LDNS_RSASHA512          = 10,  /* RFC 5702 */
+-        LDNS_ECC_GOST           = 12,  /* RFC 5933 */
+-        LDNS_ECDSAP256SHA256    = 13,  /* RFC 6605 */
+-        LDNS_ECDSAP384SHA384    = 14,  /* RFC 6605 */
+-        LDNS_INDIRECT           = 252,
+-        LDNS_PRIVATEDNS         = 253,
+-        LDNS_PRIVATEOID         = 254
+-};
+-typedef enum ldns_enum_algorithm ldns_algorithm;
+-
+-/**
+- * Hashing algorithms used in the DS record
+- */
+-enum ldns_enum_hash
+-{
+-        LDNS_SHA1               = 1,  /* RFC 4034 */
+-        LDNS_SHA256             = 2,  /* RFC 4509 */
+-        LDNS_HASH_GOST          = 3,  /* RFC 5933 */
+-        LDNS_SHA384             = 4   /* RFC 6605 */
+-};
+-typedef enum ldns_enum_hash ldns_hash;
+-
+-/**
+- * Algorithms used in dns for signing
+- */
+-enum ldns_enum_signing_algorithm
+-{
+-	LDNS_SIGN_RSAMD5	 = LDNS_RSAMD5,
+-	LDNS_SIGN_RSASHA1	 = LDNS_RSASHA1,
+-	LDNS_SIGN_DSA		 = LDNS_DSA,
+-	LDNS_SIGN_RSASHA1_NSEC3  = LDNS_RSASHA1_NSEC3,
+-	LDNS_SIGN_RSASHA256	 = LDNS_RSASHA256,
+-	LDNS_SIGN_RSASHA512	 = LDNS_RSASHA512,
+-	LDNS_SIGN_DSA_NSEC3	 = LDNS_DSA_NSEC3,
+-	LDNS_SIGN_ECC_GOST       = LDNS_ECC_GOST,
+-        LDNS_SIGN_ECDSAP256SHA256 = LDNS_ECDSAP256SHA256,
+-        LDNS_SIGN_ECDSAP384SHA384 = LDNS_ECDSAP384SHA384,
+-	LDNS_SIGN_HMACMD5	 = 157,	/* not official! This type is for TSIG, not DNSSEC */
+-	LDNS_SIGN_HMACSHA1	 = 158,	/* not official! This type is for TSIG, not DNSSEC */
+-	LDNS_SIGN_HMACSHA256 = 159  /* ditto */
+-};
+-typedef enum ldns_enum_signing_algorithm ldns_signing_algorithm;
+-
+-/**
+- * General key structure, can contain all types of keys that
+- * are used in DNSSEC. Mostly used to store private keys, since
+- * public keys can also be stored in a \ref ldns_rr with type
+- * \ref LDNS_RR_TYPE_DNSKEY.
+- *
+- * This structure can also store some variables that influence the
+- * signatures generated by signing with this key, for instance the
+- * inception date.
+- */
+-struct ldns_struct_key {
+-	ldns_signing_algorithm _alg;
+-	/** Whether to use this key when signing */
+-	bool _use;
+-	/** Storage pointers for the types of keys supported */
+-	/* TODO remove unions? */
+-	struct {
+-#if LDNS_BUILD_CONFIG_HAVE_SSL
+-#ifndef S_SPLINT_S
+-		/* The key can be an OpenSSL EVP Key
+-		 */
+-		EVP_PKEY *key;
+-#endif
+-#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */
+-		/**
+-		 * The key can be an HMAC key
+-		 */
+-		struct {
+-			unsigned char *key;
+-			size_t size;
+-		} hmac;
+-		/** the key structure can also just point to some external
+-		 *  key data
+-		 */
+-		void *external_key;
+-	} _key;
+-	/** Depending on the key we can have extra data */
+-	union {
+-                /** Some values that influence generated signatures */
+-		struct {
+-			/** The TTL of the rrset that is currently signed */
+-			uint32_t orig_ttl;
+-			/** The inception date of signatures made with this key. */
+-			uint32_t inception;
+-			/** The expiration date of signatures made with this key. */
+-			uint32_t expiration;
+-			/** The keytag of this key. */
+-			uint16_t keytag;
+-			/** The dnssec key flags as specified in RFC4035, like ZSK and KSK */
+-			uint16_t flags;
+-		}  dnssec;
+-	} _extra;
+-	/** Owner name of the key */
+-	ldns_rdf *_pubkey_owner;
+-};
+-typedef struct ldns_struct_key ldns_key;
+-
+-/**
+- * Same as rr_list, but now for keys 
+- */
+-struct ldns_struct_key_list
+-{
+-	size_t _key_count;
+-	ldns_key **_keys;
+-};
+-typedef struct ldns_struct_key_list ldns_key_list;
+-
+-
+-/**
+- * Creates a new empty key list
+- * \return a new ldns_key_list structure pointer
+- */
+-ldns_key_list *ldns_key_list_new(void);
+-
+-/** 
+- * Creates a new empty key structure
+- * \return a new ldns_key * structure
+- */
+-ldns_key *ldns_key_new(void);
+-
+-/**
+- * Creates a new key based on the algorithm
+- *
+- * \param[in] a The algorithm to use
+- * \param[in] size the number of bytes for the keysize
+- * \return a new ldns_key structure with the key
+- */
+-ldns_key *ldns_key_new_frm_algorithm(ldns_signing_algorithm a, uint16_t size);
+-
+-/**
+- * Creates a new priv key based on the 
+- * contents of the file pointed by fp.
+- *
+- * The file should be in Private-key-format v1.x.
+- *
+- * \param[out] k the new ldns_key structure
+- * \param[in] fp the file pointer to use
+- * \return an error or LDNS_STATUS_OK
+- */
+-ldns_status ldns_key_new_frm_fp(ldns_key **k, FILE *fp);
+-
+-/**
+- * Creates a new private key based on the 
+- * contents of the file pointed by fp
+- *
+- * The file should be in Private-key-format v1.x.
+- *
+- * \param[out] k the new ldns_key structure
+- * \param[in] fp the file pointer to use
+- * \param[in] line_nr pointer to an integer containing the current line number (for debugging purposes)
+- * \return an error or LDNS_STATUS_OK
+- */
+-ldns_status ldns_key_new_frm_fp_l(ldns_key **k, FILE *fp, int *line_nr);
+-
+-#if LDNS_BUILD_CONFIG_HAVE_SSL
+-/**
+- * Read the key with the given id from the given engine and store it
+- * in the given ldns_key structure. The algorithm type is set
+- */
+-ldns_status ldns_key_new_frm_engine(ldns_key **key, ENGINE *e, char *key_id, ldns_algorithm);
+-
+-
+-/**
+- * frm_fp helper function. This function parses the
+- * remainder of the (RSA) priv. key file generated from bind9
+- * \param[in] fp the file to parse
+- * \return NULL on failure otherwise a RSA structure
+- */
+-RSA *ldns_key_new_frm_fp_rsa(FILE *fp);
+-#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */
+-
+-#if LDNS_BUILD_CONFIG_HAVE_SSL
+-/**
+- * frm_fp helper function. This function parses the
+- * remainder of the (RSA) priv. key file generated from bind9
+- * \param[in] fp the file to parse
+- * \param[in] line_nr pointer to an integer containing the current line number (for debugging purposes)
+- * \return NULL on failure otherwise a RSA structure
+- */
+-RSA *ldns_key_new_frm_fp_rsa_l(FILE *fp, int *line_nr);
+-#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */
+-
+-#if LDNS_BUILD_CONFIG_HAVE_SSL
+-/**
+- * frm_fp helper function. This function parses the
+- * remainder of the (DSA) priv. key file
+- * \param[in] fp the file to parse
+- * \return NULL on failure otherwise a RSA structure
+- */
+-DSA *ldns_key_new_frm_fp_dsa(FILE *fp);
+-#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */
+-
+-#if LDNS_BUILD_CONFIG_HAVE_SSL
+-/**
+- * frm_fp helper function. This function parses the
+- * remainder of the (DSA) priv. key file
+- * \param[in] fp the file to parse
+- * \param[in] line_nr pointer to an integer containing the current line number (for debugging purposes)
+- * \return NULL on failure otherwise a RSA structure
+- */
+-DSA *ldns_key_new_frm_fp_dsa_l(FILE *fp, int *line_nr);
+-#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */
+-
+-#if LDNS_BUILD_CONFIG_HAVE_SSL
+-/**
+- * frm_fp helper function. This function parses the
+- * remainder of the (HMAC-MD5) key file
+- * This function allocated a buffer that needs to be freed
+- * \param[in] fp the file to parse
+- * \param[out] hmac_size the number of bits in the resulting buffer
+- * \return NULL on failure otherwise a newly allocated char buffer
+- */
+-unsigned char *ldns_key_new_frm_fp_hmac(FILE *fp, size_t *hmac_size);
+-#endif
+-
+-#if LDNS_BUILD_CONFIG_HAVE_SSL
+-/**
+- * frm_fp helper function. This function parses the
+- * remainder of the (HMAC-MD5) key file
+- * This function allocated a buffer that needs to be freed
+- * \param[in] fp the file to parse
+- * \param[in] line_nr pointer to an integer containing the current line number (for error reporting purposes)
+- * \param[out] hmac_size the number of bits in the resulting buffer
+- * \return NULL on failure otherwise a newly allocated char buffer
+- */
+-unsigned char *ldns_key_new_frm_fp_hmac_l(FILE *fp, int *line_nr, size_t *hmac_size);
+-#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */
+-
+-/* acces write functions */
+-/**
+- * Set the key's algorithm
+- * \param[in] k the key
+- * \param[in] l the algorithm
+- */
+-void ldns_key_set_algorithm(ldns_key *k, ldns_signing_algorithm l);
+-#if LDNS_BUILD_CONFIG_HAVE_SSL
+-/**
+- * Set the key's evp key
+- * \param[in] k the key
+- * \param[in] e the evp key
+- */
+-void ldns_key_set_evp_key(ldns_key *k, EVP_PKEY *e);
+-
+-/**
+- * Set the key's rsa data.
+- * The rsa data should be freed by the user.
+- * \param[in] k the key
+- * \param[in] r the rsa data
+- */
+-void ldns_key_set_rsa_key(ldns_key *k, RSA *r);
+-
+-/**
+- * Set the key's dsa data
+- * The dsa data should be freed by the user.
+- * \param[in] k the key
+- * \param[in] d the dsa data
+- */
+-void ldns_key_set_dsa_key(ldns_key *k, DSA *d);
+-
+-/**
+- * Assign the key's rsa data
+- * The rsa data will be freed automatically when the key is freed.
+- * \param[in] k the key
+- * \param[in] r the rsa data
+- */
+-void ldns_key_assign_rsa_key(ldns_key *k, RSA *r);
+-
+-/**
+- * Assign the key's dsa data
+- * The dsa data will be freed automatically when the key is freed.
+- * \param[in] k the key
+- * \param[in] d the dsa data
+- */
+-void ldns_key_assign_dsa_key(ldns_key *k, DSA *d);
+-
+-/** 
+- * Get the PKEY id for GOST, loads GOST into openssl as a side effect.
+- * Only available if GOST is compiled into the library and openssl.
+- * \return the gost id for EVP_CTX creation.
+- */
+-int ldns_key_EVP_load_gost_id(void);
+-
+-/** Release the engine reference held for the GOST engine. */
+-void ldns_key_EVP_unload_gost(void);
+-#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */
+-
+-/**
+- * Set the key's hmac data
+- * \param[in] k the key
+- * \param[in] hmac the raw key data
+- */
+-void ldns_key_set_hmac_key(ldns_key *k, unsigned char *hmac);
+-
+-/**
+- * Set the key id data. This is used if the key points to
+- * some externally stored key data
+- * 
+- * Only the pointer is set, the data there is not copied,
+- * and must be freed manually; ldns_key_deep_free() does 
+- * *not* free this data
+- * \param[in] key the key
+- * \param[in] external_key key id data
+- */
+-void ldns_key_set_external_key(ldns_key *key, void *external_key);
+-
+-/**
+- * Set the key's hmac size
+- * \param[in] k the key
+- * \param[in] hmac_size the size of the hmac data
+- */
+-void ldns_key_set_hmac_size(ldns_key *k, size_t hmac_size);
+-/**
+- * Set the key's original ttl
+- * \param[in] k the key
+- * \param[in] t the ttl
+- */
+-void ldns_key_set_origttl(ldns_key *k, uint32_t t);
+-/**
+- * Set the key's inception date (seconds after epoch)
+- * \param[in] k the key
+- * \param[in] i the inception
+- */
+-void ldns_key_set_inception(ldns_key *k, uint32_t i);
+-/**
+- * Set the key's expiration date (seconds after epoch)
+- * \param[in] k the key
+- * \param[in] e the expiration
+- */
+-void ldns_key_set_expiration(ldns_key *k, uint32_t e);
+-/**
+- * Set the key's pubkey owner
+- * \param[in] k the key
+- * \param[in] r the owner
+- */
+-void ldns_key_set_pubkey_owner(ldns_key *k, ldns_rdf *r);
+-/**
+- * Set the key's key tag
+- * \param[in] k the key
+- * \param[in] tag the keytag
+- */
+-void ldns_key_set_keytag(ldns_key *k, uint16_t tag);
+-/**
+- * Set the key's flags
+- * \param[in] k the key
+- * \param[in] flags the flags
+- */
+-void ldns_key_set_flags(ldns_key *k, uint16_t flags);
+-/**
+- * Set the keylist's key count to count
+- * \param[in] key the key
+- * \param[in] count the cuont
+- */
+-void ldns_key_list_set_key_count(ldns_key_list *key, size_t count);
+-
+-/**     
+- * pushes a key to a keylist
+- * \param[in] key_list the key_list to push to 
+- * \param[in] key the key to push 
+- * \return false on error, otherwise true
+- */      
+-bool ldns_key_list_push_key(ldns_key_list *key_list, ldns_key *key);
+-
+-/**
+- * returns the number of keys in the key list
+- * \param[in] key_list the key_list
+- * \return the numbers of keys in the list
+- */
+-size_t ldns_key_list_key_count(const ldns_key_list *key_list);
+-
+-/**
+- * returns a pointer to the key in the list at the given position
+- * \param[in] key the key
+- * \param[in] nr the position in the list
+- * \return the key
+- */
+-ldns_key *ldns_key_list_key(const ldns_key_list *key, size_t nr);
+-
+-#if LDNS_BUILD_CONFIG_HAVE_SSL
+-/**
+- * returns the (openssl) RSA struct contained in the key
+- * \param[in] k the key to look in
+- * \return the RSA * structure in the key
+- */
+-RSA *ldns_key_rsa_key(const ldns_key *k);
+-/**
+- * returns the (openssl) EVP struct contained in the key
+- * \param[in] k the key to look in
+- * \return the RSA * structure in the key
+- */
+-EVP_PKEY *ldns_key_evp_key(const ldns_key *k);
+-#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */
+-
+-/**
+- * returns the (openssl) DSA struct contained in the key
+- */
+-#if LDNS_BUILD_CONFIG_HAVE_SSL
+-DSA *ldns_key_dsa_key(const ldns_key *k);
+-#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */
+-
+-/**
+- * return the signing alg of the key
+- * \param[in] k the key
+- * \return the algorithm
+- */
+-ldns_signing_algorithm ldns_key_algorithm(const ldns_key *k);
+-/**
+- * set the use flag
+- * \param[in] k the key
+- * \param[in] v the boolean value to set the _use field to
+- */
+-void ldns_key_set_use(ldns_key *k, bool v);
+-/**
+- * return the use flag
+- * \param[in] k the key
+- * \return the boolean value of the _use field
+- */
+-bool ldns_key_use(const ldns_key *k);
+-/**
+- * return the hmac key data
+- * \param[in] k the key
+- * \return the hmac key data
+- */
+-unsigned char *ldns_key_hmac_key(const ldns_key *k);
+-/**
+- * return the key id key data
+- * \param[in] k the key
+- * \return the key id data
+- */
+-void *ldns_key_external_key(const ldns_key *k);
+-/**
+- * return the hmac key size
+- * \param[in] k the key
+- * \return the hmac key size
+- */
+-size_t ldns_key_hmac_size(const ldns_key *k);
+-/**
+- * return the original ttl of the key
+- * \param[in] k the key
+- * \return the original ttl
+- */
+-uint32_t ldns_key_origttl(const ldns_key *k);
+-/**
+- * return the key's inception date
+- * \param[in] k the key
+- * \return the inception date
+- */
+-uint32_t ldns_key_inception(const ldns_key *k);
+-/**
+- * return the key's expiration date
+- * \param[in] k the key
+- * \return the experiration date
+- */
+-uint32_t ldns_key_expiration(const ldns_key *k);
+-/**
+- * return the keytag
+- * \param[in] k the key
+- * \return the keytag
+- */
+-uint16_t ldns_key_keytag(const ldns_key *k);
+-/**
+- * return the public key's owner
+- * \param[in] k the key
+- * \return the owner
+- */
+-ldns_rdf *ldns_key_pubkey_owner(const ldns_key *k);
+-/**
+- * Set the 'use' flag for all keys in the list
+- * \param[in] keys The key_list
+- * \param[in] v The value to set the use flags to
+- */
+-void
+-ldns_key_list_set_use(ldns_key_list *keys, bool v);
+-
+-/**
+- * return the flag of the key
+- * \param[in] k the key
+- * \return the flag
+- */
+-uint16_t ldns_key_flags(const ldns_key *k);
+-
+-/**     
+- * pops the last rr from a keylist
+- * \param[in] key_list the rr_list to pop from
+- * \return NULL if nothing to pop. Otherwise the popped RR
+- */
+-ldns_key *ldns_key_list_pop_key(ldns_key_list *key_list);
+-
+-/** 
+- * converts a ldns_key to a public key rr
+- * If the key data exists at an external point, the corresponding
+- * rdata field must still be added with ldns_rr_rdf_push() to the
+- * result rr of this function
+- *
+- * \param[in] k the ldns_key to convert
+- * \return ldns_rr representation of the key
+- */
+-ldns_rr *ldns_key2rr(const ldns_key *k);
+-
+-/**
+- * print a private key to the file ouput
+- * 
+- * \param[in] output the FILE descriptor where to print to
+- * \param[in] k the ldns_key to print
+- */
+-void ldns_key_print(FILE *output, const ldns_key *k);
+-
+-/**
+- * frees a key structure, but not its internal data structures
+- *
+- * \param[in] key the key object to free
+- */
+-void ldns_key_free(ldns_key *key);
+-
+-/**
+- * frees a key structure and all its internal data structures, except
+- * the data set by ldns_key_set_external_key()
+- *
+- * \param[in] key the key object to free
+- */
+-void ldns_key_deep_free(ldns_key *key);
+-
+-/**
+- * Frees a key list structure
+- * \param[in] key_list the key list object to free
+- */
+-void ldns_key_list_free(ldns_key_list *key_list);
+-
+-/**
+- * Instantiates a DNSKEY or DS RR from file.
+- * \param[in] filename the file to read the record from
+- * \return the corresponding RR, or NULL if the parsing failed
+- */
+-ldns_rr * ldns_read_anchor_file(const char *filename);
+-
+-/**
+- * Returns the 'default base name' for key files;
+- * IE. K\<zone\>+\<alg\>+\<keytag\>
+- * (without the .key or .private)
+- * The memory for this is allocated by this function,
+- * and should be freed by the caller
+- * 
+- * \param[in] key the key to get the file name from
+- * \returns A string containing the file base name
+- */
+-char *ldns_key_get_file_base_name(ldns_key *key);
+-
+-/**
+- * See if a key algorithm is supported
+- * \param[in] algo the signing algorithm number.
+- * \returns true if supported.
+- */
+-int ldns_key_algo_supported(int algo);
+-
+-/**
+- * Get signing algorithm by name.  Comparison is case insensitive.
+- * \param[in] name string with the name.
+- * \returns 0 on parse failure or the algorithm number.
+- */
+-ldns_signing_algorithm ldns_get_signing_algorithm_by_name(const char* name);
+-
+-#ifdef __cplusplus
+-}
+-#endif
+-
+-#endif /* LDNS_KEYS_H */
+diff --git a/include/ldns/ldns.h b/include/ldns/ldns.h
+deleted file mode 100644
+index 60663ef..0000000
+--- a/include/ldns/ldns.h
++++ /dev/null
+@@ -1,158 +0,0 @@
+-/*
+- * dns.h -- defines for the Domain Name System
+- *
+- * Copyright (c) 2005-2008, NLnet Labs. All rights reserved.
+- *
+- * See LICENSE for the license.
+- *
+- * This library was created by:
+- * Jelte Jansen, Erik Rozendaal and Miek Gieben
+- *
+- * A bunch of defines that are used in the DNS.
+- */
+-
+-
+-/**
+-\mainpage LDNS Documentation
+-
+-\section introduction Introduction
+-
+-The goal of ldns is to simplify DNS programming, it supports recent RFCs
+-like the DNSSEC documents, and allow developers to easily create software
+-conforming to current RFCs, and experimental software for current Internet
+-drafts. A secondary benefit of using ldns is speed, because ldns is written
+-in C, and although it is not optimized for performance, it should be a lot
+-faster than Perl.
+-
+-The first main tool to use ldns is Drill, from which part of the library was
+-derived. From version 1.0.0 on, drill is included in the ldns release
+-and will not be distributed separately anymore. The library also includes some
+-other examples and tools to show how it can be used. These can be found in the
+-examples/ directory in the tarball.
+-
+-ldns depends on OpenSSL for it's cryptographic functions.
+-Feature list
+-
+-  - Transparent IPv4 and IPv6 support (overridable if necessary),
+-  - TSIG support,
+-  - DNSSEC support; signing and verification,
+-  - small size,
+-  - online documentation as well as manual pages.
+-
+-If you want to send us patches please use the code from git.
+-
+-\section using_ldns Using ldns
+-
+-Almost all interaction between an application and ldns goes through the ldns
+-data structures (\ref ldns_rr, \ref ldns_pkt, etc.). These are input or
+-output to the functions of ldns. For example, \ref ldns_zone_new_frm_fp
+-reads a zone from a \c FILE pointer, and returns an \ref ldns_zone
+-structure.
+-
+-
+-Let's use Drill as an example. Drill is a tool much like dig, whose most
+-basic function is to send 1 query to a nameserver and print the response.
+-
+-To be able to do this, drill uses the resolver module of ldns, which acts as
+-a stub resolver. The resolver module uses the net module to actually send
+-the query that drill requested. It then uses the wire2host module to
+-translate the response and place it in ldns' internal structures. These are
+-passed back to drill, which then uses the host2str module to print the
+-response in presentation format.
+-
+-\section gettingstarted Getting Started
+-
+-See the \ref design page for a very high level description of the design
+-choices made for ldns. 
+-
+-For an overview of the functions and types ldns provides, you can check out
+-the \ref ldns ldns header file descriptions.
+-
+-If you want to see some libdns action, you can read our tutorials:
+-  - \ref tutorial1_mx
+-  - \ref tutorial2_zone
+-  - \ref tutorial3_signzone
+-
+-Or you can just use the menu above to browse through the API docs.
+-
+-<div style="visibility:hidden;">
+-\image html LogoInGradientBar2-y100.png
+-</div>
+-*/
+-
+-/**
+- * \file ldns.h
+- *
+- * Including this file will include all ldns files, and define some lookup tables.
+- */
+-
+-#ifndef LDNS_DNS_H
+-#define LDNS_DNS_H
+-
+-#include <stdio.h>
+-#include <stdlib.h>
+-
+-#include <ldns/util.h>
+-#include <ldns/buffer.h>
+-#include <ldns/common.h>
+-#include <ldns/dane.h>
+-#include <ldns/dname.h>
+-#include <ldns/dnssec.h>
+-#include <ldns/dnssec_verify.h>
+-#include <ldns/dnssec_sign.h>
+-#include <ldns/duration.h>
+-#include <ldns/error.h>
+-#include <ldns/higher.h>
+-#include <ldns/host2str.h>
+-#include <ldns/host2wire.h>
+-#include <ldns/net.h>
+-#include <ldns/packet.h>
+-#include <ldns/rdata.h>
+-#include <ldns/resolver.h>
+-#include <ldns/rr.h>
+-#include <ldns/str2host.h>
+-#include <ldns/tsig.h>
+-#include <ldns/update.h>
+-#include <ldns/wire2host.h>
+-#include <ldns/rr_functions.h>
+-#include <ldns/keys.h>
+-#include <ldns/parse.h>
+-#include <ldns/zone.h>
+-#include <ldns/dnssec_zone.h>
+-#include <ldns/radix.h>
+-#include <ldns/rbtree.h>
+-#include <ldns/sha1.h>
+-#include <ldns/sha2.h>
+-
+-#ifdef __cplusplus
+-extern "C" {
+-#endif
+-
+-#define LDNS_IP4ADDRLEN      (32/8)
+-#define LDNS_IP6ADDRLEN      (128/8)
+-#define LDNS_PORT	53
+-#define LDNS_ROOT_LABEL_STR     "."
+-#define LDNS_DEFAULT_TTL	3600
+-
+-/* lookup tables for standard DNS stuff  */
+-
+-/** Taken from RFC 2538, section 2.1.  */
+-extern ldns_lookup_table ldns_certificate_types[];
+-/** Taken from RFC 2535, section 7.  */
+-extern ldns_lookup_table ldns_algorithms[];
+-/** Taken from RFC 2538.  */
+-extern ldns_lookup_table ldns_cert_algorithms[];
+-/** rr types  */
+-extern ldns_lookup_table ldns_rr_classes[];
+-/** Response codes */
+-extern ldns_lookup_table ldns_rcodes[];
+-/** Operation codes */
+-extern ldns_lookup_table ldns_opcodes[];
+-/** EDNS flags */
+-extern ldns_lookup_table ldns_edns_flags[];
+-
+-#ifdef __cplusplus
+-}
+-#endif
+-
+-#endif /* LDNS_DNS_H */
+diff --git a/include/ldns/net.h b/include/ldns/net.h
+deleted file mode 100644
+index 692a9fb..0000000
+--- a/include/ldns/net.h
++++ /dev/null
+@@ -1,207 +0,0 @@
+-/*
+- * net.h
+- *
+- * DNS Resolver definitions
+- *
+- * a Net::DNS like library for C
+- *
+- * (c) NLnet Labs, 2005-2006
+- *
+- * See the file LICENSE for the license
+- */
+-
+-#ifndef LDNS_NET_H
+-#define LDNS_NET_H
+-
+-#include <ldns/ldns.h>
+-#include <sys/socket.h>
+-
+-#ifdef __cplusplus
+-extern "C" {
+-#endif
+-
+-#define LDNS_DEFAULT_TIMEOUT_SEC 5
+-#define LDNS_DEFAULT_TIMEOUT_USEC 0
+-
+-/**
+- * \file
+- *
+- * Contains functions to send and receive packets over a network.
+- */
+-
+-/**
+- * Sends a buffer to an ip using udp and return the respons as a ldns_pkt
+- * \param[in] qbin the ldns_buffer to be send
+- * \param[in] to the ip addr to send to
+- * \param[in] tolen length of the ip addr
+- * \param[in] timeout the timeout value for the network
+- * \param[out] answersize size of the packet
+- * \param[out] result packet with the answer
+- * \return status
+- */
+-ldns_status ldns_udp_send(uint8_t **result, ldns_buffer *qbin, const struct sockaddr_storage *to, socklen_t tolen, struct timeval timeout, size_t *answersize);
+-
+-/**
+- * Send an udp query and don't wait for an answer but return
+- * the socket
+- * \param[in] qbin the ldns_buffer to be send
+- * \param[in] to the ip addr to send to
+- * \param[in] tolen length of the ip addr
+- * \param[in] timeout *unused*, was the timeout value for the network
+- * \return the socket used
+- */
+-int ldns_udp_bgsend(ldns_buffer *qbin, const struct sockaddr_storage *to, socklen_t tolen, struct timeval timeout);
+-
+-/**
+- * Send an tcp query and don't wait for an answer but return
+- * the socket
+- * \param[in] qbin the ldns_buffer to be send
+- * \param[in] to the ip addr to send to
+- * \param[in] tolen length of the ip addr
+- * \param[in] timeout the timeout value for the connect attempt
+- * \return the socket used
+- */
+-int ldns_tcp_bgsend(ldns_buffer *qbin, const struct sockaddr_storage *to, socklen_t tolen, struct timeval timeout);
+-
+-/**
+- * Sends a buffer to an ip using tcp and return the respons as a ldns_pkt
+- * \param[in] qbin the ldns_buffer to be send
+- * \param[in] qbin the ldns_buffer to be send
+- * \param[in] to the ip addr to send to
+- * \param[in] tolen length of the ip addr
+- * \param[in] timeout the timeout value for the network
+- * \param[out] answersize size of the packet
+- * \param[out] result packet with the answer
+- * \return status
+- */
+-ldns_status ldns_tcp_send(uint8_t **result, ldns_buffer *qbin, const struct sockaddr_storage *to, socklen_t tolen, struct timeval timeout, size_t *answersize);
+-
+-/**
+- * Sends ptk to the nameserver at the resolver object. Returns the data
+- * as a ldns_pkt
+- * 
+- * \param[out] pkt packet received from the nameserver
+- * \param[in] r the resolver to use 
+- * \param[in] query_pkt the query to send
+- * \return status
+- */
+-ldns_status ldns_send(ldns_pkt **pkt, ldns_resolver *r, const ldns_pkt *query_pkt);
+-
+-/**
+- * Sends and ldns_buffer (presumably containing a packet to the nameserver at the resolver object. Returns the data
+- * as a ldns_pkt
+- * 
+- * \param[out] pkt packet received from the nameserver
+- * \param[in] r the resolver to use 
+- * \param[in] qb the buffer to send
+- * \param[in] tsig_mac the tsig MAC to authenticate the response with (NULL to do no TSIG authentication)
+- * \return status
+- */
+-ldns_status ldns_send_buffer(ldns_pkt **pkt, ldns_resolver *r, ldns_buffer *qb, ldns_rdf *tsig_mac);
+-
+-/**
+- * Create a tcp socket to the specified address
+- * \param[in] to ip and family
+- * \param[in] tolen length of to
+- * \param[in] timeout timeout for the connect attempt
+- * \return a socket descriptor
+- */
+-int ldns_tcp_connect(const struct sockaddr_storage *to, socklen_t tolen, struct timeval timeout);
+-
+-/**
+- * Create a udp socket to the specified address
+- * \param[in] to ip and family
+- * \param[in] timeout *unused*, was timeout for the socket
+- * \return a socket descriptor
+- */
+-int ldns_udp_connect(const struct sockaddr_storage *to, struct timeval timeout);
+-
+-/**
+- * send a query via tcp to a server. Don't want for the answer
+- *
+- * \param[in] qbin the buffer to send
+- * \param[in] sockfd the socket to use
+- * \param[in] to which ip to send it
+- * \param[in] tolen socketlen
+- * \return number of bytes sent
+- */
+-ssize_t ldns_tcp_send_query(ldns_buffer *qbin, int sockfd, const struct sockaddr_storage *to, socklen_t tolen);
+-
+-/**
+- * send a query via udp to a server. Don;t want for the answer
+- *
+- * \param[in] qbin the buffer to send
+- * \param[in] sockfd the socket to use
+- * \param[in] to which ip to send it
+- * \param[in] tolen socketlen
+- * \return number of bytes sent
+- */
+-ssize_t ldns_udp_send_query(ldns_buffer *qbin, int sockfd, const struct sockaddr_storage *to, socklen_t tolen);
+-
+-/**
+- * Gives back a raw packet from the wire and reads the header data from the given
+- * socket. Allocates the data (of size size) itself, so don't forget to free
+- *
+- * \param[in] sockfd the socket to read from
+- * \param[out] size the number of bytes that are read
+- * \param[in] timeout the time allowed between packets.
+- * \return the data read
+- */
+-uint8_t *ldns_tcp_read_wire_timeout(int sockfd, size_t *size, struct timeval timeout);
+-
+-/**
+- * This routine may block. Use ldns_tcp_read_wire_timeout, it checks timeouts.
+- * Gives back a raw packet from the wire and reads the header data from the given
+- * socket. Allocates the data (of size size) itself, so don't forget to free
+- *
+- * \param[in] sockfd the socket to read from
+- * \param[out] size the number of bytes that are read
+- * \return the data read
+- */
+-uint8_t *ldns_tcp_read_wire(int sockfd, size_t *size);
+-
+-/**
+- * Gives back a raw packet from the wire and reads the header data from the given
+- * socket. Allocates the data (of size size) itself, so don't forget to free
+- *
+- * \param[in] sockfd the socket to read from
+- * \param[in] fr the address of the client (if applicable)
+- * \param[in] *frlen the lenght of the client's addr (if applicable)
+- * \param[out] size the number of bytes that are read
+- * \return the data read
+- */
+-uint8_t *ldns_udp_read_wire(int sockfd, size_t *size, struct sockaddr_storage *fr, socklen_t *frlen);
+-
+-/**
+- * returns the native sockaddr representation from the rdf.
+- * \param[in] rd the ldns_rdf to operate on
+- * \param[in] port what port to use. 0 means; use default (53)
+- * \param[out] size what is the size of the sockaddr_storage
+- * \return struct sockaddr* the address in the format so other
+- * functions can use it (sendto)
+- */
+-struct sockaddr_storage * ldns_rdf2native_sockaddr_storage(const ldns_rdf *rd, uint16_t port, size_t *size);
+-
+-/**
+- * returns an rdf with the sockaddr info. works for ip4 and ip6
+- * \param[in] sock the struct sockaddr_storage to convert
+- * \param[in] port what port was used. When NULL this is not set
+- * \return ldns_rdf* wth the address
+- */
+-ldns_rdf * ldns_sockaddr_storage2rdf(struct sockaddr_storage *sock, uint16_t *port);
+-
+-/**
+- * Prepares the resolver for an axfr query
+- * The query is sent and the answers can be read with ldns_axfr_next
+- * \param[in] resolver the resolver to use
+- * \param[in] domain the domain to exfr
+- * \param[in] c the class to use
+- * \return ldns_status the status of the transfer
+- */
+-ldns_status ldns_axfr_start(ldns_resolver *resolver, ldns_rdf *domain, ldns_rr_class c);
+-
+-#ifdef __cplusplus
+-}
+-#endif
+-
+-#endif  /* LDNS_NET_H */
+diff --git a/include/ldns/packet.h b/include/ldns/packet.h
+deleted file mode 100644
+index e66aa34..0000000
+--- a/include/ldns/packet.h
++++ /dev/null
+@@ -1,891 +0,0 @@
+-/*
+- * packet.h
+- *
+- * DNS packet definitions
+- *
+- * a Net::DNS like library for C
+- *
+- * (c) NLnet Labs, 2005-2006
+- *
+- * See the file LICENSE for the license
+- */
+-
+-/**
+- * \file
+- *
+- * Contains the definition of ldns_pkt and its parts, as well
+- * as functions to manipulate those.
+- */
+-
+-
+-#ifndef LDNS_PACKET_H
+-#define LDNS_PACKET_H
+-
+-#define LDNS_MAX_PACKETLEN         65535
+-
+-/* allow flags to be given to mk_query */
+-#define LDNS_QR		1       /* QueRy - query flag */
+-#define LDNS_AA		2       /* Authoritative Answer - server flag */
+-#define LDNS_TC		4       /* TrunCated - server flag */
+-#define LDNS_RD		8       /* Recursion Desired - query flag */
+-#define LDNS_CD		16      /* Checking Disabled - query flag */
+-#define LDNS_RA		32      /* Recursion Available - server flag */
+-#define LDNS_AD		64      /* Authenticated Data - server flag */
+-
+-#include <ldns/error.h>
+-#include <ldns/common.h>
+-#include <ldns/rr.h>
+-#include <sys/time.h>
+-
+-#ifdef __cplusplus
+-extern "C" {
+-#endif
+-
+-/* opcodes for pkt's */
+-enum ldns_enum_pkt_opcode {
+-	LDNS_PACKET_QUERY = 0,
+-	LDNS_PACKET_IQUERY = 1,
+-	LDNS_PACKET_STATUS = 2, /* there is no 3?? DNS is weird */
+-	LDNS_PACKET_NOTIFY = 4,
+-	LDNS_PACKET_UPDATE = 5
+-};
+-typedef enum ldns_enum_pkt_opcode ldns_pkt_opcode;
+-
+-/* rcodes for pkts */
+-enum ldns_enum_pkt_rcode {
+-	LDNS_RCODE_NOERROR = 0,
+-	LDNS_RCODE_FORMERR = 1,
+-	LDNS_RCODE_SERVFAIL = 2,
+-	LDNS_RCODE_NXDOMAIN = 3,
+-	LDNS_RCODE_NOTIMPL = 4,
+-	LDNS_RCODE_REFUSED = 5,
+-	LDNS_RCODE_YXDOMAIN = 6,
+-	LDNS_RCODE_YXRRSET = 7,
+-	LDNS_RCODE_NXRRSET = 8,
+-	LDNS_RCODE_NOTAUTH = 9,
+-	LDNS_RCODE_NOTZONE = 10
+-};
+-typedef enum ldns_enum_pkt_rcode ldns_pkt_rcode;
+-
+-/**
+- *  Header of a dns packet
+- *
+- * Contains the information about the packet itself, as specified in RFC1035
+-<pre>
+-4.1.1. Header section format
+-
+-The header contains the following fields:
+-
+-                                    1  1  1  1  1  1
+-      0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
+-    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+-    |                      ID                       |
+-    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+-    |QR|   Opcode  |AA|TC|RD|RA|   Z    |   RCODE   |
+-    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+-    |                    QDCOUNT                    |
+-    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+-    |                    ANCOUNT                    |
+-    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+-    |                    NSCOUNT                    |
+-    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+-    |                    ARCOUNT                    |
+-    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+-
+-where:
+-
+-ID              A 16 bit identifier assigned by the program that
+-                generates any kind of query.  This identifier is copied
+-                the corresponding reply and can be used by the requester
+-                to match up replies to outstanding queries.
+-
+-QR              A one bit field that specifies whether this message is a
+-                query (0), or a response (1).
+-
+-OPCODE          A four bit field that specifies kind of query in this
+-                message.  This value is set by the originator of a query
+-                and copied into the response.  The values are:
+-
+-                0               a standard query (QUERY)
+-
+-                1               an inverse query (IQUERY)
+-
+-                2               a server status request (STATUS)
+-
+-                3-15            reserved for future use
+-
+-AA              Authoritative Answer - this bit is valid in responses,
+-                and specifies that the responding name server is an
+-                authority for the domain name in question section.
+-
+-                Note that the contents of the answer section may have
+-                multiple owner names because of aliases.  The AA bit
+-
+-                corresponds to the name which matches the query name, or
+-                the first owner name in the answer section.
+-
+-TC              TrunCation - specifies that this message was truncated
+-                due to length greater than that permitted on the
+-                transmission channel.
+-
+-RD              Recursion Desired - this bit may be set in a query and
+-                is copied into the response.  If RD is set, it directs
+-                the name server to pursue the query recursively.
+-                Recursive query support is optional.
+-
+-RA              Recursion Available - this be is set or cleared in a
+-                response, and denotes whether recursive query support is
+-                available in the name server.
+-
+-Z               Reserved for future use.  Must be zero in all queries
+-                and responses.
+-
+-RCODE           Response code - this 4 bit field is set as part of
+-                responses.  The values have the following
+-                interpretation:
+-
+-                0               No error condition
+-
+-                1               Format error - The name server was
+-                                unable to interpret the query.
+-
+-                2               Server failure - The name server was
+-                                unable to process this query due to a
+-                                problem with the name server.
+-
+-                3               Name Error - Meaningful only for
+-                                responses from an authoritative name
+-                                server, this code signifies that the
+-                                domain name referenced in the query does
+-                                not exist.
+-
+-                4               Not Implemented - The name server does
+-                                not support the requested kind of query.
+-
+-                5               Refused - The name server refuses to
+-                                perform the specified operation for
+-                                policy reasons.  For example, a name
+-                                server may not wish to provide the
+-                                information to the particular requester,
+-                                or a name server may not wish to perform
+-                                a particular operation (e.g., zone
+-
+-                                transfer) for particular data.
+-
+-                6-15            Reserved for future use.
+-
+-QDCOUNT         an unsigned 16 bit integer specifying the number of
+-                entries in the question section.
+-
+-ANCOUNT         an unsigned 16 bit integer specifying the number of
+-                resource records in the answer section.
+-
+-NSCOUNT         an unsigned 16 bit integer specifying the number of name
+-                server resource records in the authority records
+-                section.
+-
+-ARCOUNT         an unsigned 16 bit integer specifying the number of
+-                resource records in the additional records section.
+-
+-</pre>
+- */
+-struct ldns_struct_hdr
+-{
+-	/**  Id of a packet */
+-	uint16_t _id;
+-	/**  Query bit (0=query, 1=answer) */
+-	bool _qr;
+-	/**  Authoritative answer */
+-	bool _aa;
+-	/**  Packet truncated */
+-	bool _tc;
+-	/**  Recursion desired */
+-	bool _rd;
+-	/**  Checking disabled */
+-	bool _cd;
+-	/**  Recursion available */
+-	bool _ra;
+-	/**  Authentic data */
+-	bool _ad;
+-	/**  Query type */
+-	ldns_pkt_opcode _opcode;	 /* XXX 8 bits? */
+-	/**  Response code */
+-	uint8_t _rcode;
+-	/**  question sec */
+-	uint16_t _qdcount;
+-	/**  answer sec */
+-	uint16_t _ancount;
+-	/**  auth sec */
+-	uint16_t _nscount;
+-	/**  add sec */
+-	uint16_t _arcount;
+-};
+-typedef struct ldns_struct_hdr ldns_hdr;
+-
+-/**
+- * DNS packet
+- *
+- * This structure contains a complete DNS packet (either a query or an answer)
+- *
+- * It is the complete representation of what you actually send to a
+- * nameserver, and what it sends back (assuming you are the client here).
+- */
+-struct ldns_struct_pkt
+-{
+-	/** Header section */
+-	ldns_hdr *_header;
+-	/* extra items needed in a packet */
+-	/** The size of the wire format of the packet in octets */
+-	ldns_rdf *_answerfrom;
+-        /** Timestamp of the time the packet was sent or created */
+-	struct timeval timestamp;
+-	/** The duration of the query this packet is an answer to */
+-	uint32_t _querytime;
+-	/** The size of the wire format of the packet in octets */
+-	size_t _size;
+-	/** Optional tsig rr */
+-	ldns_rr *_tsig_rr;
+-	/** EDNS0 available buffer size, see RFC2671 */
+-	uint16_t _edns_udp_size;
+-	/** EDNS0 Extended rcode */
+-	uint8_t _edns_extended_rcode;
+-	/** EDNS Version */
+-	uint8_t _edns_version;
+-        /* OPT pseudo-RR presence flag */
+-        uint8_t _edns_present;
+-	/** Reserved EDNS data bits */
+-	uint16_t _edns_z;
+-	/** Arbitrary EDNS rdata */
+-	ldns_rdf *_edns_data;
+-	/**  Question section */
+-	ldns_rr_list	*_question;
+-	/**  Answer section */
+-	ldns_rr_list	*_answer;
+-	/**  Authority section */
+-	ldns_rr_list	*_authority;
+-	/**  Additional section */
+-	ldns_rr_list	*_additional;
+-};
+-typedef struct ldns_struct_pkt ldns_pkt;
+-
+-/**
+- * The sections of a packet
+- */
+-enum ldns_enum_pkt_section {
+-	LDNS_SECTION_QUESTION = 0,
+-	LDNS_SECTION_ANSWER = 1,
+-	LDNS_SECTION_AUTHORITY = 2,
+-	LDNS_SECTION_ADDITIONAL = 3,
+-	/** bogus section, if not interested */
+-	LDNS_SECTION_ANY = 4,
+-	/** used to get all non-question rrs from a packet */
+-	LDNS_SECTION_ANY_NOQUESTION = 5
+-};
+-typedef enum ldns_enum_pkt_section ldns_pkt_section;	
+-
+-/**
+- * The different types of packets
+- */
+-enum ldns_enum_pkt_type {
+-	LDNS_PACKET_QUESTION,
+-	LDNS_PACKET_REFERRAL,
+-	LDNS_PACKET_ANSWER,
+-	LDNS_PACKET_NXDOMAIN,
+-	LDNS_PACKET_NODATA,
+-	LDNS_PACKET_UNKNOWN
+-};
+-typedef enum ldns_enum_pkt_type ldns_pkt_type;
+-
+-/* prototypes */
+-
+-/* read */
+-
+-/**
+- * Read the packet id
+- * \param[in] p the packet
+- * \return the packet id
+- */
+-uint16_t ldns_pkt_id(const ldns_pkt *p);
+-/**
+- * Read the packet's qr bit
+- * \param[in] p the packet
+- * \return value of the bit
+- */
+-bool ldns_pkt_qr(const ldns_pkt *p);
+-/**
+- * Read the packet's aa bit
+- * \param[in] p the packet
+- * \return value of the bit
+- */
+-bool ldns_pkt_aa(const ldns_pkt *p);
+-/**
+- * Read the packet's tc bit
+- * \param[in] p the packet
+- * \return value of the bit
+- */
+-bool ldns_pkt_tc(const ldns_pkt *p);
+-/**
+- * Read the packet's rd bit
+- * \param[in] p the packet
+- * \return value of the bit
+- */
+-bool ldns_pkt_rd(const ldns_pkt *p);
+-/**
+- * Read the packet's cd bit
+- * \param[in] p the packet
+- * \return value of the bit
+- */
+-bool ldns_pkt_cd(const ldns_pkt *p);
+-/**
+- * Read the packet's ra bit
+- * \param[in] p the packet
+- * \return value of the bit
+- */
+-bool ldns_pkt_ra(const ldns_pkt *p);
+-/**
+- * Read the packet's ad bit
+- * \param[in] p the packet
+- * \return value of the bit
+- */
+-bool ldns_pkt_ad(const ldns_pkt *p);
+-/**
+- * Read the packet's code
+- * \param[in] p the packet
+- * \return the opcode
+- */
+-ldns_pkt_opcode ldns_pkt_get_opcode(const ldns_pkt *p);
+-/**
+- * Return the packet's respons code
+- * \param[in] p the packet
+- * \return the respons code
+- */
+-ldns_pkt_rcode ldns_pkt_get_rcode(const ldns_pkt *p);
+-/**
+- * Return the packet's qd count 
+- * \param[in] p the packet
+- * \return the qd count
+- */
+-uint16_t ldns_pkt_qdcount(const ldns_pkt *p);
+-/**
+- * Return the packet's an count
+- * \param[in] p the packet
+- * \return the an count
+- */
+-uint16_t ldns_pkt_ancount(const ldns_pkt *p);
+-/**
+- * Return the packet's ns count
+- * \param[in] p the packet
+- * \return the ns count
+- */
+-uint16_t ldns_pkt_nscount(const ldns_pkt *p);
+-/**
+- * Return the packet's ar count
+- * \param[in] p the packet
+- * \return the ar count
+- */
+-uint16_t ldns_pkt_arcount(const ldns_pkt *p);
+-
+-/** 
+- * Return the packet's answerfrom
+- * \param[in] p packet
+- * \return the name of the server
+- */
+-ldns_rdf *ldns_pkt_answerfrom(const ldns_pkt *p);
+-
+-/**
+- * Return the packet's timestamp
+- * \param[in] p the packet
+- * \return the timestamp
+- */
+-struct timeval ldns_pkt_timestamp(const ldns_pkt *p);
+-/**
+- * Return the packet's querytime
+- * \param[in] p the packet
+- * \return the querytime
+- */
+-uint32_t ldns_pkt_querytime(const ldns_pkt *p);
+-
+-/**
+- * Return the packet's size in bytes
+- * \param[in] p the packet
+- * \return the size
+- */
+-size_t ldns_pkt_size(const ldns_pkt *p);
+-
+-/**
+- * Return the number of RRs in the given section.
+- * Returns the sum of all RRs when LDNS_SECTION_ANY is given.
+- * Returns the sum of all non-question RRs when LDNS_SECTION_ANY_NOQUESTION
+- * is given.
+- * \param[in] p the packet
+- * \param[in] s the section
+- * \return the number of RRs in the given section
+- */
+-uint16_t ldns_pkt_section_count(const ldns_pkt *p, ldns_pkt_section s);
+-
+-/**
+- * Return the packet's tsig pseudo rr's
+- * \param[in] p the packet
+- * \return the tsig rr
+- */
+-ldns_rr *ldns_pkt_tsig(const ldns_pkt *p);
+-
+-/**
+- * Return the packet's question section
+- * \param[in] p the packet
+- * \return the section
+- */
+-ldns_rr_list *ldns_pkt_question(const ldns_pkt *p);
+-/**
+- * Return the packet's answer section
+- * \param[in] p the packet
+- * \return the section
+- */
+-ldns_rr_list *ldns_pkt_answer(const ldns_pkt *p);
+-/**
+- * Return the packet's authority section
+- * \param[in] p the packet
+- * \return the section
+- */
+-ldns_rr_list *ldns_pkt_authority(const ldns_pkt *p);
+-/**
+- * Return the packet's additional section
+- * \param[in] p the packet
+- * \return the section
+- */
+-ldns_rr_list *ldns_pkt_additional(const ldns_pkt *p);
+-/**
+- * Return the packet's question, answer, authority and additional sections
+- * concatenated, in a new rr_list clone.
+- * \param[in] p the packet
+- * \return the rrs
+- */
+-ldns_rr_list *ldns_pkt_all(const ldns_pkt *p);
+-/**
+- * Return the packet's answer, authority and additional sections concatenated, 
+- * in a new rr_list clone.  Like ldns_pkt_all but without the questions.
+- * \param[in] p the packet
+- * \return the rrs except the question rrs
+- */
+-ldns_rr_list *ldns_pkt_all_noquestion(const ldns_pkt *p);
+-
+-/**
+- * return all the rr_list's in the packet. Clone the lists, instead
+- * of returning pointers. 
+- * \param[in] p the packet to look in
+- * \param[in] s what section(s) to return
+- * \return ldns_rr_list with the rr's or NULL if none were found
+- */
+-ldns_rr_list *ldns_pkt_get_section_clone(const ldns_pkt *p, ldns_pkt_section s);
+-
+-/**
+- * return all the rr with a specific name from a packet. Optionally
+- * specify from which section in the packet
+- * \param[in] p the packet
+- * \param[in] r the name
+- * \param[in] s the packet's section
+- * \return a list with the rr's or NULL if none were found
+- */
+-ldns_rr_list *ldns_pkt_rr_list_by_name(ldns_pkt *p, ldns_rdf *r, ldns_pkt_section s);
+-/**
+- * return all the rr with a specific type from a packet. Optionally
+- * specify from which section in the packet
+- * \param[in] p the packet
+- * \param[in] t the type
+- * \param[in] s the packet's section
+- * \return a list with the rr's or NULL if none were found
+- */
+-ldns_rr_list *ldns_pkt_rr_list_by_type(const ldns_pkt *p, ldns_rr_type t, ldns_pkt_section s);
+-/**
+- * return all the rr with a specific type and type from a packet. Optionally
+- * specify from which section in the packet
+- * \param[in] packet the packet
+- * \param[in] ownername the name
+- * \param[in] type the type
+- * \param[in] sec the packet's section
+- * \return a list with the rr's or NULL if none were found
+- */
+-ldns_rr_list *ldns_pkt_rr_list_by_name_and_type(const ldns_pkt *packet, const ldns_rdf *ownername, ldns_rr_type type, ldns_pkt_section sec);
+-
+-
+-/**
+- * check to see if an rr exist in the packet
+- * \param[in] pkt the packet to examine
+- * \param[in] sec in which section to look
+- * \param[in] rr the rr to look for
+- */
+-bool ldns_pkt_rr(ldns_pkt *pkt, ldns_pkt_section sec, ldns_rr *rr);
+-
+-
+-/**
+- * sets the flags in a packet.
+- * \param[in] pkt the packet to operate on
+- * \param[in] flags ORed values: LDNS_QR| LDNS_AR for instance
+- * \return true on success otherwise false
+- */
+-bool ldns_pkt_set_flags(ldns_pkt *pkt, uint16_t flags);
+-
+-/**
+- * Set the packet's id
+- * \param[in] p the packet
+- * \param[in] id the id to set
+- */
+-void ldns_pkt_set_id(ldns_pkt *p, uint16_t id);
+-/**
+- * Set the packet's id to a random value
+- * \param[in] p the packet
+- */
+-void ldns_pkt_set_random_id(ldns_pkt *p);
+-/**
+- * Set the packet's qr bit
+- * \param[in] p the packet
+- * \param[in] b the value to set (boolean)
+- */
+-void ldns_pkt_set_qr(ldns_pkt *p, bool b);
+-/**
+- * Set the packet's aa bit
+- * \param[in] p the packet
+- * \param[in] b the value to set (boolean)
+- */
+-void ldns_pkt_set_aa(ldns_pkt *p, bool b);
+-/**
+- * Set the packet's tc bit
+- * \param[in] p the packet
+- * \param[in] b the value to set (boolean)
+- */
+-void ldns_pkt_set_tc(ldns_pkt *p, bool b);
+-/**
+- * Set the packet's rd bit
+- * \param[in] p the packet
+- * \param[in] b the value to set (boolean)
+- */
+-void ldns_pkt_set_rd(ldns_pkt *p, bool b);
+-/**
+- * Set the packet's cd bit
+- * \param[in] p the packet
+- * \param[in] b the value to set (boolean)
+- */
+-void ldns_pkt_set_cd(ldns_pkt *p, bool b);
+-/**
+- * Set the packet's ra bit
+- * \param[in] p the packet
+- * \param[in] b the value to set (boolean)
+- */
+-void ldns_pkt_set_ra(ldns_pkt *p, bool b);
+-/**
+- * Set the packet's ad bit
+- * \param[in] p the packet
+- * \param[in] b the value to set (boolean)
+- */
+-void ldns_pkt_set_ad(ldns_pkt *p, bool b);
+-
+-/**
+- * Set the packet's opcode
+- * \param[in] p the packet
+- * \param[in] c the opcode
+- */
+-void ldns_pkt_set_opcode(ldns_pkt *p, ldns_pkt_opcode c);
+-/**
+- * Set the packet's respons code
+- * \param[in] p the packet
+- * \param[in] c the rcode
+- */
+-void ldns_pkt_set_rcode(ldns_pkt *p, uint8_t c);
+-/**
+- * Set the packet's qd count
+- * \param[in] p the packet
+- * \param[in] c the count
+- */
+-void ldns_pkt_set_qdcount(ldns_pkt *p, uint16_t c);
+-/**
+- * Set the packet's an count
+- * \param[in] p the packet
+- * \param[in] c the count
+- */
+-void ldns_pkt_set_ancount(ldns_pkt *p, uint16_t c);
+-/**
+- * Set the packet's ns count
+- * \param[in] p the packet
+- * \param[in] c the count
+- */
+-void ldns_pkt_set_nscount(ldns_pkt *p, uint16_t c);
+-/**
+- * Set the packet's arcount
+- * \param[in] p the packet
+- * \param[in] c the count
+- */
+-void ldns_pkt_set_arcount(ldns_pkt *p, uint16_t c);
+-/**
+- * Set the packet's answering server
+- * \param[in] p the packet
+- * \param[in] r the address
+- */
+-void ldns_pkt_set_answerfrom(ldns_pkt *p, ldns_rdf *r);
+-/**
+- * Set the packet's query time
+- * \param[in] p the packet
+- * \param[in] t the querytime in msec
+- */
+-void ldns_pkt_set_querytime(ldns_pkt *p, uint32_t t);
+-/**
+- * Set the packet's size
+- * \param[in] p the packet
+- * \param[in] s the size
+- */
+-void ldns_pkt_set_size(ldns_pkt *p, size_t s);
+-
+-/**
+- * Set the packet's timestamp
+- * \param[in] p the packet
+- * \param[in] timeval the timestamp
+- */
+-void ldns_pkt_set_timestamp(ldns_pkt *p, struct timeval timeval);
+-/**
+- * Set a packet's section count to x
+- * \param[in] p the packet
+- * \param[in] s the section
+- * \param[in] x the section count
+- */
+-void ldns_pkt_set_section_count(ldns_pkt *p, ldns_pkt_section s, uint16_t x);
+-/**
+- * Set the packet's tsig rr
+- * \param[in] p the packet
+- * \param[in] t the tsig rr
+- */
+-void ldns_pkt_set_tsig(ldns_pkt *p, ldns_rr *t);
+-
+-/**
+- * looks inside the packet to determine
+- * what kind of packet it is, AUTH, NXDOMAIN, REFERRAL, etc.
+- * \param[in] p the packet to examine
+- * \return the type of packet
+- */
+-ldns_pkt_type ldns_pkt_reply_type(ldns_pkt *p);
+-
+-/**
+- * return the packet's edns udp size
+- * \param[in] packet the packet
+- * \return the size
+- */
+-uint16_t ldns_pkt_edns_udp_size(const ldns_pkt *packet);
+-/**
+- * return the packet's edns extended rcode
+- * \param[in] packet the packet
+- * \return the rcode
+- */
+-uint8_t ldns_pkt_edns_extended_rcode(const ldns_pkt *packet);
+-/**
+- * return the packet's edns version
+- * \param[in] packet the packet
+- * \return the version
+- */
+-uint8_t ldns_pkt_edns_version(const ldns_pkt *packet);
+-/**
+- * return the packet's edns z value
+- * \param[in] packet the packet
+- * \return the z value
+- */
+-uint16_t ldns_pkt_edns_z(const ldns_pkt *packet);
+-/**
+- * return the packet's edns data
+- * \param[in] packet the packet
+- * \return the data
+- */
+-ldns_rdf *ldns_pkt_edns_data(const ldns_pkt *packet);
+-
+-/**
+- * return the packet's edns do bit
+- * \param[in] packet the packet
+- * \return the bit's value
+- */
+-bool ldns_pkt_edns_do(const ldns_pkt *packet);
+-/**
+- * Set the packet's edns do bit
+- * \param[in] packet the packet
+- * \param[in] value the bit's new value
+- */
+-void ldns_pkt_set_edns_do(ldns_pkt *packet, bool value);
+-
+-/**
+- * returns true if this packet needs and EDNS rr to be sent.
+- * At the moment the only reason is an expected packet
+- * size larger than 512 bytes, but for instance dnssec would
+- * be a good reason too.
+- *
+- * \param[in] packet the packet to check
+- * \return true if packet needs edns rr
+- */
+-bool ldns_pkt_edns(const ldns_pkt *packet);
+-
+-/**
+- * Set the packet's edns udp size
+- * \param[in] packet the packet
+- * \param[in] s the size
+- */
+-void ldns_pkt_set_edns_udp_size(ldns_pkt *packet, uint16_t s);
+-/**
+- * Set the packet's edns extended rcode
+- * \param[in] packet the packet
+- * \param[in] c the code
+- */
+-void ldns_pkt_set_edns_extended_rcode(ldns_pkt *packet, uint8_t c);
+-/**
+- * Set the packet's edns version
+- * \param[in] packet the packet
+- * \param[in] v the version
+- */
+-void ldns_pkt_set_edns_version(ldns_pkt *packet, uint8_t v);
+-/**
+- * Set the packet's edns z value
+- * \param[in] packet the packet
+- * \param[in] z the value
+- */
+-void ldns_pkt_set_edns_z(ldns_pkt *packet, uint16_t z);
+-/**
+- * Set the packet's edns data
+- * \param[in] packet the packet
+- * \param[in] data the data
+- */
+-void ldns_pkt_set_edns_data(ldns_pkt *packet, ldns_rdf *data);
+-
+-/**
+- * allocates and initializes a ldns_pkt structure.
+- * \return pointer to the new packet
+- */
+-ldns_pkt *ldns_pkt_new(void);
+-
+-/**
+- * frees the packet structure and all data that it contains.
+- * \param[in] packet The packet structure to free
+- * \return void
+- */
+-void ldns_pkt_free(ldns_pkt *packet);
+-
+-/**
+- * creates a query packet for the given name, type, class.
+- * \param[out] p the packet to be returned
+- * \param[in] rr_name the name to query for (as string)
+- * \param[in] rr_type the type to query for
+- * \param[in] rr_class the class to query for
+- * \param[in] flags packet flags
+- * \return LDNS_STATUS_OK or a ldns_status mesg with the error
+- */
+-ldns_status ldns_pkt_query_new_frm_str(ldns_pkt **p, const char *rr_name, ldns_rr_type rr_type, ldns_rr_class rr_class , uint16_t flags);
+-
+-/**
+- * creates an IXFR request packet for the given name, class.
+- * adds the SOA record to the authority section.
+- * \param[out] p the packet to be returned
+- * \param[in] rr_name the name to query for (as string)
+- * \param[in] rr_class the class to query for
+- * \param[in] flags packet flags
+- * \param[in] soa soa record to be added to the authority section
+- * \return LDNS_STATUS_OK or a ldns_status mesg with the error
+- */
+-ldns_status ldns_pkt_ixfr_request_new_frm_str(ldns_pkt **p, const char *rr_name, ldns_rr_class rr_class, uint16_t flags, ldns_rr* soa);
+-
+-/**
+- * creates a packet with a query in it for the given name, type and class.
+- * \param[in] rr_name the name to query for
+- * \param[in] rr_type the type to query for
+- * \param[in] rr_class the class to query for
+- * \param[in] flags packet flags
+- * \return ldns_pkt* a pointer to the new pkt
+- */
+-ldns_pkt *ldns_pkt_query_new(ldns_rdf *rr_name, ldns_rr_type rr_type, ldns_rr_class rr_class, uint16_t flags);
+-
+-/**
+- * creates an IXFR request packet for the given name, type and class.
+- * adds the SOA record to the authority section.
+- * \param[in] rr_name the name to query for
+- * \param[in] rr_class the class to query for
+- * \param[in] flags packet flags
+- * \param[in] soa soa record to be added to the authority section
+- * \return ldns_pkt* a pointer to the new pkt
+- */
+-ldns_pkt *ldns_pkt_ixfr_request_new(ldns_rdf *rr_name, ldns_rr_class rr_class, uint16_t flags, ldns_rr* soa);
+-
+-/**
+- * clones the given packet, creating a fully allocated copy
+- *
+- * \param[in] pkt the packet to clone
+- * \return ldns_pkt* pointer to the new packet
+- */
+-ldns_pkt *ldns_pkt_clone(const ldns_pkt *pkt);
+-
+-/**
+- * directly set the additional section
+- * \param[in] p packet to operate on
+- * \param[in] rr rrlist to set
+- */
+-void ldns_pkt_set_additional(ldns_pkt *p, ldns_rr_list *rr);
+-
+-/**
+- * directly set the answer section
+- * \param[in] p packet to operate on
+- * \param[in] rr rrlist to set
+- */
+-void ldns_pkt_set_answer(ldns_pkt *p, ldns_rr_list *rr);
+-
+-/**
+- * directly set the question section
+- * \param[in] p packet to operate on
+- * \param[in] rr rrlist to set
+- */
+-void ldns_pkt_set_question(ldns_pkt *p, ldns_rr_list *rr);
+-
+-/**
+- * directly set the auhority section
+- * \param[in] p packet to operate on
+- * \param[in] rr rrlist to set
+- */
+-void ldns_pkt_set_authority(ldns_pkt *p, ldns_rr_list *rr);
+-
+-/**
+- * push an rr on a packet
+- * \param[in] packet packet to operate on
+- * \param[in] section where to put it
+- * \param[in] rr rr to push
+- * \return a boolean which is true when the rr was added
+- */
+-bool ldns_pkt_push_rr(ldns_pkt *packet, ldns_pkt_section section, ldns_rr *rr);
+-
+-/**
+- * push an rr on a packet, provided the RR is not there.
+- * \param[in] pkt packet to operate on
+- * \param[in] sec where to put it
+- * \param[in] rr rr to push
+- * \return a boolean which is true when the rr was added
+- */
+-bool ldns_pkt_safe_push_rr(ldns_pkt *pkt, ldns_pkt_section sec, ldns_rr *rr);
+-
+-/**
+- * push a rr_list on a packet
+- * \param[in] packet packet to operate on
+- * \param[in] section where to put it
+- * \param[in] list the rr_list to push
+- * \return a boolean which is true when the rr was added
+- */
+-bool ldns_pkt_push_rr_list(ldns_pkt *packet, ldns_pkt_section section, ldns_rr_list *list);
+-
+-/**
+- * push an rr_list to a packet, provided the RRs are not already there.
+- * \param[in] pkt packet to operate on
+- * \param[in] sec where to put it
+- * \param[in] list the rr_list to push
+- * \return a boolean which is true when the rr was added
+- */
+-bool ldns_pkt_safe_push_rr_list(ldns_pkt *pkt, ldns_pkt_section sec, ldns_rr_list *list);
+-
+-/**
+- * check if a packet is empty
+- * \param[in] p packet
+- * \return true: empty, false: not empty
+- */
+-bool ldns_pkt_empty(ldns_pkt *p);
+-
+-#ifdef __cplusplus
+-}
+-#endif
+-
+-#endif  /* LDNS_PACKET_H */
+diff --git a/include/ldns/parse.h b/include/ldns/parse.h
+deleted file mode 100644
+index 0e9034c..0000000
+--- a/include/ldns/parse.h
++++ /dev/null
+@@ -1,167 +0,0 @@
+-/*
+- * parse.h 
+- *
+- * a Net::DNS like library for C
+- * LibDNS Team @ NLnet Labs
+- * (c) NLnet Labs, 2005-2006
+- * See the file LICENSE for the license
+- */
+-
+-#ifndef LDNS_PARSE_H
+-#define LDNS_PARSE_H
+-
+-#include <ldns/common.h>
+-#include <ldns/buffer.h>
+-
+-#ifdef __cplusplus
+-extern "C" {
+-#endif
+-
+-#define LDNS_PARSE_SKIP_SPACE		"\f\n\r\v"
+-#define LDNS_PARSE_NORMAL		" \f\n\r\t\v"
+-#define LDNS_PARSE_NO_NL		" \t"
+-#define LDNS_MAX_LINELEN		10230
+-#define LDNS_MAX_KEYWORDLEN		32
+-
+-
+-/**
+- * \file
+- *
+- * Contains some low-level parsing functions, mostly used in the _frm_str
+- * family of functions.
+- */
+- 
+-/**
+- * different type of directives in zone files
+- * We now deal with $TTL, $ORIGIN and $INCLUDE.
+- * The latter is not implemented in ldns (yet)
+- */
+-enum ldns_enum_directive
+-{
+-	LDNS_DIR_TTL,
+-	LDNS_DIR_ORIGIN,
+-	LDNS_DIR_INCLUDE
+-};
+-typedef enum ldns_enum_directive ldns_directive;
+-
+-/** 
+- * returns a token/char from the stream F.
+- * This function deals with ( and ) in the stream,
+- * and ignores them when encountered
+- * \param[in] *f the file to read from
+- * \param[out] *token the read token is put here
+- * \param[in] *delim chars at which the parsing should stop
+- * \param[in] *limit how much to read. If 0 the builtin maximum is used
+- * \return 0 on error of EOF of the stream F.  Otherwise return the length of what is read
+- */
+-ssize_t ldns_fget_token(FILE *f, char *token, const char *delim, size_t limit);
+-
+-/** 
+- * returns a token/char from the stream F.
+- * This function deals with ( and ) in the stream,
+- * and ignores when it finds them.
+- * \param[in] *f the file to read from
+- * \param[out] *token the token is put here
+- * \param[in] *delim chars at which the parsing should stop
+- * \param[in] *limit how much to read. If 0 use builtin maximum
+- * \param[in] line_nr pointer to an integer containing the current line number (for debugging purposes)
+- * \return 0 on error of EOF of F otherwise return the length of what is read
+- */
+-ssize_t ldns_fget_token_l(FILE *f, char *token, const char *delim, size_t limit, int *line_nr);
+-
+-/**
+- * returns a token/char from the buffer b.
+- * This function deals with ( and ) in the buffer,
+- * and ignores when it finds them.
+- * \param[in] *b the buffer to read from
+- * \param[out] *token the token is put here
+- * \param[in] *delim chars at which the parsing should stop
+- * \param[in] *limit how much to read. If 0 the builtin maximum is used
+- * \returns 0 on error of EOF of b. Otherwise return the length of what is read
+- */
+-ssize_t ldns_bget_token(ldns_buffer *b, char *token, const char *delim, size_t limit);
+-
+-/*
+- * searches for keyword and delim in a file. Gives everything back
+- * after the keyword + k_del until we hit d_del
+- * \param[in] f file pointer to read from
+- * \param[in] keyword keyword to look for
+- * \param[in] k_del keyword delimeter 
+- * \param[out] data the data found 
+- * \param[in] d_del the data delimeter
+- * \param[in] data_limit maximum size the the data buffer
+- * \return the number of character read
+- */
+-ssize_t ldns_fget_keyword_data(FILE *f, const char *keyword, const char *k_del, char *data, const char *d_del, size_t data_limit);
+-
+-/*
+- * searches for keyword and delim. Gives everything back
+- * after the keyword + k_del until we hit d_del
+- * \param[in] f file pointer to read from
+- * \param[in] keyword keyword to look for
+- * \param[in] k_del keyword delimeter 
+- * \param[out] data the data found 
+- * \param[in] d_del the data delimeter
+- * \param[in] data_limit maximum size the the data buffer
+- * \param[in] line_nr pointer to an integer containing the current line number (for
+-debugging purposes)
+- * \return the number of character read
+- */
+-ssize_t ldns_fget_keyword_data_l(FILE *f, const char *keyword, const char *k_del, char *data, const char *d_del, size_t data_limit, int *line_nr);
+-
+-/*
+- * searches for keyword and delim in a buffer. Gives everything back
+- * after the keyword + k_del until we hit d_del
+- * \param[in] b buffer pointer to read from
+- * \param[in] keyword keyword to look for
+- * \param[in] k_del keyword delimeter 
+- * \param[out] data the data found 
+- * \param[in] d_del the data delimeter
+- * \param[in] data_limit maximum size the the data buffer
+- * \return the number of character read
+- */
+-ssize_t ldns_bget_keyword_data(ldns_buffer *b, const char *keyword, const char *k_del, char *data, const char *d_del, size_t data_limit);
+-
+-/**
+- * returns the next character from a buffer. Advances the position pointer with 1.
+- * When end of buffer is reached returns EOF. This is the buffer's equivalent
+- * for getc().
+- * \param[in] *buffer buffer to read from
+- * \return EOF on failure otherwise return the character
+- */
+-int ldns_bgetc(ldns_buffer *buffer);
+-
+-/**
+- * skips all of the characters in the given string in the buffer, moving
+- * the position to the first character that is not in *s.
+- * \param[in] *buffer buffer to use
+- * \param[in] *s characters to skip
+- * \return void
+- */
+-void ldns_bskipcs(ldns_buffer *buffer, const char *s);
+-
+-/**
+- * skips all of the characters in the given string in the fp, moving
+- * the position to the first character that is not in *s.
+- * \param[in] *fp file to use
+- * \param[in] *s characters to skip
+- * \return void
+- */
+-void ldns_fskipcs(FILE *fp, const char *s);
+-
+-
+-/**
+- * skips all of the characters in the given string in the fp, moving
+- * the position to the first character that is not in *s.
+- * \param[in] *fp file to use
+- * \param[in] *s characters to skip
+- * \param[in] line_nr pointer to an integer containing the current line number (for debugging purposes)
+- * \return void
+- */
+-void ldns_fskipcs_l(FILE *fp, const char *s, int *line_nr);
+-
+-#ifdef __cplusplus
+-}
+-#endif
+-
+-#endif /* LDNS_PARSE_H */
+diff --git a/include/ldns/radix.h b/include/ldns/radix.h
+deleted file mode 100644
+index 1885959..0000000
+--- a/include/ldns/radix.h
++++ /dev/null
+@@ -1,240 +0,0 @@
+-/*
+- * radix.h -- generic radix tree
+- *
+- * Copyright (c) 2012, NLnet Labs. All rights reserved.
+- *
+- * This software is open source.
+- *
+- * Redistribution and use in source and binary forms, with or without
+- * modification, are permitted provided that the following conditions
+- * are met:
+- *
+- * Redistributions of source code must retain the above copyright notice,
+- * this list of conditions and the following disclaimer.
+- *
+- * Redistributions in binary form must reproduce the above copyright notice,
+- * this list of conditions and the following disclaimer in the documentation
+- * and/or other materials provided with the distribution.
+- *
+- * Neither the name of the NLNET LABS nor the names of its contributors may
+- * be used to endorse or promote products derived from this software without
+- * specific prior written permission.
+- *
+- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+- * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+- * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+- *
+- */
+-
+-/**
+- * \file
+- * Radix tree. Implementation taken from NSD 4, adjusted for use in ldns.
+- *
+- */
+-
+-#ifndef LDNS_RADIX_H_
+-#define	LDNS_RADIX_H_
+-
+-#include <ldns/error.h>
+-
+-#ifdef __cplusplus
+-extern "C" {
+-#endif
+-
+-typedef uint16_t radix_strlen_t;
+-typedef struct ldns_radix_array_t ldns_radix_array_t;
+-typedef struct ldns_radix_node_t ldns_radix_node_t;
+-typedef struct ldns_radix_t ldns_radix_t;
+-
+-/** Radix node select edge array */
+-struct ldns_radix_array_t {
+-	/** Additional string after the selection byte for this edge. */
+-	uint8_t* str;
+-	/** Length of additional string for this edge. */
+-	radix_strlen_t len;
+-	/** Node that deals with byte+str. */
+-	ldns_radix_node_t* edge;
+-};
+-
+-/** A node in a radix tree */
+-struct ldns_radix_node_t {
+-	/** Key corresponding to this node. */
+-	uint8_t* key;
+-	/** Key length corresponding to this node. */
+-	radix_strlen_t klen;
+-	/** Data corresponding to this node. */
+-	void* data;
+-	/** Parent node. */
+-	ldns_radix_node_t* parent;
+-	/** Index in the the parent node select edge array. */
+-	uint8_t parent_index;
+-	/** Length of the array. */
+-	uint16_t len;
+-	/** Offset of the array. */
+-	uint16_t offset;
+-	/** Capacity of the array. */
+-	uint16_t capacity;
+-	/** Select edge array. */
+-	ldns_radix_array_t* array;
+-};
+-
+-/** An entire radix tree */
+-struct ldns_radix_t {
+-	/** Root. */
+-	ldns_radix_node_t* root;
+-	/** Number of nodes in tree. */
+-	size_t count;
+-};
+-
+-/**
+- * Create a new radix tree.
+- * @return: new radix tree.
+- *
+- */
+-ldns_radix_t* ldns_radix_create(void);
+-
+-/**
+- * Initialize radix tree.
+- * @param tree: uninitialized radix tree.
+- *
+- */
+-void ldns_radix_init(ldns_radix_t* tree);
+-
+-/**
+- * Free the radix tree.
+- * @param tree: radix tree.
+- *
+- */
+-void ldns_radix_free(ldns_radix_t* tree);
+-
+-/**
+- * Insert data into the tree.
+- * @param tree: tree to insert to.
+- * @param key:  key.
+- * @param len:  length of key.
+- * @param data: data.
+- * @return: status.
+- *
+- */
+-ldns_status ldns_radix_insert(ldns_radix_t* tree, uint8_t* key,
+-	radix_strlen_t len, void* data);
+-
+-/**
+- * Delete data from the tree.
+- * @param tree: tree to insert to.
+- * @param key:  key.
+- * @param len:  length of key.
+- * @return: unlinked data or NULL if not present.
+- *
+- */
+-void* ldns_radix_delete(ldns_radix_t* tree, uint8_t* key, radix_strlen_t len);
+-
+-/**
+- * Search data in the tree.
+- * @param tree: tree to insert to.
+- * @param key:  key.
+- * @param len:  length of key.
+- * @return: the radix node or NULL if not found.
+- *
+- */
+-ldns_radix_node_t* ldns_radix_search(ldns_radix_t* tree, uint8_t* key,
+-	radix_strlen_t len);
+-
+-/**
+- * Search data in the tree, and if not found, find the closest smaller
+- * element in the tree.
+- * @param tree: tree to insert to.
+- * @param key:  key.
+- * @param len:  length of key.
+- * @param result: the radix node with the exact or closest match. NULL if
+- *                the key is smaller than the smallest key in the tree.
+- * @return 1 if exact match, 0 otherwise.
+- *
+- */
+-int ldns_radix_find_less_equal(ldns_radix_t* tree, uint8_t* key,
+-	radix_strlen_t len, ldns_radix_node_t** result);
+-
+-/**
+- * Get the first element in the tree.
+- * @param tree: tree.
+- * @return: the radix node with the first element.
+- *
+- */
+-ldns_radix_node_t* ldns_radix_first(ldns_radix_t* tree);
+-
+-/**
+- * Get the last element in the tree.
+- * @param tree: tree.
+- * @return: the radix node with the last element.
+- *
+- */
+-ldns_radix_node_t* ldns_radix_last(ldns_radix_t* tree);
+-
+-/**
+- * Next element.
+- * @param node: node.
+- * @return: node with next element.
+- *
+- */
+-ldns_radix_node_t* ldns_radix_next(ldns_radix_node_t* node);
+-
+-/**
+- * Previous element.
+- * @param node: node.
+- * @return: node with previous element.
+- *
+- */
+-ldns_radix_node_t* ldns_radix_prev(ldns_radix_node_t* node);
+-
+-/**
+- * Split radix tree intwo.
+- * @param tree1: one tree.
+- * @param num: number of elements to split off.
+- * @param tree2: another tree.
+- * @return: status.
+- *
+- */
+-ldns_status ldns_radix_split(ldns_radix_t* tree1, size_t num,
+-	ldns_radix_t** tree2);
+-
+-/**
+- * Join two radix trees.
+- * @param tree1: one tree.
+- * @param tree2: another tree.
+- * @return: status.
+- *
+- */
+-ldns_status ldns_radix_join(ldns_radix_t* tree1, ldns_radix_t* tree2);
+-
+-/**
+- * Call function for all nodes in the tree, such that leaf nodes are
+- * called before parent nodes.
+- * @param node: start node.
+- * @param func: function.
+- * @param arg: user argument.
+- *
+- */
+-void ldns_radix_traverse_postorder(ldns_radix_node_t* node,
+-        void (*func)(ldns_radix_node_t*, void*), void* arg);
+-
+-/**
+- * Print radix tree (for debugging purposes).
+- * @param fd: file descriptor.
+- * @param tree: tree.
+- *
+- */
+-void ldns_radix_printf(FILE* fd, ldns_radix_t* tree);
+-
+-#ifdef __cplusplus
+-}
+-#endif
+-
+-#endif /* LDNS_RADIX_H_ */
+diff --git a/include/ldns/rbtree.h b/include/ldns/rbtree.h
+deleted file mode 100644
+index c891934..0000000
+--- a/include/ldns/rbtree.h
++++ /dev/null
+@@ -1,230 +0,0 @@
+-/*
+- * rbtree.h -- generic red-black tree
+- *
+- * Copyright (c) 2001-2008, NLnet Labs. All rights reserved.
+- *
+- * This software is open source.
+- *
+- * Redistribution and use in source and binary forms, with or without
+- * modification, are permitted provided that the following conditions
+- * are met:
+- *
+- * Redistributions of source code must retain the above copyright notice,
+- * this list of conditions and the following disclaimer.
+- *
+- * Redistributions in binary form must reproduce the above copyright notice,
+- * this list of conditions and the following disclaimer in the documentation
+- * and/or other materials provided with the distribution.
+- *
+- * Neither the name of the NLNET LABS nor the names of its contributors may
+- * be used to endorse or promote products derived from this software without
+- * specific prior written permission.
+- *
+- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+- * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+- * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+- *
+- */
+-
+-/**
+- * \file
+- * Red black tree. Implementation taken from NSD 3.0.5, adjusted for use
+- * in unbound (memory allocation, logging and so on).
+- */
+-
+-#ifndef LDNS_RBTREE_H_
+-#define	LDNS_RBTREE_H_
+-
+-#ifdef __cplusplus
+-extern "C" {
+-#endif
+-
+-/**
+- * This structure must be the first member of the data structure in
+- * the rbtree.  This allows easy casting between an rbnode_t and the
+- * user data (poor man's inheritance).
+- * Or you can use the data pointer member to get to your data item.
+- */
+-typedef struct ldns_rbnode_t ldns_rbnode_t;
+-/**
+- * The rbnode_t struct definition.
+- */
+-struct ldns_rbnode_t {
+-	/** parent in rbtree, RBTREE_NULL for root */
+-	ldns_rbnode_t   *parent;
+-	/** left node (smaller items) */
+-	ldns_rbnode_t   *left;
+-	/** right node (larger items) */
+-	ldns_rbnode_t   *right;
+-	/** pointer to sorting key */
+-	const void *key;
+-	/** pointer to data */
+-	const void *data;
+-	/** colour of this node */
+-	uint8_t	    color;
+-};
+-
+-/** The nullpointer, points to empty node */
+-#define	LDNS_RBTREE_NULL &ldns_rbtree_null_node
+-/** the global empty node */
+-extern	ldns_rbnode_t	ldns_rbtree_null_node;
+-
+-/** An entire red black tree */
+-typedef struct ldns_rbtree_t ldns_rbtree_t;
+-/** definition for tree struct */
+-struct ldns_rbtree_t {
+-	/** The root of the red-black tree */
+-	ldns_rbnode_t    *root;
+-
+-	/** The number of the nodes in the tree */
+-	size_t       count;
+-
+-	/**
+-	 * Key compare function. <0,0,>0 like strcmp.
+-	 * Return 0 on two NULL ptrs.
+-	 */
+-	int (*cmp) (const void *, const void *);
+-};
+-
+-/**
+- * Create new tree (malloced) with given key compare function.
+- * @param cmpf: compare function (like strcmp) takes pointers to two keys.
+- * @return: new tree, empty.
+- */
+-ldns_rbtree_t *ldns_rbtree_create(int (*cmpf)(const void *, const void *));
+-
+-/**
+- * Free the complete tree (but not its keys)
+- * @param rbtree The tree to free
+- */
+-void ldns_rbtree_free(ldns_rbtree_t *rbtree);
+-
+-/**
+- * Init a new tree (malloced by caller) with given key compare function.
+- * @param rbtree: uninitialised memory for new tree, returned empty.
+- * @param cmpf: compare function (like strcmp) takes pointers to two keys.
+- */
+-void ldns_rbtree_init(ldns_rbtree_t *rbtree, int (*cmpf)(const void *, const void *));
+-
+-/**
+- * Insert data into the tree.
+- * @param rbtree: tree to insert to.
+- * @param data: element to insert.
+- * @return: data ptr or NULL if key already present.
+- */
+-ldns_rbnode_t *ldns_rbtree_insert(ldns_rbtree_t *rbtree, ldns_rbnode_t *data);
+-
+-/**
+- * Insert data into the tree (reversed arguments, for use as callback)
+- * \param[in] data element to insert
+- * \param[out] rbtree tree to insert in to
+- * \return data ptr or NULL if key is already present
+- */
+-void ldns_rbtree_insert_vref(ldns_rbnode_t *data, void *rbtree);
+-
+-/**
+- * Delete element from tree.
+- * @param rbtree: tree to delete from.
+- * @param key: key of item to delete.
+- * @return: node that is now unlinked from the tree. User to delete it.
+- * returns 0 if node not present
+- */
+-ldns_rbnode_t *ldns_rbtree_delete(ldns_rbtree_t *rbtree, const void *key);
+-
+-/**
+- * Find key in tree. Returns NULL if not found.
+- * @param rbtree: tree to find in.
+- * @param key: key that must match.
+- * @return: node that fits or NULL.
+- */
+-ldns_rbnode_t *ldns_rbtree_search(ldns_rbtree_t *rbtree, const void *key);
+-
+-/**
+- * Find, but match does not have to be exact.
+- * @param rbtree: tree to find in.
+- * @param key: key to find position of.
+- * @param result: set to the exact node if present, otherwise to element that
+- *   precedes the position of key in the tree. NULL if no smaller element.
+- * @return: true if exact match in result. Else result points to <= element,
+- * or NULL if key is smaller than the smallest key.
+- */
+-int ldns_rbtree_find_less_equal(ldns_rbtree_t *rbtree, const void *key,
+-	ldns_rbnode_t **result);
+-
+-/**
+- * Returns first (smallest) node in the tree
+- * @param rbtree: tree
+- * @return: smallest element or NULL if tree empty.
+- */
+-ldns_rbnode_t *ldns_rbtree_first(ldns_rbtree_t *rbtree);
+-
+-/**
+- * Returns last (largest) node in the tree
+- * @param rbtree: tree
+- * @return: largest element or NULL if tree empty.
+- */
+-ldns_rbnode_t *ldns_rbtree_last(ldns_rbtree_t *rbtree);
+-
+-/**
+- * Returns next larger node in the tree
+- * @param rbtree: tree
+- * @return: next larger element or NULL if no larger in tree.
+- */
+-ldns_rbnode_t *ldns_rbtree_next(ldns_rbnode_t *rbtree);
+-
+-/**
+- * Returns previous smaller node in the tree
+- * @param rbtree: tree
+- * @return: previous smaller element or NULL if no previous in tree.
+- */
+-ldns_rbnode_t *ldns_rbtree_previous(ldns_rbnode_t *rbtree);
+-
+-/**
+- * split off 'elements' number of elements from the start
+- * of the name tree and return a new tree containing those
+- * elements
+- */
+-ldns_rbtree_t *ldns_rbtree_split(ldns_rbtree_t *tree, size_t elements);
+-
+-/**
+- * add all node from the second tree to the first (removing them from the
+- * second), and fix up nsec(3)s if present
+- */
+-void ldns_rbtree_join(ldns_rbtree_t *tree1, ldns_rbtree_t *tree2);
+-
+-/**
+- * Call with node=variable of struct* with rbnode_t as first element.
+- * with type is the type of a pointer to that struct.
+- */
+-#define LDNS_RBTREE_FOR(node, type, rbtree) \
+-	for(node=(type)ldns_rbtree_first(rbtree); \
+-		(ldns_rbnode_t*)node != LDNS_RBTREE_NULL; \
+-		node = (type)ldns_rbtree_next((ldns_rbnode_t*)node))
+-
+-/**
+- * Call function for all elements in the redblack tree, such that
+- * leaf elements are called before parent elements. So that all
+- * elements can be safely free()d.
+- * Note that your function must not remove the nodes from the tree.
+- * Since that may trigger rebalances of the rbtree.
+- * @param tree: the tree
+- * @param func: function called with element and user arg.
+- * 	The function must not alter the rbtree.
+- * @param arg: user argument.
+- */
+-void ldns_traverse_postorder(ldns_rbtree_t* tree,
+-	void (*func)(ldns_rbnode_t*, void*), void* arg);
+-
+-#ifdef __cplusplus
+-}
+-#endif
+-
+-#endif /* UTIL_RBTREE_H_ */
+diff --git a/include/ldns/rdata.h b/include/ldns/rdata.h
+deleted file mode 100644
+index 22665b1..0000000
+--- a/include/ldns/rdata.h
++++ /dev/null
+@@ -1,451 +0,0 @@
+-/*
+- * rdata.h
+- *
+- * rdata definitions
+- *
+- * a Net::DNS like library for C
+- *
+- * (c) NLnet Labs, 2005-2006
+- *
+- * See the file LICENSE for the license
+- */
+-
+-
+-/**
+- * \file
+- *
+- * Defines ldns_rdf and functions to manipulate those.
+- */
+-
+-
+-#ifndef LDNS_RDATA_H
+-#define LDNS_RDATA_H
+-
+-#include <ldns/common.h>
+-#include <ldns/error.h>
+-
+-#ifdef __cplusplus
+-extern "C" {
+-#endif
+-
+-#define LDNS_MAX_RDFLEN	65535
+-
+-#define LDNS_RDF_SIZE_BYTE              1
+-#define LDNS_RDF_SIZE_WORD              2
+-#define LDNS_RDF_SIZE_DOUBLEWORD        4
+-#define LDNS_RDF_SIZE_6BYTES            6
+-#define LDNS_RDF_SIZE_8BYTES            8
+-#define LDNS_RDF_SIZE_16BYTES           16
+-
+-#define LDNS_NSEC3_VARS_OPTOUT_MASK 0x01
+-
+-/**
+- * The different types of RDATA fields.
+- */
+-enum ldns_enum_rdf_type
+-{
+-	/** none */
+-	LDNS_RDF_TYPE_NONE,
+-	/** domain name */
+-	LDNS_RDF_TYPE_DNAME,
+-	/** 8 bits */
+-	LDNS_RDF_TYPE_INT8,
+-	/** 16 bits */
+-	LDNS_RDF_TYPE_INT16,
+-	/** 32 bits */
+-	LDNS_RDF_TYPE_INT32,
+-	/** A record */
+-	LDNS_RDF_TYPE_A,
+-	/** AAAA record */
+-	LDNS_RDF_TYPE_AAAA,
+-	/** txt string */
+-	LDNS_RDF_TYPE_STR,
+-	/** apl data */
+-	LDNS_RDF_TYPE_APL,
+-	/** b32 string */
+-	LDNS_RDF_TYPE_B32_EXT,
+-	/** b64 string */
+-	LDNS_RDF_TYPE_B64,
+-	/** hex string */
+-	LDNS_RDF_TYPE_HEX,
+-	/** nsec type codes */
+-	LDNS_RDF_TYPE_NSEC,
+-	/** a RR type */
+-	LDNS_RDF_TYPE_TYPE,
+-	/** a class */
+-	LDNS_RDF_TYPE_CLASS,
+-	/** certificate algorithm */
+-	LDNS_RDF_TYPE_CERT_ALG,
+-	/** a key algorithm */
+-	LDNS_RDF_TYPE_ALG,
+-	/** unknown types */
+-	LDNS_RDF_TYPE_UNKNOWN,
+-	/** time (32 bits) */
+-	LDNS_RDF_TYPE_TIME,
+-	/** period */
+-	LDNS_RDF_TYPE_PERIOD,
+-	/** tsig time 48 bits */
+-	LDNS_RDF_TYPE_TSIGTIME,
+-	/** Represents the Public Key Algorithm, HIT and Public Key fields
+-	    for the HIP RR types.  A HIP specific rdf type is used because of
+-	    the unusual layout in wireformat (see RFC 5205 Section 5) */
+-	LDNS_RDF_TYPE_HIP,
+-	/** variable length any type rdata where the length
+-	    is specified by the first 2 bytes */
+-	LDNS_RDF_TYPE_INT16_DATA,
+-	/** protocol and port bitmaps */
+-	LDNS_RDF_TYPE_SERVICE,
+-	/** location data */
+-	LDNS_RDF_TYPE_LOC,
+-	/** well known services */
+-	LDNS_RDF_TYPE_WKS,
+-	/** NSAP */
+-	LDNS_RDF_TYPE_NSAP,
+-	/** ATMA */
+-	LDNS_RDF_TYPE_ATMA,
+-	/** IPSECKEY */
+-	LDNS_RDF_TYPE_IPSECKEY,
+-	/** nsec3 hash salt */
+-	LDNS_RDF_TYPE_NSEC3_SALT,
+-	/** nsec3 base32 string (with length byte on wire */
+-	LDNS_RDF_TYPE_NSEC3_NEXT_OWNER,
+-
+-	/** 4 shorts represented as 4 * 16 bit hex numbers
+-	 *  separated by colons. For NID and L64.
+-	 */
+-	LDNS_RDF_TYPE_ILNP64,
+-
+-	/** 6 * 8 bit hex numbers separated by dashes. For EUI48. */
+-	LDNS_RDF_TYPE_EUI48,
+-	/** 8 * 8 bit hex numbers separated by dashes. For EUI64. */
+-	LDNS_RDF_TYPE_EUI64,
+-
+-	/** A non-zero sequence of US-ASCII letters and numbers in lower case.
+-	 *  For CAA.
+-	 */
+-	LDNS_RDF_TYPE_TAG,
+-
+-	/** A <character-string> encoding of the value field as specified 
+-	 * [RFC1035], Section 5.1., encoded as remaining rdata.
+-	 * For CAA.
+-	 */
+-	LDNS_RDF_TYPE_LONG_STR,
+-
+-	/** Since RFC7218 TLSA records can be given with mnemonics,
+-	 * hence these rdata field types.  But as with DNSKEYs, the output
+-	 * is always numeric.
+-	 */
+-	LDNS_RDF_TYPE_CERTIFICATE_USAGE,
+-	LDNS_RDF_TYPE_SELECTOR,
+-	LDNS_RDF_TYPE_MATCHING_TYPE,
+-
+-	/* Aliases */
+-	LDNS_RDF_TYPE_BITMAP = LDNS_RDF_TYPE_NSEC
+-};
+-typedef enum ldns_enum_rdf_type ldns_rdf_type;
+-
+-/**
+- * algorithms used in CERT rrs
+- */
+-enum ldns_enum_cert_algorithm
+-{
+-        LDNS_CERT_PKIX		= 1,
+-        LDNS_CERT_SPKI		= 2,
+-        LDNS_CERT_PGP		= 3,
+-        LDNS_CERT_IPKIX         = 4,
+-        LDNS_CERT_ISPKI         = 5,
+-        LDNS_CERT_IPGP          = 6,
+-        LDNS_CERT_ACPKIX        = 7,
+-        LDNS_CERT_IACPKIX       = 8,
+-        LDNS_CERT_URI		= 253,
+-        LDNS_CERT_OID		= 254
+-};
+-typedef enum ldns_enum_cert_algorithm ldns_cert_algorithm;
+-
+-
+-
+-/**
+- * Resource record data field.
+- *
+- * The data is a network ordered array of bytes, which size is specified by
+- * the (16-bit) size field. To correctly parse it, use the type
+- * specified in the (16-bit) type field with a value from \ref ldns_rdf_type.
+- */
+-struct ldns_struct_rdf
+-{
+-	/** The size of the data (in octets) */
+-	size_t _size;
+-	/** The type of the data */
+-	ldns_rdf_type _type;
+-	/** Pointer to the data (raw octets) */
+-	void  *_data;
+-};
+-typedef struct ldns_struct_rdf ldns_rdf;
+-
+-/* prototypes */
+-
+-/* write access functions */
+-
+-/**
+- * sets the size of the rdf.
+- * \param[in] *rd the rdf to operate on
+- * \param[in] size the new size
+- * \return void
+- */
+-void ldns_rdf_set_size(ldns_rdf *rd, size_t size);
+-
+-/**
+- * sets the size of the rdf.
+- * \param[in] *rd the rdf to operate on
+- * \param[in] type the new type
+- * \return void
+- */
+-void ldns_rdf_set_type(ldns_rdf *rd, ldns_rdf_type type);
+-
+-/**
+- * sets the size of the rdf.
+- * \param[in] *rd the rdf to operate on
+- * \param[in] *data pointer to the new data
+- * \return void
+- */
+-void ldns_rdf_set_data(ldns_rdf *rd, void *data);
+-
+-/* read access */
+-
+-/**
+- * returns the size of the rdf.
+- * \param[in] *rd the rdf to read from
+- * \return uint16_t with the size
+- */
+-size_t ldns_rdf_size(const ldns_rdf *rd);
+-
+-/**
+- * returns the type of the rdf. We need to insert _get_
+- * here to prevent conflict the the rdf_type TYPE.
+- * \param[in] *rd the rdf to read from
+- * \return ldns_rdf_type with the type
+- */
+-ldns_rdf_type ldns_rdf_get_type(const ldns_rdf *rd);
+-
+-/**
+- * returns the data of the rdf.
+- * \param[in] *rd the rdf to read from
+- *
+- * \return uint8_t* pointer to the rdf's data
+- */
+-uint8_t *ldns_rdf_data(const ldns_rdf *rd);
+-
+-/* creator functions */
+-
+-/**
+- * allocates a new rdf structure and fills it.
+- * This function DOES NOT copy the contents from
+- * the buffer, unlinke ldns_rdf_new_frm_data()
+- * \param[in] type type of the rdf
+- * \param[in] size size of the buffer
+- * \param[in] data pointer to the buffer to be copied
+- * \return the new rdf structure or NULL on failure
+- */
+-ldns_rdf *ldns_rdf_new(ldns_rdf_type type, size_t size, void *data);
+-
+-/**
+- * allocates a new rdf structure and fills it.
+- * This function _does_ copy the contents from
+- * the buffer, unlinke ldns_rdf_new()
+- * \param[in] type type of the rdf
+- * \param[in] size size of the buffer
+- * \param[in] data pointer to the buffer to be copied
+- * \return the new rdf structure or NULL on failure
+- */
+-ldns_rdf *ldns_rdf_new_frm_data(ldns_rdf_type type, size_t size, const void *data);
+-
+-/**
+- * creates a new rdf from a string.
+- * \param[in] type   type to use
+- * \param[in] str string to use
+- * \return ldns_rdf* or NULL in case of an error
+- */
+-ldns_rdf *ldns_rdf_new_frm_str(ldns_rdf_type type, const char *str);
+-
+-/**
+- * creates a new rdf from a file containing a string.
+- * \param[out] r the new rdf
+- * \param[in] type   type to use
+- * \param[in] fp the file pointer  to use
+- * \return LDNS_STATUS_OK or the error
+- */
+-ldns_status ldns_rdf_new_frm_fp(ldns_rdf **r, ldns_rdf_type type, FILE *fp);
+-
+-/**
+- * creates a new rdf from a file containing a string.
+- * \param[out] r the new rdf
+- * \param[in] type   type to use
+- * \param[in] fp the file pointer  to use
+- * \param[in] line_nr pointer to an integer containing the current line number (for debugging purposes)
+- * \return LDNS_STATUS_OK or the error
+- */
+-ldns_status ldns_rdf_new_frm_fp_l(ldns_rdf **r, ldns_rdf_type type, FILE *fp, int *line_nr);
+-
+-/* destroy functions */
+-
+-/**
+- * frees a rdf structure, leaving the
+- * data pointer intact.
+- * \param[in] rd the pointer to be freed
+- * \return void
+- */
+-void ldns_rdf_free(ldns_rdf *rd);
+-
+-/**
+- * frees a rdf structure _and_ frees the
+- * data. rdf should be created with _new_frm_data
+- * \param[in] rd the rdf structure to be freed
+- * \return void
+- */
+-void ldns_rdf_deep_free(ldns_rdf *rd);
+-
+-/* conversion functions */
+-
+-/**
+- * returns the rdf containing the native uint8_t repr.
+- * \param[in] type the ldns_rdf type to use
+- * \param[in] value the uint8_t to use
+- * \return ldns_rdf* with the converted value
+- */
+-ldns_rdf *ldns_native2rdf_int8(ldns_rdf_type type, uint8_t value);
+-
+-/**
+- * returns the rdf containing the native uint16_t representation.
+- * \param[in] type the ldns_rdf type to use
+- * \param[in] value the uint16_t to use
+- * \return ldns_rdf* with the converted value
+- */
+-ldns_rdf *ldns_native2rdf_int16(ldns_rdf_type type, uint16_t value);
+-
+-/**
+- * returns an rdf that contains the given int32 value.
+- *
+- * Because multiple rdf types can contain an int32, the
+- * type must be specified
+- * \param[in] type the ldns_rdf type to use
+- * \param[in] value the uint32_t to use
+- * \return ldns_rdf* with the converted value
+- */
+-ldns_rdf *ldns_native2rdf_int32(ldns_rdf_type type, uint32_t value);
+-
+-/**
+- * returns an int16_data rdf that contains the data in the
+- * given array, preceded by an int16 specifying the length.
+- *
+- * The memory is copied, and an LDNS_RDF_TYPE_INT16DATA is returned
+- * \param[in] size the size of the data
+- * \param[in] *data pointer to the actual data
+- *
+- * \return ldns_rd* the rdf with the data
+- */
+-ldns_rdf *ldns_native2rdf_int16_data(size_t size, uint8_t *data);
+-
+-/**
+- * reverses an rdf, only actually useful for AAAA and A records.
+- * The returned rdf has the type LDNS_RDF_TYPE_DNAME!
+- * \param[in] *rd rdf to be reversed
+- * \return the reversed rdf (a newly created rdf)
+- */
+-ldns_rdf *ldns_rdf_address_reverse(ldns_rdf *rd);
+-
+-/**
+- * returns the native uint8_t representation from the rdf.
+- * \param[in] rd the ldns_rdf to operate on
+- * \return uint8_t the value extracted
+- */
+-uint8_t 	ldns_rdf2native_int8(const ldns_rdf *rd);
+-
+-/**
+- * returns the native uint16_t representation from the rdf.
+- * \param[in] rd the ldns_rdf to operate on
+- * \return uint16_t the value extracted
+- */
+-uint16_t	ldns_rdf2native_int16(const ldns_rdf *rd);
+-
+-/**
+- * returns the native uint32_t representation from the rdf.
+- * \param[in] rd the ldns_rdf to operate on
+- * \return uint32_t the value extracted
+- */
+-uint32_t ldns_rdf2native_int32(const ldns_rdf *rd);
+-
+-/**
+- * returns the native time_t representation from the rdf.
+- * \param[in] rd the ldns_rdf to operate on
+- * \return time_t the value extracted (32 bits currently)
+- */
+-time_t ldns_rdf2native_time_t(const ldns_rdf *rd);
+-
+-/**
+- * converts a ttl value (like 5d2h) to a long.
+- * \param[in] nptr the start of the string
+- * \param[out] endptr points to the last char in case of error
+- * \return the convert duration value
+- */
+-uint32_t ldns_str2period(const char *nptr, const char **endptr);
+-
+-/**
+- * removes \\DDD, \\[space] and other escapes from the input.
+- * See RFC 1035, section 5.1.
+- * \param[in] word what to check
+- * \param[in] length the string
+- * \return ldns_status mesg
+- */
+-ldns_status ldns_octet(char *word, size_t *length);
+-
+-/**
+- * clones a rdf structure. The data is copied.
+- * \param[in] rd rdf to be copied
+- * \return a new rdf structure
+- */
+-ldns_rdf *ldns_rdf_clone(const ldns_rdf *rd);
+-
+-/**
+- * compares two rdf's on their wire formats.
+- * (To order dnames according to rfc4034, use ldns_dname_compare)
+- * \param[in] rd1 the first one
+- * \param[in] rd2 the second one
+- * \return 0 if equal
+- * \return -1 if rd1 comes before rd2
+- * \return +1 if rd2 comes before rd1
+- */
+-int ldns_rdf_compare(const ldns_rdf *rd1, const ldns_rdf *rd2);
+-
+-/**
+- * Gets the algorithm value, the HIT and Public Key data from the rdf with
+- * type LDNS_RDF_TYPE_HIP.
+- * \param[in] rdf the rdf with type LDNS_RDF_TYPE_HIP
+- * \param[out] alg      the algorithm
+- * \param[out] hit_size the size of the HIT data
+- * \param[out] hit      the hit data
+- * \param[out] pk_size  the size of the Public Key data
+- * \param[out] pk       the  Public Key data
+- * \return LDNS_STATUS_OK on success, and the error otherwise
+- */
+-ldns_status ldns_rdf_hip_get_alg_hit_pk(ldns_rdf *rdf, uint8_t* alg,
+-		uint8_t *hit_size, uint8_t** hit,
+-		uint16_t *pk_size, uint8_t** pk);
+-
+-/**
+- * Creates a new LDNS_RDF_TYPE_HIP rdf from given data.
+- * \param[out] rdf      the newly created LDNS_RDF_TYPE_HIP rdf
+- * \param[in]  alg      the algorithm
+- * \param[in]  hit_size the size of the HIT data
+- * \param[in]  hit      the hit data
+- * \param[in]  pk_size  the size of the Public Key data
+- * \param[in]  pk       the  Public Key data
+- * \return LDNS_STATUS_OK on success, and the error otherwise
+- */
+-ldns_status ldns_rdf_hip_new_frm_alg_hit_pk(ldns_rdf** rdf, uint8_t alg,
+-		uint8_t hit_size, uint8_t *hit, uint16_t pk_size, uint8_t *pk);
+-
+-#ifdef __cplusplus
+-}
+-#endif
+-
+-#endif	/* LDNS_RDATA_H */
+diff --git a/include/ldns/resolver.h b/include/ldns/resolver.h
+deleted file mode 100644
+index 228485c..0000000
+--- a/include/ldns/resolver.h
++++ /dev/null
+@@ -1,805 +0,0 @@
+-/*
+- * resolver.h
+- *
+- * DNS Resolver definitions
+- *
+- * a Net::DNS like library for C
+- *
+- * (c) NLnet Labs, 2005-2006
+- *
+- * See the file LICENSE for the license
+- */
+-
+-/**
+- * \file
+- *
+- * Defines the  ldns_resolver structure, a stub resolver that can send queries and parse answers.
+- *
+- */
+-
+-#ifndef LDNS_RESOLVER_H
+-#define LDNS_RESOLVER_H
+-
+-#include <ldns/error.h>
+-#include <ldns/common.h>
+-#include <ldns/rr.h>
+-#include <ldns/tsig.h>
+-#include <ldns/rdata.h>
+-#include <ldns/packet.h>
+-#include <sys/time.h>
+-
+-#ifdef __cplusplus
+-extern "C" {
+-#endif
+-
+-/** Default location of the resolv.conf file */
+-#define LDNS_RESOLV_CONF	"/etc/resolv.conf"
+-/** Default location of the hosts file */
+-#define LDNS_RESOLV_HOSTS	"/etc/hosts"
+-
+-#define LDNS_RESOLV_KEYWORD     -1
+-#define LDNS_RESOLV_DEFDOMAIN	0
+-#define LDNS_RESOLV_NAMESERVER	1
+-#define LDNS_RESOLV_SEARCH	2
+-#define LDNS_RESOLV_SORTLIST	3
+-#define LDNS_RESOLV_OPTIONS	4
+-#define LDNS_RESOLV_ANCHOR	5
+-#define LDNS_RESOLV_KEYWORDS    6
+-
+-#define LDNS_RESOLV_INETANY		0
+-#define LDNS_RESOLV_INET		1
+-#define LDNS_RESOLV_INET6		2
+-
+-#define LDNS_RESOLV_RTT_INF             0       /* infinity */
+-#define LDNS_RESOLV_RTT_MIN             1       /* reachable */
+-
+-/**
+- * DNS stub resolver structure
+- */
+-struct ldns_struct_resolver
+-{
+-	/**  Port to send queries to */
+-	uint16_t _port;
+-
+-	/** Array of nameservers to query (IP addresses or dnames) */
+-	ldns_rdf **_nameservers;
+-	/** Number of nameservers in \c _nameservers */
+-	size_t _nameserver_count; /* how many do we have */
+-
+-	/**  Round trip time; 0 -> infinity. Unit: ms? */
+-	size_t *_rtt;
+-
+-	/**  Whether or not to be recursive */
+-	bool _recursive;
+-
+-	/**  Print debug information */
+-	bool _debug;
+-
+-	/**  Default domain to add to non fully qualified domain names */
+-	ldns_rdf *_domain;
+-
+-	/**  Searchlist array, add the names in this array if a query cannot be found */
+-	ldns_rdf **_searchlist;
+-
+-	/** Number of entries in the searchlist array */
+-	size_t _searchlist_count;
+-
+-	/**  Number of times to retry before giving up */
+-	uint8_t _retry;
+-	/**  Time to wait before retrying */
+-	uint8_t _retrans;
+-	/**  Use new fallback mechanism (try EDNS, then do TCP) */
+-	bool _fallback;
+-
+-	/**  Whether to do DNSSEC */
+-	bool _dnssec;
+-	/**  Whether to set the CD bit on DNSSEC requests */
+-	bool _dnssec_cd;
+-	/** Optional trust anchors for complete DNSSEC validation */
+-	ldns_rr_list * _dnssec_anchors;
+-	/**  Whether to use tcp or udp (tcp if the value is true)*/
+-	bool _usevc;
+-	/**  Whether to ignore the tc bit */
+-	bool _igntc;
+-	/**  Whether to use ip6: 0->does not matter, 1 is IPv4, 2 is IPv6 */
+-	uint8_t _ip6;
+-	/**  If true append the default domain */
+-	bool _defnames;
+-	/**  If true apply the search list */
+-	bool _dnsrch;
+-	/**  Timeout for socket connections */
+-	struct timeval _timeout;
+-	/**  Only try the first nameserver, and return with an error directly if it fails */
+-	bool _fail;
+-	/**  Randomly choose a nameserver */
+-	bool _random;
+-	/** Keep some things to make AXFR possible */
+-	int _socket;
+-	/** Count the number of LDNS_RR_TYPE_SOA RRs we have seen so far
+-	 * (the second one signifies the end of the AXFR)
+-	 */
+-	int _axfr_soa_count;
+-	/* when axfring we get complete packets from the server
+-	   but we want to give the caller 1 rr at a time, so
+-	   keep the current pkt */
+-        /** Packet currently handled when doing part of an AXFR */
+-	ldns_pkt *_cur_axfr_pkt;
+-	/** Counter for within the AXFR packets */
+-	uint16_t _axfr_i;
+-	/* EDNS0 available buffer size */
+-	uint16_t _edns_udp_size;
+-	/* serial for IXFR */
+-	uint32_t _serial;
+-
+-	/* Optional tsig key for signing queries,
+-	outgoing messages are signed if and only if both are set
+-	*/
+-	/** Name of the key to use with TSIG, if _tsig_keyname and _tsig_keydata both contain values, outgoing messages are automatically signed with TSIG. */
+-	char *_tsig_keyname;
+-	/** Secret key data to use with TSIG, if _tsig_keyname and _tsig_keydata both contain values, outgoing messages are automatically signed with TSIG. */
+-	char *_tsig_keydata;
+-	/** TSIG signing algorithm */
+-	char *_tsig_algorithm;
+-
+-	/** Source address to query from */
+-	ldns_rdf *_source;
+-};
+-typedef struct ldns_struct_resolver ldns_resolver;
+-
+-/* prototypes */
+-/* read access functions */
+-
+-/**
+- * Get the port the resolver should use
+- * \param[in] r the resolver
+- * \return the port number
+- */
+-uint16_t ldns_resolver_port(const ldns_resolver *r);
+-
+-/**
+- * Get the source address the resolver should use
+- * \param[in] r the resolver
+- * \return the source rdf
+- */
+-ldns_rdf *ldns_resolver_source(const ldns_resolver *r);
+-
+-/**
+- * Is the resolver set to recurse
+- * \param[in] r the resolver
+- * \return true if so, otherwise false
+- */
+-bool ldns_resolver_recursive(const ldns_resolver *r);
+-
+-/**
+- * Get the debug status of the resolver
+- * \param[in] r the resolver
+- * \return true if so, otherwise false
+- */
+-bool ldns_resolver_debug(const ldns_resolver *r);
+-
+-/**
+- * Get the number of retries
+- * \param[in] r the resolver
+- * \return the number of retries
+- */
+-uint8_t ldns_resolver_retry(const ldns_resolver *r);
+-
+-/**
+- * Get the retransmit interval
+- * \param[in] r the resolver
+- * \return the retransmit interval
+- */
+-uint8_t ldns_resolver_retrans(const ldns_resolver *r);
+-
+-/**
+- * Get the truncation fallback status
+- * \param[in] r the resolver
+- * \return whether the truncation fallback mechanism is used
+- */
+-bool ldns_resolver_fallback(const ldns_resolver *r);
+-
+-/**
+- * Does the resolver use ip6 or ip4
+- * \param[in] r the resolver
+- * \return 0: both, 1: ip4, 2:ip6
+- */
+-uint8_t ldns_resolver_ip6(const ldns_resolver *r);
+-
+-/**
+- * Get the resolver's udp size
+- * \param[in] r the resolver
+- * \return the udp mesg size
+- */
+-uint16_t ldns_resolver_edns_udp_size(const ldns_resolver *r);
+-/**
+- * Does the resolver use tcp or udp
+- * \param[in] r the resolver
+- * \return true: tcp, false: udp
+- */
+-bool ldns_resolver_usevc(const ldns_resolver *r);
+-/**
+- * Does the resolver only try the first nameserver
+- * \param[in] r the resolver
+- * \return true: yes, fail, false: no, try the others
+- */
+-bool ldns_resolver_fail(const ldns_resolver *r);
+-/**
+- * Does the resolver apply default domain name
+- * \param[in] r the resolver
+- * \return true: yes, false: no
+- */
+-bool ldns_resolver_defnames(const ldns_resolver *r);
+-/**
+- * Does the resolver apply search list
+- * \param[in] r the resolver
+- * \return true: yes, false: no
+- */
+-bool ldns_resolver_dnsrch(const ldns_resolver *r);
+-/**
+- * Does the resolver do DNSSEC
+- * \param[in] r the resolver
+- * \return true: yes, false: no
+- */
+-bool ldns_resolver_dnssec(const ldns_resolver *r);
+-/**
+- * Does the resolver set the CD bit
+- * \param[in] r the resolver
+- * \return true: yes, false: no
+- */
+-bool ldns_resolver_dnssec_cd(const ldns_resolver *r);
+-/**
+- * Get the resolver's DNSSEC anchors
+- * \param[in] r the resolver
+- * \return an rr_list containg trusted DNSSEC anchors
+- */
+-ldns_rr_list * ldns_resolver_dnssec_anchors(const ldns_resolver *r);
+-/**
+- * Does the resolver ignore the TC bit (truncated)
+- * \param[in] r the resolver
+- * \return true: yes, false: no
+- */
+-bool ldns_resolver_igntc(const ldns_resolver *r);
+-/**
+- * Does the resolver randomize the nameserver before usage
+- * \param[in] r the resolver
+- * \return true: yes, false: no
+- */
+-bool ldns_resolver_random(const ldns_resolver *r);
+-/**
+- * How many nameserver are configured in the resolver
+- * \param[in] r the resolver
+- * \return number of nameservers
+- */
+-size_t ldns_resolver_nameserver_count(const ldns_resolver *r);
+-/**
+- * What is the default dname to add to relative queries
+- * \param[in] r the resolver
+- * \return the dname which is added
+- */
+-ldns_rdf *ldns_resolver_domain(const ldns_resolver *r);
+-/**
+- * What is the timeout on socket connections
+- * \param[in] r the resolver
+- * \return the timeout as struct timeval
+- */
+-struct timeval ldns_resolver_timeout(const ldns_resolver *r);
+-/**
+- * What is the searchlist as used by the resolver
+- * \param[in] r the resolver
+- * \return a ldns_rdf pointer to a list of the addresses
+- */
+-ldns_rdf** ldns_resolver_searchlist(const ldns_resolver *r);
+-/**
+- * Return the configured nameserver ip address
+- * \param[in] r the resolver
+- * \return a ldns_rdf pointer to a list of the addresses
+- */
+-ldns_rdf** ldns_resolver_nameservers(const ldns_resolver *r);
+-/**
+- * Return the used round trip times for the nameservers
+- * \param[in] r the resolver
+- * \return a size_t* pointer to the list.
+- * yet)
+- */
+-size_t * ldns_resolver_rtt(const ldns_resolver *r);
+-/**
+- * Return the used round trip time for a specific nameserver
+- * \param[in] r the resolver
+- * \param[in] pos the index to the nameserver
+- * \return the rrt, 0: infinite, >0: undefined (as of * yet)
+- */
+-size_t ldns_resolver_nameserver_rtt(const ldns_resolver *r, size_t pos);
+-/**
+- * Return the tsig keyname as used by the nameserver
+- * \param[in] r the resolver
+- * \return the name used.
+- */
+-char *ldns_resolver_tsig_keyname(const ldns_resolver *r);
+-/**
+- * Return the tsig algorithm as used by the nameserver
+- * \param[in] r the resolver
+- * \return the algorithm used.
+- */
+-char *ldns_resolver_tsig_algorithm(const ldns_resolver *r);
+-/**
+- * Return the tsig keydata as used by the nameserver
+- * \param[in] r the resolver
+- * \return the keydata used.
+- */
+-char *ldns_resolver_tsig_keydata(const ldns_resolver *r);
+-/**
+- * pop the last nameserver from the resolver.
+- * \param[in] r the resolver
+- * \return the popped address or NULL if empty
+- */
+-ldns_rdf* ldns_resolver_pop_nameserver(ldns_resolver *r);
+-
+-/**
+- * Return the resolver's searchlist count
+- * \param[in] r the resolver
+- * \return the searchlist count
+- */
+-size_t ldns_resolver_searchlist_count(const ldns_resolver *r);
+-
+-/* write access function */
+-/**
+- * Set the port the resolver should use
+- * \param[in] r the resolver
+- * \param[in] p the port number
+- */
+-void ldns_resolver_set_port(ldns_resolver *r, uint16_t p);
+-
+-/**
+- * Set the source rdf (address) the resolver should use
+- * \param[in] r the resolver
+- * \param[in] s the source address
+- */
+-void ldns_resolver_set_source(ldns_resolver *r, ldns_rdf *s);
+-
+-/**
+- * Set the resolver recursion
+- * \param[in] r the resolver
+- * \param[in] b true: set to recurse, false: unset
+- */
+-void ldns_resolver_set_recursive(ldns_resolver *r, bool b);
+-
+-/**
+- * Set the resolver debugging
+- * \param[in] r the resolver
+- * \param[in] b true: debug on: false debug off
+- */
+-void ldns_resolver_set_debug(ldns_resolver *r, bool b);
+-
+-/**
+- * Incremental the resolver's nameserver count.
+- * \param[in] r the resolver
+- */
+-void ldns_resolver_incr_nameserver_count(ldns_resolver *r);
+-
+-/**
+- * Decrement the resolver's nameserver count.
+- * \param[in] r the resolver
+- */
+-void ldns_resolver_dec_nameserver_count(ldns_resolver *r);
+-
+-/**
+- * Set the resolver's nameserver count directly.
+- * \param[in] r the resolver
+- * \param[in] c the nameserver count
+- */
+-void ldns_resolver_set_nameserver_count(ldns_resolver *r, size_t c);
+-
+-/**
+- * Set the resolver's nameserver count directly by using an rdf list
+- * \param[in] r the resolver
+- * \param[in] rd the resolver addresses
+- */
+-void ldns_resolver_set_nameservers(ldns_resolver *r, ldns_rdf **rd);
+-
+-/**
+- * Set the resolver's default domain. This gets appended when no
+- * absolute name is given
+- * \param[in] r the resolver
+- * \param[in] rd the name to append
+- */
+-void ldns_resolver_set_domain(ldns_resolver *r, ldns_rdf *rd);
+-
+-/**
+- * Set the resolver's socket time out when talking to remote hosts
+- * \param[in] r the resolver
+- * \param[in] timeout the timeout to use
+- */
+-void ldns_resolver_set_timeout(ldns_resolver *r, struct timeval timeout);
+-
+-/**
+- * Push a new rd to the resolver's searchlist
+- * \param[in] r the resolver
+- * \param[in] rd to push
+- */
+-void ldns_resolver_push_searchlist(ldns_resolver *r, ldns_rdf *rd);
+-
+-/**
+- * Whether the resolver uses the name set with _set_domain
+- * \param[in] r the resolver
+- * \param[in] b true: use the defaults, false: don't use them
+- */
+-void ldns_resolver_set_defnames(ldns_resolver *r, bool b);
+-
+-/**
+- * Whether the resolver uses a virtual circuit (TCP)
+- * \param[in] r the resolver
+- * \param[in] b true: use TCP, false: don't use TCP
+- */
+-void ldns_resolver_set_usevc(ldns_resolver *r, bool b);
+-
+-/**
+- * Whether the resolver uses the searchlist
+- * \param[in] r the resolver
+- * \param[in] b true: use the list, false: don't use the list
+- */
+-void ldns_resolver_set_dnsrch(ldns_resolver *r, bool b);
+-
+-/**
+- * Whether the resolver uses DNSSEC
+- * \param[in] r the resolver
+- * \param[in] b true: use DNSSEC, false: don't use DNSSEC
+- */
+-void ldns_resolver_set_dnssec(ldns_resolver *r, bool b);
+-
+-/**
+- * Whether the resolver uses the checking disable bit
+- * \param[in] r the resolver
+- * \param[in] b true: enable , false: don't use TCP
+- */
+-void ldns_resolver_set_dnssec_cd(ldns_resolver *r, bool b);
+-/**
+- * Set the resolver's DNSSEC anchor list directly. RRs should be of type DS or DNSKEY.
+- * \param[in] r the resolver
+- * \param[in] l the list of RRs to use as trust anchors
+- */
+-void ldns_resolver_set_dnssec_anchors(ldns_resolver *r, ldns_rr_list * l);
+-
+-/**
+- * Push a new trust anchor to the resolver. It must be a DS or DNSKEY rr
+- * \param[in] r the resolver.
+- * \param[in] rr the RR to add as a trust anchor.
+- * \return a status
+- */
+-ldns_status ldns_resolver_push_dnssec_anchor(ldns_resolver *r, ldns_rr *rr);
+-
+-/**
+- * Set the resolver retrans timeout (in seconds)
+- * \param[in] r the resolver
+- * \param[in] re the retransmission interval in seconds
+- */
+-void ldns_resolver_set_retrans(ldns_resolver *r, uint8_t re);
+-
+-/**
+- * Set whether the resolvers truncation fallback mechanism is used
+- * when ldns_resolver_query() is called.
+- * \param[in] r the resolver
+- * \param[in] fallback whether to use the fallback mechanism
+- */
+-void ldns_resolver_set_fallback(ldns_resolver *r, bool fallback);
+-
+-/**
+- * Set the number of times a resolver should retry a nameserver before the
+- * next one is tried.
+- * \param[in] r the resolver
+- * \param[in] re the number of retries
+- */
+-void ldns_resolver_set_retry(ldns_resolver *r, uint8_t re);
+-
+-/**
+- * Whether the resolver uses ip6
+- * \param[in] r the resolver
+- * \param[in] i 0: no pref, 1: ip4, 2: ip6
+- */
+-void ldns_resolver_set_ip6(ldns_resolver *r, uint8_t i);
+-
+-/**
+- * Whether or not to fail after one failed query
+- * \param[in] r the resolver
+- * \param[in] b true: yes fail, false: continue with next nameserver
+- */
+-void ldns_resolver_set_fail(ldns_resolver *r, bool b);
+-
+-/**
+- * Whether or not to ignore the TC bit
+- * \param[in] r the resolver
+- * \param[in] b true: yes ignore, false: don't ignore
+- */
+-void ldns_resolver_set_igntc(ldns_resolver *r, bool b);
+-
+-/**
+- * Set maximum udp size
+- * \param[in] r the resolver
+- * \param[in] s the udp max size
+- */
+-void ldns_resolver_set_edns_udp_size(ldns_resolver *r, uint16_t s);
+-
+-/**
+- * Set the tsig key name
+- * \param[in] r the resolver
+- * \param[in] tsig_keyname the tsig key name
+- */
+-void ldns_resolver_set_tsig_keyname(ldns_resolver *r, char *tsig_keyname);
+-
+-/**
+- * Set the tsig algorithm
+- * \param[in] r the resolver
+- * \param[in] tsig_algorithm the tsig algorithm
+- */
+-void ldns_resolver_set_tsig_algorithm(ldns_resolver *r, char *tsig_algorithm);
+-
+-/**
+- * Set the tsig key data
+- * \param[in] r the resolver
+- * \param[in] tsig_keydata the key data
+- */
+-void ldns_resolver_set_tsig_keydata(ldns_resolver *r, char *tsig_keydata);
+-
+-/**
+- * Set round trip time for all nameservers. Note this currently
+- * differentiates between: unreachable and reachable.
+- * \param[in] r the resolver
+- * \param[in] rtt a list with the times
+- */
+-void ldns_resolver_set_rtt(ldns_resolver *r, size_t *rtt);
+-
+-/**
+- * Set round trip time for a specific nameserver. Note this
+- * currently differentiates between: unreachable and reachable.
+- * \param[in] r the resolver
+- * \param[in] pos the nameserver position
+- * \param[in] value the rtt
+- */
+-void ldns_resolver_set_nameserver_rtt(ldns_resolver *r, size_t pos, size_t value);
+-
+-/**
+- * Should the nameserver list be randomized before each use
+- * \param[in] r the resolver
+- * \param[in] b: true: randomize, false: don't
+- */
+-void ldns_resolver_set_random(ldns_resolver *r, bool b);
+-
+-/**
+- * Push a new nameserver to the resolver. It must be an IP
+- * address v4 or v6.
+- * \param[in] r the resolver
+- * \param[in] n the ip address
+- * \return ldns_status a status
+- */
+-ldns_status ldns_resolver_push_nameserver(ldns_resolver *r, ldns_rdf *n);
+-
+-/**
+- * Push a new nameserver to the resolver. It must be an
+- * A or AAAA RR record type
+- * \param[in] r the resolver
+- * \param[in] rr the resource record
+- * \return ldns_status a status
+- */
+-ldns_status ldns_resolver_push_nameserver_rr(ldns_resolver *r, ldns_rr *rr);
+-
+-/**
+- * Push a new nameserver rr_list to the resolver.
+- * \param[in] r the resolver
+- * \param[in] rrlist the rr_list to push
+- * \return ldns_status a status
+- */
+-ldns_status ldns_resolver_push_nameserver_rr_list(ldns_resolver *r, ldns_rr_list *rrlist);
+-
+-/**
+- * Send the query for using the resolver and take the search list into account
+- * The search algorithm is as follows:
+- * If the name is absolute, try it as-is, otherwise apply the search list
+- * \param[in] *r operate using this resolver
+- * \param[in] *rdf query for this name
+- * \param[in] t query for this type (may be 0, defaults to A)
+- * \param[in] c query for this class (may be 0, default to IN)
+- * \param[in] flags the query flags
+- *
+- * \return ldns_pkt* a packet with the reply from the nameserver
+- */
+-ldns_pkt* ldns_resolver_search(const ldns_resolver *r, const ldns_rdf *rdf, ldns_rr_type t, ldns_rr_class c, uint16_t flags);
+-
+-
+-/**
+- * Send the query for using the resolver and take the search list into account
+- * The search algorithm is as follows:
+- * If the name is absolute, try it as-is, otherwise apply the search list
+- * \param[out] pkt a packet with the reply from the nameserver
+- * \param[in] *r operate using this resolver
+- * \param[in] *rdf query for this name
+- * \param[in] t query for this type (may be 0, defaults to A)
+- * \param[in] c query for this class (may be 0, default to IN)
+- * \param[in] flags the query flags
+- *
+- * \return ldns_status LDNS_STATUS_OK on success
+- */
+-ldns_status ldns_resolver_search_status(ldns_pkt** pkt, ldns_resolver *r, const ldns_rdf *rdf, ldns_rr_type t, ldns_rr_class c, uint16_t flags);
+-
+-/**
+- * Form a query packet from a resolver and name/type/class combo
+- * \param[out] **q a pointer to a ldns_pkt pointer (initialized by this function)
+- * \param[in] *r operate using this resolver
+- * \param[in] *name query for this name
+- * \param[in] t query for this type (may be 0, defaults to A)
+- * \param[in] c query for this class (may be 0, default to IN)
+- * \param[in] f the query flags
+- *
+- * \return ldns_pkt* a packet with the reply from the nameserver
+- */
+-ldns_status ldns_resolver_prepare_query_pkt(ldns_pkt **q, ldns_resolver *r, const  ldns_rdf *name, ldns_rr_type t, ldns_rr_class c, uint16_t f);
+-
+-/**
+- * Send the query for name as-is
+- * \param[out] **answer a pointer to a ldns_pkt pointer (initialized by this function)
+- * \param[in] *r operate using this resolver
+- * \param[in] *name query for this name
+- * \param[in] t query for this type (may be 0, defaults to A)
+- * \param[in] c query for this class (may be 0, default to IN)
+- * \param[in] flags the query flags
+- *
+- * \return ldns_pkt* a packet with the reply from the nameserver
+- */
+-ldns_status ldns_resolver_send(ldns_pkt **answer, ldns_resolver *r, const ldns_rdf *name, ldns_rr_type t, ldns_rr_class c, uint16_t flags);
+-
+-/**
+- * Send the given packet to a nameserver
+- * \param[out] **answer a pointer to a ldns_pkt pointer (initialized by this function)
+- * \param[in] *r operate using this resolver
+- * \param[in] *query_pkt query
+- */
+-ldns_status ldns_resolver_send_pkt(ldns_pkt **answer, ldns_resolver *r, ldns_pkt *query_pkt);
+-
+-/**
+- * Send a query to a nameserver
+- * \param[out] pkt a packet with the reply from the nameserver
+- * \param[in] *r operate using this resolver
+- * \param[in] *name query for this name
+- * \param[in] *t query for this type (may be 0, defaults to A)
+- * \param[in] *c query for this class (may be 0, default to IN)
+- * \param[in] flags the query flags
+- *
+- * \return ldns_status LDNS_STATUS_OK on success
+- * if _defnames is true the default domain will be added
+- */
+-ldns_status ldns_resolver_query_status(ldns_pkt** pkt, ldns_resolver *r, const ldns_rdf *name, ldns_rr_type t, ldns_rr_class c, uint16_t flags);
+-
+-
+-/**
+- * Send a query to a nameserver
+- * \param[in] *r operate using this resolver 
+- *               (despite the const in the declaration,
+- *                the struct is altered as a side-effect)
+- * \param[in] *name query for this name
+- * \param[in] *t query for this type (may be 0, defaults to A)
+- * \param[in] *c query for this class (may be 0, default to IN)
+- * \param[in] flags the query flags
+- *
+- * \return ldns_pkt* a packet with the reply from the nameserver
+- * if _defnames is true the default domain will be added
+- */
+-ldns_pkt* ldns_resolver_query(const ldns_resolver *r, const ldns_rdf *name, ldns_rr_type t, ldns_rr_class c, uint16_t flags);
+-
+-
+-/**
+- * Create a new resolver structure
+- * \return ldns_resolver* pointer to new structure
+- */
+-ldns_resolver* ldns_resolver_new(void);
+-
+-/**
+- * Clone a resolver
+- * \param[in] r the resolver to clone
+- * \return ldns_resolver* pointer to new structure
+- */
+-ldns_resolver* ldns_resolver_clone(ldns_resolver *r);
+-
+-/**
+- * Create a resolver structure from a file like /etc/resolv.conf
+- * \param[out] r the new resolver
+- * \param[in] fp file pointer to create new resolver from
+- *      if NULL use /etc/resolv.conf
+- * \return LDNS_STATUS_OK or the error
+- */
+-ldns_status ldns_resolver_new_frm_fp(ldns_resolver **r, FILE *fp);
+-
+-/**
+- * Create a resolver structure from a file like /etc/resolv.conf
+- * \param[out] r the new resolver
+- * \param[in] fp file pointer to create new resolver from
+- *      if NULL use /etc/resolv.conf
+- * \param[in] line_nr pointer to an integer containing the current line number (for debugging purposes)
+- * \return LDNS_STATUS_OK or the error
+- */
+-ldns_status ldns_resolver_new_frm_fp_l(ldns_resolver **r, FILE *fp, int *line_nr);
+-
+-/**
+- * Configure a resolver by means of a resolv.conf file
+- * The file may be NULL in which case there will  be
+- * looked the RESOLV_CONF (defaults to /etc/resolv.conf
+- * \param[out] r the new resolver
+- * \param[in] filename the filename to use
+- * \return LDNS_STATUS_OK or the error
+- */
+-ldns_status ldns_resolver_new_frm_file(ldns_resolver **r, const char *filename);
+-
+-/**
+- * Frees the allocated space for this resolver. Only frees the resolver pionter! You should probably be using _deep_free.
+- * \param res resolver to free
+- */
+-void ldns_resolver_free(ldns_resolver *res);
+-
+-/**
+- * Frees the allocated space for this resolver and all it's data
+- * \param res resolver to free
+- */
+-void ldns_resolver_deep_free(ldns_resolver *res);
+-
+-/**
+- * Get the next stream of RRs in a AXFR
+- * \param[in] resolver the resolver to use. First ldns_axfr_start() must be
+- * called
+- * \return ldns_rr the next RR from the AXFR stream
+- * After you get this returned RR (not NULL: on error), then check if 
+- * ldns_axfr_complete() is true to see if the zone transfer has completed.
+- */
+-ldns_rr* ldns_axfr_next(ldns_resolver *resolver);
+-
+-/**
+- * Abort a transfer that is in progress
+- * \param[in] resolver the resolver that is used
+- */
+-void ldns_axfr_abort(ldns_resolver *resolver);
+-
+-/**
+- * Returns true if the axfr transfer has completed (i.e. 2 SOA RRs and no errors were encountered
+- * \param[in] resolver the resolver that is used
+- * \return bool true if axfr transfer was completed without error
+- */
+-bool ldns_axfr_complete(const ldns_resolver *resolver);
+-
+-/**
+- * Returns a pointer to the last ldns_pkt that was sent by the server in the AXFR transfer
+- * uasable for instance to get the error code on failure
+- * \param[in] res the resolver that was used in the axfr transfer
+- * \return ldns_pkt the last packet sent
+- */
+-ldns_pkt *ldns_axfr_last_pkt(const ldns_resolver *res);
+-
+-/**
+- * Get the serial for requesting IXFR.
+- * \param[in] r the resolver
+- * \param[in] serial serial
+- */
+-void ldns_resolver_set_ixfr_serial(ldns_resolver *r, uint32_t serial);
+-
+-/**
+- * Get the serial for requesting IXFR.
+- * \param[in] res the resolver
+- * \return uint32_t serial
+- */
+-uint32_t ldns_resolver_get_ixfr_serial(const ldns_resolver *res);
+-
+-/**
+- * Randomize the nameserver list in the resolver
+- * \param[in] r the resolver
+- */
+-void ldns_resolver_nameservers_randomize(ldns_resolver *r);
+-
+-/**
+- * Returns true if at least one of the provided keys is a trust anchor
+- * \param[in] r the current resolver
+- * \param[in] keys the keyset to check
+- * \param[out] trusted_keys the subset of trusted keys in the 'keys' rrset
+- * \return true if at least one of the provided keys is a configured trust anchor
+- */
+-bool ldns_resolver_trusted_key(const ldns_resolver *r, ldns_rr_list * keys, ldns_rr_list * trusted_keys);
+-
+-#ifdef __cplusplus
+-}
+-#endif
+-
+-#endif  /* LDNS_RESOLVER_H */
+diff --git a/include/ldns/rr.h b/include/ldns/rr.h
+deleted file mode 100644
+index 75ac352..0000000
+--- a/include/ldns/rr.h
++++ /dev/null
+@@ -1,929 +0,0 @@
+-/*
+- * rr.h -  resource record definitions
+- *
+- * a Net::DNS like library for C
+- *
+- * (c) NLnet Labs, 2005-2006
+- *
+- * See the file LICENSE for the license
+- */
+-
+-/**
+- * \file
+- *
+- * Contains the definition of ldns_rr and functions to manipulate those.
+- */
+-
+-
+-#ifndef LDNS_RR_H
+-#define LDNS_RR_H
+-
+-#include <ldns/common.h>
+-#include <ldns/rdata.h>
+-#include <ldns/buffer.h>
+-#include <ldns/error.h>
+-
+-#ifdef __cplusplus
+-extern "C" {
+-#endif
+-
+-/** Maximum length of a dname label */
+-#define LDNS_MAX_LABELLEN     63
+-/** Maximum length of a complete dname */
+-#define LDNS_MAX_DOMAINLEN    255
+-/** Maximum number of pointers in 1 dname */
+-#define LDNS_MAX_POINTERS	65535
+-/** The bytes TTL, CLASS and length use up in an rr */
+-#define LDNS_RR_OVERHEAD	10
+-
+-/* The first fields are contiguous and can be referenced instantly */
+-#define LDNS_RDATA_FIELD_DESCRIPTORS_COMMON 258
+-
+-
+-
+-/**
+- *  The different RR classes.
+- */
+-enum ldns_enum_rr_class
+-{
+-	/** the Internet */
+-	LDNS_RR_CLASS_IN 	= 1,
+-	/** Chaos class */
+-	LDNS_RR_CLASS_CH	= 3,
+-	/** Hesiod (Dyer 87) */
+-	LDNS_RR_CLASS_HS	= 4,
+-    /** None class, dynamic update */
+-    LDNS_RR_CLASS_NONE      = 254,
+-	/** Any class */
+-	LDNS_RR_CLASS_ANY	= 255,
+-
+-	LDNS_RR_CLASS_FIRST     = 0,
+-	LDNS_RR_CLASS_LAST      = 65535,
+-	LDNS_RR_CLASS_COUNT     = LDNS_RR_CLASS_LAST - LDNS_RR_CLASS_FIRST + 1
+-};
+-typedef enum ldns_enum_rr_class ldns_rr_class;
+-
+-/**
+- *  Used to specify whether compression is allowed.
+- */
+-enum ldns_enum_rr_compress
+-{
+-	/** compression is allowed */
+-	LDNS_RR_COMPRESS,
+-	LDNS_RR_NO_COMPRESS
+-};
+-typedef enum ldns_enum_rr_compress ldns_rr_compress;
+-
+-/**
+- * The different RR types.
+- */
+-enum ldns_enum_rr_type
+-{
+-	/**  a host address */
+-	LDNS_RR_TYPE_A = 1,
+-	/**  an authoritative name server */
+-	LDNS_RR_TYPE_NS = 2,
+-	/**  a mail destination (Obsolete - use MX) */
+-	LDNS_RR_TYPE_MD = 3,
+-	/**  a mail forwarder (Obsolete - use MX) */
+-	LDNS_RR_TYPE_MF = 4,
+-	/**  the canonical name for an alias */
+-	LDNS_RR_TYPE_CNAME = 5,
+-	/**  marks the start of a zone of authority */
+-	LDNS_RR_TYPE_SOA = 6,
+-	/**  a mailbox domain name (EXPERIMENTAL) */
+-	LDNS_RR_TYPE_MB = 7,
+-	/**  a mail group member (EXPERIMENTAL) */
+-	LDNS_RR_TYPE_MG = 8,
+-	/**  a mail rename domain name (EXPERIMENTAL) */
+-	LDNS_RR_TYPE_MR = 9,
+-	/**  a null RR (EXPERIMENTAL) */
+-	LDNS_RR_TYPE_NULL = 10,
+-	/**  a well known service description */
+-	LDNS_RR_TYPE_WKS = 11,
+-	/**  a domain name pointer */
+-	LDNS_RR_TYPE_PTR = 12,
+-	/**  host information */
+-	LDNS_RR_TYPE_HINFO = 13,
+-	/**  mailbox or mail list information */
+-	LDNS_RR_TYPE_MINFO = 14,
+-	/**  mail exchange */
+-	LDNS_RR_TYPE_MX = 15,
+-	/**  text strings */
+-	LDNS_RR_TYPE_TXT = 16,
+-	/**  RFC1183 */
+-	LDNS_RR_TYPE_RP = 17,
+-	/**  RFC1183 */
+-	LDNS_RR_TYPE_AFSDB = 18,
+-	/**  RFC1183 */
+-	LDNS_RR_TYPE_X25 = 19,
+-	/**  RFC1183 */
+-	LDNS_RR_TYPE_ISDN = 20,
+-	/**  RFC1183 */
+-	LDNS_RR_TYPE_RT = 21,
+-	/**  RFC1706 */
+-	LDNS_RR_TYPE_NSAP = 22,
+-	/**  RFC1348 */
+-	LDNS_RR_TYPE_NSAP_PTR = 23,
+-	/**  2535typecode */
+-	LDNS_RR_TYPE_SIG = 24,
+-	/**  2535typecode */
+-	LDNS_RR_TYPE_KEY = 25,
+-	/**  RFC2163 */
+-	LDNS_RR_TYPE_PX = 26,
+-	/**  RFC1712 */
+-	LDNS_RR_TYPE_GPOS = 27,
+-	/**  ipv6 address */
+-	LDNS_RR_TYPE_AAAA = 28,
+-	/**  LOC record  RFC1876 */
+-	LDNS_RR_TYPE_LOC = 29,
+-	/**  2535typecode */
+-	LDNS_RR_TYPE_NXT = 30,
+-	/**  draft-ietf-nimrod-dns-01.txt */
+-	LDNS_RR_TYPE_EID = 31,
+-	/**  draft-ietf-nimrod-dns-01.txt */
+-	LDNS_RR_TYPE_NIMLOC = 32,
+-	/**  SRV record RFC2782 */
+-	LDNS_RR_TYPE_SRV = 33,
+-	/**  http://www.jhsoft.com/rfc/af-saa-0069.000.rtf */
+-	LDNS_RR_TYPE_ATMA = 34,
+-	/**  RFC2915 */
+-	LDNS_RR_TYPE_NAPTR = 35,
+-	/**  RFC2230 */
+-	LDNS_RR_TYPE_KX = 36,
+-	/**  RFC2538 */
+-	LDNS_RR_TYPE_CERT = 37,
+-	/**  RFC2874 */
+-	LDNS_RR_TYPE_A6 = 38,
+-	/**  RFC2672 */
+-	LDNS_RR_TYPE_DNAME = 39,
+-	/**  dnsind-kitchen-sink-02.txt */
+-	LDNS_RR_TYPE_SINK = 40,
+-	/**  Pseudo OPT record... */
+-	LDNS_RR_TYPE_OPT = 41,
+-	/**  RFC3123 */
+-	LDNS_RR_TYPE_APL = 42,
+-	/**  RFC4034, RFC3658 */
+-	LDNS_RR_TYPE_DS = 43,
+-	/**  SSH Key Fingerprint */
+-	LDNS_RR_TYPE_SSHFP = 44, /* RFC 4255 */
+-	/**  IPsec Key */
+-	LDNS_RR_TYPE_IPSECKEY = 45, /* RFC 4025 */
+-	/**  DNSSEC */
+-	LDNS_RR_TYPE_RRSIG = 46, /* RFC 4034 */
+-	LDNS_RR_TYPE_NSEC = 47, /* RFC 4034 */
+-	LDNS_RR_TYPE_DNSKEY = 48, /* RFC 4034 */
+-
+-	LDNS_RR_TYPE_DHCID = 49, /* RFC 4701 */
+-	/* NSEC3 */
+-	LDNS_RR_TYPE_NSEC3 = 50, /* RFC 5155 */
+-	LDNS_RR_TYPE_NSEC3PARAM = 51, /* RFC 5155 */
+-	LDNS_RR_TYPE_NSEC3PARAMS = 51,
+-	LDNS_RR_TYPE_TLSA = 52, /* RFC 6698 */
+-
+-	LDNS_RR_TYPE_HIP = 55, /* RFC 5205 */
+-
+-	/** draft-reid-dnsext-zs */
+-	LDNS_RR_TYPE_NINFO = 56,
+-	/** draft-reid-dnsext-rkey */
+-	LDNS_RR_TYPE_RKEY = 57,
+-        /** draft-ietf-dnsop-trust-history */
+-        LDNS_RR_TYPE_TALINK = 58,
+-	LDNS_RR_TYPE_CDS = 59, /* RFC 7344 */
+-	LDNS_RR_TYPE_CDNSKEY = 60, /* RFC 7344 */
+-	/** draft-ietf-dane-openpgpkey */
+-	LDNS_RR_TYPE_OPENPGPKEY = 61,
+-
+-	LDNS_RR_TYPE_SPF = 99, /* RFC 4408 */
+-
+-	LDNS_RR_TYPE_UINFO = 100,
+-	LDNS_RR_TYPE_UID = 101,
+-	LDNS_RR_TYPE_GID = 102,
+-	LDNS_RR_TYPE_UNSPEC = 103,
+-
+-	LDNS_RR_TYPE_NID = 104, /* RFC 6742 */
+-	LDNS_RR_TYPE_L32 = 105, /* RFC 6742 */
+-	LDNS_RR_TYPE_L64 = 106, /* RFC 6742 */
+-	LDNS_RR_TYPE_LP = 107, /* RFC 6742 */
+-
+-	LDNS_RR_TYPE_EUI48 = 108, /* RFC 7043 */
+-	LDNS_RR_TYPE_EUI64 = 109, /* RFC 7043 */
+-
+-	LDNS_RR_TYPE_TKEY = 249, /* RFC 2930 */
+-	LDNS_RR_TYPE_TSIG = 250,
+-	LDNS_RR_TYPE_IXFR = 251,
+-	LDNS_RR_TYPE_AXFR = 252,
+-	/**  A request for mailbox-related records (MB, MG or MR) */
+-	LDNS_RR_TYPE_MAILB = 253,
+-	/**  A request for mail agent RRs (Obsolete - see MX) */
+-	LDNS_RR_TYPE_MAILA = 254,
+-	/**  any type (wildcard) */
+-	LDNS_RR_TYPE_ANY = 255,
+-	/** draft-faltstrom-uri-06 */
+-	LDNS_RR_TYPE_URI = 256,
+-	LDNS_RR_TYPE_CAA = 257, /* RFC 6844 */
+-
+-	/** DNSSEC Trust Authorities */
+-	LDNS_RR_TYPE_TA = 32768,
+-	/* RFC 4431, 5074, DNSSEC Lookaside Validation */
+-	LDNS_RR_TYPE_DLV = 32769,
+-
+-	/* type codes from nsec3 experimental phase
+-	LDNS_RR_TYPE_NSEC3 = 65324,
+-	LDNS_RR_TYPE_NSEC3PARAMS = 65325, */
+-	LDNS_RR_TYPE_FIRST = 0,
+-	LDNS_RR_TYPE_LAST  = 65535,
+-	LDNS_RR_TYPE_COUNT = LDNS_RR_TYPE_LAST - LDNS_RR_TYPE_FIRST + 1
+-};
+-typedef enum ldns_enum_rr_type ldns_rr_type;
+-
+-/**
+- * Resource Record
+- *
+- * This is the basic DNS element that contains actual data
+- *
+- * From RFC1035:
+- * <pre>
+-3.2.1. Format
+-
+-All RRs have the same top level format shown below:
+-
+-                                    1  1  1  1  1  1
+-      0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
+-    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+-    |                                               |
+-    /                                               /
+-    /                      NAME                     /
+-    |                                               |
+-    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+-    |                      TYPE                     |
+-    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+-    |                     CLASS                     |
+-    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+-    |                      TTL                      |
+-    |                                               |
+-    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+-    |                   RDLENGTH                    |
+-    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--|
+-    /                     RDATA                     /
+-    /                                               /
+-    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+-
+-where:
+-
+-NAME            an owner name, i.e., the name of the node to which this
+-                resource record pertains.
+-
+-TYPE            two octets containing one of the RR TYPE codes.
+-
+-CLASS           two octets containing one of the RR CLASS codes.
+-
+-TTL             a 32 bit signed integer that specifies the time interval
+-                that the resource record may be cached before the source
+-                of the information should again be consulted.  Zero
+-                values are interpreted to mean that the RR can only be
+-                used for the transaction in progress, and should not be
+-                cached.  For example, SOA records are always distributed
+-                with a zero TTL to prohibit caching.  Zero values can
+-                also be used for extremely volatile data.
+-
+-RDLENGTH        an unsigned 16 bit integer that specifies the length in
+-                octets of the RDATA field.
+-
+-RDATA           a variable length string of octets that describes the
+-                resource.  The format of this information varies
+-                according to the TYPE and CLASS of the resource record.
+- * </pre>
+- *
+- * The actual amount and type of rdata fields depend on the RR type of the
+- * RR, and can be found by using \ref ldns_rr_descriptor functions.
+- */
+-struct ldns_struct_rr
+-{
+-	/**  Owner name, uncompressed */
+-	ldns_rdf	*_owner;
+-	/**  Time to live  */
+-	uint32_t	_ttl;
+-	/**  Number of data fields */
+-	size_t	        _rd_count;
+-	/**  the type of the RR. A, MX etc. */
+-	ldns_rr_type	_rr_type;
+-	/**  Class of the resource record.  */
+-	ldns_rr_class	_rr_class;
+-	/* everything in the rdata is in network order */
+-	/**  The array of rdata's */
+-	ldns_rdf	 **_rdata_fields;
+-	/**  question rr [it would be nicer if thous is after _rd_count]
+-		 ABI change: Fix this in next major release
+-	 */
+-	bool		_rr_question;
+-};
+-typedef struct ldns_struct_rr ldns_rr;
+-
+-/**
+- * List or Set of Resource Records
+- *
+- * Contains a list of rr's <br>
+- * No official RFC-like checks are made
+- */
+-struct ldns_struct_rr_list
+-{
+-	size_t _rr_count;
+-	size_t _rr_capacity;
+-	ldns_rr **_rrs;
+-};
+-typedef struct ldns_struct_rr_list ldns_rr_list;
+-
+-/**
+- * Contains all information about resource record types.
+- *
+- * This structure contains, for all rr types, the rdata fields that are defined.
+- */
+-struct ldns_struct_rr_descriptor
+-{
+-	/** Type of the RR that is described here */
+-	ldns_rr_type    _type;
+-	/** Textual name of the RR type.  */
+-	const char *_name;
+-	/** Minimum number of rdata fields in the RRs of this type.  */
+-	uint8_t     _minimum;
+-	/** Maximum number of rdata fields in the RRs of this type.  */
+-	uint8_t     _maximum;
+-	/** Wireformat specification for the rr, i.e. the types of rdata fields in their respective order. */
+-	const ldns_rdf_type *_wireformat;
+-	/** Special rdf types */
+-	ldns_rdf_type _variable;
+-	/** Specifies whether compression can be used for dnames in this RR type. */
+-	ldns_rr_compress _compress;
+-	/** The number of DNAMEs in the _wireformat string, for parsing. */
+-	uint8_t _dname_count;
+-};
+-typedef struct ldns_struct_rr_descriptor ldns_rr_descriptor;
+-
+-
+-/**
+- * Create a rr type bitmap rdf providing enough space to set all 
+- * known (to ldns) rr types.
+- * \param[out] rdf the constructed rdf
+- * \return LDNS_STATUS_OK if all went well.
+- */
+-ldns_status ldns_rdf_bitmap_known_rr_types_space(ldns_rdf** rdf);
+-
+-/**
+- * Create a rr type bitmap rdf with at least all known (to ldns) rr types set.
+- * \param[out] rdf the constructed rdf
+- * \return LDNS_STATUS_OK if all went well.
+- */
+-ldns_status ldns_rdf_bitmap_known_rr_types(ldns_rdf** rdf);
+-
+-
+-/**
+- * creates a new rr structure.
+- * \return ldns_rr *
+- */
+-ldns_rr* ldns_rr_new(void);
+-
+-/**
+- * creates a new rr structure, based on the given type.
+- * alloc enough space to hold all the rdf's
+- */
+-ldns_rr* ldns_rr_new_frm_type(ldns_rr_type t);
+-
+-/**
+- * frees an RR structure
+- * \param[in] *rr the RR to be freed
+- * \return void
+- */
+-void ldns_rr_free(ldns_rr *rr);
+-
+-/**
+- * creates an rr from a string.
+- * The string should be a fully filled-in rr, like
+- * ownername <space> TTL <space> CLASS <space>
+- * TYPE <space> RDATA.
+- * \param[out] n the rr to return
+- * \param[in] str the string to convert
+- * \param[in] default_ttl default ttl value for the rr.
+- *            If 0 DEF_TTL will be used
+- * \param[in] origin when the owner is relative add this.
+- *	The caller must ldns_rdf_deep_free it.
+- * \param[out] prev the previous ownername. if this value is not NULL,
+- * the function overwrites this with the ownername found in this
+- * string. The caller must then ldns_rdf_deep_free it.
+- * \return a status msg describing an error or LDNS_STATUS_OK
+- */
+-ldns_status ldns_rr_new_frm_str(ldns_rr **n, const char *str,
+-                                uint32_t default_ttl, ldns_rdf *origin,
+-                                ldns_rdf **prev);
+-
+-/**
+- * creates an rr for the question section from a string, i.e.
+- * without RDATA fields
+- * Origin and previous RR functionality are the same as in
+- * ldns_rr_new_frm_str()
+- * \param[out] n the rr to return
+- * \param[in] str the string to convert
+- * \param[in] origin when the owner is relative add this.
+- *	The caller must ldns_rdf_deep_free it.
+- * \param prev the previous ownername. the function overwrite this with
+- * the current found ownername. The caller must ldns_rdf_deep_free it.
+- * \return a status msg describing an error or LDNS_STATUS_OK
+- */
+-ldns_status ldns_rr_new_question_frm_str(ldns_rr **n, const char *str,
+-                                ldns_rdf *origin, ldns_rdf **prev);
+-
+-/**
+- * creates a new rr from a file containing a string.
+- * \param[out] rr the new rr
+- * \param[in] fp the file pointer to use
+- * \param[in] default_ttl pointer to a default ttl for the rr. If NULL DEF_TTL will be used
+- *            the pointer will be updated if the file contains a $TTL directive
+- * \param[in] origin when the owner is relative add this
+- * 	      the pointer will be updated if the file contains a $ORIGIN directive
+- *	      The caller must ldns_rdf_deep_free it.
+- * \param[in] prev when the owner is whitespaces use this as the * ownername
+- *            the pointer will be updated after the call
+- *	      The caller must ldns_rdf_deep_free it.
+- * \return a ldns_status with an error or LDNS_STATUS_OK
+- */
+-ldns_status ldns_rr_new_frm_fp(ldns_rr **rr, FILE *fp, uint32_t *default_ttl, ldns_rdf **origin, ldns_rdf **prev);
+-
+-/**
+- * creates a new rr from a file containing a string.
+- * \param[out] rr the new rr
+- * \param[in] fp the file pointer to use
+- * \param[in] default_ttl a default ttl for the rr. If NULL DEF_TTL will be used
+- *            the pointer will be updated if the file contains a $TTL directive
+- * \param[in] origin when the owner is relative add this
+- * 	      the pointer will be updated if the file contains a $ORIGIN directive
+- *	      The caller must ldns_rdf_deep_free it.
+- * \param[in] line_nr pointer to an integer containing the current line number (for debugging purposes)
+- * \param[in] prev when the owner is whitespaces use this as the * ownername
+- *            the pointer will be updated after the call
+- *	      The caller must ldns_rdf_deep_free it.
+- * \return a ldns_status with an error or LDNS_STATUS_OK
+- */
+-ldns_status ldns_rr_new_frm_fp_l(ldns_rr **rr, FILE *fp, uint32_t *default_ttl, ldns_rdf **origin, ldns_rdf **prev, int *line_nr);
+-
+-/**
+- * sets the owner in the rr structure.
+- * \param[in] *rr rr to operate on
+- * \param[in] *owner set to this owner
+- * \return void
+- */
+-void ldns_rr_set_owner(ldns_rr *rr, ldns_rdf *owner);
+-
+-/**
+- * sets the question flag in the rr structure.
+- * \param[in] *rr rr to operate on
+- * \param[in] question question flag
+- * \return void
+- */
+-void ldns_rr_set_question(ldns_rr *rr, bool question);
+-
+-/**
+- * sets the ttl in the rr structure.
+- * \param[in] *rr rr to operate on
+- * \param[in] ttl set to this ttl
+- * \return void
+- */
+-void ldns_rr_set_ttl(ldns_rr *rr, uint32_t ttl);
+-
+-/**
+- * sets the rd_count in the rr.
+- * \param[in] *rr rr to operate on
+- * \param[in] count set to this count
+- * \return void
+- */
+-void ldns_rr_set_rd_count(ldns_rr *rr, size_t count);
+-
+-/**
+- * sets the type in the rr.
+- * \param[in] *rr rr to operate on
+- * \param[in] rr_type set to this type
+- * \return void
+- */
+-void ldns_rr_set_type(ldns_rr *rr, ldns_rr_type rr_type);
+-
+-/**
+- * sets the class in the rr.
+- * \param[in] *rr rr to operate on
+- * \param[in] rr_class set to this class
+- * \return void
+- */
+-void ldns_rr_set_class(ldns_rr *rr, ldns_rr_class rr_class);
+-
+-/**
+- * sets a rdf member, it will be set on the
+- * position given. The old value is returned, like pop.
+- * \param[in] *rr the rr to operate on
+- * \param[in] *f the rdf to set
+- * \param[in] position the position the set the rdf
+- * \return  the old value in the rr, NULL on failyre
+- */
+-ldns_rdf* ldns_rr_set_rdf(ldns_rr *rr, const ldns_rdf *f, size_t position);
+-
+-/**
+- * sets rd_field member, it will be
+- * placed in the next available spot.
+- * \param[in] *rr rr to operate on
+- * \param[in] *f the data field member to set
+- * \return bool
+- */
+-bool ldns_rr_push_rdf(ldns_rr *rr, const ldns_rdf *f);
+-
+-/**
+- * removes a rd_field member, it will be
+- * popped from the last position.
+- * \param[in] *rr rr to operate on
+- * \return rdf which was popped (null if nothing)
+- */
+-ldns_rdf* ldns_rr_pop_rdf(ldns_rr *rr);
+-
+-/**
+- * returns the rdata field member counter.
+- * \param[in] *rr rr to operate on
+- * \param[in] nr the number of the rdf to return
+- * \return ldns_rdf *
+- */
+-ldns_rdf* ldns_rr_rdf(const ldns_rr *rr, size_t nr);
+-
+-/**
+- * returns the owner name of an rr structure.
+- * \param[in] *rr rr to operate on
+- * \return ldns_rdf *
+- */
+-ldns_rdf* ldns_rr_owner(const ldns_rr *rr);
+-
+-/**
+- * returns the question flag of an rr structure.
+- * \param[in] *rr rr to operate on
+- * \return bool true if question
+- */
+-bool ldns_rr_is_question(const ldns_rr *rr);
+-
+-/**
+- * returns the ttl of an rr structure.
+- * \param[in] *rr the rr to read from
+- * \return the ttl of the rr
+- */
+-uint32_t ldns_rr_ttl(const ldns_rr *rr);
+-
+-/**
+- * returns the rd_count of an rr structure.
+- * \param[in] *rr the rr to read from
+- * \return the rd count of the rr
+- */
+-size_t ldns_rr_rd_count(const ldns_rr *rr);
+-
+-/**
+- * returns the type of the rr.
+- * \param[in] *rr the rr to read from
+- * \return the type of the rr
+- */
+-ldns_rr_type ldns_rr_get_type(const ldns_rr *rr);
+-
+-/**
+- * returns the class of the rr.
+- * \param[in] *rr the rr to read from
+- * \return the class of the rr
+- */
+-ldns_rr_class ldns_rr_get_class(const ldns_rr *rr);
+-
+-/* rr_lists */
+-
+-/**
+- * returns the number of rr's in an rr_list.
+- * \param[in] rr_list  the rr_list to read from
+- * \return the number of rr's
+- */
+-size_t ldns_rr_list_rr_count(const ldns_rr_list *rr_list);
+-
+-/**
+- * sets the number of rr's in an rr_list.
+- * \param[in] rr_list the rr_list to set the count on
+- * \param[in] count the number of rr in this list
+- * \return void
+- */
+-void ldns_rr_list_set_rr_count(ldns_rr_list *rr_list, size_t count);
+-
+-/**
+- * set a rr on a specific index in a ldns_rr_list
+- * \param[in] rr_list the rr_list to use
+- * \param[in] r the rr to set
+- * \param[in] count index into the rr_list
+- * \return the old rr which was stored in the rr_list, or
+- * NULL is the index was too large
+- * set a specific rr */
+-ldns_rr * ldns_rr_list_set_rr(ldns_rr_list *rr_list, const ldns_rr *r, size_t count);
+-
+-/**
+- * returns a specific rr of an rrlist.
+- * \param[in] rr_list the rr_list to read from
+- * \param[in] nr return this rr
+- * \return the rr at position nr
+- */
+-ldns_rr* ldns_rr_list_rr(const ldns_rr_list *rr_list, size_t nr);
+-
+-/**
+- * creates a new rr_list structure.
+- * \return a new rr_list structure
+- */
+-ldns_rr_list* ldns_rr_list_new(void);
+-
+-/**
+- * frees an rr_list structure.
+- * \param[in] rr_list the list to free
+- */
+-void ldns_rr_list_free(ldns_rr_list *rr_list);
+-
+-/**
+- * frees an rr_list structure and all rrs contained therein.
+- * \param[in] rr_list the list to free
+- */
+-void ldns_rr_list_deep_free(ldns_rr_list *rr_list);
+-
+-/**
+- * concatenates two ldns_rr_lists together. This modifies
+- * *left (to extend it and add the pointers from *right).
+- * \param[in] left the leftside
+- * \param[in] right the rightside
+- * \return a left with right concatenated to it
+- */
+-bool ldns_rr_list_cat(ldns_rr_list *left, ldns_rr_list *right);
+-
+-/**
+- * concatenates two ldns_rr_lists together, but makes clones of the rr's 
+- * (instead of pointer copying).
+- * \param[in] left the leftside
+- * \param[in] right the rightside
+- * \return a new rr_list with leftside/rightside concatenated
+- */
+-ldns_rr_list* ldns_rr_list_cat_clone(ldns_rr_list *left, ldns_rr_list *right);
+-
+-/**
+- * pushes an rr to an rrlist.
+- * \param[in] rr_list the rr_list to push to 
+- * \param[in] rr the rr to push 
+- * \return false on error, otherwise true
+- */
+-bool ldns_rr_list_push_rr(ldns_rr_list *rr_list, const ldns_rr *rr);
+-
+-/**
+- * pushes an rr_list to an rrlist.
+- * \param[in] rr_list the rr_list to push to 
+- * \param[in] push_list the rr_list to push 
+- * \return false on error, otherwise true
+- */
+-bool ldns_rr_list_push_rr_list(ldns_rr_list *rr_list, const ldns_rr_list *push_list);
+-
+-/**
+- * pops the last rr from an rrlist.
+- * \param[in] rr_list the rr_list to pop from
+- * \return NULL if nothing to pop. Otherwise the popped RR
+- */
+-ldns_rr* ldns_rr_list_pop_rr(ldns_rr_list *rr_list);
+-
+-/**
+- * pops an  rr_list of size s from an rrlist.
+- * \param[in] rr_list the rr_list to pop from
+- * \param[in] size the number of rr's to pop 
+- * \return NULL if nothing to pop. Otherwise the popped rr_list
+- */
+-ldns_rr_list* ldns_rr_list_pop_rr_list(ldns_rr_list *rr_list, size_t size);
+-
+-/**
+- * returns true if the given rr is one of the rrs in the
+- * list, or if it is equal to one
+- * \param[in] rr_list the rr_list to check
+- * \param[in] rr the rr to check
+- * \return true if rr_list contains rr, false otherwise
+- */
+-bool ldns_rr_list_contains_rr(const ldns_rr_list *rr_list, ldns_rr *rr); 
+-
+-/**
+- * checks if an rr_list is a rrset.
+- * \param[in] rr_list the rr_list to check
+- * \return true if it is an rrset otherwise false
+- */
+-bool ldns_is_rrset(ldns_rr_list *rr_list);
+-
+-/**
+- * pushes an rr to an rrset (which really are rr_list's).
+- * \param[in] *rr_list the rrset to push the rr to
+- * \param[in] *rr the rr to push
+- * \return true if the push succeeded otherwise false
+- */
+-bool ldns_rr_set_push_rr(ldns_rr_list *rr_list, ldns_rr *rr);
+-
+-/**
+- * pops the last rr from an rrset. This function is there only
+- * for the symmetry.
+- * \param[in] rr_list the rr_list to pop from
+- * \return NULL if nothing to pop. Otherwise the popped RR
+- *
+- */
+-ldns_rr* ldns_rr_set_pop_rr(ldns_rr_list *rr_list);
+-
+-/**
+- * pops the first rrset from the list,
+- * the list must be sorted, so that all rr's from each rrset
+- * are next to each other
+- */
+-ldns_rr_list *ldns_rr_list_pop_rrset(ldns_rr_list *rr_list);
+-
+-
+-/**
+- * retrieves a rrtype by looking up its name.
+- * \param[in] name a string with the name
+- * \return the type which corresponds with the name
+- */
+-ldns_rr_type ldns_get_rr_type_by_name(const char *name);
+-
+-/**
+- * retrieves a class by looking up its name.
+- * \param[in] name string with the name
+- * \return the cass which corresponds with the name
+- */
+-ldns_rr_class ldns_get_rr_class_by_name(const char *name);
+-
+-/**
+- * clones a rr and all its data
+- * \param[in] rr the rr to clone
+- * \return the new rr or NULL on failure
+- */
+-ldns_rr* ldns_rr_clone(const ldns_rr *rr);
+-
+-/**
+- * clones an rrlist.
+- * \param[in] rrlist the rrlist to clone
+- * \return the cloned rr list
+- */
+-ldns_rr_list* ldns_rr_list_clone(const ldns_rr_list *rrlist);
+-
+-/**
+- * sorts an rr_list (canonical wire format). the sorting is done inband.
+- * \param[in] unsorted the rr_list to be sorted
+- * \return void
+- */
+-void ldns_rr_list_sort(ldns_rr_list *unsorted);
+-
+-/**
+- * compares two rrs. The TTL is not looked at.
+- * \param[in] rr1 the first one
+- * \param[in] rr2 the second one
+- * \return 0 if equal
+- *         -1 if rr1 comes before rr2
+- *         +1 if rr2 comes before rr1
+- */
+-int ldns_rr_compare(const ldns_rr *rr1, const ldns_rr *rr2);
+-
+-/**
+- * compares two rrs, up to the rdata.
+- * \param[in] rr1 the first one
+- * \param[in] rr2 the second one
+- * \return 0 if equal
+- *         -1 if rr1 comes before rr2
+- *         +1 if rr2 comes before rr1
+- */
+-int ldns_rr_compare_no_rdata(const ldns_rr *rr1, const ldns_rr *rr2);
+-
+-/**
+- * compares the wireformat of two rrs, contained in the given buffers.
+- * \param[in] rr1_buf the first one
+- * \param[in] rr2_buf the second one
+- * \return 0 if equal
+- *         -1 if rr1_buf comes before rr2_buf
+- *         +1 if rr2_buf comes before rr1_buf
+- */
+-int ldns_rr_compare_wire(ldns_buffer *rr1_buf, ldns_buffer *rr2_buf);
+-
+-/**
+- * returns true of the given rr's are equal.
+- * Also returns true if one record is a DS that represents the
+- * same DNSKEY record as the other record
+- * \param[in] rr1 the first rr
+- * \param[in] rr2 the second rr
+- * \return true if equal otherwise false
+- */
+-bool ldns_rr_compare_ds(const ldns_rr *rr1, const ldns_rr *rr2);
+-
+-/**
+- * compares two rr listss.
+- * \param[in] rrl1 the first one
+- * \param[in] rrl2 the second one
+- * \return 0 if equal
+- *         -1 if rrl1 comes before rrl2
+- *         +1 if rrl2 comes before rrl1
+- */
+-int ldns_rr_list_compare(const ldns_rr_list *rrl1, const ldns_rr_list *rrl2);
+-
+-/** 
+- * calculates the uncompressed size of an RR.
+- * \param[in] r the rr to operate on
+- * \return size of the rr
+- */
+-size_t ldns_rr_uncompressed_size(const ldns_rr *r);
+-
+-/** 
+- * converts each dname in a rr to its canonical form.
+- * \param[in] rr the rr to work on
+- * \return void
+- */
+-void ldns_rr2canonical(ldns_rr *rr);
+-
+-/** 
+- * converts each dname in each rr in a rr_list to its canonical form.
+- * \param[in] rr_list the rr_list to work on
+- * \return void
+- */
+-void ldns_rr_list2canonical(ldns_rr_list *rr_list);
+-
+-/** 
+- * counts the number of labels of the ownername.
+- * \param[in] rr count the labels of this rr
+- * \return the number of labels
+- */
+-uint8_t ldns_rr_label_count(ldns_rr *rr);
+-
+-/**
+- * returns the resource record descriptor for the given rr type.
+- *
+- * \param[in] type the type value of the rr type
+- *\return the ldns_rr_descriptor for this type
+- */
+-const ldns_rr_descriptor *ldns_rr_descript(uint16_t type);
+-
+-/**
+- * returns the minimum number of rdata fields of the rr type this descriptor describes.
+- *
+- * \param[in]  descriptor for an rr type
+- * \return the minimum number of rdata fields
+- */
+-size_t ldns_rr_descriptor_minimum(const ldns_rr_descriptor *descriptor);
+-
+-/**
+- * returns the maximum number of rdata fields of the rr type this descriptor describes.
+- *
+- * \param[in]  descriptor for an rr type
+- * \return the maximum number of rdata fields
+- */
+-size_t ldns_rr_descriptor_maximum(const ldns_rr_descriptor *descriptor);
+-
+-/**
+- * returns the rdf type for the given rdata field number of the rr type for the given descriptor.
+- *
+- * \param[in] descriptor for an rr type
+- * \param[in] field the field number
+- * \return the rdf type for the field
+- */
+-ldns_rdf_type ldns_rr_descriptor_field_type(const ldns_rr_descriptor *descriptor, size_t field);
+-
+-/**
+- * Return the rr_list which matches the rdf at position field. Think
+- * type-covered stuff for RRSIG
+- * 
+- * \param[in] l the rr_list to look in
+- * \param[in] r the rdf to use for the comparison
+- * \param[in] pos at which position can we find the rdf
+- * 
+- * \return a new rr list with only the RRs that match 
+- *
+- */
+-ldns_rr_list *ldns_rr_list_subtype_by_rdf(ldns_rr_list *l, ldns_rdf *r, size_t pos);
+-
+-/**
+- * convert an rdf of type LDNS_RDF_TYPE_TYPE to an actual
+- * LDNS_RR_TYPE. This is usefull in the case when inspecting
+- * the rrtype covered field of an RRSIG.
+- * \param[in] rd the rdf to look at
+- * \return a ldns_rr_type with equivalent LDNS_RR_TYPE
+- *
+- */
+-ldns_rr_type    ldns_rdf2rr_type(const ldns_rdf *rd);
+-
+-/**
+- * Returns the type of the first element of the RR
+- * If there are no elements present, 0 is returned
+- * 
+- * \param[in] rr_list The rr list
+- * \return rr_type of the first element, or 0 if the list is empty
+- */
+-ldns_rr_type
+-ldns_rr_list_type(const ldns_rr_list *rr_list);
+-
+-/**
+- * Returns the owner domain name rdf of the first element of the RR
+- * If there are no elements present, NULL is returned
+- * 
+- * \param[in] rr_list The rr list
+- * \return dname of the first element, or NULL if the list is empty
+- */
+-ldns_rdf *
+-ldns_rr_list_owner(const ldns_rr_list *rr_list);
+-
+-#ifdef __cplusplus
+-}
+-#endif
+-
+-#endif /* LDNS_RR_H */
+diff --git a/include/ldns/rr_functions.h b/include/ldns/rr_functions.h
+deleted file mode 100644
+index 09a28dd..0000000
+--- a/include/ldns/rr_functions.h
++++ /dev/null
+@@ -1,363 +0,0 @@
+-/*
+- * rr_functions.h
+- *
+- * the .h file with defs for the per rr
+- * functions
+- *
+- * a Net::DNS like library for C
+- * 
+- * (c) NLnet Labs, 2005-2006
+- * 
+- * See the file LICENSE for the license
+- */
+-#ifndef LDNS_RR_FUNCTIONS_H
+-#define LDNS_RR_FUNCTIONS_H
+-
+-#ifdef __cplusplus
+-extern "C" {
+-#endif
+-
+-/**
+- * \file
+- *
+- * Defines some extra convenience functions for ldns_rr structures
+- */
+-
+-/* A / AAAA */
+-/**
+- * returns the address of a LDNS_RR_TYPE_A rr
+- * \param[in] r the resource record
+- * \return a ldns_rdf* with the address or NULL on failure
+- */
+-ldns_rdf* ldns_rr_a_address(const ldns_rr *r);
+-
+-/**
+- * sets the address of a LDNS_RR_TYPE_A rr
+- * \param[in] r the rr to use
+- * \param[in] f the address to set
+- * \return true on success, false otherwise
+- */
+-bool ldns_rr_a_set_address(ldns_rr *r, ldns_rdf *f);
+-
+-/* NS */
+-/**
+- * returns the name of a LDNS_RR_TYPE_NS rr
+- * \param[in] r the resource record
+- * \return a ldns_rdf* with the name or NULL on failure
+- */
+-ldns_rdf* ldns_rr_ns_nsdname(const ldns_rr *r);
+-
+-/* MX */
+-/**
+- * returns the mx pref. of a LDNS_RR_TYPE_MX rr
+- * \param[in] r the resource record
+- * \return a ldns_rdf* with the preference or NULL on failure
+- */
+-ldns_rdf* ldns_rr_mx_preference(const ldns_rr *r);
+-/**
+- * returns the mx host of a LDNS_RR_TYPE_MX rr
+- * \param[in] r the resource record
+- * \return a ldns_rdf* with the name of the MX host or NULL on failure
+- */
+-ldns_rdf* ldns_rr_mx_exchange(const ldns_rr *r);
+-
+-/* RRSIG */
+-/**
+- * returns the type covered of a LDNS_RR_TYPE_RRSIG rr
+- * \param[in] r the resource record
+- * \return a ldns_rdf* with the type covered or NULL on failure
+- */
+-ldns_rdf* ldns_rr_rrsig_typecovered(const ldns_rr *r);
+-/**
+- * sets the typecovered of a LDNS_RR_TYPE_RRSIG rr
+- * \param[in] r the rr to use
+- * \param[in] f the typecovered to set
+- * \return true on success, false otherwise
+- */
+-bool ldns_rr_rrsig_set_typecovered(ldns_rr *r, ldns_rdf *f);
+-/**
+- * returns the algorithm of a LDNS_RR_TYPE_RRSIG RR
+- * \param[in] r the resource record
+- * \return a ldns_rdf* with the algorithm or NULL on failure
+- */
+-ldns_rdf* ldns_rr_rrsig_algorithm(const ldns_rr *r);
+-/**
+- * sets the algorithm of a LDNS_RR_TYPE_RRSIG rr
+- * \param[in] r the rr to use
+- * \param[in] f the algorithm to set
+- * \return true on success, false otherwise
+- */
+-bool ldns_rr_rrsig_set_algorithm(ldns_rr *r, ldns_rdf *f);
+-/**
+- * returns the number of labels of a LDNS_RR_TYPE_RRSIG RR
+- * \param[in] r the resource record
+- * \return a ldns_rdf* with the number of labels or NULL on failure
+- */
+-ldns_rdf *ldns_rr_rrsig_labels(const ldns_rr *r);
+-/**
+- * sets the number of labels of a LDNS_RR_TYPE_RRSIG rr
+- * \param[in] r the rr to use
+- * \param[in] f the number of labels to set
+- * \return true on success, false otherwise
+- */
+-bool ldns_rr_rrsig_set_labels(ldns_rr *r, ldns_rdf *f);
+-/**
+- * returns the original TTL of a LDNS_RR_TYPE_RRSIG RR
+- * \param[in] r the resource record
+- * \return a ldns_rdf* with the original TTL or NULL on failure
+- */
+-ldns_rdf* ldns_rr_rrsig_origttl(const ldns_rr *r);
+-/**
+- * sets the original TTL of a LDNS_RR_TYPE_RRSIG rr
+- * \param[in] r the rr to use
+- * \param[in] f the original TTL to set
+- * \return true on success, false otherwise
+- */
+-bool ldns_rr_rrsig_set_origttl(ldns_rr *r, ldns_rdf *f);
+-/**
+- * returns the expiration time of a LDNS_RR_TYPE_RRSIG RR
+- * \param[in] r the resource record
+- * \return a ldns_rdf* with the expiration time or NULL on failure
+- */
+-ldns_rdf* ldns_rr_rrsig_expiration(const ldns_rr *r);
+-/**
+- * sets the expireation date of a LDNS_RR_TYPE_RRSIG rr
+- * \param[in] r the rr to use
+- * \param[in] f the expireation date to set
+- * \return true on success, false otherwise
+- */
+-bool ldns_rr_rrsig_set_expiration(ldns_rr *r, ldns_rdf *f);
+-/**
+- * returns the inception time of a LDNS_RR_TYPE_RRSIG RR
+- * \param[in] r the resource record
+- * \return a ldns_rdf* with the inception time or NULL on failure
+- */
+-ldns_rdf* ldns_rr_rrsig_inception(const ldns_rr *r);
+-/**
+- * sets the inception date of a LDNS_RR_TYPE_RRSIG rr
+- * \param[in] r the rr to use
+- * \param[in] f the inception date to set
+- * \return true on success, false otherwise
+- */
+-bool ldns_rr_rrsig_set_inception(ldns_rr *r, ldns_rdf *f);
+-/**
+- * returns the keytag of a LDNS_RR_TYPE_RRSIG RR
+- * \param[in] r the resource record
+- * \return a ldns_rdf* with the keytag or NULL on failure
+- */
+-ldns_rdf* ldns_rr_rrsig_keytag(const ldns_rr *r);
+-/**
+- * sets the keytag of a LDNS_RR_TYPE_RRSIG rr
+- * \param[in] r the rr to use
+- * \param[in] f the keytag to set
+- * \return true on success, false otherwise
+- */
+-bool ldns_rr_rrsig_set_keytag(ldns_rr *r, ldns_rdf *f);
+-/**
+- * returns the signers name of a LDNS_RR_TYPE_RRSIG RR
+- * \param[in] r the resource record
+- * \return a ldns_rdf* with the signers name or NULL on failure
+- */
+-ldns_rdf* ldns_rr_rrsig_signame(const ldns_rr *r);
+-/**
+- * sets the signers name of a LDNS_RR_TYPE_RRSIG rr
+- * \param[in] r the rr to use
+- * \param[in] f the signers name to set
+- * \return true on success, false otherwise
+- */
+-bool ldns_rr_rrsig_set_signame(ldns_rr *r, ldns_rdf *f);
+-/**
+- * returns the signature data of a LDNS_RR_TYPE_RRSIG RR
+- * \param[in] r the resource record
+- * \return a ldns_rdf* with the signature data or NULL on failure
+- */
+-ldns_rdf* ldns_rr_rrsig_sig(const ldns_rr *r);
+-/**
+- * sets the signature data of a LDNS_RR_TYPE_RRSIG rr
+- * \param[in] r the rr to use
+- * \param[in] f the signature data to set
+- * \return true on success, false otherwise
+- */
+-bool ldns_rr_rrsig_set_sig(ldns_rr *r, ldns_rdf *f);
+-
+-/* DNSKEY */
+-/**
+- * returns the flags of a LDNS_RR_TYPE_DNSKEY rr
+- * \param[in] r the resource record
+- * \return a ldns_rdf* with the flags or NULL on failure
+- */
+-ldns_rdf* ldns_rr_dnskey_flags(const ldns_rr *r);
+-/**
+- * sets the flags of a LDNS_RR_TYPE_DNSKEY rr
+- * \param[in] r the rr to use
+- * \param[in] f the flags to set
+- * \return true on success, false otherwise
+- */
+-bool ldns_rr_dnskey_set_flags(ldns_rr *r, ldns_rdf *f);
+-/**
+- * returns the protocol of a LDNS_RR_TYPE_DNSKEY rr
+- * \param[in] r the resource record
+- * \return a ldns_rdf* with the protocol or NULL on failure
+- */
+-ldns_rdf* ldns_rr_dnskey_protocol(const ldns_rr *r);
+-/**
+- * sets the protocol of a LDNS_RR_TYPE_DNSKEY rr
+- * \param[in] r the rr to use
+- * \param[in] f the protocol to set
+- * \return true on success, false otherwise
+- */
+-bool ldns_rr_dnskey_set_protocol(ldns_rr *r, ldns_rdf *f);
+-/**
+- * returns the algorithm of a LDNS_RR_TYPE_DNSKEY rr
+- * \param[in] r the resource record
+- * \return a ldns_rdf* with the algorithm or NULL on failure
+- */
+-ldns_rdf* ldns_rr_dnskey_algorithm(const ldns_rr *r);
+-/**
+- * sets the algorithm of a LDNS_RR_TYPE_DNSKEY rr
+- * \param[in] r the rr to use
+- * \param[in] f the algorithm to set
+- * \return true on success, false otherwise
+- */
+-bool ldns_rr_dnskey_set_algorithm(ldns_rr *r, ldns_rdf *f);
+-/**
+- * returns the key data of a LDNS_RR_TYPE_DNSKEY rr
+- * \param[in] r the resource record
+- * \return a ldns_rdf* with the key data or NULL on failure
+- */
+-ldns_rdf* ldns_rr_dnskey_key(const ldns_rr *r);
+-/**
+- * sets the key data of a LDNS_RR_TYPE_DNSKEY rr
+- * \param[in] r the rr to use
+- * \param[in] f the key data to set
+- * \return true on success, false otherwise
+- */
+-bool ldns_rr_dnskey_set_key(ldns_rr *r, ldns_rdf *f);
+-
+-/**
+- * get the length of the keydata in bits
+- * \param[in] keydata the raw key data
+- * \param[in] len the length of the keydata
+- * \param[in] alg the cryptographic algorithm this is a key for
+- * \return the keysize in bits, or 0 on error
+- */
+-size_t ldns_rr_dnskey_key_size_raw(const unsigned char *keydata,
+-                                   const size_t len,
+-                                   const ldns_algorithm alg);
+-
+-/**
+- * get the length of the keydata in bits
+- * \param[in] key the key rr to use
+- * \return the keysize in bits
+- */
+-size_t ldns_rr_dnskey_key_size(const ldns_rr *key);
+-
+-/**
+- * The type of function to be passed to ldns_rr_soa_increment_func,
+- * ldns_rr_soa_increment_func_data or ldns_rr_soa_increment_int.
+- * The function will be called with as the first argument the current serial
+- * number of the SOA RR to be updated, and as the second argument a value
+- * given when calling ldns_rr_soa_increment_func_data or 
+- * ldns_rr_soa_increment_int. With ldns_rr_soa_increment_int the pointer
+- * value holds the integer value passed to ldns_rr_soa_increment_int,
+- * and it should be cast to intptr_t to be used as an integer by the
+- * serial modifying function.
+- */
+-typedef uint32_t (*ldns_soa_serial_increment_func_t)(uint32_t, void*);
+-
+-/**
+- * Function to be used with dns_rr_soa_increment_func_int, to set the soa
+- * serial number. 
+- * \param[in] unused the (unused) current serial number.
+- * \param[in] data the serial number to be set.
+- */
+-uint32_t ldns_soa_serial_identity(uint32_t unused, void *data);
+-
+-/**
+- * Function to be used with dns_rr_soa_increment_func, to increment the soa
+- * serial number with one. 
+- * \param[in] s the current serial number.
+- * \param[in] unused unused.
+- */
+-uint32_t ldns_soa_serial_increment(uint32_t s, void *unused);
+-
+-/**
+- * Function to be used with dns_rr_soa_increment_func_int, to increment the soa
+- * serial number with a certain amount. 
+- * \param[in] s the current serial number.
+- * \param[in] data the amount to add to the current serial number.
+- */
+-uint32_t ldns_soa_serial_increment_by(uint32_t s, void *data);
+-
+-/**
+- * Function to be used with ldns_rr_soa_increment_func or 
+- * ldns_rr_soa_increment_func_int to set the soa serial to the number of 
+- * seconds since unix epoch (1-1-1970 00:00). 
+- * When data is given (i.e. the function is called via
+- * ldns_rr_soa_increment_func_int), it is used as the current time. 
+- * When the resulting serial number is smaller than the current serial number,
+- * the current serial number is increased by one.
+- * \param[in] s the current serial number.
+- * \param[in] data the time in seconds since 1-1-1970 00:00
+- */
+-uint32_t ldns_soa_serial_unixtime(uint32_t s, void *data);
+-
+-/**
+- * Function to be used with ldns_rr_soa_increment_func or 
+- * ldns_rr_soa_increment_func_int to set the soa serial to the current date
+- * succeeded by a two digit iteration (datecounter).
+- * When data is given (i.e. the function is called via
+- * ldns_rr_soa_increment_func_int), it is used as the current time. 
+- * When the resulting serial number is smaller than the current serial number,
+- * the current serial number is increased by one.
+- * \param[in] s the current serial number.
+- * \param[in] data the time in seconds since 1-1-1970 00:00
+- */
+-uint32_t ldns_soa_serial_datecounter(uint32_t s, void *data);
+-
+-/**
+- * Increment the serial number of the given SOA by one.
+- * \param[in] soa The soa rr to be incremented
+- */
+-void ldns_rr_soa_increment(
+-		ldns_rr *soa);
+-
+-/**
+- * Increment the serial number of the given SOA with the given function.
+- * Included functions to be used here are: ldns_rr_soa_increment, 
+- * ldns_soa_serial_unixtime and ldns_soa_serial_datecounter.
+- * \param[in] soa The soa rr to be incremented
+- * \param[in] f the function to use to increment the soa rr.
+- */
+-void ldns_rr_soa_increment_func(
+-		ldns_rr *soa, ldns_soa_serial_increment_func_t f);
+-
+-/**
+- * Increment the serial number of the given SOA with the given function
+- * passing it the given data argument.
+- * \param[in] soa The soa rr to be incremented
+- * \param[in] f the function to use to increment the soa rr.
+- * \param[in] data this argument will be passed to f as the second argument.
+- */
+-void ldns_rr_soa_increment_func_data(
+-		ldns_rr *soa, ldns_soa_serial_increment_func_t f, void *data);
+-
+-/**
+- * Increment the serial number of the given SOA with the given function
+- * using data as an argument for the function.
+- * Included functions to be used here are: ldns_soa_serial_identity,
+- * ldns_rr_soa_increment_by, ldns_soa_serial_unixtime and 
+- * ldns_soa_serial_datecounter.
+- * \param[in] soa The soa rr to be incremented
+- * \param[in] f the function to use to increment the soa rr.
+- * \param[in] data this argument will be passed to f as the second argument
+- *                 (by casting it to void*).
+- */
+-void ldns_rr_soa_increment_func_int(
+-		ldns_rr *soa, ldns_soa_serial_increment_func_t f, int data);
+-
+-#ifdef __cplusplus
+-}
+-#endif
+-
+-#endif /* LDNS_RR_FUNCTIONS_H */
+diff --git a/include/ldns/sha1.h b/include/ldns/sha1.h
+deleted file mode 100644
+index d5b1082..0000000
+--- a/include/ldns/sha1.h
++++ /dev/null
+@@ -1,38 +0,0 @@
+-#ifndef LDNS_SHA1_H
+-#define LDNS_SHA1_H
+-
+-#ifdef __cplusplus
+-extern "C" {
+-#endif
+- 
+-#define LDNS_SHA1_BLOCK_LENGTH               64
+-#define LDNS_SHA1_DIGEST_LENGTH              20
+-
+-typedef struct {
+-        uint32_t       state[5];
+-        uint64_t       count;
+-        unsigned char   buffer[LDNS_SHA1_BLOCK_LENGTH];
+-} ldns_sha1_ctx;
+-  
+-void ldns_sha1_init(ldns_sha1_ctx * context);
+-void ldns_sha1_transform(uint32_t state[5], const unsigned char buffer[LDNS_SHA1_BLOCK_LENGTH]);
+-void ldns_sha1_update(ldns_sha1_ctx *context, const unsigned char *data, unsigned int len);
+-void ldns_sha1_final(unsigned char digest[LDNS_SHA1_DIGEST_LENGTH], ldns_sha1_ctx *context);
+-
+-/**
+- * Convenience function to digest a fixed block of data at once.
+- *
+- * \param[in] data the data to digest
+- * \param[in] data_len the length of data in bytes
+- * \param[out] digest the length of data in bytes
+- *             This pointer MUST have LDNS_SHA1_DIGEST_LENGTH bytes
+- *             available
+- * \return the SHA1 digest of the given data
+- */
+-unsigned char *ldns_sha1(unsigned char *data, unsigned int data_len, unsigned char *digest);
+-
+-#ifdef __cplusplus
+-}
+-#endif
+-
+-#endif /* LDNS_SHA1_H */
+diff --git a/include/ldns/sha2.h b/include/ldns/sha2.h
+deleted file mode 100644
+index 238767a..0000000
+--- a/include/ldns/sha2.h
++++ /dev/null
+@@ -1,149 +0,0 @@
+-/*
+- * FILE:	sha2.h
+- * AUTHOR:	Aaron D. Gifford - http://www.aarongifford.com/
+- * 
+- * Copyright (c) 2000-2001, Aaron D. Gifford
+- * All rights reserved.
+- *
+- * Modified by Jelte Jansen to fit in ldns, and not clash with any
+- * system-defined SHA code.
+- * Changes:
+- *  - Renamed (external) functions and constants to fit ldns style
+- *  - Removed uintXX vs. u_intXX smartness, since ldns needs uintXX
+- *    anyway
+- *  - BYTE ORDER check replaced by simple ifdef as defined or not by
+- *    configure.ac
+- *  - Removed _End and _Data functions
+- *  - Added ldns_shaX(data, len, digest) functions
+- * 
+- * 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.
+- * 3. Neither the name of the copyright holder nor the names of contributors
+- *    may be used to endorse or promote products derived from this software
+- *    without specific prior written permission.
+- * 
+- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``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 OR CONTRIBUTOR(S) 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.
+- *
+- * $Id: sha2.h,v 1.1 2001/11/08 00:02:01 adg Exp adg $
+- */
+-
+-#ifndef __LDNS_SHA2_H__
+-#define __LDNS_SHA2_H__
+-
+-#ifdef __cplusplus
+-extern "C" {
+-#endif
+-
+-
+-/*
+- * Import u_intXX_t size_t type definitions from system headers.  You
+- * may need to change this, or define these things yourself in this
+- * file.
+- */
+-#include <sys/types.h>
+-
+-#if LDNS_BUILD_CONFIG_HAVE_INTTYPES_H
+-
+-#include <inttypes.h>
+-
+-#endif /* LDNS_BUILD_CONFIG_HAVE_INTTYPES_H */
+-
+-
+-/*** SHA-256/384/512 Various Length Definitions ***********************/
+-#define LDNS_SHA256_BLOCK_LENGTH		64
+-#define LDNS_SHA256_DIGEST_LENGTH		32
+-#define LDNS_SHA256_DIGEST_STRING_LENGTH	(LDNS_SHA256_DIGEST_LENGTH * 2 + 1)
+-#define LDNS_SHA384_BLOCK_LENGTH		128
+-#define LDNS_SHA384_DIGEST_LENGTH		48
+-#define LDNS_SHA384_DIGEST_STRING_LENGTH	(LDNS_SHA384_DIGEST_LENGTH * 2 + 1)
+-#define LDNS_SHA512_BLOCK_LENGTH		128
+-#define LDNS_SHA512_DIGEST_LENGTH		64
+-#define LDNS_SHA512_DIGEST_STRING_LENGTH	(LDNS_SHA512_DIGEST_LENGTH * 2 + 1)
+-
+-
+-/*** SHA-256/384/512 Context Structures *******************************/
+-
+-typedef struct _ldns_sha256_CTX {
+-	uint32_t	state[8];
+-	uint64_t	bitcount;
+-	uint8_t	buffer[LDNS_SHA256_BLOCK_LENGTH];
+-} ldns_sha256_CTX;
+-typedef struct _ldns_sha512_CTX {
+-	uint64_t	state[8];
+-	uint64_t	bitcount[2];
+-	uint8_t	buffer[LDNS_SHA512_BLOCK_LENGTH];
+-} ldns_sha512_CTX;
+-
+-typedef ldns_sha512_CTX ldns_sha384_CTX;
+-
+-
+-/*** SHA-256/384/512 Function Prototypes ******************************/
+-void ldns_sha256_init(ldns_sha256_CTX *);
+-void ldns_sha256_update(ldns_sha256_CTX*, const uint8_t*, size_t);
+-void ldns_sha256_final(uint8_t[LDNS_SHA256_DIGEST_LENGTH], ldns_sha256_CTX*);
+-
+-void ldns_sha384_init(ldns_sha384_CTX*);
+-void ldns_sha384_update(ldns_sha384_CTX*, const uint8_t*, size_t);
+-void ldns_sha384_final(uint8_t[LDNS_SHA384_DIGEST_LENGTH], ldns_sha384_CTX*);
+-
+-void ldns_sha512_init(ldns_sha512_CTX*);
+-void ldns_sha512_update(ldns_sha512_CTX*, const uint8_t*, size_t);
+-void ldns_sha512_final(uint8_t[LDNS_SHA512_DIGEST_LENGTH], ldns_sha512_CTX*);
+-
+-/**
+- * Convenience function to digest a fixed block of data at once.
+- *
+- * \param[in] data the data to digest
+- * \param[in] data_len the length of data in bytes
+- * \param[out] digest the length of data in bytes
+- *             This pointer MUST have LDNS_SHA256_DIGEST_LENGTH bytes
+- *             available
+- * \return the SHA1 digest of the given data
+- */
+-unsigned char *ldns_sha256(unsigned char *data, unsigned int data_len, unsigned char *digest);
+-
+-/**
+- * Convenience function to digest a fixed block of data at once.
+- *
+- * \param[in] data the data to digest
+- * \param[in] data_len the length of data in bytes
+- * \param[out] digest the length of data in bytes
+- *             This pointer MUST have LDNS_SHA384_DIGEST_LENGTH bytes
+- *             available
+- * \return the SHA1 digest of the given data
+- */
+-unsigned char *ldns_sha384(unsigned char *data, unsigned int data_len, unsigned char *digest);
+-
+-/**
+- * Convenience function to digest a fixed block of data at once.
+- *
+- * \param[in] data the data to digest
+- * \param[in] data_len the length of data in bytes
+- * \param[out] digest the length of data in bytes
+- *             This pointer MUST have LDNS_SHA512_DIGEST_LENGTH bytes
+- *             available
+- * \return the SHA1 digest of the given data
+- */
+-unsigned char *ldns_sha512(unsigned char *data, unsigned int data_len, unsigned char *digest);
+-
+-#ifdef	__cplusplus
+-}
+-#endif /* __cplusplus */
+-
+-#endif /* __LDNS_SHA2_H__ */
+diff --git a/include/ldns/str2host.h b/include/ldns/str2host.h
+deleted file mode 100644
+index d639970..0000000
+--- a/include/ldns/str2host.h
++++ /dev/null
+@@ -1,319 +0,0 @@
+-/**
+- * str2host.h - conversion from str to the host fmt
+- *
+- * a Net::DNS like library for C
+- *
+- * (c) NLnet Labs, 2005-2006
+- *
+- * See the file LICENSE for the license
+- */
+-
+-#ifndef LDNS_2HOST_H
+-#define LDNS_2HOST_H
+-
+-#include <ldns/common.h>
+-#include <ldns/error.h>
+-#include <ldns/rr.h>
+-#include <ldns/rdata.h>
+-#include <ldns/packet.h>
+-#include <ldns/buffer.h>
+-#include <ctype.h>
+-
+-#ifdef __cplusplus
+-extern "C" {
+-#endif
+-
+-/**
+- * \file
+- *
+- * Defines functions to convert dns data in presentation format or text files
+- * to internal structures.
+- */
+-
+-/**
+- * convert a byte into wireformat
+- * \param[in] rd the rdf where to put the data
+- * \param[in] bytestr the string to be converted
+- * \return ldns_status
+- */
+-ldns_status ldns_str2rdf_int8(ldns_rdf **rd, const char *bytestr);
+-
+-/**
+- * convert a string to a int16 in wireformat
+- * \param[in] rd the rdf where to put the data
+- * \param[in] shortstr the string to be converted
+- * \return ldns_status
+- */
+-ldns_status ldns_str2rdf_int16(ldns_rdf **rd, const char *shortstr);
+-
+-/**
+- * convert a strings into a 4 byte int in wireformat
+- * \param[in] rd the rdf where to put the data
+- * \param[in] longstr the string to be converted
+- * \return ldns_status
+- */
+-ldns_status ldns_str2rdf_int32(ldns_rdf **rd, const char *longstr);
+-
+-/**
+- * convert a time string to a time value in wireformat
+- * \param[in] rd the rdf where to put the data
+- * \param[in] time the string to be converted
+- * \return ldns_status
+- */
+-ldns_status ldns_str2rdf_time(ldns_rdf **rd, const char *time);
+-
+-/* convert string with NSEC3 salt to wireformat) 
+- * \param[in] rd the rdf where to put the data
+- * \param[in] str the string to be converted
+- * return ldns_status
+- */
+-ldns_status ldns_str2rdf_nsec3_salt(ldns_rdf **rd, const char *nsec3_salt);
+-
+-/* convert a time period (think TTL's) to wireformat) 
+- * \param[in] rd the rdf where to put the data
+- * \param[in] str the string to be converted
+- * return ldns_status
+- */
+-ldns_status ldns_str2rdf_period(ldns_rdf **rd, const char *str);
+-
+-/**
+- * convert str with an A record into wireformat
+- * \param[in] rd the rdf where to put the data
+- * \param[in] str the string to be converted
+- * \return ldns_status
+- */
+-ldns_status ldns_str2rdf_a(ldns_rdf **rd, const char *str);
+-
+-/**
+- * convert the str with an AAAA record into wireformat
+- * \param[in] rd the rdf where to put the data
+- * \param[in] str the string to be converted
+- * \return ldns_status
+- */
+-ldns_status ldns_str2rdf_aaaa(ldns_rdf **rd, const char *str);
+-
+-/**
+- * convert a string into wireformat (think txt record)
+- * \param[in] rd the rdf where to put the data
+- * \param[in] str the string to be converted (NULL terminated)
+- * \return ldns_status
+- */
+-ldns_status ldns_str2rdf_str(ldns_rdf **rd, const char *str);
+-
+-/**
+- * convert str with the apl record into wireformat
+- * \param[in] rd the rdf where to put the data
+- * \param[in] str the string to be converted
+- * \return ldns_status
+- */
+-ldns_status ldns_str2rdf_apl(ldns_rdf **rd, const char *str);
+-
+-/**
+- * convert the string with the b64 data into wireformat
+- * \param[in] rd the rdf where to put the data
+- * \param[in] str the string to be converted
+- * \return ldns_status
+- */
+-ldns_status ldns_str2rdf_b64(ldns_rdf **rd, const char *str);
+-
+-/**
+- * convert the string with the b32 ext hex data into wireformat
+- * \param[in] rd the rdf where to put the data
+- * \param[in] str the string to be converted
+- * \return ldns_status
+- */
+-ldns_status ldns_str2rdf_b32_ext(ldns_rdf **rd, const char *str);
+-
+-/**
+- * convert a hex value into wireformat
+- * \param[in] rd the rdf where to put the data
+- * \param[in] str the string to be converted
+- * \return ldns_status
+- */
+-ldns_status ldns_str2rdf_hex(ldns_rdf **rd, const char *str);
+-
+-/**
+- * convert string with nsec into wireformat
+- * \param[in] rd the rdf where to put the data
+- * \param[in] str the string to be converted
+- * \return ldns_status
+- */
+-ldns_status ldns_str2rdf_nsec(ldns_rdf **rd, const char *str);
+-
+-/**
+- * convert a rrtype into wireformat
+- * \param[in] rd the rdf where to put the data
+- * \param[in] str the string to be converted
+- * \return ldns_status
+- */
+-ldns_status ldns_str2rdf_type(ldns_rdf **rd, const char *str);
+-
+-/**
+- * convert string with a classname into wireformat
+- * \param[in] rd the rdf where to put the data
+- * \param[in] str the string to be converted
+- * \return ldns_status
+- */
+-ldns_status ldns_str2rdf_class(ldns_rdf **rd, const char *str);
+-
+-/**
+- * convert an certificate algorithm value into wireformat
+- * \param[in] rd the rdf where to put the data
+- * \param[in] str the string to be converted
+- * \return ldns_status
+- */
+-ldns_status ldns_str2rdf_cert_alg(ldns_rdf **rd, const char *str);
+-
+-/**
+- * convert an algorithm value into wireformat
+- * \param[in] rd the rdf where to put the data
+- * \param[in] str the string to be converted
+- * \return ldns_status
+- */
+-ldns_status ldns_str2rdf_alg(ldns_rdf **rd, const char *str);
+-
+-/**
+- * convert a tlsa certificate usage value into wireformat
+- * \param[in] rd the rdf where to put the data
+- * \param[in] str the string to be converted
+- * \return ldns_status
+- */
+-ldns_status ldns_str2rdf_certificate_usage(ldns_rdf **rd, const char *str);
+-
+-/**
+- * convert a tlsa selector value into wireformat
+- * \param[in] rd the rdf where to put the data
+- * \param[in] str the string to be converted
+- * \return ldns_status
+- */
+-ldns_status ldns_str2rdf_selector(ldns_rdf **rd, const char *str);
+-
+-/**
+- * convert a tlsa matching type value into wireformat
+- * \param[in] rd the rdf where to put the data
+- * \param[in] str the string to be converted
+- * \return ldns_status
+- */
+-ldns_status ldns_str2rdf_matching_type(ldns_rdf **rd, const char *str);
+-
+-/**
+- * convert a string with a unknown RR into wireformat
+- * \param[in] rd the rdf where to put the data
+- * \param[in] str the string to be converted
+- * \return ldns_status
+- */
+-ldns_status ldns_str2rdf_unknown(ldns_rdf **rd, const char *str);
+-
+-/**
+- * convert string with a protocol service into wireformat
+- * \param[in] rd the rdf where to put the data
+- * \param[in] str the string to be converted
+- * \return ldns_status
+- */
+-ldns_status ldns_str2rdf_service(ldns_rdf **rd, const char *str);
+-
+-/**
+- * convert a string with a LOC RR into wireformat
+- * \param[in] rd the rdf where to put the data
+- * \param[in] str the string to be converted
+- * \return ldns_status
+- */
+-ldns_status ldns_str2rdf_loc(ldns_rdf **rd, const char *str);
+-
+-/**
+- * convert string with a WKS RR into wireformat
+- * \param[in] rd the rdf where to put the data
+- * \param[in] str the string to be converted
+- * \return ldns_status
+- */
+-ldns_status ldns_str2rdf_wks(ldns_rdf **rd, const char *str);
+-
+-/**
+- * convert a str with a NSAP RR into wireformat
+- * \param[in] rd the rdf where to put the data
+- * \param[in] str the string to be converted
+- * \return ldns_status
+- */
+-ldns_status ldns_str2rdf_nsap(ldns_rdf **rd, const char *str);
+-
+-/**
+- * convert a str with a ATMA RR into wireformat
+- * \param[in] rd the rdf where to put the data
+- * \param[in] str the string to be converted
+- * \return ldns_status
+- */
+-ldns_status ldns_str2rdf_atma(ldns_rdf **rd, const char *str);
+-
+-/**
+- * convert a str with a IPSECKEY RR into wireformat
+- * \param[in] rd the rdf where to put the data
+- * \param[in] str the string to be converted
+- * \return ldns_status
+- */
+-ldns_status ldns_str2rdf_ipseckey(ldns_rdf **rd, const char *str);
+-
+-/**
+- * convert a dname string into wireformat
+- * \param[in] rd the rdf where to put the data
+- * \param[in] str the string to be converted
+- * \return ldns_status
+- */
+-ldns_status ldns_str2rdf_dname(ldns_rdf **rd, const char *str);
+-
+-/**
+- * convert 4 * 16bit hex separated by colons into wireformat
+- * \param[in] rd the rdf where to put the data
+- * \param[in] str the string to be converted
+- * \return ldns_status
+- */
+-ldns_status ldns_str2rdf_ilnp64(ldns_rdf **rd, const char *str);
+-
+-/**
+- * convert 6 hex bytes separated by dashes into wireformat
+- * \param[in] rd the rdf where to put the data
+- * \param[in] str the string to be converted
+- * \return ldns_status
+- */
+-ldns_status ldns_str2rdf_eui48(ldns_rdf **rd, const char *str);
+-
+-/**
+- * convert 8 hex bytes separated by dashes into wireformat
+- * \param[in] rd the rdf where to put the data
+- * \param[in] str the string to be converted
+- * \return ldns_status
+- */
+-ldns_status ldns_str2rdf_eui64(ldns_rdf **rd, const char *str);
+-
+-/**
+- * Convert a non-zero sequence of US-ASCII letters and numbers into wireformat
+- * \param[in] rd the rdf where to put the data
+- * \param[in] str the string to be converted
+- * \return ldns_status
+- */
+-ldns_status ldns_str2rdf_tag(ldns_rdf **rd, const char *str);
+-
+-/**
+- * Convert a <character-string> encoding of the value field as specified 
+- * [RFC1035], Section 5.1., encoded as one bug chunk of data.
+- * \param[in] rd the rdf where to put the data
+- * \param[in] str the string to be converted
+- * \return ldns_status
+- */
+-ldns_status ldns_str2rdf_long_str(ldns_rdf **rd, const char *str);
+-
+-/**
+- * Convert a "<algorithm> <hit> <pk>" encoding of the value field as specified 
+- * in Section 6. of [RFC5205], encoded as wireformat as specified in Section 5.
+- * of [RFC5205].
+- * \param[in] rd the rdf where to put the data
+- * \param[in] str the string to be converted
+- * \return ldns_status
+- */
+-ldns_status ldns_str2rdf_hip(ldns_rdf **rd, const char *str);
+-
+-
+-#ifdef __cplusplus
+-}
+-#endif
+-
+-#endif /* LDNS_2HOST_H */
+diff --git a/include/ldns/tsig.h b/include/ldns/tsig.h
+deleted file mode 100644
+index 676045f..0000000
+--- a/include/ldns/tsig.h
++++ /dev/null
+@@ -1,101 +0,0 @@
+-/*
+- * tsig.h -- defines for TSIG [RFC2845]
+- *
+- * Copyright (c) 2005-2008, NLnet Labs. All rights reserved.
+- *
+- * See LICENSE for the license.
+- */
+-
+-#ifndef LDNS_TSIG_H
+-#define LDNS_TSIG_H
+-
+-#ifdef __cplusplus
+-extern "C" {
+-#endif
+-
+-/**
+- * \file
+- *
+- * Defines functions for TSIG usage
+- */
+-
+-
+-/**
+- * Contains credentials for TSIG
+-*/
+-typedef struct ldns_tsig_credentials_struct
+-{
+-    char *algorithm;
+-    char *keyname;
+-    char *keydata;
+-    /* XXX More eventually. */
+-} ldns_tsig_credentials;
+-
+-char *ldns_tsig_algorithm(ldns_tsig_credentials *);
+-char *ldns_tsig_keyname(ldns_tsig_credentials *);
+-char *ldns_tsig_keydata(ldns_tsig_credentials *);
+-char *ldns_tsig_keyname_clone(ldns_tsig_credentials *);
+-char *ldns_tsig_keydata_clone(ldns_tsig_credentials *);
+-
+-/**
+- * verifies the tsig rr for the given packet and key.
+- * The wire must be given too because tsig does not sign normalized packets.
+- * \param[in] pkt the packet to verify
+- * \param[in] wire needed to verify the mac
+- * \param[in] wire_size size of wire
+- * \param[in] key_name the name of the shared key
+- * \param[in] key_data the key in base 64 format
+- * \param[in] mac original mac
+- * \return true if tsig is correct, false if not, or if tsig is not set
+- */
+-bool ldns_pkt_tsig_verify(ldns_pkt *pkt, uint8_t *wire, size_t wire_size, const char *key_name, const char *key_data, ldns_rdf *mac);
+-
+-/**
+- * verifies the tsig rr for the given packet and key.
+- * The wire must be given too because tsig does not sign normalized packets.
+- * \param[in] pkt the packet to verify
+- * \param[in] wire needed to verify the mac
+- * \param[in] wire_size size of wire
+- * \param[in] key_name the name of the shared key
+- * \param[in] key_data the key in base 64 format
+- * \param[in] mac original mac
+- * \param[in] tsig_timers_only must be zero for the first packet and positive for subsequent packets. If zero, all digest
+-   components are used to verify the _mac. If non-zero, only the TSIG timers are used to verify the mac.
+- * \return true if tsig is correct, false if not, or if tsig is not set
+- */
+-bool ldns_pkt_tsig_verify_next(ldns_pkt *pkt, uint8_t *wire, size_t wire_size, const char *key_name, const char *key_data, ldns_rdf *mac,
+-    int tsig_timers_only);
+-
+-/**
+- * creates a tsig rr for the given packet and key.
+- * \param[in] pkt the packet to sign
+- * \param[in] key_name the name of the shared key
+- * \param[in] key_data the key in base 64 format
+- * \param[in] fudge seconds of error permitted in time signed
+- * \param[in] algorithm_name the name of the algorithm used
+- * \param[in] query_mac is added to the digest if not NULL (so NULL is for signing queries, not NULL is for signing answers)
+- * \return status (OK if success)
+- */
+-ldns_status ldns_pkt_tsig_sign(ldns_pkt *pkt, const char *key_name, const char *key_data, uint16_t fudge,
+-    const char *algorithm_name, ldns_rdf *query_mac);
+-
+-/**
+- * creates a tsig rr for the given packet and key.
+- * \param[in] pkt the packet to sign
+- * \param[in] key_name the name of the shared key
+- * \param[in] key_data the key in base 64 format
+- * \param[in] fudge seconds of error permitted in time signed
+- * \param[in] algorithm_name the name of the algorithm used
+- * \param[in] query_mac is added to the digest if not NULL (so NULL is for signing queries, not NULL is for signing answers)
+- * \param[in] tsig_timers_only must be zero for the first packet and positive for subsequent packets. If zero, all digest
+-   components are used to create the query_mac. If non-zero, only the TSIG timers are used to create the query_mac.
+- * \return status (OK if success)
+- */
+-ldns_status ldns_pkt_tsig_sign_next(ldns_pkt *pkt, const char *key_name, const char *key_data, uint16_t fudge,
+-    const char *algorithm_name, ldns_rdf *query_mac, int tsig_timers_only);
+-
+-#ifdef __cplusplus
+-}
+-#endif
+-
+-#endif /* LDNS_TSIG_H */
+diff --git a/include/ldns/update.h b/include/ldns/update.h
+deleted file mode 100644
+index d3459d3..0000000
+--- a/include/ldns/update.h
++++ /dev/null
+@@ -1,115 +0,0 @@
+-/*
+- * update.h
+- *
+- * Functions for RFC 2136 Dynamic Update
+- *
+- * Copyright (c) 2005-2008, NLnet Labs. All rights reserved.
+- *
+- * See LICENSE for the license.
+- */
+-
+-/**
+- * \file
+- *
+- * Defines functions to perform UPDATE queries
+- */
+-
+-
+-#ifndef LDNS_UPDATE_H
+-#define LDNS_UPDATE_H
+-
+-#include <ldns/resolver.h>
+-
+-#ifdef __cplusplus
+-extern "C" {
+-#endif
+-
+-/**
+- * create an update packet from zone name, class and the rr lists
+- * \param[in] zone_rdf name of the zone
+- * \param[in] clas zone class
+- * \param[in] pr_rrlist list of Prerequisite Section RRs
+- * \param[in] up_rrlist list of Updates Section RRs
+- * \param[in] ad_rrlist list of Additional Data Section RRs (currently unused)
+- * \return the new packet
+- */
+-ldns_pkt *ldns_update_pkt_new(ldns_rdf *zone_rdf, ldns_rr_class clas, ldns_rr_list *pr_rrlist, ldns_rr_list *up_rrlist, ldns_rr_list *ad_rrlist);
+-
+-/**
+- * add tsig credentials to
+- * a packet from a resolver
+- * \param[in] p packet to copy to
+- * \param[in] r resolver to copy from
+- *
+- * \return status wether successfull or not
+- */
+-ldns_status ldns_update_pkt_tsig_add(ldns_pkt *p, ldns_resolver *r);
+-
+-/* access functions */
+-
+-/**
+- * Get the zo count
+- * \param[in] p the packet
+- * \return the zo count
+- */
+-uint16_t ldns_update_zocount(const ldns_pkt *p);
+-/**
+- * Get the zo count
+- * \param[in] p the packet
+- * \return the pr count
+- */
+-uint16_t ldns_update_prcount(const ldns_pkt *p);
+-/**
+- * Get the zo count
+- * \param[in] p the packet
+- * \return the up count
+- */
+-uint16_t ldns_update_upcount(const ldns_pkt *p);
+-/**
+- * Get the zo count
+- * \param[in] p the packet
+- * \return the ad count
+- */
+-uint16_t ldns_update_ad(const ldns_pkt *p);
+-/**
+- * Set the zo count
+- * \param[in] p the packet
+- * \param[in] c the zo count to set
+- */
+-void ldns_update_set_zo(ldns_pkt *p, uint16_t c);
+-/**
+- * Set the pr count
+- * \param[in] p the packet
+- * \param[in] c the pr count to set
+- */
+-void ldns_update_set_prcount(ldns_pkt *p, uint16_t c);
+-/**
+- * Set the up count
+- * \param[in] p the packet
+- * \param[in] c the up count to set
+- */
+-void ldns_update_set_upcount(ldns_pkt *p, uint16_t c);
+-/**
+- * Set the ad count
+- * \param[in] p the packet
+- * \param[in] c the ad count to set
+- */
+-void ldns_update_set_adcount(ldns_pkt *p, uint16_t c);
+-
+-/* soa functions that need to be configured */
+-/*
+- * Not sure if we want to keep these like this, therefore
+- * not documented
+- */
+-ldns_status ldns_update_soa_mname(ldns_rdf *zone, ldns_resolver *r, ldns_rr_class c, ldns_rdf **mname);
+-/* 
+- * Not sure if we want to keep these like this, therefore
+- * not documented
+- */
+-ldns_status ldns_update_soa_zone_mname(const char *fqdn, ldns_resolver *r, ldns_rr_class c, ldns_rdf **zone_rdf, ldns_rdf **mname_rdf);
+-
+-#ifdef __cplusplus
+-}
+-#endif
+-
+-#endif  /* LDNS_UPDATE_H */
+diff --git a/include/ldns/util.h b/include/ldns/util.h
+deleted file mode 100644
+index 86848eb..0000000
+--- a/include/ldns/util.h
++++ /dev/null
+@@ -1,392 +0,0 @@
+-/*
+- * util.h
+- *  
+- * helper function header file
+- * 
+- * a Net::DNS like library for C
+- * 
+- * (c) NLnet Labs, 2004
+- * 
+- * See the file LICENSE for the license
+- */
+-
+-#ifndef _UTIL_H
+-#define _UTIL_H
+-
+-#include "EXTERN.h"
+-#include "perl.h"
+-#include <ldns/common.h>
+-#include <time.h>
+-#include <stdio.h>
+-
+-#ifdef __cplusplus
+-extern "C" {
+-#endif
+-
+-#define dprintf(X,Y) fprintf(stderr, (X), (Y))
+-/* #define	dprintf(X, Y)  */
+-
+-#define LDNS_VERSION "1.6.18"
+-#define LDNS_REVISION ((1<<16)|(6<<8)|(18))
+-
+-/**
+- * splint static inline workaround
+- */
+-#ifdef S_SPLINT_S
+-#  define INLINE 
+-#else
+-#  ifdef SWIG
+-#    define INLINE static
+-#  else
+-#    define INLINE static inline
+-#  endif
+-#endif
+-
+-/**
+- * Memory management macros
+- */
+-#define LDNS_MALLOC(type)		LDNS_XMALLOC(type, 1)
+-
+-#define LDNS_XMALLOC(type, count)	((type *) malloc((count) * sizeof(type)))
+-
+-#define LDNS_CALLOC(type, count)	((type *) calloc((count), sizeof(type)))
+-
+-#define LDNS_REALLOC(ptr, type)		LDNS_XREALLOC((ptr), type, 1)
+-
+-#define LDNS_XREALLOC(ptr, type, count)				\
+-	((type *) realloc((ptr), (count) * sizeof(type)))
+-
+-#define LDNS_FREE(ptr) \
+-	do { free((ptr)); (ptr) = NULL; } while (0)
+-
+-#define LDNS_DEP     printf("DEPRECATED FUNCTION!\n");
+-
+-/*
+- * Copy data allowing for unaligned accesses in network byte order
+- * (big endian).
+- */
+-INLINE uint16_t
+-ldns_read_uint16(const void *src)
+-{
+-#ifdef ALLOW_UNALIGNED_ACCESSES
+-	return ntohs(*(const uint16_t *) src);
+-#else
+-	const uint8_t *p = (const uint8_t *) src;
+-	return ((uint16_t) p[0] << 8) | (uint16_t) p[1];
+-#endif
+-}
+-
+-INLINE uint32_t
+-ldns_read_uint32(const void *src)
+-{
+-#ifdef ALLOW_UNALIGNED_ACCESSES
+-	return ntohl(*(const uint32_t *) src);
+-#else
+-	const uint8_t *p = (const uint8_t *) src;
+-	return (  ((uint32_t) p[0] << 24)
+-		| ((uint32_t) p[1] << 16)
+-		| ((uint32_t) p[2] << 8)
+-		|  (uint32_t) p[3]);
+-#endif
+-}
+-
+-/*
+- * Copy data allowing for unaligned accesses in network byte order
+- * (big endian).
+- */
+-INLINE void
+-ldns_write_uint16(void *dst, uint16_t data)
+-{
+-#ifdef ALLOW_UNALIGNED_ACCESSES
+-	* (uint16_t *) dst = htons(data);
+-#else
+-	uint8_t *p = (uint8_t *) dst;
+-	p[0] = (uint8_t) ((data >> 8) & 0xff);
+-	p[1] = (uint8_t) (data & 0xff);
+-#endif
+-}
+-
+-INLINE void
+-ldns_write_uint32(void *dst, uint32_t data)
+-{
+-#ifdef ALLOW_UNALIGNED_ACCESSES
+-	* (uint32_t *) dst = htonl(data);
+-#else
+-	uint8_t *p = (uint8_t *) dst;
+-	p[0] = (uint8_t) ((data >> 24) & 0xff);
+-	p[1] = (uint8_t) ((data >> 16) & 0xff);
+-	p[2] = (uint8_t) ((data >> 8) & 0xff);
+-	p[3] = (uint8_t) (data & 0xff);
+-#endif
+-}
+-
+-/* warning. */
+-INLINE void
+-ldns_write_uint64_as_uint48(void *dst, uint64_t data)
+-{
+-	uint8_t *p = (uint8_t *) dst;
+-	p[0] = (uint8_t) ((data >> 40) & 0xff);
+-	p[1] = (uint8_t) ((data >> 32) & 0xff);
+-	p[2] = (uint8_t) ((data >> 24) & 0xff);
+-	p[3] = (uint8_t) ((data >> 16) & 0xff);
+-	p[4] = (uint8_t) ((data >> 8) & 0xff);
+-	p[5] = (uint8_t) (data & 0xff);
+-}
+-
+-
+-/**
+- * Structure to do a Schwartzian-like transformation, for instance when
+- * sorting. If you need a transformation on the objects that are sorted,
+- * you can sue this to store the transformed values, so you do not
+- * need to do the transformation again for each comparison
+- */
+-struct ldns_schwartzian_compare_struct {
+-	void *original_object;
+-	void *transformed_object;
+-};
+-
+-/** A general purpose lookup table
+- *  
+- *  Lookup tables are arrays of (id, name) pairs,
+- *  So you can for instance lookup the RCODE 3, which is "NXDOMAIN",
+- *  and vice versa. The lookup tables themselves are defined wherever needed,
+- *  for instance in \ref host2str.c
+- */
+-struct ldns_struct_lookup_table {
+-        int id;
+-        const char *name;
+-};
+-typedef struct ldns_struct_lookup_table ldns_lookup_table;
+-  
+-/**
+- * Looks up the table entry by name, returns NULL if not found.
+- * \param[in] table the lookup table to search in
+- * \param[in] name what to search for
+- * \return the item found
+- */
+-ldns_lookup_table *ldns_lookup_by_name(ldns_lookup_table table[],
+-                                       const char *name);
+-
+-/**
+- * Looks up the table entry by id, returns NULL if not found.
+- * \param[in] table the lookup table to search in
+- * \param[in] id what to search for
+- * \return the item found
+- */
+-ldns_lookup_table *ldns_lookup_by_id(ldns_lookup_table table[], int id);
+-
+-/**
+- * Returns the value of the specified bit
+- * The bits are counted from left to right, so bit #0 is the
+- * left most bit.
+- * \param[in] bits array holding the bits
+- * \param[in] index to the wanted bit
+- * \return 
+- */
+-int ldns_get_bit(uint8_t bits[], size_t index);
+-
+-
+-/**
+- * Returns the value of the specified bit
+- * The bits are counted from right to left, so bit #0 is the
+- * right most bit.
+- * \param[in] bits array holding the bits
+- * \param[in] index to the wanted bit
+- * \return 1 or 0 depending no the bit state
+- */
+-int ldns_get_bit_r(uint8_t bits[], size_t index);
+-
+-/**
+- * sets the specified bit in the specified byte to
+- * 1 if value is true, 0 if false
+- * The bits are counted from right to left, so bit #0 is the
+- * right most bit.
+- * \param[in] byte the bit to set the bit in
+- * \param[in] bit_nr the bit to set (0 <= n <= 7)
+- * \param[in] value whether to set the bit to 1 or 0
+- * \return 1 or 0 depending no the bit state
+- */
+-void ldns_set_bit(uint8_t *byte, int bit_nr, bool value);
+-
+-/**
+- * Returns the value of a to the power of b
+- * (or 1 of b < 1)
+- */
+-/*@unused@*/
+-INLINE long
+-ldns_power(long a, long b) {
+-	long result = 1;
+-	while (b > 0) {
+-		if (b & 1) {
+-			result *= a;
+-			if (b == 1) {
+-				return result;
+-			}
+-		}
+-		a *= a;
+-		b /= 2;
+-	}
+-	return result;
+-}
+-
+-/**
+- * Returns the int value of the given (hex) digit
+- * \param[in] ch the hex char to convert
+- * \return the converted decimal value
+- */
+-int ldns_hexdigit_to_int(char ch);
+-
+-/**
+- * Returns the char (hex) representation of the given int
+- * \param[in] ch the int to convert
+- * \return the converted hex char
+- */
+-char ldns_int_to_hexdigit(int ch);
+-
+-/**
+- * Converts a hex string to binary data
+- *
+- * \param[out] data The binary result is placed here.
+- * At least strlen(str)/2 bytes should be allocated
+- * \param[in] str The hex string to convert.
+- * This string should not contain spaces
+- * \return The number of bytes of converted data, or -1 if one of the arguments * is NULL, or -2 if the string length is not an even number
+- */
+-int
+-ldns_hexstring_to_data(uint8_t *data, const char *str);
+-
+-/**
+- * Show the internal library version
+- * \return a string with the version in it
+- */
+-const char * ldns_version(void);
+-
+-/**
+- * Convert TM to seconds since epoch (midnight, January 1st, 1970).
+- * Like timegm(3), which is not always available.
+- * \param[in] tm a struct tm* with the date
+- * \return the seconds since epoch
+- */
+-time_t ldns_mktime_from_utc(const struct tm *tm);
+-
+-time_t mktime_from_utc(const struct tm *tm);
+-
+-/**
+- * The function interprets time as the number of seconds since epoch
+- * with respect to now using serial arithmitics (rfc1982).
+- * That number of seconds is then converted to broken-out time information.
+- * This is especially usefull when converting the inception and expiration
+- * fields of RRSIG records.
+- *
+- * \param[in] time number of seconds since epoch (midnight, January 1st, 1970)
+- *            to be intepreted as a serial arithmitics number relative to now.
+- * \param[in] now number of seconds since epoch (midnight, January 1st, 1970)
+- *            to which the time value is compared to determine the final value.
+- * \param[out] result the struct with the broken-out time information
+- * \return result on success or NULL on error
+- */
+-struct tm * ldns_serial_arithmitics_gmtime_r(int32_t time, time_t now, struct tm *result);
+- 
+-/**
+- * Seed the random function.
+- * If the file descriptor is specified, the random generator is seeded with
+- * data from that file. If not, /dev/urandom is used.
+- *
+- * applications should call this if they need entropy data within ldns
+- * If openSSL is available, it is automatically seeded from /dev/urandom
+- * or /dev/random.
+- *
+- * If you need more entropy, or have no openssl available, this function
+- * MUST be called at the start of the program
+- *
+- * If openssl *is* available, this function just adds more entropy
+- *
+- * \param[in] fd a file providing entropy data for the seed
+- * \param[in] size the number of bytes to use as entropy data. If this is 0,
+- *            only the minimal amount is taken (usually 4 bytes)
+- * \return 0 if seeding succeeds, 1 if it fails
+- */
+-int ldns_init_random(FILE *fd, unsigned int size);
+-
+-/**
+- * Get random number.
+- * \return random number.
+- *
+- */
+-uint16_t ldns_get_random(void);
+-
+-/**
+- * Encode data as BubbleBabble
+- *
+- * \param[in] data a pointer to data to be encoded
+- * \param[in] len size the number of bytes of data
+- * \return a string of BubbleBabble
+- */
+-char *ldns_bubblebabble(uint8_t *data, size_t len);
+-
+-
+-INLINE time_t ldns_time(time_t *t) { return time(t); }
+-
+-
+-/**
+- * calculates the size needed to store the result of b32_ntop
+- */
+-/*@unused@*/
+-INLINE size_t ldns_b32_ntop_calculate_size(size_t src_data_length)
+-{
+-	return src_data_length == 0 ? 0 : ((src_data_length - 1) / 5 + 1) * 8;
+-}
+-
+-INLINE size_t ldns_b32_ntop_calculate_size_no_padding(size_t src_data_length)
+-{
+-	return ((src_data_length + 3) * 8 / 5) - 4;
+-}
+-
+-int ldns_b32_ntop(const uint8_t* src_data, size_t src_data_length,
+-	     char* target_text_buffer, size_t target_text_buffer_size);
+-
+-int ldns_b32_ntop_extended_hex(const uint8_t* src_data, size_t src_data_length,
+-	     char* target_text_buffer, size_t target_text_buffer_size);
+-
+-#if ! LDNS_BUILD_CONFIG_HAVE_B32_NTOP
+-
+-int b32_ntop(const uint8_t* src_data, size_t src_data_length,
+-	     char* target_text_buffer, size_t target_text_buffer_size);
+-
+-int b32_ntop_extended_hex(const uint8_t* src_data, size_t src_data_length,
+-	     char* target_text_buffer, size_t target_text_buffer_size);
+-
+-#endif /* ! LDNS_BUILD_CONFIG_HAVE_B32_NTOP */
+-
+-
+-/**
+- * calculates the size needed to store the result of b32_pton
+- */
+-/*@unused@*/
+-INLINE size_t ldns_b32_pton_calculate_size(size_t src_text_length)
+-{
+-	return src_text_length * 5 / 8;
+-}
+-
+-int ldns_b32_pton(const char* src_text, size_t src_text_length,
+-	       	uint8_t* target_data_buffer, size_t target_data_buffer_size);
+-
+-int ldns_b32_pton_extended_hex(const char* src_text, size_t src_text_length,
+-		uint8_t* target_data_buffer, size_t target_data_buffer_size);
+-
+-#if ! LDNS_BUILD_CONFIG_HAVE_B32_PTON
+-
+-int b32_pton(const char* src_text, size_t src_text_length,
+-	       	uint8_t* target_data_buffer, size_t target_data_buffer_size);
+-
+-int b32_pton_extended_hex(const char* src_text, size_t src_text_length,
+-		uint8_t* target_data_buffer, size_t target_data_buffer_size);
+-
+-#endif /* ! LDNS_BUILD_CONFIG_HAVE_B32_PTON */
+-
+-
+-#ifdef __cplusplus
+-}
+-#endif
+-
+-#endif /* !_UTIL_H */
+diff --git a/include/ldns/wire2host.h b/include/ldns/wire2host.h
+deleted file mode 100644
+index 53155b3..0000000
+--- a/include/ldns/wire2host.h
++++ /dev/null
+@@ -1,197 +0,0 @@
+-/*
+- * wire2host.h - from wire conversion routines
+- *
+- * a Net::DNS like library for C
+- *
+- * (c) NLnet Labs, 2005-2006
+- *
+- * See the file LICENSE for the license
+- */
+-
+-/**
+- * \file
+- *
+- * Contains functions that translate dns data from the wire format (as sent
+- * by servers and clients) to the internal structures.
+- */
+- 
+-#ifndef LDNS_WIRE2HOST_H
+-#define LDNS_WIRE2HOST_H
+-
+-#include <ldns/rdata.h>
+-#include <ldns/common.h>
+-#include <ldns/error.h>
+-#include <ldns/rr.h>
+-#include <ldns/packet.h>
+-
+-#ifdef __cplusplus
+-extern "C" {
+-#endif
+-
+-/* The length of the header */
+-#define	LDNS_HEADER_SIZE	12
+-
+-/* First octet of flags */
+-#define	LDNS_RD_MASK		0x01U
+-#define	LDNS_RD_SHIFT	0
+-#define	LDNS_RD_WIRE(wirebuf)	(*(wirebuf+2) & LDNS_RD_MASK)
+-#define	LDNS_RD_SET(wirebuf)	(*(wirebuf+2) |= LDNS_RD_MASK)
+-#define	LDNS_RD_CLR(wirebuf)	(*(wirebuf+2) &= ~LDNS_RD_MASK)
+-
+-#define LDNS_TC_MASK		0x02U
+-#define LDNS_TC_SHIFT	1
+-#define	LDNS_TC_WIRE(wirebuf)	(*(wirebuf+2) & LDNS_TC_MASK)
+-#define	LDNS_TC_SET(wirebuf)	(*(wirebuf+2) |= LDNS_TC_MASK)
+-#define	LDNS_TC_CLR(wirebuf)	(*(wirebuf+2) &= ~LDNS_TC_MASK)
+-
+-#define	LDNS_AA_MASK		0x04U
+-#define	LDNS_AA_SHIFT	2
+-#define	LDNS_AA_WIRE(wirebuf)	(*(wirebuf+2) & LDNS_AA_MASK)
+-#define	LDNS_AA_SET(wirebuf)	(*(wirebuf+2) |= LDNS_AA_MASK)
+-#define	LDNS_AA_CLR(wirebuf)	(*(wirebuf+2) &= ~LDNS_AA_MASK)
+-
+-#define	LDNS_OPCODE_MASK	0x78U
+-#define	LDNS_OPCODE_SHIFT	3
+-#define	LDNS_OPCODE_WIRE(wirebuf)	((*(wirebuf+2) & LDNS_OPCODE_MASK) >> LDNS_OPCODE_SHIFT)
+-#define	LDNS_OPCODE_SET(wirebuf, opcode) \
+-	(*(wirebuf+2) = ((*(wirebuf+2)) & ~LDNS_OPCODE_MASK) | ((opcode) << LDNS_OPCODE_SHIFT))
+-
+-#define	LDNS_QR_MASK		0x80U
+-#define	LDNS_QR_SHIFT	7
+-#define	LDNS_QR_WIRE(wirebuf)	(*(wirebuf+2) & LDNS_QR_MASK)
+-#define	LDNS_QR_SET(wirebuf)	(*(wirebuf+2) |= LDNS_QR_MASK)
+-#define	LDNS_QR_CLR(wirebuf)	(*(wirebuf+2) &= ~LDNS_QR_MASK)
+-
+-/* Second octet of flags */
+-#define	LDNS_RCODE_MASK	0x0fU
+-#define	LDNS_RCODE_SHIFT	0
+-#define	LDNS_RCODE_WIRE(wirebuf)	(*(wirebuf+3) & LDNS_RCODE_MASK)
+-#define	LDNS_RCODE_SET(wirebuf, rcode) \
+-	(*(wirebuf+3) = ((*(wirebuf+3)) & ~LDNS_RCODE_MASK) | (rcode))
+-
+-#define	LDNS_CD_MASK		0x10U
+-#define	LDNS_CD_SHIFT	4
+-#define	LDNS_CD_WIRE(wirebuf)	(*(wirebuf+3) & LDNS_CD_MASK)
+-#define	LDNS_CD_SET(wirebuf)	(*(wirebuf+3) |= LDNS_CD_MASK)
+-#define	LDNS_CD_CLR(wirebuf)	(*(wirebuf+3) &= ~LDNS_CD_MASK)
+-
+-#define	LDNS_AD_MASK		0x20U
+-#define	LDNS_AD_SHIFT	5
+-#define	LDNS_AD_WIRE(wirebuf)	(*(wirebuf+3) & LDNS_AD_MASK)
+-#define	LDNS_AD_SET(wirebuf)	(*(wirebuf+3) |= LDNS_AD_MASK)
+-#define	LDNS_AD_CLR(wirebuf)	(*(wirebuf+3) &= ~LDNS_AD_MASK)
+-
+-#define	LDNS_Z_MASK		0x40U
+-#define	LDNS_Z_SHIFT		6
+-#define	LDNS_Z_WIRE(wirebuf)	(*(wirebuf+3) & LDNS_Z_MASK)
+-#define	LDNS_Z_SET(wirebuf)	(*(wirebuf+3) |= LDNS_Z_MASK)
+-#define	LDNS_Z_CLR(wirebuf)	(*(wirebuf+3) &= ~LDNS_Z_MASK)
+-
+-#define	LDNS_RA_MASK		0x80U
+-#define	LDNS_RA_SHIFT	7
+-#define	LDNS_RA_WIRE(wirebuf)	(*(wirebuf+3) & LDNS_RA_MASK)
+-#define	LDNS_RA_SET(wirebuf)	(*(wirebuf+3) |= LDNS_RA_MASK)
+-#define	LDNS_RA_CLR(wirebuf)	(*(wirebuf+3) &= ~LDNS_RA_MASK)
+-
+-/* Query ID */
+-#define	LDNS_ID_WIRE(wirebuf)		(ldns_read_uint16(wirebuf))
+-#define	LDNS_ID_SET(wirebuf, id)	(ldns_write_uint16(wirebuf, id))
+-
+-/* Counter of the question section */
+-#define LDNS_QDCOUNT_OFF		4
+-/*
+-#define	QDCOUNT(wirebuf)		(ntohs(*(uint16_t *)(wirebuf+QDCOUNT_OFF)))
+-*/
+-#define	LDNS_QDCOUNT(wirebuf)		(ldns_read_uint16(wirebuf+LDNS_QDCOUNT_OFF))
+-
+-/* Counter of the answer section */
+-#define LDNS_ANCOUNT_OFF		6
+-#define	LDNS_ANCOUNT(wirebuf)		(ldns_read_uint16(wirebuf+LDNS_ANCOUNT_OFF))
+-
+-/* Counter of the authority section */
+-#define LDNS_NSCOUNT_OFF		8
+-#define	LDNS_NSCOUNT(wirebuf)		(ldns_read_uint16(wirebuf+LDNS_NSCOUNT_OFF))
+-
+-/* Counter of the additional section */
+-#define LDNS_ARCOUNT_OFF		10
+-#define	LDNS_ARCOUNT(wirebuf)		(ldns_read_uint16(wirebuf+LDNS_ARCOUNT_OFF))
+-
+-/**
+- * converts the data on the uint8_t bytearray (in wire format) to a DNS packet.
+- * This function will initialize and allocate memory space for the packet 
+- * structure.
+- * 
+- * \param[in] packet pointer to the structure to hold the packet
+- * \param[in] data pointer to the buffer with the data
+- * \param[in] len the length of the data buffer (in bytes)
+- * \return LDNS_STATUS_OK if everything succeeds, error otherwise
+- */
+-ldns_status ldns_wire2pkt(ldns_pkt **packet, const uint8_t *data, size_t len);
+-
+-/**
+- * converts the data on the uint8_t bytearray (in wire format) to a DNS packet.
+- * This function will initialize and allocate memory space for the packet 
+- * structure.
+- * 
+- * \param[in] packet pointer to the structure to hold the packet
+- * \param[in] buffer the buffer with the data
+- * \return LDNS_STATUS_OK if everything succeeds, error otherwise
+- */
+-ldns_status ldns_buffer2pkt_wire(ldns_pkt **packet, ldns_buffer *buffer);
+-
+-/**
+- * converts the data on the uint8_t bytearray (in wire format) to a DNS 
+- * dname rdata field. This function will initialize and allocate memory
+- * space for the dname structure. The length of the wiredata of this rdf 
+- * is added to the *pos value.
+- *
+- * \param[in] dname pointer to the structure to hold the rdata value
+- * \param[in] wire pointer to the buffer with the data
+- * \param[in] max the length of the data buffer (in bytes)
+- * \param[in] pos the position of the rdf in the buffer (ie. the number of bytes 
+- *            from the start of the buffer)
+- * \return LDNS_STATUS_OK if everything succeeds, error otherwise
+- */
+-ldns_status ldns_wire2dname(ldns_rdf **dname, const uint8_t *wire, size_t max, size_t *pos);
+-
+-/**
+- * converts the data on the uint8_t bytearray (in wire format) to DNS 
+- * rdata fields, and adds them to the list of rdfs of the given rr.
+- * This function will initialize and allocate memory space for the dname
+- * structures.
+- * The length of the wiredata of these rdfs is added to the *pos value.
+- *
+- * All rdfs belonging to the RR are read; the rr should have no rdfs
+- * yet. An error is returned if the format cannot be parsed.
+- *
+- * \param[in] rr pointer to the ldns_rr structure to hold the rdata value
+- * \param[in] wire pointer to the buffer with the data
+- * \param[in] max the length of the data buffer (in bytes)
+- * \param[in] pos the position of the rdf in the buffer (ie. the number of bytes 
+- *            from the start of the buffer)
+- * \return LDNS_STATUS_OK if everything succeeds, error otherwise
+- */
+-ldns_status ldns_wire2rdf(ldns_rr *rr, const uint8_t *wire, size_t max, size_t *pos);
+-
+-/**
+- * converts the data on the uint8_t bytearray (in wire format) to a DNS 
+- * resource record.
+- * This function will initialize and allocate memory space for the rr
+- * structure.
+- * The length of the wiredata of this rr is added to the *pos value.
+- * 
+- * \param[in] rr pointer to the structure to hold the rdata value
+- * \param[in] wire pointer to the buffer with the data
+- * \param[in] max the length of the data buffer (in bytes)
+- * \param[in] pos the position of the rr in the buffer (ie. the number of bytes 
+- *            from the start of the buffer)
+- * \param[in] section the section in the packet the rr is meant for
+- * \return LDNS_STATUS_OK if everything succeeds, error otherwise
+- */
+-ldns_status ldns_wire2rr(ldns_rr **rr, const uint8_t *wire, size_t max, size_t *pos, ldns_pkt_section section);
+-
+-#ifdef __cplusplus
+-}
+-#endif
+-
+-#endif /* LDNS_WIRE2HOST_H */
+diff --git a/include/ldns/zone.h b/include/ldns/zone.h
+deleted file mode 100644
+index 0d129a0..0000000
+--- a/include/ldns/zone.h
++++ /dev/null
+@@ -1,176 +0,0 @@
+-/**
+- * zone.h
+- *
+- * zone definitions
+- *  - what is it
+- *  - get_glue function
+- *  - search etc
+- *
+- * a Net::DNS like library for C
+- *
+- * (c) NLnet Labs, 2005-2006
+- *
+- * See the file LICENSE for the license
+- */
+-
+-/**
+- * \file
+- *
+- * Defines the ldns_zone structure and functions to manipulate it.
+- */
+- 
+-
+-#ifndef LDNS_ZONE_H
+-#define LDNS_ZONE_H
+-
+-#include <ldns/common.h>
+-#include <ldns/rdata.h>
+-#include <ldns/rr.h>
+-#include <ldns/error.h>
+-
+-#ifdef __cplusplus
+-extern "C" {
+-#endif
+-
+-/** 
+- * DNS Zone
+- *
+- * A list of RR's with some
+- * extra information which comes from the SOA RR
+- * Note: nothing has been done to make this efficient (yet).
+- */
+-struct ldns_struct_zone
+-{
+-	/** the soa defines a zone */
+-	ldns_rr 	*_soa;
+-	/* basicly a zone is a list of rr's */
+-	ldns_rr_list 	*_rrs;
+-	/* we could change this to be a b-tree etc etc todo */
+-};
+-typedef struct ldns_struct_zone ldns_zone;	
+-	
+-/**
+- * create a new ldns_zone structure
+- * \return a pointer to a ldns_zone structure
+- */
+-ldns_zone * ldns_zone_new(void);
+-
+-/**
+- * Return the soa record of a zone
+- * \param[in] z the zone to read from
+- * \return the soa record in the zone
+- */
+-ldns_rr * ldns_zone_soa(const ldns_zone *z);
+-
+-/**
+- * Returns the number of resource records in the zone, NOT counting the SOA record
+- * \param[in] z the zone to read from
+- * \return the number of rr's in the zone
+- */
+-size_t ldns_zone_rr_count(const ldns_zone *z);
+-
+-/**
+- * Set the zone's soa record
+- * \param[in] z the zone to put the new soa in
+- * \param[in] soa the soa to set
+- */
+-void ldns_zone_set_soa(ldns_zone *z, ldns_rr *soa);
+-
+-/**
+- * Get a list of a zone's content. Note that the SOA
+- * isn't included in this list. You need to get the 
+- * with ldns_zone_soa.
+- * \param[in] z the zone to read from
+- * \return the rrs from this zone
+- */
+-ldns_rr_list * ldns_zone_rrs(const ldns_zone *z);
+-
+-/**
+- * Set the zone's contents
+- * \param[in] z the zone to put the new soa in
+- * \param[in] rrlist the rrlist to use
+- */
+-void ldns_zone_set_rrs(ldns_zone *z, ldns_rr_list *rrlist);
+-
+-/**
+- * push an rrlist to a zone structure. This function use pointer
+- * copying, so the rr_list structure inside z is modified!
+- * \param[in] z the zone to add to
+- * \param[in] list the list to add
+- * \return a true on succes otherwise falsed
+- */
+-bool ldns_zone_push_rr_list(ldns_zone *z, ldns_rr_list *list);
+-
+-/**
+- * push an single rr to a zone structure. This function use pointer
+- * copying, so the rr_list structure inside z is modified!
+- * \param[in] z the zone to add to
+- * \param[in] rr the rr to add
+- * \return a true on succes otherwise falsed
+- */
+-bool ldns_zone_push_rr(ldns_zone *z, ldns_rr *rr);
+-
+-/**
+- * Retrieve all resource records from the zone that are glue
+- * records. The resulting list does are pointer references
+- * to the zone's data.
+- *
+- * Due to the current zone implementation (as a list of rr's), this
+- * function is extremely slow. Another (probably better) way to do this
+- * is to use an ldns_dnssec_zone structure and the 
+- * ldns_dnssec_mark_and_get_glue() function.
+- *
+- * \param[in] z the zone to look for glue
+- * \return the rr_list with the glue
+- */
+-ldns_rr_list *ldns_zone_glue_rr_list(const ldns_zone *z);
+-
+-/**
+- * Create a new zone from a file
+- * \param[out] z the new zone
+- * \param[in] *fp the filepointer to use
+- * \param[in] *origin the zones' origin
+- * \param[in] ttl default ttl to use
+- * \param[in] c default class to use (IN)
+- *
+- * \return ldns_status mesg with an error or LDNS_STATUS_OK
+- */
+-ldns_status ldns_zone_new_frm_fp(ldns_zone **z, FILE *fp, ldns_rdf *origin, uint32_t ttl, ldns_rr_class c);
+-
+-/**
+- * Create a new zone from a file, keep track of the line numbering
+- * \param[out] z the new zone
+- * \param[in] *fp the filepointer to use
+- * \param[in] *origin the zones' origin
+- * \param[in] ttl default ttl to use
+- * \param[in] c default class to use (IN)
+- * \param[out] line_nr used for error msg, to get to the line number
+- *
+- * \return ldns_status mesg with an error or LDNS_STATUS_OK
+- */
+-ldns_status ldns_zone_new_frm_fp_l(ldns_zone **z, FILE *fp, ldns_rdf *origin, uint32_t ttl, ldns_rr_class c, int *line_nr);
+-
+-/**
+- * Frees the allocated memory for the zone, and the rr_list structure in it
+- * \param[in] zone the zone to free
+- */
+-void ldns_zone_free(ldns_zone *zone);
+-
+-/**
+- * Frees the allocated memory for the zone, the soa rr in it, 
+- * and the rr_list structure in it, including the rr's in that. etc.
+- * \param[in] zone the zone to free
+- */
+-void ldns_zone_deep_free(ldns_zone *zone);
+-
+-/**
+- * Sort the rrs in a zone, with the current impl. this is slow
+- * \param[in] zone the zone to sort
+- */
+-void ldns_zone_sort(ldns_zone *zone);
+-
+-#ifdef __cplusplus
+-}
+-#endif
+-
+-#endif /* LDNS_ZONE_H */
+diff --git a/ldns/include/ldns/buffer.h b/ldns/include/ldns/buffer.h
+new file mode 100644
+index 0000000..3b64198
+--- /dev/null
++++ b/ldns/include/ldns/buffer.h
+@@ -0,0 +1,645 @@
++/*
++ * buffer.h -- generic memory buffer.
++ *
++ * Copyright (c) 2005-2008, NLnet Labs. All rights reserved.
++ *
++ * See LICENSE for the license.
++ *
++ *
++ * The buffer module implements a generic buffer.  The API is based on
++ * the java.nio.Buffer interface.
++ */
++
++#ifndef LDNS_BUFFER_H
++#define LDNS_BUFFER_H
++
++#include <assert.h>
++#include <stdarg.h>
++#include <string.h>
++
++#include <ldns/error.h>
++#include <ldns/common.h>
++
++#include "ldns/util.h"
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/**
++ * number of initial bytes in buffer of
++ * which we cannot tell the size before hand
++ */
++#define LDNS_MIN_BUFLEN	512
++
++/**
++ * \file buffer.h
++ *
++ * This file contains the definition of ldns_buffer, and functions to manipulate those.
++ */
++
++/** 
++ * implementation of buffers to ease operations
++ *
++ * ldns_buffers can contain arbitrary information, per octet. You can write
++ * to the current end of a buffer, read from the current position, and
++ * access any data within it.
++ *
++ * Example use of buffers is in the source code of \ref host2str.c
++ */
++struct ldns_struct_buffer
++{
++	/** The current position used for reading/writing */ 
++	size_t   _position;
++
++	/** The read/write limit */
++	size_t   _limit;
++
++	/** The amount of data the buffer can contain */
++	size_t   _capacity;
++
++	/** The data contained in the buffer */
++	uint8_t *_data;
++
++	/** If the buffer is fixed it cannot be resized */
++	unsigned _fixed : 1;
++
++	/** The current state of the buffer. If writing to the buffer fails
++	 * for any reason, this value is changed. This way, you can perform
++	 * multiple writes in sequence and check for success afterwards. */
++	ldns_status _status;
++};
++typedef struct ldns_struct_buffer ldns_buffer;
++
++
++#ifdef NDEBUG
++INLINE void
++ldns_buffer_invariant(ldns_buffer *ATTR_UNUSED(buffer))
++{
++}
++#else
++INLINE void
++ldns_buffer_invariant(ldns_buffer *buffer)
++{
++	assert(buffer != NULL);
++	assert(buffer->_position <= buffer->_limit);
++	assert(buffer->_limit <= buffer->_capacity);
++	assert(buffer->_data != NULL);
++}
++#endif
++
++/**
++ * creates a new buffer with the specified capacity.
++ *
++ * \param[in] capacity the size (in bytes) to allocate for the buffer
++ * \return the created buffer
++ */
++ldns_buffer *ldns_buffer_new(size_t capacity);
++
++/**
++ * creates a buffer with the specified data.  The data IS copied
++ * and MEMORY allocations are done.  The buffer is not fixed and can
++ * be resized using buffer_reserve().
++ *
++ * \param[in] buffer pointer to the buffer to put the data in
++ * \param[in] data the data to encapsulate in the buffer
++ * \param[in] size the size of the data
++ */
++void ldns_buffer_new_frm_data(ldns_buffer *buffer, void *data, size_t size);
++
++/**
++ * clears the buffer and make it ready for writing.  The buffer's limit
++ * is set to the capacity and the position is set to 0.
++ * \param[in] buffer the buffer to clear
++ */
++INLINE void ldns_buffer_clear(ldns_buffer *buffer)
++{
++	ldns_buffer_invariant(buffer);
++
++	/* reset status here? */
++
++	buffer->_position = 0;
++	buffer->_limit = buffer->_capacity;
++}
++
++/**
++ * makes the buffer ready for reading the data that has been written to
++ * the buffer.  The buffer's limit is set to the current position and
++ * the position is set to 0.
++ *
++ * \param[in] buffer the buffer to flip
++ * \return void
++ */
++INLINE void ldns_buffer_flip(ldns_buffer *buffer)
++{
++	ldns_buffer_invariant(buffer);
++
++	buffer->_limit = buffer->_position;
++	buffer->_position = 0;
++}
++
++/**
++ * make the buffer ready for re-reading the data.  The buffer's
++ * position is reset to 0.
++ * \param[in] buffer the buffer to rewind
++ */
++INLINE void ldns_buffer_rewind(ldns_buffer *buffer)
++{
++	ldns_buffer_invariant(buffer);
++
++	buffer->_position = 0;
++}
++
++/**
++ * returns the current position in the buffer (as a number of bytes)
++ * \param[in] buffer the buffer
++ * \return the current position
++ */
++INLINE size_t
++ldns_buffer_position(ldns_buffer *buffer)
++{
++	return buffer->_position;
++}
++
++/**
++ * sets the buffer's position to MARK.  The position must be less than
++ * or equal to the buffer's limit.
++ * \param[in] buffer the buffer
++ * \param[in] mark the mark to use
++ */
++INLINE void
++ldns_buffer_set_position(ldns_buffer *buffer, size_t mark)
++{
++	assert(mark <= buffer->_limit);
++	buffer->_position = mark;
++}
++
++/**
++ * changes the buffer's position by COUNT bytes.  The position must not
++ * be moved behind the buffer's limit or before the beginning of the
++ * buffer.
++ * \param[in] buffer the buffer
++ * \param[in] count the count to use
++ */
++INLINE void
++ldns_buffer_skip(ldns_buffer *buffer, ssize_t count)
++{
++	assert(buffer->_position + count <= buffer->_limit);
++	buffer->_position += count;
++}
++
++/**
++ * returns the maximum size of the buffer
++ * \param[in] buffer
++ * \return the size
++ */
++INLINE size_t
++ldns_buffer_limit(ldns_buffer *buffer)
++{
++	return buffer->_limit;
++}
++
++/**
++ * changes the buffer's limit.  If the buffer's position is greater
++ * than the new limit the position is set to the limit.
++ * \param[in] buffer the buffer
++ * \param[in] limit the new limit
++ */
++INLINE void
++ldns_buffer_set_limit(ldns_buffer *buffer, size_t limit)
++{
++	assert(limit <= buffer->_capacity);
++	buffer->_limit = limit;
++	if (buffer->_position > buffer->_limit)
++		buffer->_position = buffer->_limit;
++}
++
++/**
++ * returns the number of bytes the buffer can hold.
++ * \param[in] buffer the buffer
++ * \return the number of bytes
++ */
++INLINE size_t
++ldns_buffer_capacity(ldns_buffer *buffer)
++{
++	return buffer->_capacity;
++}
++
++/**
++ * changes the buffer's capacity.  The data is reallocated so any
++ * pointers to the data may become invalid.  The buffer's limit is set
++ * to the buffer's new capacity.
++ * \param[in] buffer the buffer
++ * \param[in] capacity the capacity to use
++ * \return whether this failed or succeeded
++ */
++bool ldns_buffer_set_capacity(ldns_buffer *buffer, size_t capacity);
++
++/**
++ * ensures BUFFER can contain at least AMOUNT more bytes.  The buffer's
++ * capacity is increased if necessary using buffer_set_capacity().
++ *
++ * The buffer's limit is always set to the (possibly increased)
++ * capacity.
++ * \param[in] buffer the buffer
++ * \param[in] amount amount to use
++ * \return whether this failed or succeeded
++ */
++bool ldns_buffer_reserve(ldns_buffer *buffer, size_t amount);
++
++/**
++ * returns a pointer to the data at the indicated position.
++ * \param[in] buffer the buffer
++ * \param[in] at position
++ * \return the pointer to the data
++ */
++INLINE uint8_t *
++ldns_buffer_at(const ldns_buffer *buffer, size_t at)
++{
++	assert(at <= buffer->_limit);
++	return buffer->_data + at;
++}
++
++/**
++ * returns a pointer to the beginning of the buffer (the data at
++ * position 0).
++ * \param[in] buffer the buffer
++ * \return the pointer
++ */
++INLINE uint8_t *
++ldns_buffer_begin(const ldns_buffer *buffer)
++{
++	return ldns_buffer_at(buffer, 0);
++}
++
++/**
++ * returns a pointer to the end of the buffer (the data at the buffer's
++ * limit).
++ * \param[in] buffer the buffer
++ * \return the pointer
++ */
++INLINE uint8_t *
++ldns_buffer_end(ldns_buffer *buffer)
++{
++	return ldns_buffer_at(buffer, buffer->_limit);
++}
++
++/**
++ * returns a pointer to the data at the buffer's current position.
++ * \param[in] buffer the buffer
++ * \return the pointer
++ */
++INLINE uint8_t *
++ldns_buffer_current(ldns_buffer *buffer)
++{
++	return ldns_buffer_at(buffer, buffer->_position);
++}
++
++/**
++ * returns the number of bytes remaining between the indicated position and
++ * the limit.
++ * \param[in] buffer the buffer
++ * \param[in] at indicated position
++ * \return number of bytes
++ */
++INLINE size_t
++ldns_buffer_remaining_at(ldns_buffer *buffer, size_t at)
++{
++	ldns_buffer_invariant(buffer);
++	assert(at <= buffer->_limit);
++	return buffer->_limit - at;
++}
++
++/**
++ * returns the number of bytes remaining between the buffer's position and
++ * limit.
++ * \param[in] buffer the buffer
++ * \return the number of bytes
++ */
++INLINE size_t
++ldns_buffer_remaining(ldns_buffer *buffer)
++{
++	return ldns_buffer_remaining_at(buffer, buffer->_position);
++}
++
++/**
++ * checks if the buffer has at least COUNT more bytes available.
++ * Before reading or writing the caller needs to ensure enough space
++ * is available!
++ * \param[in] buffer the buffer
++ * \param[in] at indicated position
++ * \param[in] count how much is available
++ * \return true or false (as int?)
++ */
++INLINE int
++ldns_buffer_available_at(ldns_buffer *buffer, size_t at, size_t count)
++{
++	return count <= ldns_buffer_remaining_at(buffer, at);
++}
++
++/**
++ * checks if the buffer has count bytes available at the current position
++ * \param[in] buffer the buffer
++ * \param[in] count how much is available
++ * \return true or false (as int?)
++ */
++INLINE int
++ldns_buffer_available(ldns_buffer *buffer, size_t count)
++{
++	return ldns_buffer_available_at(buffer, buffer->_position, count);
++}
++
++/**
++ * writes the given data to the buffer at the specified position
++ * \param[in] buffer the buffer
++ * \param[in] at the position (in number of bytes) to write the data at
++ * \param[in] data pointer to the data to write to the buffer
++ * \param[in] count the number of bytes of data to write
++ */
++INLINE void
++ldns_buffer_write_at(ldns_buffer *buffer, size_t at, const void *data, size_t count)
++{
++	assert(ldns_buffer_available_at(buffer, at, count));
++	memcpy(buffer->_data + at, data, count);
++}
++
++/**
++ * writes count bytes of data to the current position of the buffer
++ * \param[in] buffer the buffer
++ * \param[in] data the data to write
++ * \param[in] count the lenght of the data to write
++ */
++INLINE void
++ldns_buffer_write(ldns_buffer *buffer, const void *data, size_t count)
++{
++	ldns_buffer_write_at(buffer, buffer->_position, data, count);
++	buffer->_position += count;
++}
++
++/**
++ * copies the given (null-delimited) string to the specified position at the buffer
++ * \param[in] buffer the buffer
++ * \param[in] at the position in the buffer
++ * \param[in] str the string to write
++ */
++INLINE void
++ldns_buffer_write_string_at(ldns_buffer *buffer, size_t at, const char *str)
++{
++	ldns_buffer_write_at(buffer, at, str, strlen(str));
++}
++
++/**
++ * copies the given (null-delimited) string to the current position at the buffer
++ * \param[in] buffer the buffer
++ * \param[in] str the string to write
++ */
++INLINE void
++ldns_buffer_write_string(ldns_buffer *buffer, const char *str)
++{
++	ldns_buffer_write(buffer, str, strlen(str));
++}
++
++/**
++ * writes the given byte of data at the given position in the buffer
++ * \param[in] buffer the buffer
++ * \param[in] at the position in the buffer
++ * \param[in] data the 8 bits to write
++ */
++INLINE void
++ldns_buffer_write_u8_at(ldns_buffer *buffer, size_t at, uint8_t data)
++{
++	assert(ldns_buffer_available_at(buffer, at, sizeof(data)));
++	buffer->_data[at] = data;
++}
++
++/**
++ * writes the given byte of data at the current position in the buffer
++ * \param[in] buffer the buffer
++ * \param[in] data the 8 bits to write
++ */
++INLINE void
++ldns_buffer_write_u8(ldns_buffer *buffer, uint8_t data)
++{
++	ldns_buffer_write_u8_at(buffer, buffer->_position, data);
++	buffer->_position += sizeof(data);
++}
++
++/**
++ * writes the given 2 byte integer at the given position in the buffer
++ * \param[in] buffer the buffer
++ * \param[in] at the position in the buffer
++ * \param[in] data the 16 bits to write
++ */
++INLINE void
++ldns_buffer_write_u16_at(ldns_buffer *buffer, size_t at, uint16_t data)
++{
++	assert(ldns_buffer_available_at(buffer, at, sizeof(data)));
++	ldns_write_uint16(buffer->_data + at, data);
++}
++
++/**
++ * writes the given 2 byte integer at the current position in the buffer
++ * \param[in] buffer the buffer
++ * \param[in] data the 16 bits to write
++ */
++INLINE void
++ldns_buffer_write_u16(ldns_buffer *buffer, uint16_t data)
++{
++	ldns_buffer_write_u16_at(buffer, buffer->_position, data);
++	buffer->_position += sizeof(data);
++}
++
++/**
++ * writes the given 4 byte integer at the given position in the buffer
++ * \param[in] buffer the buffer
++ * \param[in] at the position in the buffer
++ * \param[in] data the 32 bits to write
++ */
++INLINE void
++ldns_buffer_write_u32_at(ldns_buffer *buffer, size_t at, uint32_t data)
++{
++	assert(ldns_buffer_available_at(buffer, at, sizeof(data)));
++	ldns_write_uint32(buffer->_data + at, data);
++}
++
++/**
++ * writes the given 4 byte integer at the current position in the buffer
++ * \param[in] buffer the buffer
++ * \param[in] data the 32 bits to write
++ */
++INLINE void
++ldns_buffer_write_u32(ldns_buffer *buffer, uint32_t data)
++{
++	ldns_buffer_write_u32_at(buffer, buffer->_position, data);
++	buffer->_position += sizeof(data);
++}
++
++/**
++ * copies count bytes of data at the given position to the given data-array
++ * \param[in] buffer the buffer
++ * \param[in] at the position in the buffer to start
++ * \param[out] data buffer to copy to
++ * \param[in] count the length of the data to copy
++ */
++INLINE void
++ldns_buffer_read_at(ldns_buffer *buffer, size_t at, void *data, size_t count)
++{
++	assert(ldns_buffer_available_at(buffer, at, count));
++	memcpy(data, buffer->_data + at, count);
++}
++
++/**
++ * copies count bytes of data at the current position to the given data-array
++ * \param[in] buffer the buffer
++ * \param[out] data buffer to copy to
++ * \param[in] count the length of the data to copy
++ */
++INLINE void
++ldns_buffer_read(ldns_buffer *buffer, void *data, size_t count)
++{
++	ldns_buffer_read_at(buffer, buffer->_position, data, count);
++	buffer->_position += count;
++}
++
++/**
++ * returns the byte value at the given position in the buffer
++ * \param[in] buffer the buffer
++ * \param[in] at the position in the buffer
++ * \return 1 byte integer
++ */
++INLINE uint8_t
++ldns_buffer_read_u8_at(ldns_buffer *buffer, size_t at)
++{
++	assert(ldns_buffer_available_at(buffer, at, sizeof(uint8_t)));
++	return buffer->_data[at];
++}
++
++/**
++ * returns the byte value at the current position in the buffer
++ * \param[in] buffer the buffer
++ * \return 1 byte integer
++ */
++INLINE uint8_t
++ldns_buffer_read_u8(ldns_buffer *buffer)
++{
++	uint8_t result = ldns_buffer_read_u8_at(buffer, buffer->_position);
++	buffer->_position += sizeof(uint8_t);
++	return result;
++}
++
++/**
++ * returns the 2-byte integer value at the given position in the buffer
++ * \param[in] buffer the buffer
++ * \param[in] at position in the buffer
++ * \return 2 byte integer
++ */
++INLINE uint16_t
++ldns_buffer_read_u16_at(ldns_buffer *buffer, size_t at)
++{
++	assert(ldns_buffer_available_at(buffer, at, sizeof(uint16_t)));
++	return ldns_read_uint16(buffer->_data + at);
++}
++
++/**
++ * returns the 2-byte integer value at the current position in the buffer
++ * \param[in] buffer the buffer
++ * \return 2 byte integer
++ */
++INLINE uint16_t
++ldns_buffer_read_u16(ldns_buffer *buffer)
++{
++	uint16_t result = ldns_buffer_read_u16_at(buffer, buffer->_position);
++	buffer->_position += sizeof(uint16_t);
++	return result;
++}
++
++/**
++ * returns the 4-byte integer value at the given position in the buffer
++ * \param[in] buffer the buffer
++ * \param[in] at position in the buffer
++ * \return 4 byte integer
++ */
++INLINE uint32_t
++ldns_buffer_read_u32_at(ldns_buffer *buffer, size_t at)
++{
++	assert(ldns_buffer_available_at(buffer, at, sizeof(uint32_t)));
++	return ldns_read_uint32(buffer->_data + at);
++}
++
++/**
++ * returns the 4-byte integer value at the current position in the buffer
++ * \param[in] buffer the buffer
++ * \return 4 byte integer
++ */
++INLINE uint32_t
++ldns_buffer_read_u32(ldns_buffer *buffer)
++{
++	uint32_t result = ldns_buffer_read_u32_at(buffer, buffer->_position);
++	buffer->_position += sizeof(uint32_t);
++	return result;
++}
++
++/**
++ * returns the status of the buffer
++ * \param[in] buffer
++ * \return the status
++ */
++INLINE ldns_status
++ldns_buffer_status(ldns_buffer *buffer)
++{
++	return buffer->_status;
++}
++
++/**
++ * returns true if the status of the buffer is LDNS_STATUS_OK, false otherwise
++ * \param[in] buffer the buffer
++ * \return true or false
++ */
++INLINE bool
++ldns_buffer_status_ok(ldns_buffer *buffer)
++{
++	if (buffer) {
++		return ldns_buffer_status(buffer) == LDNS_STATUS_OK;
++	} else {
++		return false;
++	}
++}
++
++/**
++ * prints to the buffer, increasing the capacity if required using
++ * buffer_reserve(). The buffer's position is set to the terminating '\\0'
++ * Returns the number of characters written (not including the
++ * terminating '\\0') or -1 on failure.
++ */
++int ldns_buffer_printf(ldns_buffer *buffer, const char *format, ...);
++/*	ATTR_FORMAT(printf, 2, 3);*/
++
++/**
++ * frees the buffer.
++ * \param[in] *buffer the buffer to be freed
++ * \return void
++ */
++void ldns_buffer_free(ldns_buffer *buffer);
++
++/**
++ * Makes the buffer fixed and returns a pointer to the data.  The
++ * caller is responsible for free'ing the result.
++ * \param[in] *buffer the buffer to be exported
++ * \return void
++ */
++void *ldns_buffer_export(ldns_buffer *buffer);
++
++/**
++ * Copy contents of the from buffer to the result buffer and then flips 
++ * the result buffer. Data will be silently truncated if the result buffer is
++ * too small.
++ * \param[out] *result resulting buffer which is copied to.
++ * \param[in] *from what to copy to result.
++ */
++void ldns_buffer_copy(ldns_buffer* result, ldns_buffer* from);
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* LDNS_BUFFER_H */
+diff --git a/ldns/include/ldns/common.h b/ldns/include/ldns/common.h
+new file mode 100644
+index 0000000..9abd9b9
+--- /dev/null
++++ b/ldns/include/ldns/common.h
+@@ -0,0 +1,78 @@
++/**
++ * \file common.h
++ *
++ * Common definitions for LDNS
++ */
++
++/**
++ * a Net::DNS like library for C
++ *
++ * (c) NLnet Labs, 2004-2006
++ *
++ * See the file LICENSE for the license
++ */
++
++#ifndef LDNS_COMMON_H
++#define LDNS_COMMON_H
++
++/*
++ * The build configuration that is used in the distributed headers,
++ * as detected and determined by the auto configure script.
++ */
++#define LDNS_BUILD_CONFIG_HAVE_SSL         1
++#define LDNS_BUILD_CONFIG_HAVE_INTTYPES_H  1
++#define LDNS_BUILD_CONFIG_HAVE_ATTR_FORMAT 1
++#define LDNS_BUILD_CONFIG_HAVE_ATTR_UNUSED 1
++#define LDNS_BUILD_CONFIG_HAVE_SOCKLEN_T   1
++#define LDNS_BUILD_CONFIG_USE_DANE         1
++#define LDNS_BUILD_CONFIG_HAVE_B32_PTON    0
++#define LDNS_BUILD_CONFIG_HAVE_B32_NTOP    0
++
++/*
++ * HAVE_STDBOOL_H is not available when distributed as a library, but no build 
++ * configuration variables may be used (like those above) because the header
++ * is sometimes only available when using special compiler flags to enable the
++ * c99 environment. Because we cannot force the usage of this flag, we have to
++ * provide a default type. Below what is suggested by the autoconf manual.
++ */
++/*@ignore@*/
++/* splint barfs on this construct */
++#ifndef __bool_true_false_are_defined
++# ifdef HAVE_STDBOOL_H
++#  include <stdbool.h>
++# else
++#  ifndef HAVE__BOOL
++#   ifdef __cplusplus
++typedef bool _Bool;
++#   else
++#    define _Bool signed char
++#   endif
++#  endif
++#  define bool _Bool
++#  define false 0
++#  define true 1
++#  define __bool_true_false_are_defined 1
++# endif
++#endif
++/*@end@*/
++
++#if LDNS_BUILD_CONFIG_HAVE_ATTR_FORMAT
++#define ATTR_FORMAT(archetype, string_index, first_to_check) \
++    __attribute__ ((format (archetype, string_index, first_to_check)))
++#else /* !LDNS_BUILD_CONFIG_HAVE_ATTR_FORMAT */
++#define ATTR_FORMAT(archetype, string_index, first_to_check) /* empty */
++#endif /* !LDNS_BUILD_CONFIG_HAVE_ATTR_FORMAT */
++
++#if defined(__cplusplus)
++#define ATTR_UNUSED(x)
++#elif LDNS_BUILD_CONFIG_HAVE_ATTR_UNUSED
++#define ATTR_UNUSED(x)  x __attribute__((unused))
++#else /* !LDNS_BUILD_CONFIG_HAVE_ATTR_UNUSED */
++#define ATTR_UNUSED(x)  x
++#endif /* !LDNS_BUILD_CONFIG_HAVE_ATTR_UNUSED */
++
++#if !LDNS_BUILD_CONFIG_HAVE_SOCKLEN_T
++typedef int socklen_t;
++#endif
++
++#endif /* LDNS_COMMON_H */
+diff --git a/ldns/include/ldns/config.h b/ldns/include/ldns/config.h
+new file mode 100644
+index 0000000..d77cc7f
+--- /dev/null
++++ b/ldns/include/ldns/config.h
+@@ -0,0 +1,590 @@
++#include "EXTERN.h"
++#include "perl.h"
++
++/* Define if building universal (internal helper macro) */
++/* #undef AC_APPLE_UNIVERSAL_BUILD */
++
++/* Define to 1 if you have the <arpa/inet.h> header file. */
++#define HAVE_ARPA_INET_H 1
++
++/* Whether the C compiler accepts the "format" attribute */
++#define HAVE_ATTR_FORMAT 1
++
++/* Whether the C compiler accepts the "unused" attribute */
++#define HAVE_ATTR_UNUSED 1
++
++/* Define to 1 if you have the `b32_ntop' function. */
++/* #undef HAVE_B32_NTOP */
++
++/* Define to 1 if you have the `b32_pton' function. */
++/* #undef HAVE_B32_PTON */
++
++/* Define to 1 if you have the `b64_ntop' function. */
++/* #undef HAVE_B64_NTOP */
++
++/* Define to 1 if you have the `b64_pton' function. */
++/* #undef HAVE_B64_PTON */
++
++/* Define to 1 if you have the `bzero' function. */
++#define HAVE_BZERO 1
++
++/* Define to 1 if you have the `calloc' function. */
++#define HAVE_CALLOC 1
++
++/* Define to 1 if you have the `ctime_r' function. */
++#define HAVE_CTIME_R 1
++
++/* Is a CAFILE given at configure time */
++#define HAVE_DANE_CA_FILE 0
++
++/* Is a CAPATH given at configure time */
++#define HAVE_DANE_CA_PATH 0
++
++/* Define to 1 if you have the declaration of `NID_secp384r1', and to 0 if you
++   don't. */
++#define HAVE_DECL_NID_SECP384R1 1
++
++/* Define to 1 if you have the declaration of `NID_X9_62_prime256v1', and to 0
++   if you don't. */
++#define HAVE_DECL_NID_X9_62_PRIME256V1 1
++
++/* Define to 1 if you have the <dlfcn.h> header file. */
++#define HAVE_DLFCN_H 1
++
++/* Define to 1 if you have the `endprotoent' function. */
++#define HAVE_ENDPROTOENT 1
++
++/* Define to 1 if you have the `endservent' function. */
++#define HAVE_ENDSERVENT 1
++
++/* Define to 1 if you have the `ENGINE_load_cryptodev' function. */
++#define HAVE_ENGINE_LOAD_CRYPTODEV 1
++
++/* Define to 1 if you have the `EVP_sha256' function. */
++#define HAVE_EVP_SHA256 1
++
++/* Define to 1 if you have the `fcntl' function. */
++#define HAVE_FCNTL 1
++
++/* Define to 1 if you have the `fork' function. */
++#define HAVE_FORK 1
++
++/* Whether getaddrinfo is available */
++#define HAVE_GETADDRINFO 1
++
++/* Define to 1 if you have the <getopt.h> header file. */
++#define HAVE_GETOPT_H 1
++
++/* Define to 1 if you have the `gmtime_r' function. */
++#define HAVE_GMTIME_R 1
++
++/* If you have HMAC_CTX_init */
++#define HAVE_HMAC_CTX_INIT 1
++
++/* Define to 1 if you have the `inet_aton' function. */
++#define HAVE_INET_ATON 1
++
++/* Define to 1 if you have the `inet_ntop' function. */
++#define HAVE_INET_NTOP 1
++
++/* Define to 1 if you have the `inet_pton' function. */
++#define HAVE_INET_PTON 1
++
++/* define if you have inttypes.h */
++#define HAVE_INTTYPES_H 1
++
++/* if the function 'ioctlsocket' is available */
++/* #undef HAVE_IOCTLSOCKET */
++
++/* Define to 1 if you have the `isascii' function. */
++#define HAVE_ISASCII 1
++
++/* Define to 1 if you have the `isblank' function. */
++#define HAVE_ISBLANK 1
++
++/* Define to 1 if you have the `pcap' library (-lpcap). */
++/* #undef HAVE_LIBPCAP */
++
++/* Define to 1 if you have the `localtime_r' function. */
++#define HAVE_LOCALTIME_R 1
++
++/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
++   to 0 otherwise. */
++#define HAVE_MALLOC 1
++
++/* Define to 1 if you have the `memmove' function. */
++#define HAVE_MEMMOVE 1
++
++/* Define to 1 if you have the <memory.h> header file. */
++#define HAVE_MEMORY_H 1
++
++/* Define to 1 if you have the `memset' function. */
++#define HAVE_MEMSET 1
++
++/* Define to 1 if you have the <netdb.h> header file. */
++#define HAVE_NETDB_H 1
++
++/* Define to 1 if you have the <netinet/if_ether.h> header file. */
++/* #undef HAVE_NETINET_IF_ETHER_H */
++
++/* Define to 1 if you have the <netinet/igmp.h> header file. */
++/* #undef HAVE_NETINET_IGMP_H */
++
++/* Define to 1 if you have the <netinet/in.h> header file. */
++#define HAVE_NETINET_IN_H 1
++
++/* Define to 1 if you have the <netinet/in_systm.h> header file. */
++/* #undef HAVE_NETINET_IN_SYSTM_H */
++
++/* Define to 1 if you have the <netinet/ip6.h> header file. */
++/* #undef HAVE_NETINET_IP6_H */
++
++/* Define to 1 if you have the <netinet/ip_compat.h> header file. */
++/* #undef HAVE_NETINET_IP_COMPAT_H */
++
++/* Define to 1 if you have the <netinet/ip.h> header file. */
++/* #undef HAVE_NETINET_IP_H */
++
++/* Define to 1 if you have the <netinet/udp.h> header file. */
++/* #undef HAVE_NETINET_UDP_H */
++
++/* Define to 1 if you have the <net/ethernet.h> header file. */
++/* #undef HAVE_NET_ETHERNET_H */
++
++/* Define to 1 if you have the <net/if.h> header file. */
++/* #undef HAVE_NET_IF_H */
++
++/* Define to 1 if you have the <openssl/err.h> header file. */
++#define HAVE_OPENSSL_ERR_H 1
++
++/* Define to 1 if you have the <openssl/rand.h> header file. */
++#define HAVE_OPENSSL_RAND_H 1
++
++/* Define to 1 if you have the <openssl/ssl.h> header file. */
++#define HAVE_OPENSSL_SSL_H 1
++
++/* Define to 1 if you have the <pcap.h> header file. */
++/* #undef HAVE_PCAP_H */
++
++/* Define to 1 if you have the `random' function. */
++#define HAVE_RANDOM 1
++
++/* Define to 1 if your system has a GNU libc compatible `realloc' function,
++   and to 0 otherwise. */
++#define HAVE_REALLOC 1
++
++/* Define to 1 if you have the `sleep' function. */
++#define HAVE_SLEEP 1
++
++/* Define to 1 if you have the `snprintf' function. */
++#define HAVE_SNPRINTF 1
++
++/* Define if you have the SSL libraries installed. */
++#define HAVE_SSL /**/
++
++/* Define to 1 if you have the <stdarg.h> header file. */
++#define HAVE_STDARG_H 1
++
++/* Define to 1 if stdbool.h conforms to C99. */
++#define HAVE_STDBOOL_H 1
++
++/* Define to 1 if you have the <stdint.h> header file. */
++#define HAVE_STDINT_H 1
++
++/* Define to 1 if you have the <stdlib.h> header file. */
++#define HAVE_STDLIB_H 1
++
++/* Define to 1 if you have the <strings.h> header file. */
++#define HAVE_STRINGS_H 1
++
++/* Define to 1 if you have the <string.h> header file. */
++#define HAVE_STRING_H 1
++
++/* Define to 1 if you have the `strlcpy' function. */
++#ifdef HAS_STRLCPY
++#define HAVE_STRLCPY 1
++#else
++#undef HAVE_STRLCPY
++#endif
++
++/* Define to 1 if you have the `strtoul' function. */
++#define HAVE_STRTOUL 1
++
++/* Define to 1 if you have the <sys/mount.h> header file. */
++#define HAVE_SYS_MOUNT_H 1
++
++/* Define to 1 if you have the <sys/param.h> header file. */
++#define HAVE_SYS_PARAM_H 1
++
++/* define if you have sys/socket.h */
++#define HAVE_SYS_SOCKET_H 1
++
++/* Define to 1 if you have the <sys/stat.h> header file. */
++#define HAVE_SYS_STAT_H 1
++
++/* define if you have sys/types.h */
++#define HAVE_SYS_TYPES_H 1
++
++/* Define to 1 if you have the `timegm' function. */
++#define HAVE_TIMEGM 1
++
++/* Define to 1 if you have the <time.h> header file. */
++#define HAVE_TIME_H 1
++
++/* define if you have unistd.h */
++#define HAVE_UNISTD_H 1
++
++/* Define to 1 if you have the `vfork' function. */
++#define HAVE_VFORK 1
++
++/* Define to 1 if you have the <vfork.h> header file. */
++/* #undef HAVE_VFORK_H */
++
++/* Define to 1 if you have the <winsock2.h> header file. */
++/* #undef HAVE_WINSOCK2_H */
++
++/* Define to 1 if `fork' works. */
++#define HAVE_WORKING_FORK 1
++
++/* Define to 1 if `vfork' works. */
++#define HAVE_WORKING_VFORK 1
++
++/* Define to 1 if you have the <ws2tcpip.h> header file. */
++/* #undef HAVE_WS2TCPIP_H */
++
++/* Define to 1 if the system has the type `_Bool'. */
++#define HAVE__BOOL 1
++
++/* Is a CAFILE given at configure time */
++/* #undef LDNS_DANE_CA_FILE */
++
++/* Is a CAPATH given at configure time */
++/* #undef LDNS_DANE_CA_PATH */
++
++/* Define to the sub-directory where libtool stores uninstalled libraries. */
++#define LT_OBJDIR ".libs/"
++
++/* Define to the address where bug reports for this package should be sent. */
++#define PACKAGE_BUGREPORT "libdns at nlnetlabs.nl"
++
++/* Define to the full name of this package. */
++#define PACKAGE_NAME "ldns"
++
++/* Define to the full name and version of this package. */
++#define PACKAGE_STRING "ldns 1.6.17"
++
++/* Define to the one symbol short name of this package. */
++#define PACKAGE_TARNAME "libdns"
++
++/* Define to the home page for this package. */
++#define PACKAGE_URL ""
++
++/* Define to the version of this package. */
++#define PACKAGE_VERSION "1.6.17"
++
++/* Define this to enable RR type NINFO. */
++/* #undef RRTYPE_NINFO */
++
++/* Define this to enable RR type OPENPGPKEY. */
++/* #undef RRTYPE_OPENPGPKEY */
++
++/* Define this to enable RR type RKEY. */
++/* #undef RRTYPE_RKEY */
++
++/* Define this to enable RR type TA. */
++/* #undef RRTYPE_TA */
++
++/* Define this to enable RR type URI. */
++/* #undef RRTYPE_URI */
++
++/* The size of `time_t', as computed by sizeof. */
++#define SIZEOF_TIME_T 8
++
++/* Define to 1 if you have the ANSI C header files. */
++#define STDC_HEADERS 1
++
++/* Define this to enable messages to stderr. */
++/* #undef STDERR_MSGS */
++
++/* System configuration dir */
++#define SYSCONFDIR sysconfdir
++
++/* Define this to enable DANE support. */
++#define USE_DANE 1
++
++/* Define this to enable ECDSA support. */
++#define USE_ECDSA 1
++
++/* Define this to enable GOST support. */
++/* #define USE_GOST 1 */
++
++/* Define this to enable SHA256 and SHA512 support. */
++#define USE_SHA2 1
++
++/* Enable extensions on AIX 3, Interix.  */
++#ifndef _ALL_SOURCE
++# define _ALL_SOURCE 1
++#endif
++/* Enable GNU extensions on systems that have them.  */
++#ifndef _GNU_SOURCE
++# define _GNU_SOURCE 1
++#endif
++/* Enable threading extensions on Solaris.  */
++#ifndef _POSIX_PTHREAD_SEMANTICS
++# define _POSIX_PTHREAD_SEMANTICS 1
++#endif
++/* Enable extensions on HP NonStop.  */
++#ifndef _TANDEM_SOURCE
++# define _TANDEM_SOURCE 1
++#endif
++/* Enable general extensions on Solaris.  */
++#ifndef __EXTENSIONS__
++# define __EXTENSIONS__ 1
++#endif
++
++
++/* Whether the windows socket API is used */
++/* #undef USE_WINSOCK */
++
++/* the version of the windows API enabled */
++#define WINVER 0x0502
++
++/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
++   significant byte first (like Motorola and SPARC, unlike Intel). */
++#if defined AC_APPLE_UNIVERSAL_BUILD
++# if defined __BIG_ENDIAN__
++#  define WORDS_BIGENDIAN 1
++# endif
++#else
++# ifndef WORDS_BIGENDIAN
++/* #  undef WORDS_BIGENDIAN */
++# endif
++#endif
++
++/* Define to 1 if on MINIX. */
++/* #undef _MINIX */
++
++/* Enable for compile on Minix */
++/* #undef _NETBSD_SOURCE */
++
++/* Define to 2 if the system does not provide POSIX.1 features except with
++   this defined. */
++/* #undef _POSIX_1_SOURCE */
++
++/* Define to 1 if you need to in order for `stat' and other things to work. */
++/* #undef _POSIX_SOURCE */
++
++/* Define to empty if `const' does not conform to ANSI C. */
++/* #undef const */
++
++/* in_addr_t */
++/* #undef in_addr_t */
++
++/* in_port_t */
++/* #undef in_port_t */
++
++/* Define to `__inline__' or `__inline' if that's what the C compiler
++   calls it, or to nothing if 'inline' is not supported under any name.  */
++#ifndef __cplusplus
++/* #undef inline */
++#endif
++
++/* Define to `short' if <sys/types.h> does not define. */
++/* #undef int16_t */
++
++/* Define to `int' if <sys/types.h> does not define. */
++/* #undef int32_t */
++
++/* Define to `long long' if <sys/types.h> does not define. */
++/* #undef int64_t */
++
++/* Define to `char' if <sys/types.h> does not define. */
++/* #undef int8_t */
++
++/* Define to `size_t' if <sys/types.h> does not define. */
++/* #undef intptr_t */
++
++/* Define to rpl_malloc if the replacement function should be used. */
++/* #undef malloc */
++
++/* Define to `int' if <sys/types.h> does not define. */
++/* #undef pid_t */
++
++/* Define to rpl_realloc if the replacement function should be used. */
++/* #undef realloc */
++
++/* Define to `unsigned int' if <sys/types.h> does not define. */
++/* #undef size_t */
++
++/* Define to 'int' if not defined */
++/* #undef socklen_t */
++
++/* Fallback member name for socket family in struct sockaddr_storage */
++/* #undef ss_family */
++
++/* Define to `int' if <sys/types.h> does not define. */
++/* #undef ssize_t */
++
++/* Define to `unsigned short' if <sys/types.h> does not define. */
++/* #undef uint16_t */
++
++/* Define to `unsigned int' if <sys/types.h> does not define. */
++/* #undef uint32_t */
++
++/* Define to `unsigned long long' if <sys/types.h> does not define. */
++/* #undef uint64_t */
++
++/* Define to `unsigned char' if <sys/types.h> does not define. */
++/* #undef uint8_t */
++
++/* Define as `fork' if `vfork' does not work. */
++/* #undef vfork */
++
++
++#include <stdio.h>
++#include <string.h>
++#include <unistd.h>
++#include <assert.h>
++
++#ifndef LITTLE_ENDIAN
++#define LITTLE_ENDIAN 1234
++#endif
++
++#ifndef BIG_ENDIAN
++#define BIG_ENDIAN 4321
++#endif
++
++#ifndef BYTE_ORDER
++#ifdef WORDS_BIGENDIAN
++#define BYTE_ORDER BIG_ENDIAN
++#else
++#define BYTE_ORDER LITTLE_ENDIAN
++#endif /* WORDS_BIGENDIAN */
++#endif /* BYTE_ORDER */
++
++#if STDC_HEADERS
++#include <stdlib.h>
++#include <stddef.h>
++#endif
++
++#ifdef HAVE_STDINT_H
++#include <stdint.h>
++#endif
++
++#ifdef HAVE_SYS_SOCKET_H
++#include <sys/socket.h>
++#endif
++
++#ifdef HAVE_NETINET_IN_H
++#include <netinet/in.h>
++#endif
++
++#ifdef HAVE_ARPA_INET_H
++#include <arpa/inet.h>
++#endif
++
++#ifdef HAVE_WINSOCK2_H
++#include <winsock2.h>
++#endif
++
++#ifdef HAVE_WS2TCPIP_H
++#include <ws2tcpip.h>
++#endif
++
++
++/* detect if we need to cast to unsigned int for FD_SET to avoid warnings */
++#ifdef HAVE_WINSOCK2_H
++#define FD_SET_T (u_int)
++#else
++#define FD_SET_T 
++#endif
++
++
++
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++int ldns_b64_ntop(uint8_t const *src, size_t srclength,
++	 	  char *target, size_t targsize);
++/**
++ * calculates the size needed to store the result of b64_ntop
++ */
++/*@unused@*/
++static inline size_t ldns_b64_ntop_calculate_size(size_t srcsize)
++{
++	return ((((srcsize + 2) / 3) * 4) + 1);
++}
++int ldns_b64_pton(char const *src, uint8_t *target, size_t targsize);
++/**
++ * calculates the size needed to store the result of ldns_b64_pton
++ */
++/*@unused@*/
++static inline size_t ldns_b64_pton_calculate_size(size_t srcsize)
++{
++	return (((((srcsize + 3) / 4) * 3)) + 1);
++}
++
++/**
++ * Given in dnssec_zone.c, also used in dnssec_sign.c:w
++
++ */
++int ldns_dname_compare_v(const void *a, const void *b);
++
++#ifndef HAVE_SLEEP
++/* use windows sleep, in millisecs, instead */
++#define sleep(x) Sleep((x)*1000)
++#endif
++
++#ifndef HAVE_RANDOM
++#define srandom(x) srand(x)
++#define random(x) rand(x)
++#endif
++
++#ifndef HAVE_TIMEGM
++#include <time.h>
++time_t timegm (struct tm *tm);
++#endif /* !TIMEGM */
++#ifndef HAVE_GMTIME_R
++struct tm *gmtime_r(const time_t *timep, struct tm *result);
++#endif
++#ifndef HAVE_LOCALTIME_R
++struct tm *localtime_r(const time_t *timep, struct tm *result);
++#endif
++#ifndef HAVE_ISBLANK
++int isblank(int c);
++#endif /* !HAVE_ISBLANK */
++#ifndef HAVE_ISASCII
++int isascii(int c);
++#endif /* !HAVE_ISASCII */
++#ifndef HAVE_SNPRINTF
++#include <stdarg.h>
++int snprintf (char *str, size_t count, const char *fmt, ...);
++int vsnprintf (char *str, size_t count, const char *fmt, va_list arg);
++#endif /* HAVE_SNPRINTF */
++#ifndef HAVE_INET_PTON
++int inet_pton(int af, const char* src, void* dst);
++#endif /* HAVE_INET_PTON */
++#ifndef HAVE_INET_NTOP
++const char *inet_ntop(int af, const void *src, char *dst, size_t size);
++#endif
++#ifndef HAVE_INET_ATON
++int inet_aton(const char *cp, struct in_addr *addr);
++#endif
++#ifndef HAVE_MEMMOVE
++void *memmove(void *dest, const void *src, size_t n);
++#endif
++#ifndef HAVE_STRLCPY
++size_t strlcpy(char *dst, const char *src, size_t siz);
++#endif
++#ifdef __cplusplus
++}
++#endif
++#ifndef HAVE_GETADDRINFO
++#include "compat/fake-rfc2553.h"
++#endif
++#ifndef HAVE_STRTOUL
++#define strtoul (unsigned long)strtol
++#endif
++
+diff --git a/ldns/include/ldns/dane.h b/ldns/include/ldns/dane.h
+new file mode 100644
+index 0000000..8234eb7
+--- /dev/null
++++ b/ldns/include/ldns/dane.h
+@@ -0,0 +1,262 @@
++/*
++ * dane.h -- defines for the DNS-Based Authentication of Named Entities (DANE)
++ *                           Transport Layer Security (TLS) Protocol: TLSA
++ *
++ * Copyright (c) 2012, NLnet Labs. All rights reserved.
++ *
++ * See LICENSE for the license.
++ *
++ */
++
++/**
++ * \file
++ *
++ * This module contains base functions for creating and verifying TLSA RR's
++ * with PKIX certificates, certificate chains and validation stores.
++ * (See RFC6394 and RFC6698).
++ * 
++ * Since those functions heavily rely op cryptographic operations,
++ * this module is dependent on openssl.
++ */
++ 
++
++#ifndef LDNS_DANE_H
++#define LDNS_DANE_H
++#if LDNS_BUILD_CONFIG_USE_DANE
++
++#include <ldns/common.h>
++#include <ldns/rdata.h>
++#include <ldns/rr.h>
++#if LDNS_BUILD_CONFIG_HAVE_SSL
++#include <openssl/ssl.h>
++#include <openssl/err.h>
++#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/**
++ * The different "Certificate usage" rdata field values for a TLSA RR.
++ */
++enum ldns_enum_tlsa_certificate_usage
++{
++	/** CA constraint */
++	LDNS_TLSA_USAGE_PKIX_TA				=   0,
++	LDNS_TLSA_USAGE_CA_CONSTRAINT			=   0,
++	/** Sevice certificate constraint */
++	LDNS_TLSA_USAGE_PKIX_EE				=   1,
++	LDNS_TLSA_USAGE_SERVICE_CERTIFICATE_CONSTRAINT	=   1,
++	/** Trust anchor assertion */
++	LDNS_TLSA_USAGE_DANE_TA				=   2,
++	LDNS_TLSA_USAGE_TRUST_ANCHOR_ASSERTION		=   2,
++	/** Domain issued certificate */
++	LDNS_TLSA_USAGE_DANE_EE				=   3,
++	LDNS_TLSA_USAGE_DOMAIN_ISSUED_CERTIFICATE	=   3,
++	/** Reserved for Private Use */
++	LDNS_TLSA_USAGE_PRIVCERT			= 255
++};
++typedef enum ldns_enum_tlsa_certificate_usage ldns_tlsa_certificate_usage;
++
++/**
++ * The different "Selector" rdata field values for a TLSA RR.
++ */
++enum ldns_enum_tlsa_selector
++{
++	/** 
++	 * Full certificate: the Certificate binary structure
++	 * as defined in [RFC5280]
++	 */
++	LDNS_TLSA_SELECTOR_CERT			=   0,
++	LDNS_TLSA_SELECTOR_FULL_CERTIFICATE	=   0,
++
++	/** 
++	 * SubjectPublicKeyInfo: DER-encoded binary structure
++	 * as defined in [RFC5280]
++	 */
++	LDNS_TLSA_SELECTOR_SPKI			=   1,
++	LDNS_TLSA_SELECTOR_SUBJECTPUBLICKEYINFO	=   1,
++
++	/** Reserved for Private Use */
++	LDNS_TLSA_SELECTOR_PRIVSEL		= 255
++};
++typedef enum ldns_enum_tlsa_selector ldns_tlsa_selector;
++
++/**
++ * The different "Matching type" rdata field values for a TLSA RR.
++ */
++enum ldns_enum_tlsa_matching_type
++{
++	/** Exact match on selected content */
++	LDNS_TLSA_MATCHING_TYPE_FULL		=   0,
++	LDNS_TLSA_MATCHING_TYPE_NO_HASH_USED	=   0,
++	/** SHA-256 hash of selected content [RFC6234] */
++	LDNS_TLSA_MATCHING_TYPE_SHA2_256	=   1,
++	LDNS_TLSA_MATCHING_TYPE_SHA256		=   1,
++	/** SHA-512 hash of selected content [RFC6234] */
++	LDNS_TLSA_MATCHING_TYPE_SHA2_512	=   2,
++	LDNS_TLSA_MATCHING_TYPE_SHA512		=   2,
++	/** Reserved for Private Use */
++	LDNS_TLSA_MATCHING_TYPE_PRIVMATCH	= 255
++};
++typedef enum ldns_enum_tlsa_matching_type ldns_tlsa_matching_type;
++
++/**
++ * Known transports to use with TLSA owner names.
++ */
++enum ldns_enum_dane_transport
++{
++	/** TCP */
++	LDNS_DANE_TRANSPORT_TCP  = 0,
++	/** UDP */
++	LDNS_DANE_TRANSPORT_UDP  = 1,
++	/** SCTP */
++	LDNS_DANE_TRANSPORT_SCTP = 2
++};
++typedef enum ldns_enum_dane_transport ldns_dane_transport;
++
++
++/**
++ * Creates a dname consisting of the given name, prefixed by the service port
++ * and type of transport: _<EM>port</EM>._<EM>transport</EM>.<EM>name</EM>.
++ *
++ * \param[out] tlsa_owner The created dname.
++ * \param[in] name The dname that should be prefixed.
++ * \param[in] port The service port number for wich the name should be created.
++ * \param[in] transport The transport for wich the name should be created.
++ * \return LDNS_STATUS_OK on success or an error code otherwise.
++ */
++ldns_status ldns_dane_create_tlsa_owner(ldns_rdf** tlsa_owner,
++		const ldns_rdf* name, uint16_t port,
++		ldns_dane_transport transport);
++
++
++#if LDNS_BUILD_CONFIG_HAVE_SSL
++/**
++ * Creates a LDNS_RDF_TYPE_HEX type rdf based on the binary data choosen by
++ * the selector and encoded using matching_type.
++ *
++ * \param[out] rdf The created created rdf of type LDNS_RDF_TYPE_HEX.
++ * \param[in] cert The certificate from which the data is selected
++ * \param[in] selector The full certificate or the public key
++ * \param[in] matching_type The full data or the SHA256 or SHA512 hash
++ *            of the selected data
++ * \return LDNS_STATUS_OK on success or an error code otherwise.
++ */
++ldns_status ldns_dane_cert2rdf(ldns_rdf** rdf, X509* cert,
++		ldns_tlsa_selector      selector,
++		ldns_tlsa_matching_type matching_type);
++
++
++/**
++ * Selects the certificate from cert, extra_certs or the pkix_validation_store
++ * based on the value of cert_usage and index.
++ *
++ * \param[out] selected_cert The selected cert.
++ * \param[in] cert The certificate to validate (or not)
++ * \param[in] extra_certs Intermediate certificates that might be necessary
++ *            during validation. May be NULL, except when the certificate 
++ *            usage is "Trust Anchor Assertion" because the trust anchor has
++ *            to be provided.(otherwise choose a "Domain issued certificate!"
++ * \param[in] pkix_validation_store Used when the certificate usage is 
++ *            "CA constraint" or "Service Certificate Constraint" to 
++ *            validate the certificate and, in case of "CA constraint",
++ *            select the CA.
++ *            When pkix_validation_store is NULL, validation is explicitely
++ *            turned off and the behaviour is then the same as for "Trust
++ *            anchor assertion" and "Domain issued certificate" respectively.
++ * \param[in] cert_usage Which certificate to use and how to validate.
++ * \param[in] index Used to select the trust anchor when certificate usage
++ *            is "Trust Anchor Assertion". 0 is the last certificate in the
++ *            validation chain. 1 the one but last, etc. When index is -1,
++ *            the last certificate is used that MUST be self-signed.
++ *            This can help to make sure that the intended (self signed)
++ *            trust anchor is actually present in extra_certs (which is a
++ *            DANE requirement).
++ *
++ * \return LDNS_STATUS_OK on success or an error code otherwise.
++ */
++ldns_status ldns_dane_select_certificate(X509** selected_cert,
++		X509* cert, STACK_OF(X509)* extra_certs,
++		X509_STORE* pkix_validation_store,
++		ldns_tlsa_certificate_usage cert_usage, int index);
++
++/**
++ * Creates a TLSA resource record from the certificate.
++ * No PKIX validation is performed! The given certificate is used as data
++ * regardless the value of certificate_usage.
++ *
++ * \param[out] tlsa The created TLSA resource record.
++ * \param[in] certificate_usage The value for the Certificate Usage field
++ * \param[in] selector The value for the Selector field
++ * \param[in] matching_type The value for the Matching Type field
++ * \param[in] cert The certificate which data will be represented
++ *
++ * \return LDNS_STATUS_OK on success or an error code otherwise.
++ */
++ldns_status ldns_dane_create_tlsa_rr(ldns_rr** tlsa,
++		ldns_tlsa_certificate_usage certificate_usage,
++		ldns_tlsa_selector          selector,
++		ldns_tlsa_matching_type     matching_type,
++		X509* cert);
++
++/**
++ * Verify if the given TLSA resource record matches the given certificate.
++ * Reporting on a TLSA rr mismatch (LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH)
++ * is preferred over PKIX failure  (LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE).
++ * So when PKIX validation is required by the TLSA Certificate usage,
++ * but the TLSA data does not match, LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH
++ * is returned whether the PKIX validated or not.
++ *
++ * \param[in] tlsa_rr The resource record that specifies what and how to
++ *            match the certificate. With tlsa_rr == NULL, regular PKIX
++ *            validation is performed.
++ * \param[in] cert The certificate to match (and validate)
++ * \param[in] extra_certs Intermediate certificates that might be necessary
++ *            creating the validation chain.
++ * \param[in] pkix_validation_store Used when the certificate usage is 
++ *            "CA constraint" or "Service Certificate Constraint" to 
++ *            validate the certificate.
++ *
++ * \return LDNS_STATUS_OK on success,
++ *         LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH on TLSA data mismatch,
++ *         LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE when TLSA matched,
++ *         but the PKIX validation failed, or other ldns_status errors.
++ */
++ldns_status ldns_dane_verify_rr(const ldns_rr* tlsa_rr,
++		X509* cert, STACK_OF(X509)* extra_certs,
++		X509_STORE* pkix_validation_store);
++
++/**
++ * Verify if any of the given TLSA resource records matches the given
++ * certificate.
++ *
++ * \param[in] tlsas The resource records that specify what and how to
++ *            match the certificate. One must match for this function
++ *            to succeed. With tlsas == NULL or the number of TLSA records
++ *            in tlsas == 0, regular PKIX validation is performed.
++ * \param[in] cert The certificate to match (and validate)
++ * \param[in] extra_certs Intermediate certificates that might be necessary
++ *            creating the validation chain.
++ * \param[in] pkix_validation_store Used when the certificate usage is 
++ *            "CA constraint" or "Service Certificate Constraint" to 
++ *            validate the certificate.
++ *
++ * \return LDNS_STATUS_OK on success,
++ *         LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE when one of the TLSA's
++ *         matched but the PKIX validation failed,
++ *         LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH when none of the TLSA's matched,
++ *         or other ldns_status errors.
++ */
++ldns_status ldns_dane_verify(ldns_rr_list* tlsas,
++		X509* cert, STACK_OF(X509)* extra_certs,
++		X509_STORE* pkix_validation_store);
++#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* LDNS_BUILD_CONFIG_USE_DANE */
++#endif /* LDNS_DANE_H */
++
+diff --git a/ldns/include/ldns/dname.h b/ldns/include/ldns/dname.h
+new file mode 100644
+index 0000000..291786b
+--- /dev/null
++++ b/ldns/include/ldns/dname.h
+@@ -0,0 +1,211 @@
++/*
++ * dname.h
++ *
++ * dname definitions
++ *
++ * a Net::DNS like library for C
++ *
++ * (c) NLnet Labs, 2004-2006
++ *
++ * See the file LICENSE for the license
++ */
++
++/**
++ * \file dname.h
++ *
++ * dname contains function to read and manipulate domain names.
++ *
++ * Example domain names are "www.nlnetlabs.nl." and "." (the root)
++ *
++ * If a domain name ends with a dot ("."), it is called a Fully Qualified
++ * Domain Name (FQDN). In certain places (for instance when reading a zone
++ * file), an origin (which is just another domain name) non-FQDNs will be
++ * placed after the current. For instance, if i have a zone file where the
++ * origin has been set to "nl.", and my file contains the name
++ * "www.nlnetlabs", it will result in "www.nlnetlabs.nl.". Internally, dnames are
++ * always absolute (the dot is added when it is missing and there is no origin).
++ *
++ * An FQDN is also
++ * known as an absolute domain name, therefore the function to check this is
++ * called \ref ldns_dname_str_absolute
++ *
++ * Domain names are stored in \ref ldns_rdf structures, with the type
++ * \ref LDNS_RDF_TYPE_DNAME
++ *
++ * This module is *NOT* about the RR type called DNAME.
++ */
++
++
++#ifndef LDNS_DNAME_H
++#define LDNS_DNAME_H
++
++#include <ldns/common.h>
++#include <ldns/rdata.h>
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++#define LDNS_DNAME_NORMALIZE        tolower
++
++/**
++ * concatenates two dnames together
++ * \param[in] rd1 the leftside
++ * \param[in] rd2 the rightside
++ * \return a new rdf with leftside/rightside
++ */
++ldns_rdf *ldns_dname_cat_clone(const ldns_rdf *rd1, const ldns_rdf *rd2);
++
++/**
++ * concatenates rd2 after rd1 (rd2 is copied, rd1 is modified)
++ * \param[in] rd1 the leftside
++ * \param[in] rd2 the rightside
++ * \return LDNS_STATUS_OK on success
++ */
++ldns_status 	ldns_dname_cat(ldns_rdf *rd1, ldns_rdf *rd2);
++
++/**
++ * Returns a clone of the given dname with the labels
++ * reversed
++ * \param[in] d the dname to reverse
++ * \return clone of the dname with the labels reversed.
++ */
++ldns_rdf *ldns_dname_reverse(const ldns_rdf *d);
++
++/**
++ * Clones the given dname from the nth label on
++ * \param[in] d The dname to clone
++ * \param[in] n the label nr to clone from, if this is 0, the complete
++ *              dname is cloned
++ * \return A newly allocated *rdf structure, containing the cloned dname,
++ *         or NULL if either d was NULL, not a dname, or if n >=
++ *         label_count
++ */
++ldns_rdf *
++ldns_dname_clone_from(const ldns_rdf *d, uint16_t n);
++
++/**
++ * chop one label off the left side of a dname. so
++ * wwww.nlnetlabs.nl, becomes nlnetlabs.nl
++ * This new name is a clone and must be freed with ldns_deep_free()
++ * \param[in] d the dname to chop
++ * \return the remaining dname
++ */
++ldns_rdf *ldns_dname_left_chop(const ldns_rdf *d);
++
++/**
++ * count the number of labels inside a LDNS_RDF_DNAME type rdf.
++ * \param[in] *r the rdf
++ * \return the number of labels
++ */
++uint8_t  ldns_dname_label_count(const ldns_rdf *r);
++
++/**
++ * creates a new dname rdf from a string.
++ * \param[in] str string to use
++ * \return ldns_rdf* or NULL in case of an error
++ */
++ldns_rdf *ldns_dname_new_frm_str(const char *str);
++
++/**
++ * Create a new dname rdf from a string
++ * \param[in] s the size of the new dname
++ * \param[in] *data pointer to the actual data
++ *
++ * \return ldns_rdf*
++ */
++ldns_rdf *ldns_dname_new(uint16_t s, void *data);
++
++/**
++ * Create a new dname rdf from data (the data is copied)
++ * \param[in] size the size of the data
++ * \param[in] *data pointer to the actual data
++ *
++ * \return ldns_rdf*
++ */
++ldns_rdf *ldns_dname_new_frm_data(uint16_t size, const void *data);
++
++/**
++ * Put a dname into canonical fmt - ie. lowercase it
++ * \param[in] rdf the dname to lowercase
++ * \return void
++ */
++void ldns_dname2canonical(const ldns_rdf *rdf);
++
++/**
++ * test wether the name sub falls under parent (i.e. is a subdomain
++ * of parent). This function will return false if the given dnames are
++ * equal.
++ * \param[in] sub the name to test
++ * \param[in] parent the parent's name
++ * \return true if sub falls under parent, otherwise false
++ */
++bool ldns_dname_is_subdomain(const ldns_rdf *sub, const ldns_rdf *parent);
++
++/**
++ * Compares the two dname rdf's according to the algorithm for ordering
++ * in RFC4034 Section 6.
++ * \param[in] dname1 First dname rdf to compare
++ * \param[in] dname2 Second dname rdf to compare
++ * \return -1 if dname1 comes before dname2, 1 if dname1 comes after dname2, and 0 if they are equal.
++ */
++int ldns_dname_compare(const ldns_rdf *dname1, const ldns_rdf *dname2);
++int ldns_dname_compare_v(const void *, const void *);
++
++/**
++ * Checks whether the dname matches the given wildcard
++ * \param[in] dname The dname to check
++ * \param[in] wildcard The wildcard to check with
++ * \return 1 If the wildcard matches, OR if 'wildcard' is not a wildcard and
++ *           the names are *exactly* the same
++ *         0 If the wildcard does not match, or if it is not a wildcard and
++ *           the names are not the same
++ */
++int ldns_dname_match_wildcard(const ldns_rdf *dname, const ldns_rdf *wildcard);
++
++/**
++ * check if middle lays in the interval defined by prev and next
++ * prev <= middle < next. This is usefull for nsec checking
++ * \param[in] prev the previous dname
++ * \param[in] middle the dname to check
++ * \param[in] next the next dname
++ * return 0 on error or unknown, -1 when middle is in the interval, +1 when not
++ */
++int ldns_dname_interval(const ldns_rdf *prev, const ldns_rdf *middle, const ldns_rdf *next);
++
++/**
++ * Checks whether the given dname string is absolute (i.e. ends with a '.')
++ * \param[in] *dname_str a string representing the dname
++ * \return true or false
++ */
++bool ldns_dname_str_absolute(const char *dname_str);
++
++/**
++ * Checks whether the given dname is absolute (i.e. ends with a '.')
++ * \param[in] *dname a rdf representing the dname
++ * \return true or false
++ */
++bool ldns_dname_absolute(const ldns_rdf *dname);
++
++/**
++ * look inside the rdf and if it is an LDNS_RDF_TYPE_DNAME
++ * try and retrieve a specific label. The labels are numbered
++ * starting from 0 (left most).
++ * \param[in] rdf the rdf to look in
++ * \param[in] labelpos return the label with this number
++ * \return a ldns_rdf* with the label as name or NULL on error
++ */
++ldns_rdf * ldns_dname_label(const ldns_rdf *rdf, uint8_t labelpos);
++
++/**
++ * Check if dname is a wildcard, starts with *.
++ * \param[in] dname: the rdf to look in
++ * \return true if a wildcard, false if not.
++ */
++int ldns_dname_is_wildcard(const ldns_rdf* dname);
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif	/* LDNS_DNAME_H */
+diff --git a/ldns/include/ldns/dnssec.h b/ldns/include/ldns/dnssec.h
+new file mode 100644
+index 0000000..f4cdafb
+--- /dev/null
++++ b/ldns/include/ldns/dnssec.h
+@@ -0,0 +1,541 @@
++/*
++ * dnssec.h -- defines for the Domain Name System (SEC) (DNSSEC)
++ *
++ * Copyright (c) 2005-2008, NLnet Labs. All rights reserved.
++ *
++ * See LICENSE for the license.
++ *
++ * A bunch of defines that are used in the DNS
++ */
++
++/**
++ * \file dnssec.h
++ *
++ * This module contains base functions for DNSSEC operations
++ * (RFC4033 t/m RFC4035).
++ * 
++ * Since those functions heavily rely op cryptographic operations,
++ * this module is dependent on openssl.
++ * 
++ */
++ 
++
++#ifndef LDNS_DNSSEC_H
++#define LDNS_DNSSEC_H
++
++#include <ldns/common.h>
++#if LDNS_BUILD_CONFIG_HAVE_SSL
++#include <openssl/ssl.h>
++#include <openssl/evp.h>
++#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */
++#include <ldns/packet.h>
++#include <ldns/keys.h>
++#include <ldns/zone.h>
++#include <ldns/resolver.h>
++#include <ldns/dnssec_zone.h>
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++#define LDNS_MAX_KEYLEN		2048
++#define LDNS_DNSSEC_KEYPROTO	3
++/* default time before sigs expire */
++#define LDNS_DEFAULT_EXP_TIME	2419200 /* 4 weeks */
++
++/** return values for the old-signature callback */
++#define LDNS_SIGNATURE_LEAVE_ADD_NEW 0
++#define LDNS_SIGNATURE_LEAVE_NO_ADD 1
++#define LDNS_SIGNATURE_REMOVE_ADD_NEW 2
++#define LDNS_SIGNATURE_REMOVE_NO_ADD 3
++
++/**
++ * Returns the first RRSIG rr that corresponds to the rrset 
++ * with the given name and type
++ * 
++ * \param[in] name The dname of the RRset covered by the RRSIG to find
++ * \param[in] type The type of the RRset covered by the RRSIG to find
++ * \param[in] rrs List of rrs to search in
++ * \returns Pointer to the first RRsig ldns_rr found, or NULL if it is
++ * not present
++ */
++ldns_rr *ldns_dnssec_get_rrsig_for_name_and_type(const ldns_rdf *name,
++									    const ldns_rr_type type,
++									    const ldns_rr_list *rrs);
++
++/**
++ * Returns the DNSKEY that corresponds to the given RRSIG rr from the list, if
++ * any
++ *
++ * \param[in] rrsig The rrsig to find the DNSKEY for
++ * \param[in] rrs The rr list to find the key in
++ * \return The DNSKEY that corresponds to the given RRSIG, or NULL if it was
++ *         not found.
++ */
++ldns_rr *ldns_dnssec_get_dnskey_for_rrsig(const ldns_rr *rrsig, const ldns_rr_list *rrs);
++
++/**
++ * Returns the rdata field that contains the bitmap of the covered types of
++ * the given NSEC record
++ *
++ * \param[in] nsec The nsec to get the covered type bitmap of
++ * \return An ldns_rdf containing the bitmap, or NULL on error
++ */
++ldns_rdf *ldns_nsec_get_bitmap(ldns_rr *nsec);
++
++
++#define LDNS_NSEC3_MAX_ITERATIONS 65535
++
++/**
++ * Returns the dname of the closest (provable) encloser
++ */
++ldns_rdf *
++ldns_dnssec_nsec3_closest_encloser(ldns_rdf *qname,
++							ldns_rr_type qtype,
++							ldns_rr_list *nsec3s);
++
++/**
++ * Checks whether the packet contains rrsigs
++ */
++bool
++ldns_dnssec_pkt_has_rrsigs(const ldns_pkt *pkt);
++
++/**
++ * Returns a ldns_rr_list containing the signatures covering the given name
++ * and type
++ */
++ldns_rr_list *ldns_dnssec_pkt_get_rrsigs_for_name_and_type(const ldns_pkt *pkt, ldns_rdf *name, ldns_rr_type type);
++
++/**
++ * Returns a ldns_rr_list containing the signatures covering the given type
++ */
++ldns_rr_list *ldns_dnssec_pkt_get_rrsigs_for_type(const ldns_pkt *pkt, ldns_rr_type type);
++
++/** 
++ * calculates a keytag of a key for use in DNSSEC.
++ *
++ * \param[in] key the key as an RR to use for the calc.
++ * \return the keytag
++ */
++uint16_t ldns_calc_keytag(const ldns_rr *key);
++
++/**
++ * Calculates keytag of DNSSEC key, operates on wireformat rdata.
++ * \param[in] key the key as uncompressed wireformat rdata.
++ * \param[in] keysize length of key data.
++ * \return the keytag
++ */
++uint16_t ldns_calc_keytag_raw(uint8_t* key, size_t keysize);
++
++#if LDNS_BUILD_CONFIG_HAVE_SSL
++/**
++ * converts a buffer holding key material to a DSA key in openssl.
++ *
++ * \param[in] key the key to convert
++ * \return a DSA * structure with the key material
++ */
++DSA *ldns_key_buf2dsa(ldns_buffer *key);
++/**
++ * Like ldns_key_buf2dsa, but uses raw buffer.
++ * \param[in] key the uncompressed wireformat of the key.
++ * \param[in] len length of key data
++ * \return a DSA * structure with the key material
++ */
++DSA *ldns_key_buf2dsa_raw(unsigned char* key, size_t len);
++
++/**
++ * Utility function to calculate hash using generic EVP_MD pointer.
++ * \param[in] data the data to hash.
++ * \param[in] len  length of data.
++ * \param[out] dest the destination of the hash, must be large enough.
++ * \param[in] md the message digest to use.
++ * \return true if worked, false on failure.
++ */
++int ldns_digest_evp(unsigned char* data, unsigned int len, 
++	unsigned char* dest, const EVP_MD* md);
++
++/**
++ * Converts a holding buffer with key material to EVP PKEY in openssl.
++ * Only available if ldns was compiled with GOST.
++ * \param[in] key data to convert
++ * \param[in] keylen length of the key data
++ * \return the key or NULL on error.
++ */
++EVP_PKEY* ldns_gost2pkey_raw(unsigned char* key, size_t keylen);
++
++/**
++ * Converts a holding buffer with key material to EVP PKEY in openssl.
++ * Only available if ldns was compiled with ECDSA.
++ * \param[in] key data to convert
++ * \param[in] keylen length of the key data
++ * \param[in] algo precise algorithm to initialize ECC group values.
++ * \return the key or NULL on error.
++ */
++EVP_PKEY* ldns_ecdsa2pkey_raw(unsigned char* key, size_t keylen, uint8_t algo);
++
++#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */
++
++#if LDNS_BUILD_CONFIG_HAVE_SSL
++/**
++ * converts a buffer holding key material to a RSA key in openssl.
++ *
++ * \param[in] key the key to convert
++ * \return a RSA * structure with the key material
++ */
++RSA *ldns_key_buf2rsa(ldns_buffer *key);
++
++/**
++ * Like ldns_key_buf2rsa, but uses raw buffer.
++ * \param[in] key the uncompressed wireformat of the key.
++ * \param[in] len length of key data
++ * \return a RSA * structure with the key material
++ */
++RSA *ldns_key_buf2rsa_raw(unsigned char* key, size_t len);
++#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */
++
++/** 
++ * returns a new DS rr that represents the given key rr.
++ *
++ * \param[in] *key the key to convert
++ * \param[in] h the hash to use LDNS_SHA1/LDNS_SHA256
++ *
++ * \return ldns_rr* a new rr pointer to a DS
++ */
++ldns_rr *ldns_key_rr2ds(const ldns_rr *key, ldns_hash h);
++
++/**
++ * Create the type bitmap for an NSEC(3) record
++ */
++ldns_rdf *
++ldns_dnssec_create_nsec_bitmap(ldns_rr_type rr_type_list[],
++						 size_t size,
++						 ldns_rr_type nsec_type);
++
++/**
++ * returns whether a rrset of the given type is found in the rrsets.
++ *
++ * \param[in] rrsets the rrsets to be tested
++ * \param[in] type the type to test for
++ * \return int 1 if the type was found, 0 otherwise.
++ */
++int
++ldns_dnssec_rrsets_contains_type (ldns_dnssec_rrsets *rrsets, ldns_rr_type type);
++
++/**
++ * Creates NSEC
++ */
++ldns_rr *
++ldns_dnssec_create_nsec(ldns_dnssec_name *from,
++				    ldns_dnssec_name *to,
++				    ldns_rr_type nsec_type);
++
++
++/**
++ * Creates NSEC3
++ */
++ldns_rr *
++ldns_dnssec_create_nsec3(ldns_dnssec_name *from,
++					ldns_dnssec_name *to,
++					ldns_rdf *zone_name,
++					uint8_t algorithm,
++					uint8_t flags,
++					uint16_t iterations,
++					uint8_t salt_length,
++					uint8_t *salt);
++
++/**
++ * Create a NSEC record
++ * \param[in] cur_owner the current owner which should be taken as the starting point
++ * \param[in] next_owner the rrlist which the nsec rr should point to 
++ * \param[in] rrs all rrs from the zone, to find all RR types of cur_owner in
++ * \return a ldns_rr with the nsec record in it
++ */
++ldns_rr * ldns_create_nsec(ldns_rdf *cur_owner, ldns_rdf *next_owner, ldns_rr_list *rrs);
++
++/**
++ * Calculates the hashed name using the given parameters
++ * \param[in] *name The owner name to calculate the hash for 
++ * \param[in] algorithm The hash algorithm to use
++ * \param[in] iterations The number of hash iterations to use
++ * \param[in] salt_length The length of the salt in bytes
++ * \param[in] salt The salt to use
++ * \return The hashed owner name rdf, without the domain name
++ */
++ldns_rdf *ldns_nsec3_hash_name(ldns_rdf *name, uint8_t algorithm, uint16_t iterations, uint8_t salt_length, uint8_t *salt);
++
++/**
++ * Sets all the NSEC3 options. The rr to set them in must be initialized with _new() and
++ * type LDNS_RR_TYPE_NSEC3
++ * \param[in] *rr The RR to set the values in
++ * \param[in] algorithm The NSEC3 hash algorithm 
++ * \param[in] flags The flags field 
++ * \param[in] iterations The number of hash iterations
++ * \param[in] salt_length The length of the salt in bytes 
++ * \param[in] salt The salt bytes
++ */
++void ldns_nsec3_add_param_rdfs(ldns_rr *rr,
++						 uint8_t algorithm,
++						 uint8_t flags,
++						 uint16_t iterations,
++						 uint8_t salt_length,
++						 uint8_t *salt);
++
++/* this will NOT return the NSEC3  completed, you will have to run the
++   finalize function on the rrlist later! */
++ldns_rr *
++ldns_create_nsec3(ldns_rdf *cur_owner,
++                  ldns_rdf *cur_zone,
++                  ldns_rr_list *rrs,
++                  uint8_t algorithm,
++                  uint8_t flags,
++                  uint16_t iterations,
++                  uint8_t salt_length,
++                  uint8_t *salt,
++                  bool emptynonterminal);
++
++/**
++ * Returns the hash algorithm used in the given NSEC3 RR
++ * \param[in] *nsec3_rr The RR to read from
++ * \return The algorithm identifier, or 0 on error
++ */
++uint8_t ldns_nsec3_algorithm(const ldns_rr *nsec3_rr);
++
++/**
++ * Returns flags field
++ */
++uint8_t
++ldns_nsec3_flags(const ldns_rr *nsec3_rr);
++
++/**
++ * Returns true if the opt-out flag has been set in the given NSEC3 RR
++ * \param[in] *nsec3_rr The RR to read from
++ * \return true if the RR has type NSEC3 and the opt-out bit has been set, false otherwise
++ */
++bool ldns_nsec3_optout(const ldns_rr *nsec3_rr);
++
++/**
++ * Returns the number of hash iterations used in the given NSEC3 RR
++ * \param[in] *nsec3_rr The RR to read from
++ * \return The number of iterations
++ */
++uint16_t ldns_nsec3_iterations(const ldns_rr *nsec3_rr);
++
++/**
++ * Returns the salt used in the given NSEC3 RR
++ * \param[in] *nsec3_rr The RR to read from
++ * \return The salt rdf, or NULL on error
++ */
++ldns_rdf *ldns_nsec3_salt(const ldns_rr *nsec3_rr);
++
++/**
++ * Returns the length of the salt used in the given NSEC3 RR
++ * \param[in] *nsec3_rr The RR to read from
++ * \return The length of the salt in bytes
++ */
++uint8_t ldns_nsec3_salt_length(const ldns_rr *nsec3_rr);
++
++/**
++ * Returns the salt bytes used in the given NSEC3 RR
++ * \param[in] *nsec3_rr The RR to read from
++ * \return The salt in bytes, this is alloced, so you need to free it
++ */
++uint8_t *ldns_nsec3_salt_data(const ldns_rr *nsec3_rr);
++
++/**
++ * Returns the first label of the next ownername in the NSEC3 chain (ie. without the domain)
++ * \param[in] nsec3_rr The RR to read from
++ * \return The first label of the next owner name in the NSEC3 chain, or NULL on error 
++ */
++ldns_rdf *ldns_nsec3_next_owner(const ldns_rr *nsec3_rr);
++
++/**
++ * Returns the bitmap specifying the covered types of the given NSEC3 RR
++ * \param[in] *nsec3_rr The RR to read from
++ * \return The covered type bitmap rdf
++ */
++ldns_rdf *ldns_nsec3_bitmap(const ldns_rr *nsec3_rr);
++
++/**
++ * Calculates the hashed name using the parameters of the given NSEC3 RR
++ * \param[in] *nsec The RR to use the parameters from
++ * \param[in] *name The owner name to calculate the hash for 
++ * \return The hashed owner name rdf, without the domain name
++ */
++ldns_rdf *ldns_nsec3_hash_name_frm_nsec3(const ldns_rr *nsec, ldns_rdf *name);
++
++/**
++ * Check if RR type t is enumerated and set in the RR type bitmap rdf.
++ * \param[in] bitmap the RR type bitmap rdf to look in
++ * \param[in] type the type to check for
++ * \return true when t is found and set, otherwise return false
++ */
++bool ldns_nsec_bitmap_covers_type(const ldns_rdf* bitmap, ldns_rr_type type);
++
++/**
++ * Checks if RR type t is enumerated in the type bitmap rdf and sets the bit.
++ * \param[in] bitmap the RR type bitmap rdf to look in
++ * \param[in] type the type to for which the bit to set
++ * \return LDNS_STATUS_OK on success. LDNS_STATUS_TYPE_NOT_IN_BITMAP is 
++ *         returned when the bitmap does not contain the bit to set.
++ */
++ldns_status ldns_nsec_bitmap_set_type(ldns_rdf* bitmap, ldns_rr_type type);
++
++/**
++ * Checks if RR type t is enumerated in the type bitmap rdf and clears the bit.
++ * \param[in] bitmap the RR type bitmap rdf to look in
++ * \param[in] type the type to for which the bit to clear
++ * \return LDNS_STATUS_OK on success. LDNS_STATUS_TYPE_NOT_IN_BITMAP is 
++ *         returned when the bitmap does not contain the bit to clear.
++ */
++ldns_status ldns_nsec_bitmap_clear_type(ldns_rdf* bitmap, ldns_rr_type type);
++
++/**
++ * Checks coverage of NSEC(3) RR name span
++ * Remember that nsec and name must both be in canonical form (ie use
++ * \ref ldns_rr2canonical and \ref ldns_dname2canonical prior to calling this
++ * function)
++ *
++ * \param[in] nsec The NSEC RR to check
++ * \param[in] name The owner dname to check, if the nsec record is a NSEC3 record, this should be the hashed name
++ * \return true if the NSEC RR covers the owner name
++ */
++bool ldns_nsec_covers_name(const ldns_rr *nsec, const ldns_rdf *name);
++
++#if LDNS_BUILD_CONFIG_HAVE_SSL
++/**
++ * verify a packet 
++ * \param[in] p the packet
++ * \param[in] t the rr set type to check
++ * \param[in] o the rr set name to check
++ * \param[in] k list of keys
++ * \param[in] s list of sigs (may be null)
++ * \param[out] good_keys keys which validated the packet
++ * \return status 
++ * 
++ */
++ldns_status ldns_pkt_verify(ldns_pkt *p, ldns_rr_type t, ldns_rdf *o, ldns_rr_list *k, ldns_rr_list *s, ldns_rr_list *good_keys);
++
++/**
++ * verify a packet 
++ * \param[in] p the packet
++ * \param[in] t the rr set type to check
++ * \param[in] o the rr set name to check
++ * \param[in] k list of keys
++ * \param[in] s list of sigs (may be null)
++ * \param[in] check_time the time for which the validation is performed
++ * \param[out] good_keys keys which validated the packet
++ * \return status 
++ * 
++ */
++ldns_status ldns_pkt_verify_time(ldns_pkt *p, ldns_rr_type t, ldns_rdf *o, ldns_rr_list *k, ldns_rr_list *s, time_t check_time, ldns_rr_list *good_keys);
++
++#endif
++
++/**
++ * chains nsec3 list
++ */
++ldns_status
++ldns_dnssec_chain_nsec3_list(ldns_rr_list *nsec3_rrs);
++
++/**
++ * compare for nsec3 sort
++ */
++int
++qsort_rr_compare_nsec3(const void *a, const void *b);
++
++/**
++ * sort nsec3 list
++ */
++void
++ldns_rr_list_sort_nsec3(ldns_rr_list *unsorted);
++
++/** 
++ * Default callback function to always leave present signatures, and
++ * add new ones
++ * \param[in] sig The signature to check for removal (unused)
++ * \param[in] n Optional argument (unused)
++ * \return LDNS_SIGNATURE_LEAVE_ADD_NEW
++ */
++int ldns_dnssec_default_add_to_signatures(ldns_rr *sig, void *n);
++/** 
++ * Default callback function to always leave present signatures, and
++ * add no new ones for the keys of these signatures
++ * \param[in] sig The signature to check for removal (unused)
++ * \param[in] n Optional argument (unused)
++ * \return LDNS_SIGNATURE_LEAVE_NO_ADD
++ */
++int ldns_dnssec_default_leave_signatures(ldns_rr *sig, void *n);
++/** 
++ * Default callback function to always remove present signatures, but
++ * add no new ones
++ * \param[in] sig The signature to check for removal (unused)
++ * \param[in] n Optional argument (unused)
++ * \return LDNS_SIGNATURE_REMOVE_NO_ADD
++ */
++int ldns_dnssec_default_delete_signatures(ldns_rr *sig, void *n);
++/** 
++ * Default callback function to always leave present signatures, and
++ * add new ones
++ * \param[in] sig The signature to check for removal (unused)
++ * \param[in] n Optional argument (unused)
++ * \return LDNS_SIGNATURE_REMOVE_ADD_NEW
++ */
++int ldns_dnssec_default_replace_signatures(ldns_rr *sig, void *n);
++
++#if LDNS_BUILD_CONFIG_HAVE_SSL
++/**
++ * Converts the DSA signature from ASN1 representation (RFC2459, as 
++ * used by OpenSSL) to raw signature data as used in DNS (rfc2536)
++ *
++ * \param[in] sig The signature in RFC2459 format
++ * \param[in] sig_len The length of the signature
++ * \return a new rdf with the signature
++ */
++ldns_rdf *
++ldns_convert_dsa_rrsig_asn12rdf(const ldns_buffer *sig,
++						  const long sig_len);
++
++/**
++ * Converts the RRSIG signature RDF (in rfc2536 format) to a buffer
++ * with the signature in rfc2459 format
++ *
++ * \param[out] target_buffer buffer to place the signature data
++ * \param[in] sig_rdf The signature rdf to convert
++ * \return LDNS_STATUS_OK on success, error code otherwise
++ */
++ldns_status
++ldns_convert_dsa_rrsig_rdf2asn1(ldns_buffer *target_buffer,
++						  const ldns_rdf *sig_rdf);
++
++/**
++ * Converts the ECDSA signature from ASN1 representation (as 
++ * used by OpenSSL) to raw signature data as used in DNS
++ * This routine is only present if ldns is compiled with ecdsa support.
++ *
++ * \param[in] sig The signature in ASN1 format
++ * \param[in] sig_len The length of the signature
++ * \return a new rdf with the signature
++ */
++ldns_rdf *
++ldns_convert_ecdsa_rrsig_asn12rdf(const ldns_buffer *sig, const long sig_len);
++
++/**
++ * Converts the RRSIG signature RDF (from DNS) to a buffer with the 
++ * signature in ASN1 format as openssl uses it.
++ * This routine is only present if ldns is compiled with ecdsa support.
++ *
++ * \param[out] target_buffer buffer to place the signature data in ASN1.
++ * \param[in] sig_rdf The signature rdf to convert
++ * \return LDNS_STATUS_OK on success, error code otherwise
++ */
++ldns_status
++ldns_convert_ecdsa_rrsig_rdf2asn1(ldns_buffer *target_buffer,
++        const ldns_rdf *sig_rdf);
++
++#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* LDNS_DNSSEC_H */
+diff --git a/ldns/include/ldns/dnssec_sign.h b/ldns/include/ldns/dnssec_sign.h
+new file mode 100644
+index 0000000..f51c7fb
+--- /dev/null
++++ b/ldns/include/ldns/dnssec_sign.h
+@@ -0,0 +1,383 @@
++/** dnssec_verify */
++
++#ifndef LDNS_DNSSEC_SIGN_H
++#define LDNS_DNSSEC_SIGN_H
++
++#include <ldns/dnssec.h>
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/* sign functions */
++
++/** Sign flag that makes DNSKEY type signed by all keys, not only by SEP keys*/
++#define LDNS_SIGN_DNSKEY_WITH_ZSK 1
++
++/**
++ * Create an empty RRSIG RR (i.e. without the actual signature data)
++ * \param[in] rrset The RRset to create the signature for
++ * \param[in] key The key that will create the signature
++ * \return signature rr
++ */
++ldns_rr *
++ldns_create_empty_rrsig(ldns_rr_list *rrset,
++                        ldns_key *key);
++
++/**
++ * Sign the buffer which contains the wiredata of an rrset, and the
++ * corresponding empty rrsig rr with the given key
++ * \param[in] sign_buf the buffer with data to sign
++ * \param[in] key the key to sign with
++ * \return an rdata field with the signature data
++ */
++ldns_rdf *
++ldns_sign_public_buffer(ldns_buffer *sign_buf, ldns_key *key);
++
++/**
++ * Sign an rrset
++ * \param[in] rrset the rrset
++ * \param[in] keys the keys to use
++ * \return a rr_list with the signatures
++ */
++ldns_rr_list *ldns_sign_public(ldns_rr_list *rrset, ldns_key_list *keys);
++
++#if LDNS_BUILD_CONFIG_HAVE_SSL
++/**
++ * Sign a buffer with the DSA key (hash with SHA1)
++ * \param[in] to_sign buffer with the data
++ * \param[in] key the key to use
++ * \return a ldns_rdf with the signed data
++ */
++ldns_rdf *ldns_sign_public_dsa(ldns_buffer *to_sign, DSA *key);
++
++/**
++ * Sign data with EVP (general method for different algorithms)
++ *
++ * \param[in] to_sign The ldns_buffer containing raw data that is
++ *                    to be signed
++ * \param[in] key The EVP_PKEY key structure to sign with
++ * \param[in] digest_type The digest algorithm to use in the creation of
++ *                        the signature
++ * \return ldns_rdf for the RRSIG ldns_rr
++ */
++ldns_rdf *ldns_sign_public_evp(ldns_buffer *to_sign,
++						 EVP_PKEY *key,
++						 const EVP_MD *digest_type);
++
++/**
++ * Sign a buffer with the RSA key (hash with SHA1)
++ * \param[in] to_sign buffer with the data
++ * \param[in] key the key to use
++ * \return a ldns_rdf with the signed data
++ */
++ldns_rdf *ldns_sign_public_rsasha1(ldns_buffer *to_sign, RSA *key);
++
++/**
++ * Sign a buffer with the RSA key (hash with MD5)
++ * \param[in] to_sign buffer with the data
++ * \param[in] key the key to use
++ * \return a ldns_rdf with the signed data
++ */
++ldns_rdf *ldns_sign_public_rsamd5(ldns_buffer *to_sign, RSA *key);
++#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */
++
++/**
++ * Marks the names in the zone that are occluded. Those names will be skipped
++ * when walking the tree with the ldns_dnssec_name_node_next_nonglue()
++ * function. But watch out! Names that are partially occluded (like glue with
++ * the same name as the delegation) will not be marked and should specifically 
++ * be taken into account separately.
++ *
++ * When glue_list is given (not NULL), in the process of marking the names, all
++ * glue resource records will be pushed to that list, even glue at the delegation name.
++ *
++ * \param[in] zone the zone in which to mark the names
++ * \param[in] glue_list the list to which to push the glue rrs
++ * \return LDNS_STATUS_OK on success, an error code otherwise
++ */
++ldns_status
++ldns_dnssec_zone_mark_and_get_glue(
++		ldns_dnssec_zone *zone, ldns_rr_list *glue_list);
++
++/**
++ * Marks the names in the zone that are occluded. Those names will be skipped
++ * when walking the tree with the ldns_dnssec_name_node_next_nonglue()
++ * function. But watch out! Names that are partially occluded (like glue with
++ * the same name as the delegation) will not be marked and should specifically 
++ * be taken into account separately.
++ *
++ * \param[in] zone the zone in which to mark the names
++ * \return LDNS_STATUS_OK on succesful completion
++ */
++ldns_status
++ldns_dnssec_zone_mark_glue(ldns_dnssec_zone *zone);
++
++/**
++ * Finds the first dnssec_name node in the rbtree that is not occluded.
++ * It *does* return names that are partially occluded.
++ *
++ * \param[in] node the first node to check
++ * \return the first node that has not been marked as glue, or NULL
++ * if not found (TODO: make that LDNS_RBTREE_NULL?)
++ */
++ldns_rbnode_t *ldns_dnssec_name_node_next_nonglue(ldns_rbnode_t *node);
++
++/**
++ * Adds NSEC records to the given dnssec_zone
++ *
++ * \param[in] zone the zone to add the records to
++ * \param[in] new_rrs ldns_rr's created by this function are
++ *            added to this rr list, so the caller can free them later
++ * \return LDNS_STATUS_OK on success, an error code otherwise
++ */
++ldns_status ldns_dnssec_zone_create_nsecs(ldns_dnssec_zone *zone,
++								  ldns_rr_list *new_rrs);
++
++/**
++ * Adds NSEC3 records to the zone
++ */
++ldns_status
++ldns_dnssec_zone_create_nsec3s(ldns_dnssec_zone *zone,
++						 ldns_rr_list *new_rrs,
++						 uint8_t algorithm,
++						 uint8_t flags,
++						 uint16_t iterations,
++						 uint8_t salt_length,
++						 uint8_t *salt);
++
++/**
++ * remove signatures if callback function tells to
++ * 
++ * \param[in] signatures list of signatures to check, and
++ *            possibly remove, depending on the value of the
++ *            callback
++ * \param[in] key_list these are marked to be used or not,
++ *            on the return value of the callback
++ * \param[in] func this function is called to specify what to
++ *            do with each signature (and corresponding key)
++ * \param[in] arg Optional argument for the callback function
++ * \returns pointer to the new signatures rrs (the original
++ *          passed to this function may have been removed)
++ */
++ldns_dnssec_rrs *ldns_dnssec_remove_signatures(ldns_dnssec_rrs *signatures,
++									  ldns_key_list *key_list,
++									  int (*func)(ldns_rr *, void *),
++									  void *arg);
++
++/**
++ * Adds signatures to the zone
++ *
++ * \param[in] zone the zone to add RRSIG Resource Records to
++ * \param[in] new_rrs the RRSIG RRs that are created are also
++ *            added to this list, so the caller can free them
++ *            later
++ * \param[in] key_list list of keys to sign with.
++ * \param[in] func Callback function to decide what keys to
++ *            use and what to do with old signatures
++ * \param[in] arg Optional argument for the callback function
++ * \param[in] flags option flags for signing process. 0 makes DNSKEY
++ * RRset signed with the minimal key set, that is only SEP keys are used
++ * for signing. If there are no SEP keys available, non-SEP keys will
++ * be used. LDNS_SIGN_DNSKEY_WITH_ZSK makes DNSKEY type signed with all
++ * keys. 0 is the default.
++ * \return LDNS_STATUS_OK on success, error otherwise
++ */
++ldns_status ldns_dnssec_zone_create_rrsigs_flg(ldns_dnssec_zone *zone,
++					ldns_rr_list *new_rrs,
++					ldns_key_list *key_list,
++					int (*func)(ldns_rr *, void*),
++					void *arg,
++					int flags);
++
++/**
++ * Adds signatures to the zone
++ *
++ * \param[in] zone the zone to add RRSIG Resource Records to
++ * \param[in] new_rrs the RRSIG RRs that are created are also
++ *            added to this list, so the caller can free them
++ *            later
++ * \param[in] key_list list of keys to sign with.
++ * \param[in] func Callback function to decide what keys to
++ *            use and what to do with old signatures
++ * \param[in] arg Optional argument for the callback function
++ * \return LDNS_STATUS_OK on success, error otherwise
++ */
++ldns_status ldns_dnssec_zone_create_rrsigs(ldns_dnssec_zone *zone,
++								   ldns_rr_list *new_rrs,
++								   ldns_key_list *key_list,
++								   int (*func)(ldns_rr *, void*),
++								   void *arg);
++
++/**
++ * signs the given zone with the given keys
++ * 
++ * \param[in] zone the zone to sign
++ * \param[in] key_list the list of keys to sign the zone with
++ * \param[in] new_rrs newly created resource records are added to this list, to free them later
++ * \param[in] func callback function that decides what to do with old signatures
++ *            This function takes an ldns_rr* and an optional void *arg argument, and returns one of four values:
++ * LDNS_SIGNATURE_LEAVE_ADD_NEW:
++ * leave the signature and add a new one for the corresponding key
++ * LDNS_SIGNATURE_REMOVE_ADD_NEW:
++ * remove the signature and replace is with a new one from the same key
++ * LDNS_SIGNATURE_LEAVE_NO_ADD:
++ * leave the signature and do not add a new one with the corresponding key
++ * LDNS_SIGNATURE_REMOVE_NO_ADD:
++ * remove the signature and do not replace 
++ *
++ * \param[in] arg optional argument for the callback function
++ * \param[in] flags option flags for signing process. 0 makes DNSKEY
++ * RRset signed with the minimal key set, that is only SEP keys are used
++ * for signing. If there are no SEP keys available, non-SEP keys will
++ * be used. LDNS_SIGN_DNSKEY_WITH_ZSK makes DNSKEY type signed with all
++ * keys. 0 is the default.
++ * \return LDNS_STATUS_OK on success, an error code otherwise
++ */
++ldns_status ldns_dnssec_zone_sign_flg(ldns_dnssec_zone *zone,
++					ldns_rr_list *new_rrs,
++					ldns_key_list *key_list,
++					int (*func)(ldns_rr *, void *),
++					void *arg, 
++					int flags);
++
++/**
++ * signs the given zone with the given new zone, with NSEC3
++ *
++ * \param[in] zone the zone to sign
++ * \param[in] key_list the list of keys to sign the zone with
++ * \param[in] new_rrs newly created resource records are added to this list, to free them later
++ * \param[in] func callback function that decides what to do with old signatures
++ * \param[in] arg optional argument for the callback function
++ * \param[in] algorithm the NSEC3 hashing algorithm to use
++ * \param[in] flags NSEC3 flags
++ * \param[in] iterations the number of NSEC3 hash iterations to use
++ * \param[in] salt_length the length (in octets) of the NSEC3 salt
++ * \param[in] salt the NSEC3 salt data
++ * \param[in] signflags option flags for signing process. 0 is the default.
++ * \return LDNS_STATUS_OK on success, an error code otherwise
++ */
++ldns_status ldns_dnssec_zone_sign_nsec3_flg(ldns_dnssec_zone *zone,
++				ldns_rr_list *new_rrs,
++				ldns_key_list *key_list,
++				int (*func)(ldns_rr *, void *),
++				void *arg,
++				uint8_t algorithm,
++				uint8_t flags,
++				uint16_t iterations,
++				uint8_t salt_length,
++				uint8_t *salt,
++				int signflags);
++
++/**
++ * signs the given zone with the given new zone, with NSEC3
++ *
++ * \param[in] zone the zone to sign
++ * \param[in] key_list the list of keys to sign the zone with
++ * \param[in] new_rrs newly created resource records are added to this list, to free them later
++ * \param[in] func callback function that decides what to do with old signatures
++ * \param[in] arg optional argument for the callback function
++ * \param[in] algorithm the NSEC3 hashing algorithm to use
++ * \param[in] flags NSEC3 flags
++ * \param[in] iterations the number of NSEC3 hash iterations to use
++ * \param[in] salt_length the length (in octets) of the NSEC3 salt
++ * \param[in] salt the NSEC3 salt data
++ * \param[in] signflags option flags for signing process. 0 is the default.
++ * \param[out] map a referenced rbtree pointer variable. The newly created 
++ *                 rbtree will contain mappings from hashed owner names to the 
++ *                 unhashed name.
++ * \return LDNS_STATUS_OK on success, an error code otherwise
++ */
++ldns_status ldns_dnssec_zone_sign_nsec3_flg_mkmap(ldns_dnssec_zone *zone,
++				ldns_rr_list *new_rrs,
++				ldns_key_list *key_list,
++				int (*func)(ldns_rr *, void *),
++				void *arg,
++				uint8_t algorithm,
++				uint8_t flags,
++				uint16_t iterations,
++				uint8_t salt_length,
++				uint8_t *salt,
++				int signflags,
++				ldns_rbtree_t **map
++				);
++
++
++/**
++ * signs the given zone with the given keys
++ * 
++ * \param[in] zone the zone to sign
++ * \param[in] key_list the list of keys to sign the zone with
++ * \param[in] new_rrs newly created resource records are added to this list, to free them later
++ * \param[in] func callback function that decides what to do with old signatures
++ *            This function takes an ldns_rr* and an optional void *arg argument, and returns one of four values:
++ * LDNS_SIGNATURE_LEAVE_ADD_NEW:
++ * leave the signature and add a new one for the corresponding key
++ * LDNS_SIGNATURE_REMOVE_ADD_NEW:
++ * remove the signature and replace is with a new one from the same key
++ * LDNS_SIGNATURE_LEAVE_NO_ADD:
++ * leave the signature and do not add a new one with the corresponding key
++ * LDNS_SIGNATURE_REMOVE_NO_ADD:
++ * remove the signature and do not replace 
++ *
++ * \param[in] arg optional argument for the callback function
++ * \return LDNS_STATUS_OK on success, an error code otherwise
++ */
++ldns_status ldns_dnssec_zone_sign(ldns_dnssec_zone *zone,
++						    ldns_rr_list *new_rrs,
++						    ldns_key_list *key_list,
++						    int (*func)(ldns_rr *, void *),
++						    void *arg);
++
++/**
++ * signs the given zone with the given new zone, with NSEC3
++ *
++ * \param[in] zone the zone to sign
++ * \param[in] key_list the list of keys to sign the zone with
++ * \param[in] new_rrs newly created resource records are added to this list, to free them later
++ * \param[in] func callback function that decides what to do with old signatures
++ * \param[in] arg optional argument for the callback function
++ * \param[in] algorithm the NSEC3 hashing algorithm to use
++ * \param[in] flags NSEC3 flags
++ * \param[in] iterations the number of NSEC3 hash iterations to use
++ * \param[in] salt_length the length (in octets) of the NSEC3 salt
++ * \param[in] salt the NSEC3 salt data
++ * \return LDNS_STATUS_OK on success, an error code otherwise
++ */
++ldns_status ldns_dnssec_zone_sign_nsec3(ldns_dnssec_zone *zone,
++								ldns_rr_list *new_rrs,
++								ldns_key_list *key_list,
++								int (*func)(ldns_rr *, void *),
++								void *arg,
++								uint8_t algorithm,
++								uint8_t flags,
++								uint16_t iterations,
++								uint8_t salt_length,
++								uint8_t *salt);
++
++/**
++ * Signs the zone, and returns a newly allocated signed zone
++ * \param[in] zone the zone to sign
++ * \param[in] key_list list of keys to sign with
++ * \return signed zone
++ */
++ldns_zone *ldns_zone_sign(const ldns_zone *zone, ldns_key_list *key_list);
++
++/**
++ * Signs the zone with NSEC3, and returns a newly allocated signed zone
++ * \param[in] zone the zone to sign
++ * \param[in] key_list list of keys to sign with
++ * \param[in] algorithm the NSEC3 hashing algorithm to use
++ * \param[in] flags NSEC3 flags
++ * \param[in] iterations the number of NSEC3 hash iterations to use
++ * \param[in] salt_length the length (in octets) of the NSEC3 salt
++ * \param[in] salt the NSEC3 salt data
++ * \return signed zone
++ */
++ldns_zone *ldns_zone_sign_nsec3(ldns_zone *zone, ldns_key_list *key_list, uint8_t algorithm, uint8_t flags, uint16_t iterations, uint8_t salt_length, uint8_t *salt);
++ 
++#ifdef __cplusplus
++}
++#endif
++
++#endif
+diff --git a/ldns/include/ldns/dnssec_verify.h b/ldns/include/ldns/dnssec_verify.h
+new file mode 100644
+index 0000000..e8b1a91
+--- /dev/null
++++ b/ldns/include/ldns/dnssec_verify.h
+@@ -0,0 +1,857 @@
++/** dnssec_verify */
++
++#ifndef LDNS_DNSSEC_VERIFY_H
++#define LDNS_DNSSEC_VERIFY_H
++
++#define LDNS_DNSSEC_TRUST_TREE_MAX_PARENTS 10
++
++#include <ldns/dnssec.h>
++#include <ldns/host2str.h>
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/**
++ * Chain structure that contains all DNSSEC data needed to
++ * verify an rrset
++ */
++typedef struct ldns_dnssec_data_chain_struct ldns_dnssec_data_chain;
++struct ldns_dnssec_data_chain_struct
++{
++	ldns_rr_list *rrset;
++	ldns_rr_list *signatures;
++	ldns_rr_type parent_type;
++	ldns_dnssec_data_chain *parent;
++	ldns_pkt_rcode packet_rcode;
++	ldns_rr_type packet_qtype;
++	bool packet_nodata;
++};
++
++/**
++ * Creates a new dnssec_chain structure
++ * \return ldns_dnssec_data_chain *
++ */
++ldns_dnssec_data_chain *ldns_dnssec_data_chain_new(void);
++
++/**
++ * Frees a dnssec_data_chain structure
++ *
++ * \param[in] *chain The chain to free
++ */
++void ldns_dnssec_data_chain_free(ldns_dnssec_data_chain *chain);
++
++/**
++ * Frees a dnssec_data_chain structure, and all data
++ * contained therein
++ *
++ * \param[in] *chain The dnssec_data_chain to free
++ */
++void ldns_dnssec_data_chain_deep_free(ldns_dnssec_data_chain *chain);
++
++/**
++ * Prints the dnssec_data_chain to the given file stream
++ * 
++ * \param[in] *out The file stream to print to
++ * \param[in] *chain The dnssec_data_chain to print
++ */
++void ldns_dnssec_data_chain_print(FILE *out, const ldns_dnssec_data_chain *chain);
++
++/**
++ * Prints the dnssec_data_chain to the given file stream
++ * 
++ * \param[in] *out The file stream to print to
++ * \param[in] *fmt The format of the textual representation
++ * \param[in] *chain The dnssec_data_chain to print
++ */
++void ldns_dnssec_data_chain_print_fmt(FILE *out, 
++		const ldns_output_format *fmt,
++		const ldns_dnssec_data_chain *chain);
++
++/**
++ * Build an ldns_dnssec_data_chain, which contains all
++ * DNSSEC data that is needed to derive the trust tree later
++ *
++ * The data_set will be cloned
++ *
++ * \param[in] *res resolver structure for further needed queries
++ * \param[in] qflags resolution flags
++ * \param[in] *data_set The original rrset where the chain ends
++ * \param[in] *pkt optional, can contain the original packet
++ * (and hence the sigs and maybe the key)
++ * \param[in] *orig_rr The original Resource Record
++ *
++ * \return the DNSSEC data chain
++ */
++ldns_dnssec_data_chain *ldns_dnssec_build_data_chain(ldns_resolver *res,
++										   const uint16_t qflags,
++										   const ldns_rr_list *data_set,
++										   const ldns_pkt *pkt,
++										   ldns_rr *orig_rr);
++
++/**
++ * Tree structure that contains the relation of DNSSEC data,
++ * and their cryptographic status.
++ *
++ * This tree is derived from a data_chain, and can be used
++ * to look whether there is a connection between an RRSET
++ * and a trusted key. The tree only contains pointers to the
++ * data_chain, and therefore one should *never* free() the
++ * data_chain when there is still a trust tree derived from
++ * that chain.
++ *
++ * Example tree:
++ *     key   key    key
++ *       \    |    /
++ *        \   |   /
++ *         \  |  /
++ *            ds
++ *            |
++ *           key
++ *            |
++ *           key
++ *            |
++ *            rr
++ *
++ * For each signature there is a parent; if the parent
++ * pointer is null, it couldn't be found and there was no
++ * denial; otherwise is a tree which contains either a
++ * DNSKEY, a DS, or a NSEC rr
++ */
++typedef struct ldns_dnssec_trust_tree_struct ldns_dnssec_trust_tree;
++struct ldns_dnssec_trust_tree_struct
++{
++	ldns_rr *rr;
++	/* the complete rrset this rr was in */
++	ldns_rr_list *rrset;
++	ldns_dnssec_trust_tree *parents[LDNS_DNSSEC_TRUST_TREE_MAX_PARENTS];
++	ldns_status parent_status[LDNS_DNSSEC_TRUST_TREE_MAX_PARENTS];
++	/** for debugging, add signatures too (you might want
++	    those if they contain errors) */
++	ldns_rr *parent_signature[LDNS_DNSSEC_TRUST_TREE_MAX_PARENTS];
++	size_t parent_count;
++};
++
++/**
++ * Creates a new (empty) dnssec_trust_tree structure
++ *
++ * \return ldns_dnssec_trust_tree *
++ */
++ldns_dnssec_trust_tree *ldns_dnssec_trust_tree_new(void);
++
++/**
++ * Frees the dnssec_trust_tree recursively
++ *
++ * There is no deep free; all data in the trust tree
++ * consists of pointers to a data_chain
++ *
++ * \param[in] tree The tree to free
++ */
++void ldns_dnssec_trust_tree_free(ldns_dnssec_trust_tree *tree);
++
++/**
++ * returns the depth of the trust tree
++ *
++ * \param[in] tree tree to calculate the depth of
++ * \return The depth of the tree
++ */
++size_t ldns_dnssec_trust_tree_depth(ldns_dnssec_trust_tree *tree);
++
++/**
++ * Prints the dnssec_trust_tree structure to the given file
++ * stream.
++ *
++ * If a link status is not LDNS_STATUS_OK; the status and
++ * relevant signatures are printed too
++ *
++ * \param[in] *out The file stream to print to
++ * \param[in] tree The trust tree to print
++ * \param[in] tabs Prepend each line with tabs*2 spaces
++ * \param[in] extended If true, add little explanation lines to the output
++ */
++void ldns_dnssec_trust_tree_print(FILE *out,
++	       	ldns_dnssec_trust_tree *tree,
++		size_t tabs,
++		bool extended);
++
++/**
++ * Prints the dnssec_trust_tree structure to the given file
++ * stream.
++ *
++ * If a link status is not LDNS_STATUS_OK; the status and
++ * relevant signatures are printed too
++ *
++ * \param[in] *out The file stream to print to
++ * \param[in] *fmt The format of the textual representation
++ * \param[in] tree The trust tree to print
++ * \param[in] tabs Prepend each line with tabs*2 spaces
++ * \param[in] extended If true, add little explanation lines to the output
++ */
++void ldns_dnssec_trust_tree_print_fmt(FILE *out,
++		const ldns_output_format *fmt,
++	       	ldns_dnssec_trust_tree *tree,
++		size_t tabs,
++		bool extended);
++
++/**
++ * Adds a trust tree as a parent for the given trust tree
++ *
++ * \param[in] *tree The tree to add the parent to
++ * \param[in] *parent The parent tree to add
++ * \param[in] *parent_signature The RRSIG relevant to this parent/child
++ *                              connection
++ * \param[in] parent_status The DNSSEC status for this parent, child and RRSIG
++ * \return LDNS_STATUS_OK if the addition succeeds, error otherwise
++ */
++ldns_status ldns_dnssec_trust_tree_add_parent(ldns_dnssec_trust_tree *tree,
++									 const ldns_dnssec_trust_tree *parent,
++									 const ldns_rr *parent_signature,
++									 const ldns_status parent_status);
++
++/**
++ * Generates a dnssec_trust_tree for the given rr from the
++ * given data_chain
++ *
++ * This does not clone the actual data; Don't free the
++ * data_chain before you are done with this tree
++ *
++ * \param[in] *data_chain The chain to derive the trust tree from
++ * \param[in] *rr The RR this tree will be about
++ * \return ldns_dnssec_trust_tree *
++ */
++ldns_dnssec_trust_tree *ldns_dnssec_derive_trust_tree(
++                            ldns_dnssec_data_chain *data_chain,
++					   ldns_rr *rr);
++
++/**
++ * Generates a dnssec_trust_tree for the given rr from the
++ * given data_chain
++ *
++ * This does not clone the actual data; Don't free the
++ * data_chain before you are done with this tree
++ *
++ * \param[in] *data_chain The chain to derive the trust tree from
++ * \param[in] *rr The RR this tree will be about
++ * \param[in] check_time the time for which the validation is performed
++ * \return ldns_dnssec_trust_tree *
++ */
++ldns_dnssec_trust_tree *ldns_dnssec_derive_trust_tree_time(
++		ldns_dnssec_data_chain *data_chain, 
++		ldns_rr *rr, time_t check_time);
++
++/**
++ * Sub function for derive_trust_tree that is used for a 'normal' rrset
++ *
++ * \param[in] new_tree The trust tree that we are building
++ * \param[in] data_chain The data chain containing the data for the trust tree
++ * \param[in] cur_sig_rr The currently relevant signature
++ */
++void ldns_dnssec_derive_trust_tree_normal_rrset(
++         ldns_dnssec_trust_tree *new_tree,
++	    ldns_dnssec_data_chain *data_chain,
++	    ldns_rr *cur_sig_rr);
++
++/**
++ * Sub function for derive_trust_tree that is used for a 'normal' rrset
++ *
++ * \param[in] new_tree The trust tree that we are building
++ * \param[in] data_chain The data chain containing the data for the trust tree
++ * \param[in] cur_sig_rr The currently relevant signature
++ * \param[in] check_time the time for which the validation is performed
++ */
++void ldns_dnssec_derive_trust_tree_normal_rrset_time(
++         ldns_dnssec_trust_tree *new_tree,
++	    ldns_dnssec_data_chain *data_chain,
++	    ldns_rr *cur_sig_rr, time_t check_time);
++
++
++/**
++ * Sub function for derive_trust_tree that is used for DNSKEY rrsets
++ *
++ * \param[in] new_tree The trust tree that we are building
++ * \param[in] data_chain The data chain containing the data for the trust tree
++ * \param[in] cur_rr The currently relevant DNSKEY RR
++ * \param[in] cur_sig_rr The currently relevant signature
++ */
++void ldns_dnssec_derive_trust_tree_dnskey_rrset(
++         ldns_dnssec_trust_tree *new_tree,
++	    ldns_dnssec_data_chain *data_chain,
++	    ldns_rr *cur_rr,
++	    ldns_rr *cur_sig_rr);
++
++/**
++ * Sub function for derive_trust_tree that is used for DNSKEY rrsets
++ *
++ * \param[in] new_tree The trust tree that we are building
++ * \param[in] data_chain The data chain containing the data for the trust tree
++ * \param[in] cur_rr The currently relevant DNSKEY RR
++ * \param[in] cur_sig_rr The currently relevant signature
++ * \param[in] check_time the time for which the validation is performed
++ */
++void ldns_dnssec_derive_trust_tree_dnskey_rrset_time(
++         ldns_dnssec_trust_tree *new_tree,
++	    ldns_dnssec_data_chain *data_chain,
++	    ldns_rr *cur_rr, ldns_rr *cur_sig_rr,
++	    time_t check_time);
++
++/**
++ * Sub function for derive_trust_tree that is used for DS rrsets
++ *
++ * \param[in] new_tree The trust tree that we are building
++ * \param[in] data_chain The data chain containing the data for the trust tree
++ * \param[in] cur_rr The currently relevant DS RR
++ */
++void ldns_dnssec_derive_trust_tree_ds_rrset(
++         ldns_dnssec_trust_tree *new_tree,
++	    ldns_dnssec_data_chain *data_chain,
++	    ldns_rr *cur_rr);
++
++/**
++ * Sub function for derive_trust_tree that is used for DS rrsets
++ *
++ * \param[in] new_tree The trust tree that we are building
++ * \param[in] data_chain The data chain containing the data for the trust tree
++ * \param[in] cur_rr The currently relevant DS RR
++ * \param[in] check_time the time for which the validation is performed
++ */
++void ldns_dnssec_derive_trust_tree_ds_rrset_time(
++         ldns_dnssec_trust_tree *new_tree,
++	    ldns_dnssec_data_chain *data_chain,
++	    ldns_rr *cur_rr, time_t check_time);
++
++/**
++ * Sub function for derive_trust_tree that is used when there are no
++ * signatures
++ *
++ * \param[in] new_tree The trust tree that we are building
++ * \param[in] data_chain The data chain containing the data for the trust tree
++ */
++void ldns_dnssec_derive_trust_tree_no_sig(
++         ldns_dnssec_trust_tree *new_tree,
++	    ldns_dnssec_data_chain *data_chain);
++
++/**
++ * Sub function for derive_trust_tree that is used when there are no
++ * signatures
++ *
++ * \param[in] new_tree The trust tree that we are building
++ * \param[in] data_chain The data chain containing the data for the trust tree
++ * \param[in] check_time the time for which the validation is performed
++ */
++void ldns_dnssec_derive_trust_tree_no_sig_time(
++         ldns_dnssec_trust_tree *new_tree,
++	    ldns_dnssec_data_chain *data_chain,
++	    time_t check_time);
++
++
++/**
++ * Returns OK if there is a trusted path in the tree to one of 
++ * the DNSKEY or DS RRs in the given list
++ *
++ * \param *tree The trust tree so search
++ * \param *keys A ldns_rr_list of DNSKEY and DS rrs to look for
++ *
++ * \return LDNS_STATUS_OK if there is a trusted path to one of
++ *                        the keys, or the *first* error encountered
++ *                        if there were no paths
++ */
++ldns_status ldns_dnssec_trust_tree_contains_keys(
++			 ldns_dnssec_trust_tree *tree,
++			 ldns_rr_list *keys);
++
++/**
++ * Verifies a list of signatures for one rrset.
++ *
++ * \param[in] rrset the rrset to verify
++ * \param[in] rrsig a list of signatures to check
++ * \param[in] keys a list of keys to check with
++ * \param[out] good_keys  if this is a (initialized) list, the pointer to keys
++ *                        from keys that validate one of the signatures
++ *                        are added to it
++ * \return status LDNS_STATUS_OK if there is at least one correct key
++ */
++ldns_status ldns_verify(ldns_rr_list *rrset,
++				    ldns_rr_list *rrsig,
++				    const ldns_rr_list *keys,
++				    ldns_rr_list *good_keys);	
++
++/**
++ * Verifies a list of signatures for one rrset.
++ *
++ * \param[in] rrset the rrset to verify
++ * \param[in] rrsig a list of signatures to check
++ * \param[in] keys a list of keys to check with
++ * \param[in] check_time the time for which the validation is performed
++ * \param[out] good_keys  if this is a (initialized) list, the pointer to keys
++ *                        from keys that validate one of the signatures
++ *                        are added to it
++ * \return status LDNS_STATUS_OK if there is at least one correct key
++ */
++ldns_status ldns_verify_time(ldns_rr_list *rrset,
++				    ldns_rr_list *rrsig,
++				    const ldns_rr_list *keys,
++				    time_t check_time,
++				    ldns_rr_list *good_keys);	
++
++
++/**
++ * Verifies a list of signatures for one rrset, but disregard the time.
++ * Inception and Expiration are not checked.
++ *
++ * \param[in] rrset the rrset to verify
++ * \param[in] rrsig a list of signatures to check
++ * \param[in] keys a list of keys to check with
++ * \param[out] good_keys  if this is a (initialized) list, the pointer to keys
++ *                        from keys that validate one of the signatures
++ *                        are added to it
++ * \return status LDNS_STATUS_OK if there is at least one correct key
++ */
++ldns_status ldns_verify_notime(ldns_rr_list *rrset,
++				    ldns_rr_list *rrsig,
++				    const ldns_rr_list *keys,
++				    ldns_rr_list *good_keys);	
++
++/**
++ * Tries to build an authentication chain from the given 
++ * keys down to the queried domain.
++ *
++ * If we find a valid trust path, return the valid keys for the domain.
++ * 
++ * \param[in] res the current resolver
++ * \param[in] domain the domain we want valid keys for
++ * \param[in] keys the current set of trusted keys
++ * \param[out] status pointer to the status variable where the result
++ *                    code will be stored
++ * \return the set of trusted keys for the domain, or NULL if no 
++ *         trust path could be built.
++ */
++ldns_rr_list *ldns_fetch_valid_domain_keys(const ldns_resolver * res,
++								   const ldns_rdf * domain,
++								   const ldns_rr_list * keys,
++								   ldns_status *status);
++
++/**
++ * Tries to build an authentication chain from the given 
++ * keys down to the queried domain.
++ *
++ * If we find a valid trust path, return the valid keys for the domain.
++ * 
++ * \param[in] res the current resolver
++ * \param[in] domain the domain we want valid keys for
++ * \param[in] keys the current set of trusted keys
++ * \param[in] check_time the time for which the validation is performed
++ * \param[out] status pointer to the status variable where the result
++ *                    code will be stored
++ * \return the set of trusted keys for the domain, or NULL if no 
++ *         trust path could be built.
++ */
++ldns_rr_list *ldns_fetch_valid_domain_keys_time(const ldns_resolver * res,
++		const ldns_rdf * domain, const ldns_rr_list * keys,
++		time_t check_time, ldns_status *status);
++
++
++/**
++ * Validates the DNSKEY RRset for the given domain using the provided 
++ * trusted keys.
++ *
++ * \param[in] res the current resolver
++ * \param[in] domain the domain we want valid keys for
++ * \param[in] keys the current set of trusted keys
++ * \return the set of trusted keys for the domain, or NULL if the RRSET
++ *         could not be validated
++ */
++ldns_rr_list *ldns_validate_domain_dnskey (const ldns_resolver *res,
++								   const ldns_rdf *domain,
++								   const ldns_rr_list *keys);
++
++/**
++ * Validates the DNSKEY RRset for the given domain using the provided 
++ * trusted keys.
++ *
++ * \param[in] res the current resolver
++ * \param[in] domain the domain we want valid keys for
++ * \param[in] keys the current set of trusted keys
++ * \param[in] check_time the time for which the validation is performed
++ * \return the set of trusted keys for the domain, or NULL if the RRSET
++ *         could not be validated
++ */
++ldns_rr_list *ldns_validate_domain_dnskey_time(
++		const ldns_resolver *res, const ldns_rdf *domain, 
++		const ldns_rr_list *keys, time_t check_time);
++
++
++/**
++ * Validates the DS RRset for the given domain using the provided trusted keys.
++ *
++ * \param[in] res the current resolver
++ * \param[in] domain the domain we want valid keys for
++ * \param[in] keys the current set of trusted keys
++ * \return the set of trusted keys for the domain, or NULL if the RRSET could not be validated
++ */
++ldns_rr_list *ldns_validate_domain_ds(const ldns_resolver *res,
++							   const ldns_rdf *
++							   domain,
++							   const ldns_rr_list * keys);
++
++/**
++ * Validates the DS RRset for the given domain using the provided trusted keys.
++ *
++ * \param[in] res the current resolver
++ * \param[in] domain the domain we want valid keys for
++ * \param[in] keys the current set of trusted keys
++ * \param[in] check_time the time for which the validation is performed
++ * \return the set of trusted keys for the domain, or NULL if the RRSET could not be validated
++ */
++ldns_rr_list *ldns_validate_domain_ds_time(
++		const ldns_resolver *res, const ldns_rdf *domain, 
++		const ldns_rr_list * keys, time_t check_time);
++
++
++/**
++ * Verifies a list of signatures for one RRset using a valid trust path.
++ *
++ * \param[in] res the current resolver
++ * \param[in] rrset the rrset to verify
++ * \param[in] rrsigs a list of signatures to check
++ * \param[out] validating_keys  if this is a (initialized) list, the
++ *                              keys from keys that validate one of
++ *                              the signatures are added to it
++ * \return status LDNS_STATUS_OK if there is at least one correct key
++ */
++ldns_status ldns_verify_trusted(ldns_resolver *res,
++						  ldns_rr_list *rrset,
++						  ldns_rr_list *rrsigs,
++						  ldns_rr_list *validating_keys);
++
++/**
++ * Verifies a list of signatures for one RRset using a valid trust path.
++ *
++ * \param[in] res the current resolver
++ * \param[in] rrset the rrset to verify
++ * \param[in] rrsigs a list of signatures to check
++ * \param[in] check_time the time for which the validation is performed
++ * \param[out] validating_keys  if this is a (initialized) list, the
++ *                              keys from keys that validate one of
++ *                              the signatures are added to it
++ * \return status LDNS_STATUS_OK if there is at least one correct key
++ */
++ldns_status ldns_verify_trusted_time(
++		ldns_resolver *res, ldns_rr_list *rrset, 
++		ldns_rr_list *rrsigs, time_t check_time,
++		ldns_rr_list *validating_keys);
++
++
++/**
++ * denial is not just a river in egypt
++ *
++ * \param[in] rr The (query) RR to check the denial of existence for
++ * \param[in] nsecs The list of NSEC RRs that are supposed to deny the
++ *                  existence of the RR
++ * \param[in] rrsigs The RRSIG RR covering the NSEC RRs
++ * \return LDNS_STATUS_OK if the NSEC RRs deny the existence, error code
++ *                        containing the reason they do not otherwise
++ */
++ldns_status ldns_dnssec_verify_denial(ldns_rr *rr,
++							   ldns_rr_list *nsecs,
++							   ldns_rr_list *rrsigs);
++
++/**
++ * Denial of existence using NSEC3 records
++ * Since NSEC3 is a bit more complicated than normal denial, some
++ * context arguments are needed
++ *
++ * \param[in] rr The (query) RR to check the denial of existence for
++ * \param[in] nsecs The list of NSEC3 RRs that are supposed to deny the
++ *                  existence of the RR
++ * \param[in] rrsigs The RRSIG rr covering the NSEC RRs
++ * \param[in] packet_rcode The RCODE value of the packet that provided the
++ *                         NSEC3 RRs
++ * \param[in] packet_qtype The original query RR type
++ * \param[in] packet_nodata True if the providing packet had an empty ANSWER
++ *                          section
++ * \return LDNS_STATUS_OK if the NSEC3 RRs deny the existence, error code
++ *                        containing the reason they do not otherwise
++ */
++ldns_status ldns_dnssec_verify_denial_nsec3(ldns_rr *rr,
++								    ldns_rr_list *nsecs,
++								    ldns_rr_list *rrsigs,
++								    ldns_pkt_rcode packet_rcode,
++								    ldns_rr_type packet_qtype,
++								    bool packet_nodata);
++
++/**
++ * Same as ldns_status ldns_dnssec_verify_denial_nsec3 but also returns
++ * the nsec rr that matched.
++ *
++ * \param[in] rr The (query) RR to check the denial of existence for
++ * \param[in] nsecs The list of NSEC3 RRs that are supposed to deny the
++ *                  existence of the RR
++ * \param[in] rrsigs The RRSIG rr covering the NSEC RRs
++ * \param[in] packet_rcode The RCODE value of the packet that provided the
++ *                         NSEC3 RRs
++ * \param[in] packet_qtype The original query RR type
++ * \param[in] packet_nodata True if the providing packet had an empty ANSWER
++ *                          section
++ * \param[in] match On match, the given (reference to a) pointer will be set 
++ *                  to point to the matching nsec resource record.
++ * \return LDNS_STATUS_OK if the NSEC3 RRs deny the existence, error code
++ *                        containing the reason they do not otherwise
++ */
++ldns_status ldns_dnssec_verify_denial_nsec3_match(ldns_rr *rr,
++						  ldns_rr_list *nsecs,
++						  ldns_rr_list *rrsigs,
++						  ldns_pkt_rcode packet_rcode,
++						  ldns_rr_type packet_qtype,
++						  bool packet_nodata,
++						  ldns_rr **match);
++/**
++ * Verifies the already processed data in the buffers
++ * This function should probably not be used directly.
++ *
++ * \param[in] rawsig_buf Buffer containing signature data to use
++ * \param[in] verify_buf Buffer containing data to verify
++ * \param[in] key_buf Buffer containing key data to use
++ * \param[in] algo Signing algorithm
++ * \return status LDNS_STATUS_OK if the data verifies. Error if not.
++ */
++ldns_status ldns_verify_rrsig_buffers(ldns_buffer *rawsig_buf,
++							   ldns_buffer *verify_buf,
++							   ldns_buffer *key_buf,
++							   uint8_t algo);
++
++/**
++ * Like ldns_verify_rrsig_buffers, but uses raw data.
++ *
++ * \param[in] sig signature data to use
++ * \param[in] siglen length of signature data to use
++ * \param[in] verify_buf Buffer containing data to verify
++ * \param[in] key key data to use
++ * \param[in] keylen length of key data to use
++ * \param[in] algo Signing algorithm
++ * \return status LDNS_STATUS_OK if the data verifies. Error if not.
++ */
++ldns_status ldns_verify_rrsig_buffers_raw(unsigned char* sig,
++								  size_t siglen, 
++								  ldns_buffer *verify_buf,
++								  unsigned char* key,
++								  size_t keylen, 
++								  uint8_t algo);
++
++/**
++ * Verifies an rrsig. All keys in the keyset are tried.
++ * \param[in] rrset the rrset to check
++ * \param[in] rrsig the signature of the rrset
++ * \param[in] keys the keys to try
++ * \param[out] good_keys  if this is a (initialized) list, the pointer to keys
++ *                        from keys that validate one of the signatures
++ *                        are added to it
++ * \return a list of keys which validate the rrsig + rrset. Returns
++ * status LDNS_STATUS_OK if at least one key matched. Else an error.
++ */
++ldns_status ldns_verify_rrsig_keylist(ldns_rr_list *rrset,
++							   ldns_rr *rrsig,
++							   const ldns_rr_list *keys,
++							   ldns_rr_list *good_keys);
++
++/**
++ * Verifies an rrsig. All keys in the keyset are tried.
++ * \param[in] rrset the rrset to check
++ * \param[in] rrsig the signature of the rrset
++ * \param[in] keys the keys to try
++ * \param[in] check_time the time for which the validation is performed
++ * \param[out] good_keys  if this is a (initialized) list, the pointer to keys
++ *                        from keys that validate one of the signatures
++ *                        are added to it
++ * \return a list of keys which validate the rrsig + rrset. Returns
++ * status LDNS_STATUS_OK if at least one key matched. Else an error.
++ */
++ldns_status ldns_verify_rrsig_keylist_time(
++		ldns_rr_list *rrset, ldns_rr *rrsig, 
++		const ldns_rr_list *keys, time_t check_time,
++	       	ldns_rr_list *good_keys);
++
++
++/**
++ * Verifies an rrsig. All keys in the keyset are tried. Time is not checked.
++ * \param[in] rrset the rrset to check
++ * \param[in] rrsig the signature of the rrset
++ * \param[in] keys the keys to try
++ * \param[out] good_keys  if this is a (initialized) list, the pointer to keys
++ *                        from keys that validate one of the signatures
++ *                        are added to it
++ * \return a list of keys which validate the rrsig + rrset. Returns
++ * status LDNS_STATUS_OK if at least one key matched. Else an error.
++ */
++ldns_status ldns_verify_rrsig_keylist_notime(ldns_rr_list *rrset,
++							   ldns_rr *rrsig,
++							   const ldns_rr_list *keys,
++							   ldns_rr_list *good_keys);
++
++/**
++ * verify an rrsig with 1 key
++ * \param[in] rrset the rrset
++ * \param[in] rrsig the rrsig to verify
++ * \param[in] key the key to use
++ * \return status message wether verification succeeded.
++ */
++ldns_status ldns_verify_rrsig(ldns_rr_list *rrset,
++						ldns_rr *rrsig,
++						ldns_rr *key);
++
++
++/**
++ * verify an rrsig with 1 key
++ * \param[in] rrset the rrset
++ * \param[in] rrsig the rrsig to verify
++ * \param[in] key the key to use
++ * \param[in] check_time the time for which the validation is performed
++ * \return status message wether verification succeeded.
++ */
++ldns_status ldns_verify_rrsig_time(
++		ldns_rr_list *rrset, ldns_rr *rrsig, 
++		ldns_rr *key, time_t check_time);
++
++
++#if LDNS_BUILD_CONFIG_HAVE_SSL
++/**
++ * verifies a buffer with signature data for a buffer with rrset data 
++ * with an EVP_PKEY
++ *
++ * \param[in] sig the signature data
++ * \param[in] rrset the rrset data, sorted and processed for verification
++ * \param[in] key the EVP key structure
++ * \param[in] digest_type The digest type of the signature
++ */
++ldns_status ldns_verify_rrsig_evp(ldns_buffer *sig,
++						    ldns_buffer *rrset,
++						    EVP_PKEY *key,
++						    const EVP_MD *digest_type);
++
++/**
++ * Like ldns_verify_rrsig_evp, but uses raw signature data.
++ * \param[in] sig the signature data, wireformat uncompressed
++ * \param[in] siglen length of the signature data
++ * \param[in] rrset the rrset data, sorted and processed for verification
++ * \param[in] key the EVP key structure
++ * \param[in] digest_type The digest type of the signature
++ */
++ldns_status ldns_verify_rrsig_evp_raw(unsigned char *sig,
++							   size_t siglen,
++							   ldns_buffer *rrset,
++							   EVP_PKEY *key,
++							   const EVP_MD *digest_type);
++#endif
++
++/**
++ * verifies a buffer with signature data (DSA) for a buffer with rrset data 
++ * with a buffer with key data.
++ *
++ * \param[in] sig the signature data
++ * \param[in] rrset the rrset data, sorted and processed for verification
++ * \param[in] key the key data
++ */
++ldns_status ldns_verify_rrsig_dsa(ldns_buffer *sig,
++						    ldns_buffer *rrset,
++						    ldns_buffer *key);
++
++/**
++ * verifies a buffer with signature data (RSASHA1) for a buffer with rrset data 
++ * with a buffer with key data.
++ *
++ * \param[in] sig the signature data
++ * \param[in] rrset the rrset data, sorted and processed for verification
++ * \param[in] key the key data
++ */
++ldns_status ldns_verify_rrsig_rsasha1(ldns_buffer *sig,
++							   ldns_buffer *rrset,
++							   ldns_buffer *key);
++
++/**
++ * verifies a buffer with signature data (RSAMD5) for a buffer with rrset data 
++ * with a buffer with key data.
++ *
++ * \param[in] sig the signature data
++ * \param[in] rrset the rrset data, sorted and processed for verification
++ * \param[in] key the key data
++ */
++ldns_status ldns_verify_rrsig_rsamd5(ldns_buffer *sig,
++							  ldns_buffer *rrset,
++							  ldns_buffer *key);
++
++/**
++ * Like ldns_verify_rrsig_dsa, but uses raw signature and key data.
++ * \param[in] sig raw uncompressed wireformat signature data
++ * \param[in] siglen length of signature data
++ * \param[in] rrset ldns buffer with prepared rrset data.
++ * \param[in] key raw uncompressed wireformat key data
++ * \param[in] keylen length of key data
++ */
++ldns_status ldns_verify_rrsig_dsa_raw(unsigned char* sig,
++							   size_t siglen,
++							   ldns_buffer* rrset,
++							   unsigned char* key,
++							   size_t keylen);
++
++/**
++ * Like ldns_verify_rrsig_rsasha1, but uses raw signature and key data.
++ * \param[in] sig raw uncompressed wireformat signature data
++ * \param[in] siglen length of signature data
++ * \param[in] rrset ldns buffer with prepared rrset data.
++ * \param[in] key raw uncompressed wireformat key data
++ * \param[in] keylen length of key data
++ */
++ldns_status ldns_verify_rrsig_rsasha1_raw(unsigned char* sig,
++								  size_t siglen,
++								  ldns_buffer* rrset,
++								  unsigned char* key,
++								  size_t keylen);
++
++/**
++ * Like ldns_verify_rrsig_rsasha256, but uses raw signature and key data.
++ * \param[in] sig raw uncompressed wireformat signature data
++ * \param[in] siglen length of signature data
++ * \param[in] rrset ldns buffer with prepared rrset data.
++ * \param[in] key raw uncompressed wireformat key data
++ * \param[in] keylen length of key data
++ */
++
++ldns_status ldns_verify_rrsig_rsasha256_raw(unsigned char* sig,
++								    size_t siglen,
++								    ldns_buffer* rrset,
++								    unsigned char* key,
++								    size_t keylen);
++
++/**
++ * Like ldns_verify_rrsig_rsasha512, but uses raw signature and key data.
++ * \param[in] sig raw uncompressed wireformat signature data
++ * \param[in] siglen length of signature data
++ * \param[in] rrset ldns buffer with prepared rrset data.
++ * \param[in] key raw uncompressed wireformat key data
++ * \param[in] keylen length of key data
++ */
++ldns_status ldns_verify_rrsig_rsasha512_raw(unsigned char* sig,
++								    size_t siglen,
++								    ldns_buffer* rrset,
++								    unsigned char* key,
++								    size_t keylen);
++
++/**
++ * Like ldns_verify_rrsig_rsamd5, but uses raw signature and key data.
++ * \param[in] sig raw uncompressed wireformat signature data
++ * \param[in] siglen length of signature data
++ * \param[in] rrset ldns buffer with prepared rrset data.
++ * \param[in] key raw uncompressed wireformat key data
++ * \param[in] keylen length of key data
++ */
++ldns_status ldns_verify_rrsig_rsamd5_raw(unsigned char* sig,
++								 size_t siglen,
++								 ldns_buffer* rrset,
++								 unsigned char* key,
++								 size_t keylen);
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif
++
+diff --git a/ldns/include/ldns/dnssec_zone.h b/ldns/include/ldns/dnssec_zone.h
+new file mode 100644
+index 0000000..b794f94
+--- /dev/null
++++ b/ldns/include/ldns/dnssec_zone.h
+@@ -0,0 +1,483 @@
++/*
++ * special zone file structures and functions for better dnssec handling
++ *
++ * A zone contains a SOA dnssec_zone_rrset, and an AVL tree of 'normal'
++ * dnssec_zone_rrsets, indexed by name and type
++ */
++
++#ifndef LDNS_DNSSEC_ZONE_H
++#define LDNS_DNSSEC_ZONE_H
++ 
++#include <ldns/rbtree.h>
++#include <ldns/host2str.h>
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/**
++ * Singly linked list of rrs
++ */
++typedef struct ldns_struct_dnssec_rrs ldns_dnssec_rrs;
++struct ldns_struct_dnssec_rrs
++{
++	ldns_rr *rr;
++	ldns_dnssec_rrs *next;
++};
++
++/**
++ * Singly linked list of RRsets
++ */
++typedef struct ldns_struct_dnssec_rrsets ldns_dnssec_rrsets;
++struct ldns_struct_dnssec_rrsets
++{
++	ldns_dnssec_rrs *rrs;
++	ldns_rr_type type;
++	ldns_dnssec_rrs *signatures;
++	ldns_dnssec_rrsets *next;
++};
++
++/**
++ * Structure containing all resource records for a domain name
++ * Including the derived NSEC3, if present
++ */
++typedef struct ldns_struct_dnssec_name ldns_dnssec_name;
++struct ldns_struct_dnssec_name
++{
++	/**
++	 * pointer to a dname containing the name.
++	 * Usually points to the owner name of the first RR of the first RRset
++	 */
++	ldns_rdf *name;
++	/** 
++	 * Usually, the name is a pointer to the owner name of the first rr for
++	 * this name, but sometimes there is no actual data to point to, 
++	 * for instance in
++	 * names representing empty nonterminals. If so, set alloced to true to
++	 * indicate that this data must also be freed when the name is freed
++	 */
++	bool name_alloced;
++	/**
++	 * The rrsets for this name
++	 */
++	ldns_dnssec_rrsets *rrsets;
++	/**
++	 * NSEC pointing to the next name (or NSEC3 pointing to the next NSEC3)
++	 */
++	ldns_rr *nsec;
++	/**
++	 * signatures for the NSEC record
++	 */
++	ldns_dnssec_rrs *nsec_signatures;
++	/**
++	 * Unlike what the name is_glue suggests, this field is set to true by
++	 * ldns_dnssec_zone_mark_glue() or ldns_dnssec_zone_mark_and_get_glue()
++	 * when the name, this dnssec_name struct represents, is occluded.
++	 * Names that contain other occluded rrsets and records with glue on
++	 * the delegation point will NOT have this bool set to true.
++	 * This field should NOT be read directly, but only via the 
++	 * ldns_dnssec_name_is_glue() function!
++	 */
++	bool is_glue;
++	/**
++	 * pointer to store the hashed name (only used when in an NSEC3 zone
++	 */
++	ldns_rdf *hashed_name;
++};
++
++/**
++ * Structure containing a dnssec zone
++ */
++struct ldns_struct_dnssec_zone {
++	/** points to the name containing the SOA RR */
++	ldns_dnssec_name *soa;
++	/** tree of ldns_dnssec_names */
++	ldns_rbtree_t *names;
++	/** tree of ldns_dnssec_names by nsec3 hashes (when applicible) */
++	ldns_rbtree_t *hashed_names;
++	/** points to the first added NSEC3 rr whose parameters will be 
++	 *  assumed for all subsequent NSEC3 rr's and which will be used
++	 *  to calculate hashed names
++	 */
++	ldns_rr *_nsec3params;
++};
++typedef struct ldns_struct_dnssec_zone ldns_dnssec_zone;
++
++/**
++ * Creates a new entry for 1 pointer to an rr and 1 pointer to the next rrs
++ * \return the allocated data
++ */
++ldns_dnssec_rrs *ldns_dnssec_rrs_new(void);
++
++/**
++ * Frees the list of rrs, but *not* the individual ldns_rr records
++ * contained in the list
++ * 
++ * \param[in] rrs the data structure to free
++ */
++void ldns_dnssec_rrs_free(ldns_dnssec_rrs *rrs);
++
++/**
++ * Frees the list of rrs, and the individual ldns_rr records
++ * contained in the list
++ * 
++ * \param[in] rrs the data structure to free
++ */
++void ldns_dnssec_rrs_deep_free(ldns_dnssec_rrs *rrs);
++
++/**
++ * Adds an RR to the list of RRs. The list will remain ordered.
++ * If an equal RR already exists, this RR will not be added.
++ *
++ * \param[in] rrs the list to add to
++ * \param[in] rr the RR to add
++ * \return LDNS_STATUS_OK on success
++ */
++ldns_status ldns_dnssec_rrs_add_rr(ldns_dnssec_rrs *rrs, ldns_rr *rr);
++
++/**
++ * Prints the given rrs to the file descriptor
++ *
++ * \param[in] out the file descriptor to print to
++ * \param[in] rrs the list of RRs to print
++ */
++void ldns_dnssec_rrs_print(FILE *out, ldns_dnssec_rrs *rrs);
++
++/**
++ * Prints the given rrs to the file descriptor
++ *
++ * \param[in] out the file descriptor to print to
++ * \param[in] fmt the format of the textual representation
++ * \param[in] rrs the list of RRs to print
++ */
++void ldns_dnssec_rrs_print_fmt(FILE *out, 
++		const ldns_output_format *fmt, ldns_dnssec_rrs *rrs);
++
++/**
++ * Creates a new list (entry) of RRsets
++ * \return the newly allocated structure
++ */
++ldns_dnssec_rrsets *ldns_dnssec_rrsets_new(void);
++
++/**
++ * Frees the list of rrsets and their rrs, but *not* the ldns_rr
++ * records in the sets
++ *
++ * \param[in] rrsets the data structure to free
++ */
++void ldns_dnssec_rrsets_free(ldns_dnssec_rrsets *rrsets);
++
++/**
++ * Frees the list of rrsets and their rrs, and the ldns_rr
++ * records in the sets
++ *
++ * \param[in] rrsets the data structure to free
++ */
++void ldns_dnssec_rrsets_deep_free(ldns_dnssec_rrsets *rrsets);
++
++/**
++ * Returns the rr type of the rrset (that is head of the given list)
++ *
++ * \param[in] rrsets the rrset to get the type of
++ * \return the rr type
++ */
++ldns_rr_type ldns_dnssec_rrsets_type(ldns_dnssec_rrsets *rrsets);
++
++/**
++ * Sets the RR type of the rrset (that is head of the given list)
++ *
++ * \param[in] rrsets the rrset to set the type of
++ * \param[in] type the type to set
++ * \return LDNS_STATUS_OK on success
++ */
++ldns_status ldns_dnssec_rrsets_set_type(ldns_dnssec_rrsets *rrsets,
++					   ldns_rr_type type);
++
++/**
++ * Add an ldns_rr to the corresponding RRset in the given list of RRsets.
++ * If it is not present, add it as a new RRset with 1 record.
++ *
++ * \param[in] rrsets the list of rrsets to add the RR to
++ * \param[in] rr the rr to add to the list of rrsets
++ * \return LDNS_STATUS_OK on success
++ */
++ldns_status ldns_dnssec_rrsets_add_rr(ldns_dnssec_rrsets *rrsets, ldns_rr *rr);
++
++/**
++ * Print the given list of rrsets to the fiven file descriptor
++ * 
++ * \param[in] out the file descriptor to print to
++ * \param[in] rrsets the list of RRsets to print
++ * \param[in] follow if set to false, only print the first RRset
++ */ 
++void ldns_dnssec_rrsets_print(FILE *out,
++		ldns_dnssec_rrsets *rrsets,
++		bool follow);
++
++/**
++ * Print the given list of rrsets to the fiven file descriptor
++ * 
++ * \param[in] out the file descriptor to print to
++ * \param[in] fmt the format of the textual representation
++ * \param[in] rrsets the list of RRsets to print
++ * \param[in] follow if set to false, only print the first RRset
++ */ 
++void ldns_dnssec_rrsets_print_fmt(FILE *out,
++		const ldns_output_format *fmt,
++		ldns_dnssec_rrsets *rrsets,
++		bool follow);
++
++
++/**
++ * Create a new data structure for a dnssec name
++ * \return the allocated structure
++ */
++ldns_dnssec_name *ldns_dnssec_name_new(void);
++
++/**
++ * Create a new data structure for a dnssec name for the given RR
++ *
++ * \param[in] rr the RR to derive properties from, and to add to the name
++ */
++ldns_dnssec_name *ldns_dnssec_name_new_frm_rr(ldns_rr *rr);
++
++/**
++ * Frees the name structure and its rrs and rrsets.
++ * Individual ldns_rr records therein are not freed
++ *
++ * \param[in] name the structure to free
++ */
++void ldns_dnssec_name_free(ldns_dnssec_name *name);
++
++/**
++ * Frees the name structure and its rrs and rrsets.
++ * Individual ldns_rr records contained in the name are also freed
++ *
++ * \param[in] name the structure to free
++ */
++void ldns_dnssec_name_deep_free(ldns_dnssec_name *name);
++
++/**
++ * Returns the domain name of the given dnssec_name structure
++ *
++ * \param[in] name the dnssec name to get the domain name from
++ * \return the domain name
++ */
++ldns_rdf *ldns_dnssec_name_name(ldns_dnssec_name *name);
++
++
++/**
++ * Sets the domain name of the given dnssec_name structure
++ *
++ * \param[in] name the dnssec name to set the domain name of
++ * \param[in] dname the domain name to set it to. This data is *not* copied.
++ */
++void ldns_dnssec_name_set_name(ldns_dnssec_name *name,
++						 ldns_rdf *dname);
++/**
++ * Returns if dnssec_name structure is marked as glue.
++ * The ldns_dnssec_zone_mark_glue() function has to be called on a zone before
++ * using this function.
++ * Only names that have only glue rrsets will be marked.
++ * Names that have other occluded rrsets and names containing glue on the 
++ * delegation point will NOT be marked!
++ *
++ * \param[in] name the dnssec name to get the domain name from
++ * \return true if the structure is marked as glue, false otherwise.
++ */
++bool ldns_dnssec_name_is_glue(ldns_dnssec_name *name);
++
++/**
++ * Sets the NSEC(3) RR of the given dnssec_name structure
++ *
++ * \param[in] name the dnssec name to set the domain name of
++ * \param[in] nsec the nsec rr to set it to. This data is *not* copied.
++ */
++void ldns_dnssec_name_set_nsec(ldns_dnssec_name *name, ldns_rr *nsec);
++
++/**
++ * Compares the domain names of the two arguments in their
++ * canonical ordening.
++ * 
++ * \param[in] a The first dnssec_name to compare
++ * \param[in] b The second dnssec_name to compare
++ * \return -1 if the domain name of a comes before that of b in canonical
++ *            ordening, 1 if it is the other way around, and 0 if they are
++ *            equal
++ */
++int ldns_dnssec_name_cmp(const void *a, const void *b);
++
++/**
++ * Inserts the given rr at the right place in the current dnssec_name
++ * No checking is done whether the name matches
++ *
++ * \param[in] name The ldns_dnssec_name to add the RR to
++ * \param[in] rr The RR to add
++ * \return LDNS_STATUS_OK on success, error code otherwise
++ */
++ldns_status ldns_dnssec_name_add_rr(ldns_dnssec_name *name,
++							 ldns_rr *rr);
++
++/**
++ * Find the RRset with the given type in within this name structure
++ *
++ * \param[in] name the name to find the RRset in
++ * \param[in] type the type of the RRset to find
++ * \return the RRset, or NULL if not present
++ */
++ldns_dnssec_rrsets *ldns_dnssec_name_find_rrset(ldns_dnssec_name *name,
++									   ldns_rr_type type);
++
++/**
++ * Find the RRset with the given name and type in the zone
++ *
++ * \param[in] zone the zone structure to find the RRset in
++ * \param[in] dname the domain name of the RRset to find
++ * \param[in] type the type of the RRset to find
++ * \return the RRset, or NULL if not present
++ */
++ldns_dnssec_rrsets *ldns_dnssec_zone_find_rrset(ldns_dnssec_zone *zone,
++									   ldns_rdf *dname,
++									   ldns_rr_type type);
++
++/**
++ * Prints the RRs in the  dnssec name structure to the given
++ * file descriptor
++ *
++ * \param[in] out the file descriptor to print to
++ * \param[in] name the name structure to print the contents of
++ */
++void ldns_dnssec_name_print(FILE *out, ldns_dnssec_name *name);
++
++/**
++ * Prints the RRs in the  dnssec name structure to the given
++ * file descriptor
++ *
++ * \param[in] out the file descriptor to print to
++ * \param[in] fmt the format of the textual representation
++ * \param[in] name the name structure to print the contents of
++ */
++void ldns_dnssec_name_print_fmt(FILE *out, 
++		const ldns_output_format *fmt, ldns_dnssec_name *name);
++
++/**
++ * Creates a new dnssec_zone structure
++ * \return the allocated structure
++ */
++ldns_dnssec_zone *ldns_dnssec_zone_new(void);
++
++/**
++ * Create a new dnssec zone from a file.
++ * \param[out] z the new zone
++ * \param[in] *fp the filepointer to use
++ * \param[in] *origin the zones' origin
++ * \param[in] c default class to use (IN)
++ * \param[in] ttl default ttl to use
++ *
++ * \return ldns_status mesg with an error or LDNS_STATUS_OK
++ */
++ldns_status ldns_dnssec_zone_new_frm_fp(ldns_dnssec_zone** z, FILE* fp,
++		ldns_rdf* origin, uint32_t ttl, ldns_rr_class c);
++
++/**
++ * Create a new dnssec zone from a file, keep track of the line numbering
++ * \param[out] z the new zone
++ * \param[in] *fp the filepointer to use
++ * \param[in] *origin the zones' origin
++ * \param[in] ttl default ttl to use
++ * \param[in] c default class to use (IN)
++ * \param[out] line_nr used for error msg, to get to the line number
++ *
++ * \return ldns_status mesg with an error or LDNS_STATUS_OK
++ */
++ldns_status ldns_dnssec_zone_new_frm_fp_l(ldns_dnssec_zone** z, FILE* fp,
++		ldns_rdf* origin, uint32_t ttl, ldns_rr_class c, int* line_nr);
++
++/**
++ * Frees the given zone structure, and its rbtree of dnssec_names
++ * Individual ldns_rr RRs within those names are *not* freed
++ * \param[in] *zone the zone to free
++ */ 
++void ldns_dnssec_zone_free(ldns_dnssec_zone *zone);
++
++/**
++ * Frees the given zone structure, and its rbtree of dnssec_names
++ * Individual ldns_rr RRs within those names are also freed
++ * \param[in] *zone the zone to free
++ */ 
++void ldns_dnssec_zone_deep_free(ldns_dnssec_zone *zone);
++
++/**
++ * Adds the given RR to the zone.
++ * It find whether there is a dnssec_name with that name present.
++ * If so, add it to that, if not create a new one. 
++ * Special handling of NSEC and RRSIG provided
++ *
++ * \param[in] zone the zone to add the RR to
++ * \param[in] rr The RR to add
++ * \return LDNS_STATUS_OK on success, an error code otherwise
++ */
++ldns_status ldns_dnssec_zone_add_rr(ldns_dnssec_zone *zone,
++							 ldns_rr *rr);
++
++/**
++ * Prints the rbtree of ldns_dnssec_name structures to the file descriptor
++ *
++ * \param[in] out the file descriptor to print the names to
++ * \param[in] tree the tree of ldns_dnssec_name structures to print
++ * \param[in] print_soa if true, print SOA records, if false, skip them
++ */
++void ldns_dnssec_zone_names_print(FILE *out, ldns_rbtree_t *tree, bool print_soa);
++
++/**
++ * Prints the rbtree of ldns_dnssec_name structures to the file descriptor
++ *
++ * \param[in] out the file descriptor to print the names to
++ * \param[in] fmt the format of the textual representation
++ * \param[in] tree the tree of ldns_dnssec_name structures to print
++ * \param[in] print_soa if true, print SOA records, if false, skip them
++ */
++void ldns_dnssec_zone_names_print_fmt(FILE *out, const ldns_output_format *fmt,
++		ldns_rbtree_t *tree, bool print_soa);
++
++/**
++ * Prints the complete zone to the given file descriptor
++ *
++ * \param[in] out the file descriptor to print to
++ * \param[in] zone the dnssec_zone to print
++ */
++void ldns_dnssec_zone_print(FILE *out, ldns_dnssec_zone *zone);
++
++/**
++ * Prints the complete zone to the given file descriptor
++ *
++ * \param[in] out the file descriptor to print to
++ * \param[in] fmt the format of the textual representation
++ * \param[in] zone the dnssec_zone to print
++ */
++void ldns_dnssec_zone_print_fmt(FILE *out, 
++		const ldns_output_format *fmt, ldns_dnssec_zone *zone);
++
++/**
++ * Adds explicit dnssec_name structures for the empty nonterminals
++ * in this zone. (this is needed for NSEC3 generation)
++ *
++ * \param[in] zone the zone to check for empty nonterminals
++ * return LDNS_STATUS_OK on success.
++ */
++ldns_status ldns_dnssec_zone_add_empty_nonterminals(ldns_dnssec_zone *zone);
++
++/**
++ * If a NSEC3PARAM is available in the apex, walks the zone and returns true
++ * on the first optout nsec3.
++ *
++ * \param[in] zone the zone to check for nsec3 optout records
++ * return true when the zone has at least one nsec3 optout record.
++ */
++bool ldns_dnssec_zone_is_nsec3_optout(ldns_dnssec_zone* zone);
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif
+diff --git a/ldns/include/ldns/duration.h b/ldns/include/ldns/duration.h
+new file mode 100644
+index 0000000..f12edc4
+--- /dev/null
++++ b/ldns/include/ldns/duration.h
+@@ -0,0 +1,109 @@
++/*
++ * $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);
++
++/**
++ * Clean up duration.
++ * \param[in] duration duration to be cleaned up
++ *
++ */
++void ldns_duration_cleanup(ldns_duration_type* duration);
++
++#endif /* LDNS_DURATION_H */
+diff --git a/ldns/include/ldns/error.h b/ldns/include/ldns/error.h
+new file mode 100644
+index 0000000..cc11958
+--- /dev/null
++++ b/ldns/include/ldns/error.h
+@@ -0,0 +1,147 @@
++/**
++ * \file error.h
++ *
++ * Defines error numbers and functions to translate those to a readable string.
++ *
++ */
++ 
++/**
++ * a Net::DNS like library for C
++ *
++ * (c) NLnet Labs, 2005-2006
++ *
++ * See the file LICENSE for the license
++ */
++
++#ifndef LDNS_ERROR_H
++#define LDNS_ERROR_H
++
++#include <ldns/util.h>
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++enum ldns_enum_status {
++	LDNS_STATUS_OK,	
++	LDNS_STATUS_EMPTY_LABEL,
++	LDNS_STATUS_LABEL_OVERFLOW,
++	LDNS_STATUS_DOMAINNAME_OVERFLOW,
++	LDNS_STATUS_DOMAINNAME_UNDERFLOW,
++	LDNS_STATUS_DDD_OVERFLOW,
++	LDNS_STATUS_PACKET_OVERFLOW,
++	LDNS_STATUS_INVALID_POINTER,
++	LDNS_STATUS_MEM_ERR,
++	LDNS_STATUS_INTERNAL_ERR,
++	LDNS_STATUS_SSL_ERR,
++	LDNS_STATUS_ERR,
++	LDNS_STATUS_INVALID_INT,
++	LDNS_STATUS_INVALID_IP4,
++	LDNS_STATUS_INVALID_IP6,
++	LDNS_STATUS_INVALID_STR,
++	LDNS_STATUS_INVALID_B32_EXT,
++	LDNS_STATUS_INVALID_B64,
++	LDNS_STATUS_INVALID_HEX,
++	LDNS_STATUS_INVALID_TIME,
++	LDNS_STATUS_NETWORK_ERR,
++	LDNS_STATUS_ADDRESS_ERR,
++	LDNS_STATUS_FILE_ERR,
++	LDNS_STATUS_UNKNOWN_INET,
++	LDNS_STATUS_NOT_IMPL,
++	LDNS_STATUS_NULL,
++	LDNS_STATUS_CRYPTO_UNKNOWN_ALGO, 
++	LDNS_STATUS_CRYPTO_ALGO_NOT_IMPL, 	
++	LDNS_STATUS_CRYPTO_NO_RRSIG,
++	LDNS_STATUS_CRYPTO_NO_DNSKEY,
++	LDNS_STATUS_CRYPTO_NO_TRUSTED_DNSKEY,
++	LDNS_STATUS_CRYPTO_NO_DS,
++	LDNS_STATUS_CRYPTO_NO_TRUSTED_DS,
++	LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY,
++	LDNS_STATUS_CRYPTO_VALIDATED,
++	LDNS_STATUS_CRYPTO_BOGUS,
++	LDNS_STATUS_CRYPTO_SIG_EXPIRED,
++	LDNS_STATUS_CRYPTO_SIG_NOT_INCEPTED,
++	LDNS_STATUS_CRYPTO_TSIG_BOGUS,
++	LDNS_STATUS_CRYPTO_TSIG_ERR,
++	LDNS_STATUS_CRYPTO_EXPIRATION_BEFORE_INCEPTION,
++	LDNS_STATUS_CRYPTO_TYPE_COVERED_ERR,
++	LDNS_STATUS_ENGINE_KEY_NOT_LOADED,
++	LDNS_STATUS_NSEC3_ERR,
++	LDNS_STATUS_RES_NO_NS,
++	LDNS_STATUS_RES_QUERY,
++	LDNS_STATUS_WIRE_INCOMPLETE_HEADER,
++	LDNS_STATUS_WIRE_INCOMPLETE_QUESTION,
++	LDNS_STATUS_WIRE_INCOMPLETE_ANSWER,
++	LDNS_STATUS_WIRE_INCOMPLETE_AUTHORITY,
++	LDNS_STATUS_WIRE_INCOMPLETE_ADDITIONAL,
++	LDNS_STATUS_NO_DATA,
++	LDNS_STATUS_CERT_BAD_ALGORITHM,
++	LDNS_STATUS_SYNTAX_TYPE_ERR,
++	LDNS_STATUS_SYNTAX_CLASS_ERR,
++	LDNS_STATUS_SYNTAX_TTL_ERR,
++	LDNS_STATUS_SYNTAX_INCLUDE_ERR_NOTIMPL,
++	LDNS_STATUS_SYNTAX_RDATA_ERR,
++	LDNS_STATUS_SYNTAX_DNAME_ERR,
++	LDNS_STATUS_SYNTAX_VERSION_ERR,
++	LDNS_STATUS_SYNTAX_ALG_ERR,
++	LDNS_STATUS_SYNTAX_KEYWORD_ERR,
++	LDNS_STATUS_SYNTAX_TTL,
++	LDNS_STATUS_SYNTAX_ORIGIN,
++	LDNS_STATUS_SYNTAX_INCLUDE,
++	LDNS_STATUS_SYNTAX_EMPTY,
++	LDNS_STATUS_SYNTAX_ITERATIONS_OVERFLOW,
++	LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR,
++	LDNS_STATUS_SYNTAX_INTEGER_OVERFLOW,
++	LDNS_STATUS_SYNTAX_BAD_ESCAPE,
++	LDNS_STATUS_SOCKET_ERROR,
++	LDNS_STATUS_SYNTAX_ERR,
++	LDNS_STATUS_DNSSEC_EXISTENCE_DENIED,
++	LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED,
++	LDNS_STATUS_DNSSEC_NSEC_WILDCARD_NOT_COVERED,
++	LDNS_STATUS_DNSSEC_NSEC3_ORIGINAL_NOT_FOUND,
++	LDNS_STATUS_MISSING_RDATA_FIELDS_RRSIG,
++	LDNS_STATUS_MISSING_RDATA_FIELDS_KEY,
++	LDNS_STATUS_CRYPTO_SIG_EXPIRED_WITHIN_MARGIN,
++	LDNS_STATUS_CRYPTO_SIG_NOT_INCEPTED_WITHIN_MARGIN,
++	LDNS_STATUS_DANE_STATUS_MESSAGES,
++	LDNS_STATUS_DANE_UNKNOWN_CERTIFICATE_USAGE,
++	LDNS_STATUS_DANE_UNKNOWN_SELECTOR,
++	LDNS_STATUS_DANE_UNKNOWN_MATCHING_TYPE,
++	LDNS_STATUS_DANE_UNKNOWN_PROTOCOL,
++	LDNS_STATUS_DANE_UNKNOWN_TRANSPORT,
++	LDNS_STATUS_DANE_MISSING_EXTRA_CERTS,
++	LDNS_STATUS_DANE_EXTRA_CERTS_NOT_USED,
++	LDNS_STATUS_DANE_OFFSET_OUT_OF_RANGE,
++	LDNS_STATUS_DANE_INSECURE,
++	LDNS_STATUS_DANE_BOGUS,
++	LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH,
++	LDNS_STATUS_DANE_NON_CA_CERTIFICATE,
++	LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE,
++	LDNS_STATUS_DANE_PKIX_NO_SELF_SIGNED_TRUST_ANCHOR,
++	LDNS_STATUS_EXISTS_ERR,
++	LDNS_STATUS_INVALID_ILNP64,
++	LDNS_STATUS_INVALID_EUI48,
++	LDNS_STATUS_INVALID_EUI64,
++	LDNS_STATUS_WIRE_RDATA_ERR,
++	LDNS_STATUS_INVALID_TAG,
++	LDNS_STATUS_TYPE_NOT_IN_BITMAP,
++	LDNS_STATUS_INVALID_RDF_TYPE,
++	LDNS_STATUS_RDATA_OVERFLOW
++};
++typedef enum ldns_enum_status ldns_status;
++
++extern ldns_lookup_table ldns_error_str[];
++
++/**
++ * look up a descriptive text by each error. This function
++ * could use a better name
++ * \param[in] err ldns_status number
++ * \return the string for that error
++ */
++const char *ldns_get_errorstr_by_id(ldns_status err);
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* LDNS_ERROR_H */
+diff --git a/ldns/include/ldns/higher.h b/ldns/include/ldns/higher.h
+new file mode 100644
+index 0000000..597e134
+--- /dev/null
++++ b/ldns/include/ldns/higher.h
+@@ -0,0 +1,113 @@
++/**
++ * \file higher.h
++ *
++ * Specifies some higher level functions that could
++ * be useful for certain applications
++ */
++
++/*
++ * a Net::DNS like library for C
++ *
++ * (c) NLnet Labs, 2005-2006
++ *
++ * See the file LICENSE for the license
++ */
++
++#ifndef LDNS_HIGHER_H
++#define LDNS_HIGHER_H
++
++#include <ldns/resolver.h>
++#include <ldns/rdata.h>
++#include <ldns/rr.h>
++#include <ldns/host2str.h>
++#include <ldns/tsig.h>
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/**
++ * Ask the resolver about name
++ * and return all address records
++ * \param[in] r the resolver to use
++ * \param[in] name the name to look for
++ * \param[in] c the class to use
++ * \param[in] flags give some optional flags to the query
++ */
++ldns_rr_list *ldns_get_rr_list_addr_by_name(ldns_resolver *r, ldns_rdf *name, ldns_rr_class c, uint16_t flags);
++
++/**
++ * ask the resolver about the address
++ * and return the name
++ * \param[in] r the resolver to use
++ * \param[in] addr the addr to look for
++ * \param[in] c the class to use
++ * \param[in] flags give some optional flags to the query
++ */
++ldns_rr_list *ldns_get_rr_list_name_by_addr(ldns_resolver *r, ldns_rdf *addr, ldns_rr_class c, uint16_t flags);
++
++/**
++ * wade through fp (a /etc/hosts like file)
++ * and return a rr_list containing all the 
++ * defined hosts in there
++ * \param[in] fp the file pointer to use
++ * \return ldns_rr_list * with the names
++ */
++ldns_rr_list *ldns_get_rr_list_hosts_frm_fp(FILE *fp);
++
++/**
++ * wade through fp (a /etc/hosts like file)
++ * and return a rr_list containing all the 
++ * defined hosts in there
++ * \param[in] fp the file pointer to use
++ * \param[in] line_nr pointer to an integer containing the current line number (for debugging purposes)
++ * \return ldns_rr_list * with the names
++ */
++ldns_rr_list *ldns_get_rr_list_hosts_frm_fp_l(FILE *fp, int *line_nr);
++
++/**
++ * wade through fp (a /etc/hosts like file)
++ * and return a rr_list containing all the 
++ * defined hosts in there
++ * \param[in] filename the filename to use (NULL for /etc/hosts)
++ * \return ldns_rr_list * with the names
++ */
++ldns_rr_list *ldns_get_rr_list_hosts_frm_file(char *filename);
++
++/**
++ * This function is a wrapper function for ldns_get_rr_list_name_by_addr
++ * and ldns_get_rr_list_addr_by_name. It's name is from the getaddrinfo() 
++ * library call. It tries to mimic that call, but without the lowlevel
++ * stuff.
++ * \param[in] res The resolver. If this value is NULL then a resolver will
++ * be created by ldns_getaddrinfo.
++ * \param[in] node the name or ip address to look up
++ * \param[in] c the class to look in
++ * \param[out] list put the found RR's in this list
++ * \return the number of RR found.
++ */
++uint16_t ldns_getaddrinfo(ldns_resolver *res, ldns_rdf *node, ldns_rr_class c, ldns_rr_list **list);
++
++/**
++ * Check if t is enumerated in the nsec type rdata
++ * \param[in] nsec the NSEC Record to look in
++ * \param[in] t the type to check for
++ * \return true when t is found, otherwise return false
++ */
++bool ldns_nsec_type_check(ldns_rr *nsec, ldns_rr_type t);
++
++/**
++ * Print a number of rdf's of the RR. The rdfnum-list must 
++ * be ended by -1, otherwise unpredictable things might happen.
++ * rdfs may be printed multiple times
++ * \param[in] fp FILE * to write to
++ * \param[in] r RR to write
++ * \param[in] rdfnum a list of rdf to print.
++ */
++void ldns_print_rr_rdf(FILE *fp, ldns_rr *r, int rdfnum, ...);
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* LDNS_HIGHER_H */
+diff --git a/ldns/include/ldns/host2str.h b/ldns/include/ldns/host2str.h
+new file mode 100644
+index 0000000..e69389e
+--- /dev/null
++++ b/ldns/include/ldns/host2str.h
+@@ -0,0 +1,891 @@
++/**
++ * host2str.h -  txt presentation of RRs
++ *
++ * a Net::DNS like library for C
++ *
++ * (c) NLnet Labs, 2005-2006
++ *
++ * See the file LICENSE for the license
++ */
++
++/**
++ * \file
++ *
++ * Contains functions to translate the main structures to their text
++ * representation, as well as functions to print them.
++ */
++
++#ifndef LDNS_HOST2STR_H
++#define LDNS_HOST2STR_H
++
++#include <ldns/common.h>
++#include <ldns/error.h>
++#include <ldns/rr.h>
++#include <ldns/rdata.h>
++#include <ldns/packet.h>
++#include <ldns/buffer.h>
++#include <ldns/resolver.h>
++#include <ldns/zone.h>
++#include <ctype.h>
++
++#include "ldns/util.h"
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++#define LDNS_APL_IP4            1
++#define LDNS_APL_IP6            2
++#define LDNS_APL_MASK           0x7f
++#define LDNS_APL_NEGATION       0x80
++
++/** 
++ * Represent a NULL pointer (instead of a pointer to a ldns_rr as "; (null)" 
++ * as opposed to outputting nothing at all in such a case.
++ */
++/*	Flag Name			Flag Nr.	Has data associated
++	---------------------------------------------------------------------*/
++#define LDNS_COMMENT_NULLS		(1 <<  0)
++/** Show key id with DNSKEY RR's as comment */
++#define LDNS_COMMENT_KEY_ID		(1 <<  1)
++/** Show if a DNSKEY is a ZSK or KSK as comment */
++#define LDNS_COMMENT_KEY_TYPE		(1 <<  2)
++/** Show DNSKEY key size as comment */
++#define LDNS_COMMENT_KEY_SIZE		(1 <<  3)
++/** Provide bubblebabble representation for DS RR's as comment */
++#define LDNS_COMMENT_BUBBLEBABBLE	(1 <<  4)
++/** Show when a NSEC3 RR has the optout flag set as comment */
++#define LDNS_COMMENT_FLAGS		(1 <<  5)
++/** Show the unhashed owner and next owner names for NSEC3 RR's as comment */
++#define LDNS_COMMENT_NSEC3_CHAIN	(1 <<  6)	/* yes */
++/** Print mark up */
++#define LDNS_COMMENT_LAYOUT		(1 <<  7)
++/** Also comment KEY_ID with RRSIGS **/
++#define LDNS_COMMENT_RRSIGS		(1 <<  8)
++#define LDNS_FMT_ZEROIZE_RRSIGS		(1 <<  9)
++#define LDNS_FMT_PAD_SOA_SERIAL		(1 << 10)
++#define LDNS_FMT_RFC3597		(1 << 11)	/* yes */
++
++#define LDNS_FMT_FLAGS_WITH_DATA			    2
++
++/** Show key id, type and size as comment for DNSKEY RR's */
++#define LDNS_COMMENT_KEY		(LDNS_COMMENT_KEY_ID  \
++					|LDNS_COMMENT_KEY_TYPE\
++					|LDNS_COMMENT_KEY_SIZE)
++
++/**
++ * Output format specifier
++ *
++ * Determines how Packets, Resource Records and Resource record data fiels are
++ * formatted when printing or converting to string.
++ * Currently it is only used to specify what aspects of a Resource Record are
++ * annotated in the comment section of the textual representation the record.
++ * This is speciefed with flags and potential exra data (such as for example
++ * a lookup map of hashes to real names for annotation NSEC3 records).
++ */
++struct ldns_struct_output_format
++{
++	/** Specification of how RR's should be formatted in text */
++	int   flags;
++	/** Potential extra data to be used with formatting RR's in text */
++	void *data;
++};
++typedef struct ldns_struct_output_format ldns_output_format;
++
++/**
++ * Output format struct with additional data for flags that use them.
++ * This struct may not be initialized directly. Use ldns_output_format_init
++ * to initialize.
++ */
++struct ldns_struct_output_format_storage
++{	int   flags;
++	ldns_rbtree_t* hashmap;    /* for LDNS_COMMENT_NSEC3_CHAIN */
++	ldns_rdf*      bitmap;     /* for LDNS_FMT_RFC3597     */
++};
++typedef struct ldns_struct_output_format_storage ldns_output_format_storage;
++
++/**
++ * Standard output format record that disables commenting in the textual 
++ * representation of Resource Records completely.
++ */
++extern const ldns_output_format *ldns_output_format_nocomments;
++/**
++ * Standard output format record that annotated only DNSKEY RR's with commenti
++ * text.
++ */
++extern const ldns_output_format *ldns_output_format_onlykeyids;
++/**
++ * The default output format record. Same as ldns_output_format_onlykeyids.
++ */
++extern const ldns_output_format *ldns_output_format_default;
++/**
++ * Standard output format record that shows all DNSKEY related information in
++ * the comment text, plus the optout flag when set with NSEC3's, plus the
++ * bubblebabble representation of DS RR's.
++ */
++extern const ldns_output_format *ldns_output_format_bubblebabble;
++
++/**
++ * Initialize output format storage to the default value.
++ * \param[in] fmt A reference to an output_format_ storage struct
++ * \return The initialized storage struct typecasted to ldns_output_format
++ */
++INLINE
++ldns_output_format* ldns_output_format_init(ldns_output_format_storage* fmt) {
++	fmt->flags   = ldns_output_format_default->flags;
++	fmt->hashmap = NULL;
++	fmt->bitmap  = NULL;
++	return (ldns_output_format*)fmt;
++}
++
++/**
++ * Set an ouput format flag.
++ */
++INLINE void ldns_output_format_set(ldns_output_format* fmt, int flag) {
++        fmt->flags |= flag;
++}
++
++/**
++ * Clear an ouput format flag.
++ */
++INLINE void ldns_output_format_clear(ldns_output_format* fmt, int flag) {
++        fmt->flags &= !flag;
++}
++
++/**
++ * Makes sure the LDNS_FMT_RFC3597 is set in the output format.
++ * Marks the type to be printed in RFC3597 format.
++ * /param[in] fmt the output format to update
++ * /param[in] the type to be printed in RFC3597 format
++ * /return LDNS_STATUS_OK on success
++ */
++ldns_status
++ldns_output_format_set_type(ldns_output_format* fmt, ldns_rr_type type);
++
++/**
++ * Makes sure the LDNS_FMT_RFC3597 is set in the output format.
++ * Marks the type to not be printed in RFC3597 format. When no other types
++ * have been marked before, all known types (except the given one) will be
++ * marked for printing in RFC3597 format.
++ * /param[in] fmt the output format to update
++ * /param[in] the type not to be printed in RFC3597 format
++ * /return LDNS_STATUS_OK on success
++ */
++ldns_status
++ldns_output_format_clear_type(ldns_output_format* fmt, ldns_rr_type type);
++
++/**
++ * Converts an ldns packet opcode value to its mnemonic, and adds that
++ * to the output buffer
++ * \param[in] *output the buffer to add the data to
++ * \param[in] opcode to find the string representation of
++ * \return LDNS_STATUS_OK on success, or a buffer failure mode on error
++ */
++ldns_status
++ldns_pkt_opcode2buffer_str(ldns_buffer *output, ldns_pkt_opcode opcode);
++
++/**
++ * Converts an ldns packet rcode value to its mnemonic, and adds that
++ * to the output buffer
++ * \param[in] *output the buffer to add the data to
++ * \param[in] rcode to find the string representation of
++ * \return LDNS_STATUS_OK on success, or a buffer failure mode on error
++ */
++ldns_status
++ldns_pkt_rcode2buffer_str(ldns_buffer *output, ldns_pkt_rcode rcode);
++
++/**
++ * Converts an ldns algorithm type to its mnemonic, and adds that
++ * to the output buffer
++ * \param[in] *output the buffer to add the data to
++ * \param[in] algorithm to find the string representation of
++ * \return LDNS_STATUS_OK on success, or a buffer failure mode on error
++ */
++ldns_status
++ldns_algorithm2buffer_str(ldns_buffer *output,
++                          ldns_algorithm algorithm);
++
++/**
++ * Converts an ldns certificate algorithm type to its mnemonic, 
++ * and adds that to the output buffer
++ * \param[in] *output the buffer to add the data to
++ * \param[in] cert_algorithm to find the string representation of
++ * \return LDNS_STATUS_OK on success, or a buffer failure mode on error
++ */
++ldns_status
++ldns_cert_algorithm2buffer_str(ldns_buffer *output,
++                               ldns_cert_algorithm cert_algorithm);
++
++
++/**
++ * Converts a packet opcode to its mnemonic and returns that as
++ * an allocated null-terminated string.
++ * Remember to free it.
++ *
++ * \param[in] opcode the opcode to convert to text
++ * \return null terminated char * data, or NULL on error
++ */
++char *ldns_pkt_opcode2str(ldns_pkt_opcode opcode);
++
++/**
++ * Converts a packet rcode to its mnemonic and returns that as
++ * an allocated null-terminated string.
++ * Remember to free it.
++ *
++ * \param[in] rcode the rcode to convert to text
++ * \return null terminated char * data, or NULL on error
++ */
++char *ldns_pkt_rcode2str(ldns_pkt_rcode rcode);
++
++/**
++ * Converts a signing algorithms to its mnemonic and returns that as
++ * an allocated null-terminated string.
++ * Remember to free it.
++ *
++ * \param[in] algorithm the algorithm to convert to text
++ * \return null terminated char * data, or NULL on error
++ */
++char *ldns_pkt_algorithm2str(ldns_algorithm algorithm);
++
++/**
++ * Converts a cert algorithm to its mnemonic and returns that as
++ * an allocated null-terminated string.
++ * Remember to free it.
++ *
++ * \param[in] cert_algorithm to convert to text
++ * \return null terminated char * data, or NULL on error
++ */
++char *ldns_pkt_cert_algorithm2str(ldns_cert_algorithm cert_algorithm);
++
++/** 
++ * Converts an LDNS_RDF_TYPE_A rdata element to string format and adds it to the output buffer 
++ * \param[in] *rdf The rdata to convert
++ * \param[in] *output The buffer to add the data to
++ * \return LDNS_STATUS_OK on success, and error status on failure
++ */
++ldns_status ldns_rdf2buffer_str_a(ldns_buffer *output, const ldns_rdf *rdf);
++
++/** 
++ * Converts an LDNS_RDF_TYPE_AAAA rdata element to string format and adds it to the output buffer 
++ * \param[in] *rdf The rdata to convert
++ * \param[in] *output The buffer to add the data to
++ * \return LDNS_STATUS_OK on success, and error status on failure
++ */
++ldns_status ldns_rdf2buffer_str_aaaa(ldns_buffer *output, const ldns_rdf *rdf);
++
++/** 
++ * Converts an LDNS_RDF_TYPE_STR rdata element to string format and adds it to the output buffer 
++ * \param[in] *rdf The rdata to convert
++ * \param[in] *output The buffer to add the data to
++ * \return LDNS_STATUS_OK on success, and error status on failure
++ */
++ldns_status ldns_rdf2buffer_str_str(ldns_buffer *output, const ldns_rdf *rdf);
++
++/** 
++ * Converts an LDNS_RDF_TYPE_B64 rdata element to string format and adds it to the output buffer 
++ * \param[in] *rdf The rdata to convert
++ * \param[in] *output The buffer to add the data to
++ * \return LDNS_STATUS_OK on success, and error status on failure
++ */
++ldns_status ldns_rdf2buffer_str_b64(ldns_buffer *output, const ldns_rdf *rdf);
++
++/** 
++ * Converts an LDNS_RDF_TYPE_B32_EXT rdata element to string format and adds it to the output buffer 
++ * \param[in] *rdf The rdata to convert
++ * \param[in] *output The buffer to add the data to
++ * \return LDNS_STATUS_OK on success, and error status on failure
++ */
++ldns_status ldns_rdf2buffer_str_b32_ext(ldns_buffer *output, const ldns_rdf *rdf);
++
++/** 
++ * Converts an LDNS_RDF_TYPE_HEX rdata element to string format and adds it to the output buffer 
++ * \param[in] *rdf The rdata to convert
++ * \param[in] *output The buffer to add the data to
++ * \return LDNS_STATUS_OK on success, and error status on failure
++ */
++ldns_status ldns_rdf2buffer_str_hex(ldns_buffer *output, const ldns_rdf *rdf);
++
++/** 
++ * Converts an LDNS_RDF_TYPE_TYPE rdata element to string format and adds it to the output buffer 
++ * \param[in] *rdf The rdata to convert
++ * \param[in] *output The buffer to add the data to
++ * \return LDNS_STATUS_OK on success, and error status on failure
++ */
++ldns_status ldns_rdf2buffer_str_type(ldns_buffer *output, const ldns_rdf *rdf);
++
++/** 
++ * Converts an LDNS_RDF_TYPE_CLASS rdata element to string format and adds it to the output buffer 
++ * \param[in] *rdf The rdata to convert
++ * \param[in] *output The buffer to add the data to
++ * \return LDNS_STATUS_OK on success, and error status on failure
++ */
++ldns_status ldns_rdf2buffer_str_class(ldns_buffer *output, const ldns_rdf *rdf);
++
++/** 
++ * Converts an LDNS_RDF_TYPE_ALG rdata element to string format and adds it to the output buffer 
++ * \param[in] *rdf The rdata to convert
++ * \param[in] *output The buffer to add the data to
++ * \return LDNS_STATUS_OK on success, and error status on failure
++ */
++ldns_status ldns_rdf2buffer_str_alg(ldns_buffer *output, const ldns_rdf *rdf);
++
++/**
++ * Converts an ldns_rr_type value to its string representation,
++ * and places it in the given buffer
++ * \param[in] *output The buffer to add the data to
++ * \param[in] type the ldns_rr_type to convert
++ * \return LDNS_STATUS_OK on success, and error status on failure
++ */
++ldns_status ldns_rr_type2buffer_str(ldns_buffer *output,
++                                    const ldns_rr_type type);
++
++/**
++ * Converts an ldns_rr_type value to its string representation,
++ * and returns that string. For unknown types, the string
++ * "TYPE<id>" is returned. This function allocates data that must be
++ * freed by the caller
++ * \param[in] type the ldns_rr_type to convert
++ * \return a newly allocated string
++ */
++char *ldns_rr_type2str(const ldns_rr_type type);
++
++/**
++ * Converts an ldns_rr_class value to its string representation,
++ * and places it in the given buffer
++ * \param[in] *output The buffer to add the data to
++ * \param[in] klass the ldns_rr_class to convert
++ * \return LDNS_STATUS_OK on success, and error status on failure
++ */
++ldns_status ldns_rr_class2buffer_str(ldns_buffer *output,
++                                     const ldns_rr_class klass);
++
++/**
++ * Converts an ldns_rr_class value to its string representation,
++ * and returns that string. For unknown types, the string
++ * "CLASS<id>" is returned. This function allocates data that must be
++ * freed by the caller
++ * \param[in] klass the ldns_rr_class to convert
++ * \return a newly allocated string
++ */
++char *ldns_rr_class2str(const ldns_rr_class klass);
++
++
++/** 
++ * Converts an LDNS_RDF_TYPE_CERT rdata element to string format and adds it to the output buffer 
++ * \param[in] *rdf The rdata to convert
++ * \param[in] *output The buffer to add the data to
++ * \return LDNS_STATUS_OK on success, and error status on failure
++ */
++ldns_status ldns_rdf2buffer_str_cert_alg(ldns_buffer *output, const ldns_rdf *rdf);
++
++/** 
++ * Converts an LDNS_RDF_TYPE_LOC rdata element to string format and adds it to the output buffer 
++ * \param[in] *rdf The rdata to convert
++ * \param[in] *output The buffer to add the data to
++ * \return LDNS_STATUS_OK on success, and error status on failure
++ */
++ldns_status ldns_rdf2buffer_str_loc(ldns_buffer *output, const ldns_rdf *rdf);
++
++/** 
++ * Converts an LDNS_RDF_TYPE_UNKNOWN rdata element to string format and adds it to the output buffer 
++ * \param[in] *rdf The rdata to convert
++ * \param[in] *output The buffer to add the data to
++ * \return LDNS_STATUS_OK on success, and error status on failure
++ */
++ldns_status ldns_rdf2buffer_str_unknown(ldns_buffer *output, const ldns_rdf *rdf);
++
++/** 
++ * Converts an LDNS_RDF_TYPE_NSAP rdata element to string format and adds it to the output buffer 
++ * \param[in] *rdf The rdata to convert
++ * \param[in] *output The buffer to add the data to
++ * \return LDNS_STATUS_OK on success, and error status on failure
++ */
++ldns_status ldns_rdf2buffer_str_nsap(ldns_buffer *output, const ldns_rdf *rdf);
++
++/** 
++ * Converts an LDNS_RDF_TYPE_ATMA rdata element to string format and adds it to the output buffer 
++ * \param[in] *rdf The rdata to convert
++ * \param[in] *output The buffer to add the data to
++ * \return LDNS_STATUS_OK on success, and error status on failure
++ */
++ldns_status ldns_rdf2buffer_str_atma(ldns_buffer *output, const ldns_rdf *rdf);
++
++/** 
++ * Converts an LDNS_RDF_TYPE_WKS rdata element to string format and adds it to the output buffer 
++ * \param[in] *rdf The rdata to convert
++ * \param[in] *output The buffer to add the data to
++ * \return LDNS_STATUS_OK on success, and error status on failure
++ */
++ldns_status ldns_rdf2buffer_str_wks(ldns_buffer *output, const ldns_rdf *rdf);
++
++/** 
++ * Converts an LDNS_RDF_TYPE_NSEC rdata element to string format and adds it to the output buffer 
++ * \param[in] *rdf The rdata to convert
++ * \param[in] *output The buffer to add the data to
++ * \return LDNS_STATUS_OK on success, and error status on failure
++ */
++ldns_status ldns_rdf2buffer_str_nsec(ldns_buffer *output, const ldns_rdf *rdf);
++
++/** 
++ * Converts an LDNS_RDF_TYPE_PERIOD rdata element to string format and adds it to the output buffer 
++ * \param[in] *rdf The rdata to convert
++ * \param[in] *output The buffer to add the data to
++ * \return LDNS_STATUS_OK on success, and error status on failure
++ */
++ldns_status ldns_rdf2buffer_str_period(ldns_buffer *output, const ldns_rdf *rdf);
++
++/** 
++ * Converts an LDNS_RDF_TYPE_TSIGTIME rdata element to string format and adds it to the output buffer 
++ * \param[in] *rdf The rdata to convert
++ * \param[in] *output The buffer to add the data to
++ * \return LDNS_STATUS_OK on success, and error status on failure
++ */
++ldns_status ldns_rdf2buffer_str_tsigtime(ldns_buffer *output, const ldns_rdf *rdf);
++
++/** 
++ * Converts an LDNS_RDF_TYPE_APL rdata element to string format and adds it to the output buffer 
++ * \param[in] *rdf The rdata to convert
++ * \param[in] *output The buffer to add the data to
++ * \return LDNS_STATUS_OK on success, and error status on failure
++ */
++ldns_status ldns_rdf2buffer_str_apl(ldns_buffer *output, const ldns_rdf *rdf);
++
++/** 
++ * Converts an LDNS_RDF_TYPE_INT16_DATA rdata element to string format and adds it to the output buffer 
++ * \param[in] *rdf The rdata to convert
++ * \param[in] *output The buffer to add the data to
++ * \return LDNS_STATUS_OK on success, and error status on failure
++ */
++ldns_status ldns_rdf2buffer_str_int16_data(ldns_buffer *output, const ldns_rdf *rdf);
++
++/** 
++ * Converts an LDNS_RDF_TYPE_IPSECKEY rdata element to string format and adds it to the output buffer 
++ * \param[in] *rdf The rdata to convert
++ * \param[in] *output The buffer to add the data to
++ * \return LDNS_STATUS_OK on success, and error status on failure
++ */
++ldns_status ldns_rdf2buffer_str_ipseckey(ldns_buffer *output, const ldns_rdf *rdf);
++
++/**
++ * Converts the data in the rdata field to presentation
++ * format (as char *) and appends it to the given buffer
++ *
++ * \param[in] output pointer to the buffer to append the data to
++ * \param[in] rdf the pointer to the rdafa field containing the data
++ * \return status
++ */
++ldns_status ldns_rdf2buffer_str(ldns_buffer *output, const ldns_rdf *rdf);
++
++/**
++ * Converts the data in the resource record to presentation
++ * format (as char *) and appends it to the given buffer.
++ * The presentation format of DNSKEY record is annotated with comments giving
++ * the id, type and size of the key.
++ *
++ * \param[in] output pointer to the buffer to append the data to
++ * \param[in] rr the pointer to the rr field to convert
++ * \return status
++ */
++ldns_status ldns_rr2buffer_str(ldns_buffer *output, const ldns_rr *rr);
++
++/**
++ * Converts the data in the resource record to presentation
++ * format (as char *) and appends it to the given buffer.
++ * The presentation format is annotated with comments giving
++ * additional information on the record.
++ *
++ * \param[in] output pointer to the buffer to append the data to
++ * \param[in] fmt how to format the textual representation of the 
++ *            resource record.
++ * \param[in] rr the pointer to the rr field to convert
++ * \return status
++ */
++ldns_status ldns_rr2buffer_str_fmt(ldns_buffer *output, 
++		const ldns_output_format *fmt, const ldns_rr *rr);
++
++/**
++ * Converts the data in the DNS packet to presentation
++ * format (as char *) and appends it to the given buffer
++ *
++ * \param[in] output pointer to the buffer to append the data to
++ * \param[in] pkt the pointer to the packet to convert
++ * \return status
++ */
++ldns_status ldns_pkt2buffer_str(ldns_buffer *output, const ldns_pkt *pkt);
++
++/**
++ * Converts the data in the DNS packet to presentation
++ * format (as char *) and appends it to the given buffer
++ *
++ * \param[in] output pointer to the buffer to append the data to
++ * \param[in] fmt how to format the textual representation of the packet
++ * \param[in] pkt the pointer to the packet to convert
++ * \return status
++ */
++ldns_status ldns_pkt2buffer_str_fmt(ldns_buffer *output,
++		const ldns_output_format *fmt, const ldns_pkt *pkt);
++
++/** 
++ * Converts an LDNS_RDF_TYPE_NSEC3_SALT rdata element to string format and adds it to the output buffer 
++ * \param[in] *rdf The rdata to convert
++ * \param[in] *output The buffer to add the data to
++ * \return LDNS_STATUS_OK on success, and error status on failure
++ */
++ldns_status ldns_rdf2buffer_str_nsec3_salt(ldns_buffer *output, const ldns_rdf *rdf);
++
++
++/**
++ * Converts the data in the DNS packet to presentation
++ * format (as char *) and appends it to the given buffer
++ *
++ * \param[in] output pointer to the buffer to append the data to
++ * \param[in] k the pointer to the private key to convert
++ * \return status
++ */
++ldns_status ldns_key2buffer_str(ldns_buffer *output, const ldns_key *k);
++
++/**
++ * Converts an LDNS_RDF_TYPE_INT8 rdata element to string format and adds it to the output buffer
++ * \param[in] *rdf The rdata to convert
++ * \param[in] *output The buffer to add the data to
++ * \return LDNS_STATUS_OK on success, and error status on failure
++ */
++ldns_status ldns_rdf2buffer_str_int8(ldns_buffer *output, const ldns_rdf *rdf);
++
++/**
++ * Converts an LDNS_RDF_TYPE_INT16 rdata element to string format and adds it to the output buffer
++ * \param[in] *rdf The rdata to convert
++ * \param[in] *output The buffer to add the data to
++ * \return LDNS_STATUS_OK on success, and error status on failure
++ */
++ldns_status ldns_rdf2buffer_str_int16(ldns_buffer *output, const ldns_rdf *rdf);
++
++/**
++ * Converts an LDNS_RDF_TYPE_INT32 rdata element to string format and adds it to the output buffer
++ * \param[in] *rdf The rdata to convert
++ * \param[in] *output The buffer to add the data to
++ * \return LDNS_STATUS_OK on success, and error status on failure
++ */
++ldns_status ldns_rdf2buffer_str_int32(ldns_buffer *output, const ldns_rdf *rdf);
++
++/**
++ * Converts an LDNS_RDF_TYPE_TIME rdata element to string format and adds it to the output buffer
++ * \param[in] *rdf The rdata to convert
++ * \param[in] *output The buffer to add the data to
++ * \return LDNS_STATUS_OK on success, and error status on failure
++ */
++ldns_status ldns_rdf2buffer_str_time(ldns_buffer *output, const ldns_rdf *rdf);
++
++/** 
++ * Converts an LDNS_RDF_TYPE_ILNP64 rdata element to 4 hexadecimal numbers
++ * separated by colons and adds it to the output buffer 
++ * \param[in] *rdf The rdata to convert
++ * \param[in] *output The buffer to add the data to
++ * \return LDNS_STATUS_OK on success, and error status on failure
++ */
++ldns_status ldns_rdf2buffer_str_ilnp64(ldns_buffer *output,
++		const ldns_rdf *rdf);
++
++/** 
++ * Converts an LDNS_RDF_TYPE_EUI48 rdata element to 6 hexadecimal numbers
++ * separated by dashes and adds it to the output buffer 
++ * \param[in] *rdf The rdata to convert
++ * \param[in] *output The buffer to add the data to
++ * \return LDNS_STATUS_OK on success, and error status on failure
++ */
++ldns_status ldns_rdf2buffer_str_eui48(ldns_buffer *output,
++		const ldns_rdf *rdf);
++
++/** 
++ * Converts an LDNS_RDF_TYPE_EUI64 rdata element to 8 hexadecimal numbers
++ * separated by dashes and adds it to the output buffer 
++ * \param[in] *rdf The rdata to convert
++ * \param[in] *output The buffer to add the data to
++ * \return LDNS_STATUS_OK on success, and error status on failure
++ */
++ldns_status ldns_rdf2buffer_str_eui64(ldns_buffer *output,
++		const ldns_rdf *rdf);
++
++/** 
++ * Adds the LDNS_RDF_TYPE_TAG rdata to the output buffer,
++ * provided it contains only alphanumeric characters.
++ * \param[in] *rdf The rdata to convert
++ * \param[in] *output The buffer to add the data to
++ * \return LDNS_STATUS_OK on success, and error status on failure
++ */
++ldns_status ldns_rdf2buffer_str_tag(ldns_buffer *output,
++		const ldns_rdf *rdf);
++
++/** 
++ * Adds the LDNS_RDF_TYPE_LONG_STR rdata to the output buffer, in-between 
++ * double quotes and all non printable characters properly escaped.
++ * \param[in] *rdf The rdata to convert
++ * \param[in] *output The buffer to add the data to
++ * \return LDNS_STATUS_OK on success, and error status on failure
++ */
++ldns_status ldns_rdf2buffer_str_long_str(ldns_buffer *output,
++	       	const ldns_rdf *rdf);
++
++/** 
++ * Converts an LDNS_RDF_TYPE_HIP rdata element to presentation format for
++ * the algorithm, HIT and Public Key and adds it the output buffer .
++ * \param[in] *rdf The rdata to convert
++ * \param[in] *output The buffer to add the data to
++ * \return LDNS_STATUS_OK on success, and error status on failure
++ */
++ldns_status ldns_rdf2buffer_str_hip(ldns_buffer *output,
++		const ldns_rdf *rdf);
++
++/**
++ * Converts the data in the rdata field to presentation format and
++ * returns that as a char *.
++ * Remember to free it.
++ *
++ * \param[in] rdf The rdata field to convert
++ * \return null terminated char * data, or NULL on error
++ */
++char *ldns_rdf2str(const ldns_rdf *rdf);
++
++/**
++ * Converts the data in the resource record to presentation format and
++ * returns that as a char *.
++ * Remember to free it.
++ *
++ * \param[in] rr The rdata field to convert
++ * \return null terminated char * data, or NULL on error
++ */
++char *ldns_rr2str(const ldns_rr *rr);
++
++/**
++ * Converts the data in the resource record to presentation format and
++ * returns that as a char *.
++ * Remember to free it.
++ *
++ * \param[in] fmt how to format the resource record
++ * \param[in] rr The rdata field to convert
++ * \return null terminated char * data, or NULL on error
++ */
++char *ldns_rr2str_fmt(const ldns_output_format *fmt, const ldns_rr *rr);
++
++/**
++ * Converts the data in the DNS packet to presentation format and
++ * returns that as a char *.
++ * Remember to free it.
++ *
++ * \param[in] pkt The rdata field to convert
++ * \return null terminated char * data, or NULL on error
++ */
++char *ldns_pkt2str(const ldns_pkt *pkt);
++
++/**
++ * Converts the data in the DNS packet to presentation format and
++ * returns that as a char *.
++ * Remember to free it.
++ *
++ * \param[in] fmt how to format the packet
++ * \param[in] pkt The rdata field to convert
++ * \return null terminated char * data, or NULL on error
++ */
++char *ldns_pkt2str_fmt(const ldns_output_format *fmt, const ldns_pkt *pkt);
++
++/**
++ * Converts a private key to the test presentation fmt and
++ * returns that as a char *.
++ * Remember to free it.
++ *
++ * \param[in] k the key to convert to text
++ * \return null terminated char * data, or NULL on error
++ */
++char *ldns_key2str(const ldns_key *k);
++
++/**
++ * Converts a list of resource records to presentation format
++ * and returns that as a char *.
++ * Remember to free it.
++ *
++ * \param[in] rr_list the rr_list to convert to text
++ * \return null terminated char * data, or NULL on error
++ */
++char *ldns_rr_list2str(const ldns_rr_list *rr_list);
++
++/**
++ * Converts a list of resource records to presentation format
++ * and returns that as a char *.
++ * Remember to free it.
++ *
++ * \param[in] fmt how to format the list of resource records
++ * \param[in] rr_list the rr_list to convert to text
++ * \return null terminated char * data, or NULL on error
++ */
++char *ldns_rr_list2str_fmt(
++		const ldns_output_format *fmt, const ldns_rr_list *rr_list);
++
++/**
++ * Returns a copy of the data in the buffer as a null terminated
++ * char * string. The returned string must be freed by the caller.
++ * The buffer must be in write modus and may thus not have been flipped.
++ *
++ * \param[in] buffer buffer containing char * data
++ * \return null terminated char * data, or NULL on error
++ */
++char *ldns_buffer2str(ldns_buffer *buffer);
++
++/**
++ * Exports and returns the data in the buffer as a null terminated
++ * char * string. The returned string must be freed by the caller.
++ * The buffer must be in write modus and may thus not have been flipped.
++ * The buffer is fixed after this function returns.
++ *
++ * \param[in] buffer buffer containing char * data
++ * \return null terminated char * data, or NULL on error
++ */
++char *ldns_buffer_export2str(ldns_buffer *buffer);
++
++/**
++ * Prints the data in the rdata field to the given file stream
++ * (in presentation format)
++ *
++ * \param[in] output the file stream to print to
++ * \param[in] rdf the rdata field to print
++ * \return void
++ */
++void ldns_rdf_print(FILE *output, const ldns_rdf *rdf);
++
++/**
++ * Prints the data in the resource record to the given file stream
++ * (in presentation format)
++ *
++ * \param[in] output the file stream to print to
++ * \param[in] rr the resource record to print
++ * \return void
++ */
++void ldns_rr_print(FILE *output, const ldns_rr *rr);
++
++/**
++ * Prints the data in the resource record to the given file stream
++ * (in presentation format)
++ *
++ * \param[in] output the file stream to print to
++ * \param[in] fmt format of the textual representation
++ * \param[in] rr the resource record to print
++ * \return void
++ */
++void ldns_rr_print_fmt(FILE *output, 
++		const ldns_output_format *fmt, const ldns_rr *rr);
++
++/**
++ * Prints the data in the DNS packet to the given file stream
++ * (in presentation format)
++ *
++ * \param[in] output the file stream to print to
++ * \param[in] pkt the packet to print
++ * \return void
++ */
++void ldns_pkt_print(FILE *output, const ldns_pkt *pkt);
++
++/**
++ * Prints the data in the DNS packet to the given file stream
++ * (in presentation format)
++ *
++ * \param[in] output the file stream to print to
++ * \param[in] fmt format of the textual representation
++ * \param[in] pkt the packet to print
++ * \return void
++ */
++void ldns_pkt_print_fmt(FILE *output, 
++		const ldns_output_format *fmt, const ldns_pkt *pkt);
++
++/**
++ * Converts a rr_list to presentation format and appends it to
++ * the output buffer
++ * \param[in] output the buffer to append output to
++ * \param[in] list the ldns_rr_list to print
++ * \return ldns_status
++ */
++ldns_status ldns_rr_list2buffer_str(ldns_buffer *output, const ldns_rr_list *list);
++
++/**
++ * Converts a rr_list to presentation format and appends it to
++ * the output buffer
++ * \param[in] output the buffer to append output to
++ * \param[in] fmt format of the textual representation
++ * \param[in] list the ldns_rr_list to print
++ * \return ldns_status
++ */
++ldns_status ldns_rr_list2buffer_str_fmt(ldns_buffer *output, 
++		const ldns_output_format *fmt, const ldns_rr_list *list);
++
++/**
++ * Converts the header of a packet to presentation format and appends it to
++ * the output buffer
++ * \param[in] output the buffer to append output to
++ * \param[in] pkt the packet to convert the header of
++ * \return ldns_status
++ */
++ldns_status ldns_pktheader2buffer_str(ldns_buffer *output, const ldns_pkt *pkt);
++
++/**
++ * print a rr_list to output
++ * \param[in] output the fd to print to
++ * \param[in] list the rr_list to print
++ */
++void ldns_rr_list_print(FILE *output, const ldns_rr_list *list);
++
++/**
++ * print a rr_list to output
++ * \param[in] output the fd to print to
++ * \param[in] fmt format of the textual representation
++ * \param[in] list the rr_list to print
++ */
++void ldns_rr_list_print_fmt(FILE *output, 
++		const ldns_output_format *fmt, const ldns_rr_list *list);
++
++/**
++ * Print a resolver (in sofar that is possible) state
++ * to output.
++ * \param[in] output the fd to print to
++ * \param[in] r the resolver to print
++ */
++void ldns_resolver_print(FILE *output, const ldns_resolver *r);
++
++/**
++ * Print a resolver (in sofar that is possible) state
++ * to output.
++ * \param[in] output the fd to print to
++ * \param[in] fmt format of the textual representation
++ * \param[in] r the resolver to print
++ */
++void ldns_resolver_print_fmt(FILE *output, 
++		const ldns_output_format *fmt, const ldns_resolver *r);
++
++/**
++ * Print a zone structure * to output. Note the SOA record
++ * is included in this output
++ * \param[in] output the fd to print to
++ * \param[in] z the zone to print
++ */
++void ldns_zone_print(FILE *output, const ldns_zone *z);
++
++/**
++ * Print a zone structure * to output. Note the SOA record
++ * is included in this output
++ * \param[in] output the fd to print to
++ * \param[in] fmt format of the textual representation
++ * \param[in] z the zone to print
++ */
++void ldns_zone_print_fmt(FILE *output, 
++		const ldns_output_format *fmt, const ldns_zone *z);
++
++/**
++ * Print the ldns_rdf containing a dname to the buffer
++ * \param[in] output the buffer to print to
++ * \param[in] dname the dname to print
++ * \return ldns_status message if the printing succeeded
++ */
++ldns_status ldns_rdf2buffer_str_dname(ldns_buffer *output, const ldns_rdf *dname);
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* LDNS_HOST2STR_H */
+diff --git a/ldns/include/ldns/host2wire.h b/ldns/include/ldns/host2wire.h
+new file mode 100644
+index 0000000..94693cd
+--- /dev/null
++++ b/ldns/include/ldns/host2wire.h
+@@ -0,0 +1,197 @@
++/*
++ * host2wire.h - 2wire conversion routines
++ *
++ * a Net::DNS like library for C
++ *
++ * (c) NLnet Labs, 2005-2006
++ *
++ * See the file LICENSE for the license
++ */
++
++/**
++ * \file
++ *
++ * Contains all functions to translate the main structures to wire format
++ */
++
++#ifndef LDNS_HOST2WIRE_H
++#define LDNS_HOST2WIRE_H
++
++#include <ldns/common.h>
++#include <ldns/error.h>
++#include <ldns/rr.h>
++#include <ldns/rdata.h>
++#include <ldns/packet.h>
++#include <ldns/buffer.h>
++#include <ctype.h>
++
++#include "ldns/util.h"
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/**
++ * Copies the dname data to the buffer in wire format
++ * \param[out] *buffer buffer to append the result to
++ * \param[in] *name rdata dname to convert
++ * \return ldns_status
++ */
++ldns_status ldns_dname2buffer_wire(ldns_buffer *buffer, const ldns_rdf *name);
++
++/**
++ * Copies the dname data to the buffer in wire format
++ * \param[out] *buffer buffer to append the result to
++ * \param[in] *name rdata dname to convert
++ * \param[out] *compression_data data structure holding state for compression
++ * \return ldns_status
++ */
++ldns_status ldns_dname2buffer_wire_compress(ldns_buffer *buffer, const ldns_rdf *name, ldns_rbtree_t *compression_data);
++
++/**
++ * Copies the rdata data to the buffer in wire format
++ * \param[out] *output buffer to append the result to
++ * \param[in] *rdf rdata to convert
++ * \return ldns_status
++ */
++ldns_status ldns_rdf2buffer_wire(ldns_buffer *output, const ldns_rdf *rdf);
++
++/**
++ * Copies the rdata data to the buffer in wire format
++ * \param[out] *output buffer to append the result to
++ * \param[in] *rdf rdata to convert
++ * \param[out] *compression_data data structure holding state for compression
++ * \return ldns_status
++ */
++ldns_status ldns_rdf2buffer_wire_compress(ldns_buffer *output, const ldns_rdf *rdf, ldns_rbtree_t *compression_data);
++
++/**
++ * Copies the rdata data to the buffer in wire format
++ * If the rdata is a dname, the letters will be lowercased
++ * during the conversion
++ * \param[out] *output buffer to append the result to
++ * \param[in] *rdf rdata to convert
++ * \return ldns_status
++ */
++ldns_status ldns_rdf2buffer_wire_canonical(ldns_buffer *output,
++								   const ldns_rdf *rdf);
++
++/**
++ * Copies the rr data to the buffer in wire format
++ * \param[out] *output buffer to append the result to
++ * \param[in] *rr resource record to convert
++ * \param[in] section the section in the packet this rr is supposed to be in
++ *            (to determine whether to add rdata or not)
++ * \return ldns_status
++ */
++ldns_status ldns_rr2buffer_wire(ldns_buffer *output,
++						  const ldns_rr *rr,
++						  int section);
++
++/**
++ * Copies the rr data to the buffer in wire format while doing DNAME compression
++ * \param[out] *output buffer to append the result to
++ * \param[in] *rr resource record to convert
++ * \param[in] section the section in the packet this rr is supposed to be in
++ *            (to determine whether to add rdata or not)
++ * \param[out] *compression_data data structure holding state information for compression
++ * \return ldns_status
++ */
++ldns_status ldns_rr2buffer_wire_compress(ldns_buffer *output,
++						  const ldns_rr *rr,
++						  int section,
++						  ldns_rbtree_t *compression_data);
++
++/**
++ * Copies the rr data to the buffer in wire format, in canonical format
++ * according to RFC3597 (every dname in rdata fields of RR's mentioned in
++ * that RFC will be lowercased)
++ * \param[out] *output buffer to append the result to
++ * \param[in] *rr resource record to convert
++ * \param[in] section the section in the packet this rr is supposed to be in
++ *            (to determine whether to add rdata or not)
++ * \return ldns_status
++ */
++ldns_status ldns_rr2buffer_wire_canonical(ldns_buffer *output,
++								  const ldns_rr *rr,
++								  int section);
++
++
++/**
++ * Converts a rrsig to wireformat BUT EXCLUDE the rrsig rdata
++ * This is needed in DNSSEC verification
++ * \param[out] output buffer to append the result to
++ * \param[in] sigrr signature rr to operate on
++ * \return ldns_status
++ */
++ldns_status ldns_rrsig2buffer_wire(ldns_buffer *output, const ldns_rr *sigrr);
++
++/**
++ * Converts an rr's rdata to wireformat, while excluding
++ * the ownername and all the stuff before the rdata.
++ * This is needed in DNSSEC keytag calculation, the ds
++ * calcalution from the key and maybe elsewhere.
++ *
++ * \param[out] *output buffer where to put the result
++ * \param[in] *rr rr to operate on
++ * \return ldns_status
++ */
++ldns_status ldns_rr_rdata2buffer_wire(ldns_buffer *output, const ldns_rr *rr);
++
++/**
++ * Copies the packet data to the buffer in wire format
++ * \param[out] *output buffer to append the result to
++ * \param[in] *pkt packet to convert
++ * \return ldns_status
++ */
++ldns_status ldns_pkt2buffer_wire(ldns_buffer *output, const ldns_pkt *pkt);
++
++/**
++ * Copies the rr_list data to the buffer in wire format
++ * \param[out] *output buffer to append the result to
++ * \param[in] *rrlist rr_list to to convert
++ * \return ldns_status
++ */
++ldns_status ldns_rr_list2buffer_wire(ldns_buffer *output, const ldns_rr_list *rrlist);
++
++/**
++ * Allocates an array of uint8_t at dest, and puts the wireformat of the
++ * given rdf in that array. The result_size value contains the
++ * length of the array, if it succeeds, and 0 otherwise (in which case
++ * the function also returns NULL)
++ *
++ * \param[out] dest pointer to the array of bytes to be created
++ * \param[in] rdf the rdata field to convert
++ * \param[out] size the size of the converted result
++ */
++ldns_status ldns_rdf2wire(uint8_t **dest, const ldns_rdf *rdf, size_t *size);
++
++/**
++ * Allocates an array of uint8_t at dest, and puts the wireformat of the
++ * given rr in that array. The result_size value contains the
++ * length of the array, if it succeeds, and 0 otherwise (in which case
++ * the function also returns NULL)
++ *
++ * If the section argument is LDNS_SECTION_QUESTION, data like ttl and rdata
++ * are not put into the result
++ *
++ * \param[out] dest pointer to the array of bytes to be created
++ * \param[in] rr the rr to convert
++ * \param[in] section the rr section, determines how the rr is written.
++ * \param[out] size the size of the converted result
++ */
++ldns_status ldns_rr2wire(uint8_t **dest, const ldns_rr *rr, int section, size_t *size);
++
++/**
++ * Allocates an array of uint8_t at dest, and puts the wireformat of the
++ * given packet in that array. The result_size value contains the
++ * length of the array, if it succeeds, and 0 otherwise (in which case
++ * the function also returns NULL)
++ */
++ldns_status ldns_pkt2wire(uint8_t **dest, const ldns_pkt *p, size_t *size);
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* LDNS_HOST2WIRE_H */
+diff --git a/ldns/include/ldns/keys.h b/ldns/include/ldns/keys.h
+new file mode 100644
+index 0000000..d3b4873
+--- /dev/null
++++ b/ldns/include/ldns/keys.h
+@@ -0,0 +1,621 @@
++/*
++ * 
++ * keys.h
++ *
++ * priv key definitions
++ *
++ * a Net::DNS like library for C
++ *
++ * (c) NLnet Labs, 2005-2006
++ *
++ * See the file LICENSE for the license
++ */
++
++/**
++ * \file
++ *
++ * Addendum to \ref dnssec.h, this module contains key and algorithm definitions and functions.
++ */
++ 
++
++#ifndef LDNS_KEYS_H
++#define LDNS_KEYS_H
++
++#include <ldns/common.h>
++#if LDNS_BUILD_CONFIG_HAVE_SSL
++#include <openssl/ssl.h>
++#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */
++#include <ldns/util.h>
++#include <errno.h>
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++extern ldns_lookup_table ldns_signing_algorithms[];
++
++#define LDNS_KEY_ZONE_KEY 0x0100   /* rfc 4034 */
++#define LDNS_KEY_SEP_KEY 0x0001    /* rfc 4034 */
++#define LDNS_KEY_REVOKE_KEY 0x0080 /* rfc 5011 */
++
++/**
++ * Algorithms used in dns
++ */
++enum ldns_enum_algorithm
++{
++        LDNS_RSAMD5             = 1,   /* RFC 4034,4035 */
++        LDNS_DH                 = 2,
++        LDNS_DSA                = 3,
++        LDNS_ECC                = 4,
++        LDNS_RSASHA1            = 5,
++        LDNS_DSA_NSEC3          = 6,
++        LDNS_RSASHA1_NSEC3      = 7,
++        LDNS_RSASHA256          = 8,   /* RFC 5702 */
++        LDNS_RSASHA512          = 10,  /* RFC 5702 */
++        LDNS_ECC_GOST           = 12,  /* RFC 5933 */
++        LDNS_ECDSAP256SHA256    = 13,  /* RFC 6605 */
++        LDNS_ECDSAP384SHA384    = 14,  /* RFC 6605 */
++        LDNS_INDIRECT           = 252,
++        LDNS_PRIVATEDNS         = 253,
++        LDNS_PRIVATEOID         = 254
++};
++typedef enum ldns_enum_algorithm ldns_algorithm;
++
++/**
++ * Hashing algorithms used in the DS record
++ */
++enum ldns_enum_hash
++{
++        LDNS_SHA1               = 1,  /* RFC 4034 */
++        LDNS_SHA256             = 2,  /* RFC 4509 */
++        LDNS_HASH_GOST          = 3,  /* RFC 5933 */
++        LDNS_SHA384             = 4   /* RFC 6605 */
++};
++typedef enum ldns_enum_hash ldns_hash;
++
++/**
++ * Algorithms used in dns for signing
++ */
++enum ldns_enum_signing_algorithm
++{
++	LDNS_SIGN_RSAMD5	 = LDNS_RSAMD5,
++	LDNS_SIGN_RSASHA1	 = LDNS_RSASHA1,
++	LDNS_SIGN_DSA		 = LDNS_DSA,
++	LDNS_SIGN_RSASHA1_NSEC3  = LDNS_RSASHA1_NSEC3,
++	LDNS_SIGN_RSASHA256	 = LDNS_RSASHA256,
++	LDNS_SIGN_RSASHA512	 = LDNS_RSASHA512,
++	LDNS_SIGN_DSA_NSEC3	 = LDNS_DSA_NSEC3,
++	LDNS_SIGN_ECC_GOST       = LDNS_ECC_GOST,
++        LDNS_SIGN_ECDSAP256SHA256 = LDNS_ECDSAP256SHA256,
++        LDNS_SIGN_ECDSAP384SHA384 = LDNS_ECDSAP384SHA384,
++	LDNS_SIGN_HMACMD5	 = 157,	/* not official! This type is for TSIG, not DNSSEC */
++	LDNS_SIGN_HMACSHA1	 = 158,	/* not official! This type is for TSIG, not DNSSEC */
++	LDNS_SIGN_HMACSHA256 = 159  /* ditto */
++};
++typedef enum ldns_enum_signing_algorithm ldns_signing_algorithm;
++
++/**
++ * General key structure, can contain all types of keys that
++ * are used in DNSSEC. Mostly used to store private keys, since
++ * public keys can also be stored in a \ref ldns_rr with type
++ * \ref LDNS_RR_TYPE_DNSKEY.
++ *
++ * This structure can also store some variables that influence the
++ * signatures generated by signing with this key, for instance the
++ * inception date.
++ */
++struct ldns_struct_key {
++	ldns_signing_algorithm _alg;
++	/** Whether to use this key when signing */
++	bool _use;
++	/** Storage pointers for the types of keys supported */
++	/* TODO remove unions? */
++	struct {
++#if LDNS_BUILD_CONFIG_HAVE_SSL
++#ifndef S_SPLINT_S
++		/* The key can be an OpenSSL EVP Key
++		 */
++		EVP_PKEY *key;
++#endif
++#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */
++		/**
++		 * The key can be an HMAC key
++		 */
++		struct {
++			unsigned char *key;
++			size_t size;
++		} hmac;
++		/** the key structure can also just point to some external
++		 *  key data
++		 */
++		void *external_key;
++	} _key;
++	/** Depending on the key we can have extra data */
++	union {
++                /** Some values that influence generated signatures */
++		struct {
++			/** The TTL of the rrset that is currently signed */
++			uint32_t orig_ttl;
++			/** The inception date of signatures made with this key. */
++			uint32_t inception;
++			/** The expiration date of signatures made with this key. */
++			uint32_t expiration;
++			/** The keytag of this key. */
++			uint16_t keytag;
++			/** The dnssec key flags as specified in RFC4035, like ZSK and KSK */
++			uint16_t flags;
++		}  dnssec;
++	} _extra;
++	/** Owner name of the key */
++	ldns_rdf *_pubkey_owner;
++};
++typedef struct ldns_struct_key ldns_key;
++
++/**
++ * Same as rr_list, but now for keys 
++ */
++struct ldns_struct_key_list
++{
++	size_t _key_count;
++	ldns_key **_keys;
++};
++typedef struct ldns_struct_key_list ldns_key_list;
++
++
++/**
++ * Creates a new empty key list
++ * \return a new ldns_key_list structure pointer
++ */
++ldns_key_list *ldns_key_list_new(void);
++
++/** 
++ * Creates a new empty key structure
++ * \return a new ldns_key * structure
++ */
++ldns_key *ldns_key_new(void);
++
++/**
++ * Creates a new key based on the algorithm
++ *
++ * \param[in] a The algorithm to use
++ * \param[in] size the number of bytes for the keysize
++ * \return a new ldns_key structure with the key
++ */
++ldns_key *ldns_key_new_frm_algorithm(ldns_signing_algorithm a, uint16_t size);
++
++/**
++ * Creates a new priv key based on the 
++ * contents of the file pointed by fp.
++ *
++ * The file should be in Private-key-format v1.x.
++ *
++ * \param[out] k the new ldns_key structure
++ * \param[in] fp the file pointer to use
++ * \return an error or LDNS_STATUS_OK
++ */
++ldns_status ldns_key_new_frm_fp(ldns_key **k, FILE *fp);
++
++/**
++ * Creates a new private key based on the 
++ * contents of the file pointed by fp
++ *
++ * The file should be in Private-key-format v1.x.
++ *
++ * \param[out] k the new ldns_key structure
++ * \param[in] fp the file pointer to use
++ * \param[in] line_nr pointer to an integer containing the current line number (for debugging purposes)
++ * \return an error or LDNS_STATUS_OK
++ */
++ldns_status ldns_key_new_frm_fp_l(ldns_key **k, FILE *fp, int *line_nr);
++
++#if LDNS_BUILD_CONFIG_HAVE_SSL
++/**
++ * Read the key with the given id from the given engine and store it
++ * in the given ldns_key structure. The algorithm type is set
++ */
++ldns_status ldns_key_new_frm_engine(ldns_key **key, ENGINE *e, char *key_id, ldns_algorithm);
++
++
++/**
++ * frm_fp helper function. This function parses the
++ * remainder of the (RSA) priv. key file generated from bind9
++ * \param[in] fp the file to parse
++ * \return NULL on failure otherwise a RSA structure
++ */
++RSA *ldns_key_new_frm_fp_rsa(FILE *fp);
++#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */
++
++#if LDNS_BUILD_CONFIG_HAVE_SSL
++/**
++ * frm_fp helper function. This function parses the
++ * remainder of the (RSA) priv. key file generated from bind9
++ * \param[in] fp the file to parse
++ * \param[in] line_nr pointer to an integer containing the current line number (for debugging purposes)
++ * \return NULL on failure otherwise a RSA structure
++ */
++RSA *ldns_key_new_frm_fp_rsa_l(FILE *fp, int *line_nr);
++#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */
++
++#if LDNS_BUILD_CONFIG_HAVE_SSL
++/**
++ * frm_fp helper function. This function parses the
++ * remainder of the (DSA) priv. key file
++ * \param[in] fp the file to parse
++ * \return NULL on failure otherwise a RSA structure
++ */
++DSA *ldns_key_new_frm_fp_dsa(FILE *fp);
++#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */
++
++#if LDNS_BUILD_CONFIG_HAVE_SSL
++/**
++ * frm_fp helper function. This function parses the
++ * remainder of the (DSA) priv. key file
++ * \param[in] fp the file to parse
++ * \param[in] line_nr pointer to an integer containing the current line number (for debugging purposes)
++ * \return NULL on failure otherwise a RSA structure
++ */
++DSA *ldns_key_new_frm_fp_dsa_l(FILE *fp, int *line_nr);
++#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */
++
++#if LDNS_BUILD_CONFIG_HAVE_SSL
++/**
++ * frm_fp helper function. This function parses the
++ * remainder of the (HMAC-MD5) key file
++ * This function allocated a buffer that needs to be freed
++ * \param[in] fp the file to parse
++ * \param[out] hmac_size the number of bits in the resulting buffer
++ * \return NULL on failure otherwise a newly allocated char buffer
++ */
++unsigned char *ldns_key_new_frm_fp_hmac(FILE *fp, size_t *hmac_size);
++#endif
++
++#if LDNS_BUILD_CONFIG_HAVE_SSL
++/**
++ * frm_fp helper function. This function parses the
++ * remainder of the (HMAC-MD5) key file
++ * This function allocated a buffer that needs to be freed
++ * \param[in] fp the file to parse
++ * \param[in] line_nr pointer to an integer containing the current line number (for error reporting purposes)
++ * \param[out] hmac_size the number of bits in the resulting buffer
++ * \return NULL on failure otherwise a newly allocated char buffer
++ */
++unsigned char *ldns_key_new_frm_fp_hmac_l(FILE *fp, int *line_nr, size_t *hmac_size);
++#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */
++
++/* acces write functions */
++/**
++ * Set the key's algorithm
++ * \param[in] k the key
++ * \param[in] l the algorithm
++ */
++void ldns_key_set_algorithm(ldns_key *k, ldns_signing_algorithm l);
++#if LDNS_BUILD_CONFIG_HAVE_SSL
++/**
++ * Set the key's evp key
++ * \param[in] k the key
++ * \param[in] e the evp key
++ */
++void ldns_key_set_evp_key(ldns_key *k, EVP_PKEY *e);
++
++/**
++ * Set the key's rsa data.
++ * The rsa data should be freed by the user.
++ * \param[in] k the key
++ * \param[in] r the rsa data
++ */
++void ldns_key_set_rsa_key(ldns_key *k, RSA *r);
++
++/**
++ * Set the key's dsa data
++ * The dsa data should be freed by the user.
++ * \param[in] k the key
++ * \param[in] d the dsa data
++ */
++void ldns_key_set_dsa_key(ldns_key *k, DSA *d);
++
++/**
++ * Assign the key's rsa data
++ * The rsa data will be freed automatically when the key is freed.
++ * \param[in] k the key
++ * \param[in] r the rsa data
++ */
++void ldns_key_assign_rsa_key(ldns_key *k, RSA *r);
++
++/**
++ * Assign the key's dsa data
++ * The dsa data will be freed automatically when the key is freed.
++ * \param[in] k the key
++ * \param[in] d the dsa data
++ */
++void ldns_key_assign_dsa_key(ldns_key *k, DSA *d);
++
++/** 
++ * Get the PKEY id for GOST, loads GOST into openssl as a side effect.
++ * Only available if GOST is compiled into the library and openssl.
++ * \return the gost id for EVP_CTX creation.
++ */
++int ldns_key_EVP_load_gost_id(void);
++
++/** Release the engine reference held for the GOST engine. */
++void ldns_key_EVP_unload_gost(void);
++#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */
++
++/**
++ * Set the key's hmac data
++ * \param[in] k the key
++ * \param[in] hmac the raw key data
++ */
++void ldns_key_set_hmac_key(ldns_key *k, unsigned char *hmac);
++
++/**
++ * Set the key id data. This is used if the key points to
++ * some externally stored key data
++ * 
++ * Only the pointer is set, the data there is not copied,
++ * and must be freed manually; ldns_key_deep_free() does 
++ * *not* free this data
++ * \param[in] key the key
++ * \param[in] external_key key id data
++ */
++void ldns_key_set_external_key(ldns_key *key, void *external_key);
++
++/**
++ * Set the key's hmac size
++ * \param[in] k the key
++ * \param[in] hmac_size the size of the hmac data
++ */
++void ldns_key_set_hmac_size(ldns_key *k, size_t hmac_size);
++/**
++ * Set the key's original ttl
++ * \param[in] k the key
++ * \param[in] t the ttl
++ */
++void ldns_key_set_origttl(ldns_key *k, uint32_t t);
++/**
++ * Set the key's inception date (seconds after epoch)
++ * \param[in] k the key
++ * \param[in] i the inception
++ */
++void ldns_key_set_inception(ldns_key *k, uint32_t i);
++/**
++ * Set the key's expiration date (seconds after epoch)
++ * \param[in] k the key
++ * \param[in] e the expiration
++ */
++void ldns_key_set_expiration(ldns_key *k, uint32_t e);
++/**
++ * Set the key's pubkey owner
++ * \param[in] k the key
++ * \param[in] r the owner
++ */
++void ldns_key_set_pubkey_owner(ldns_key *k, ldns_rdf *r);
++/**
++ * Set the key's key tag
++ * \param[in] k the key
++ * \param[in] tag the keytag
++ */
++void ldns_key_set_keytag(ldns_key *k, uint16_t tag);
++/**
++ * Set the key's flags
++ * \param[in] k the key
++ * \param[in] flags the flags
++ */
++void ldns_key_set_flags(ldns_key *k, uint16_t flags);
++/**
++ * Set the keylist's key count to count
++ * \param[in] key the key
++ * \param[in] count the cuont
++ */
++void ldns_key_list_set_key_count(ldns_key_list *key, size_t count);
++
++/**     
++ * pushes a key to a keylist
++ * \param[in] key_list the key_list to push to 
++ * \param[in] key the key to push 
++ * \return false on error, otherwise true
++ */      
++bool ldns_key_list_push_key(ldns_key_list *key_list, ldns_key *key);
++
++/**
++ * returns the number of keys in the key list
++ * \param[in] key_list the key_list
++ * \return the numbers of keys in the list
++ */
++size_t ldns_key_list_key_count(const ldns_key_list *key_list);
++
++/**
++ * returns a pointer to the key in the list at the given position
++ * \param[in] key the key
++ * \param[in] nr the position in the list
++ * \return the key
++ */
++ldns_key *ldns_key_list_key(const ldns_key_list *key, size_t nr);
++
++#if LDNS_BUILD_CONFIG_HAVE_SSL
++/**
++ * returns the (openssl) RSA struct contained in the key
++ * \param[in] k the key to look in
++ * \return the RSA * structure in the key
++ */
++RSA *ldns_key_rsa_key(const ldns_key *k);
++/**
++ * returns the (openssl) EVP struct contained in the key
++ * \param[in] k the key to look in
++ * \return the RSA * structure in the key
++ */
++EVP_PKEY *ldns_key_evp_key(const ldns_key *k);
++#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */
++
++/**
++ * returns the (openssl) DSA struct contained in the key
++ */
++#if LDNS_BUILD_CONFIG_HAVE_SSL
++DSA *ldns_key_dsa_key(const ldns_key *k);
++#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */
++
++/**
++ * return the signing alg of the key
++ * \param[in] k the key
++ * \return the algorithm
++ */
++ldns_signing_algorithm ldns_key_algorithm(const ldns_key *k);
++/**
++ * set the use flag
++ * \param[in] k the key
++ * \param[in] v the boolean value to set the _use field to
++ */
++void ldns_key_set_use(ldns_key *k, bool v);
++/**
++ * return the use flag
++ * \param[in] k the key
++ * \return the boolean value of the _use field
++ */
++bool ldns_key_use(const ldns_key *k);
++/**
++ * return the hmac key data
++ * \param[in] k the key
++ * \return the hmac key data
++ */
++unsigned char *ldns_key_hmac_key(const ldns_key *k);
++/**
++ * return the key id key data
++ * \param[in] k the key
++ * \return the key id data
++ */
++void *ldns_key_external_key(const ldns_key *k);
++/**
++ * return the hmac key size
++ * \param[in] k the key
++ * \return the hmac key size
++ */
++size_t ldns_key_hmac_size(const ldns_key *k);
++/**
++ * return the original ttl of the key
++ * \param[in] k the key
++ * \return the original ttl
++ */
++uint32_t ldns_key_origttl(const ldns_key *k);
++/**
++ * return the key's inception date
++ * \param[in] k the key
++ * \return the inception date
++ */
++uint32_t ldns_key_inception(const ldns_key *k);
++/**
++ * return the key's expiration date
++ * \param[in] k the key
++ * \return the experiration date
++ */
++uint32_t ldns_key_expiration(const ldns_key *k);
++/**
++ * return the keytag
++ * \param[in] k the key
++ * \return the keytag
++ */
++uint16_t ldns_key_keytag(const ldns_key *k);
++/**
++ * return the public key's owner
++ * \param[in] k the key
++ * \return the owner
++ */
++ldns_rdf *ldns_key_pubkey_owner(const ldns_key *k);
++/**
++ * Set the 'use' flag for all keys in the list
++ * \param[in] keys The key_list
++ * \param[in] v The value to set the use flags to
++ */
++void
++ldns_key_list_set_use(ldns_key_list *keys, bool v);
++
++/**
++ * return the flag of the key
++ * \param[in] k the key
++ * \return the flag
++ */
++uint16_t ldns_key_flags(const ldns_key *k);
++
++/**     
++ * pops the last rr from a keylist
++ * \param[in] key_list the rr_list to pop from
++ * \return NULL if nothing to pop. Otherwise the popped RR
++ */
++ldns_key *ldns_key_list_pop_key(ldns_key_list *key_list);
++
++/** 
++ * converts a ldns_key to a public key rr
++ * If the key data exists at an external point, the corresponding
++ * rdata field must still be added with ldns_rr_rdf_push() to the
++ * result rr of this function
++ *
++ * \param[in] k the ldns_key to convert
++ * \return ldns_rr representation of the key
++ */
++ldns_rr *ldns_key2rr(const ldns_key *k);
++
++/**
++ * print a private key to the file ouput
++ * 
++ * \param[in] output the FILE descriptor where to print to
++ * \param[in] k the ldns_key to print
++ */
++void ldns_key_print(FILE *output, const ldns_key *k);
++
++/**
++ * frees a key structure, but not its internal data structures
++ *
++ * \param[in] key the key object to free
++ */
++void ldns_key_free(ldns_key *key);
++
++/**
++ * frees a key structure and all its internal data structures, except
++ * the data set by ldns_key_set_external_key()
++ *
++ * \param[in] key the key object to free
++ */
++void ldns_key_deep_free(ldns_key *key);
++
++/**
++ * Frees a key list structure
++ * \param[in] key_list the key list object to free
++ */
++void ldns_key_list_free(ldns_key_list *key_list);
++
++/**
++ * Instantiates a DNSKEY or DS RR from file.
++ * \param[in] filename the file to read the record from
++ * \return the corresponding RR, or NULL if the parsing failed
++ */
++ldns_rr * ldns_read_anchor_file(const char *filename);
++
++/**
++ * Returns the 'default base name' for key files;
++ * IE. K\<zone\>+\<alg\>+\<keytag\>
++ * (without the .key or .private)
++ * The memory for this is allocated by this function,
++ * and should be freed by the caller
++ * 
++ * \param[in] key the key to get the file name from
++ * \returns A string containing the file base name
++ */
++char *ldns_key_get_file_base_name(ldns_key *key);
++
++/**
++ * See if a key algorithm is supported
++ * \param[in] algo the signing algorithm number.
++ * \returns true if supported.
++ */
++int ldns_key_algo_supported(int algo);
++
++/**
++ * Get signing algorithm by name.  Comparison is case insensitive.
++ * \param[in] name string with the name.
++ * \returns 0 on parse failure or the algorithm number.
++ */
++ldns_signing_algorithm ldns_get_signing_algorithm_by_name(const char* name);
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* LDNS_KEYS_H */
+diff --git a/ldns/include/ldns/ldns.h b/ldns/include/ldns/ldns.h
+new file mode 100644
+index 0000000..60663ef
+--- /dev/null
++++ b/ldns/include/ldns/ldns.h
+@@ -0,0 +1,158 @@
++/*
++ * dns.h -- defines for the Domain Name System
++ *
++ * Copyright (c) 2005-2008, NLnet Labs. All rights reserved.
++ *
++ * See LICENSE for the license.
++ *
++ * This library was created by:
++ * Jelte Jansen, Erik Rozendaal and Miek Gieben
++ *
++ * A bunch of defines that are used in the DNS.
++ */
++
++
++/**
++\mainpage LDNS Documentation
++
++\section introduction Introduction
++
++The goal of ldns is to simplify DNS programming, it supports recent RFCs
++like the DNSSEC documents, and allow developers to easily create software
++conforming to current RFCs, and experimental software for current Internet
++drafts. A secondary benefit of using ldns is speed, because ldns is written
++in C, and although it is not optimized for performance, it should be a lot
++faster than Perl.
++
++The first main tool to use ldns is Drill, from which part of the library was
++derived. From version 1.0.0 on, drill is included in the ldns release
++and will not be distributed separately anymore. The library also includes some
++other examples and tools to show how it can be used. These can be found in the
++examples/ directory in the tarball.
++
++ldns depends on OpenSSL for it's cryptographic functions.
++Feature list
++
++  - Transparent IPv4 and IPv6 support (overridable if necessary),
++  - TSIG support,
++  - DNSSEC support; signing and verification,
++  - small size,
++  - online documentation as well as manual pages.
++
++If you want to send us patches please use the code from git.
++
++\section using_ldns Using ldns
++
++Almost all interaction between an application and ldns goes through the ldns
++data structures (\ref ldns_rr, \ref ldns_pkt, etc.). These are input or
++output to the functions of ldns. For example, \ref ldns_zone_new_frm_fp
++reads a zone from a \c FILE pointer, and returns an \ref ldns_zone
++structure.
++
++
++Let's use Drill as an example. Drill is a tool much like dig, whose most
++basic function is to send 1 query to a nameserver and print the response.
++
++To be able to do this, drill uses the resolver module of ldns, which acts as
++a stub resolver. The resolver module uses the net module to actually send
++the query that drill requested. It then uses the wire2host module to
++translate the response and place it in ldns' internal structures. These are
++passed back to drill, which then uses the host2str module to print the
++response in presentation format.
++
++\section gettingstarted Getting Started
++
++See the \ref design page for a very high level description of the design
++choices made for ldns. 
++
++For an overview of the functions and types ldns provides, you can check out
++the \ref ldns ldns header file descriptions.
++
++If you want to see some libdns action, you can read our tutorials:
++  - \ref tutorial1_mx
++  - \ref tutorial2_zone
++  - \ref tutorial3_signzone
++
++Or you can just use the menu above to browse through the API docs.
++
++<div style="visibility:hidden;">
++\image html LogoInGradientBar2-y100.png
++</div>
++*/
++
++/**
++ * \file ldns.h
++ *
++ * Including this file will include all ldns files, and define some lookup tables.
++ */
++
++#ifndef LDNS_DNS_H
++#define LDNS_DNS_H
++
++#include <stdio.h>
++#include <stdlib.h>
++
++#include <ldns/util.h>
++#include <ldns/buffer.h>
++#include <ldns/common.h>
++#include <ldns/dane.h>
++#include <ldns/dname.h>
++#include <ldns/dnssec.h>
++#include <ldns/dnssec_verify.h>
++#include <ldns/dnssec_sign.h>
++#include <ldns/duration.h>
++#include <ldns/error.h>
++#include <ldns/higher.h>
++#include <ldns/host2str.h>
++#include <ldns/host2wire.h>
++#include <ldns/net.h>
++#include <ldns/packet.h>
++#include <ldns/rdata.h>
++#include <ldns/resolver.h>
++#include <ldns/rr.h>
++#include <ldns/str2host.h>
++#include <ldns/tsig.h>
++#include <ldns/update.h>
++#include <ldns/wire2host.h>
++#include <ldns/rr_functions.h>
++#include <ldns/keys.h>
++#include <ldns/parse.h>
++#include <ldns/zone.h>
++#include <ldns/dnssec_zone.h>
++#include <ldns/radix.h>
++#include <ldns/rbtree.h>
++#include <ldns/sha1.h>
++#include <ldns/sha2.h>
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++#define LDNS_IP4ADDRLEN      (32/8)
++#define LDNS_IP6ADDRLEN      (128/8)
++#define LDNS_PORT	53
++#define LDNS_ROOT_LABEL_STR     "."
++#define LDNS_DEFAULT_TTL	3600
++
++/* lookup tables for standard DNS stuff  */
++
++/** Taken from RFC 2538, section 2.1.  */
++extern ldns_lookup_table ldns_certificate_types[];
++/** Taken from RFC 2535, section 7.  */
++extern ldns_lookup_table ldns_algorithms[];
++/** Taken from RFC 2538.  */
++extern ldns_lookup_table ldns_cert_algorithms[];
++/** rr types  */
++extern ldns_lookup_table ldns_rr_classes[];
++/** Response codes */
++extern ldns_lookup_table ldns_rcodes[];
++/** Operation codes */
++extern ldns_lookup_table ldns_opcodes[];
++/** EDNS flags */
++extern ldns_lookup_table ldns_edns_flags[];
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* LDNS_DNS_H */
+diff --git a/ldns/include/ldns/net.h b/ldns/include/ldns/net.h
+new file mode 100644
+index 0000000..692a9fb
+--- /dev/null
++++ b/ldns/include/ldns/net.h
+@@ -0,0 +1,207 @@
++/*
++ * net.h
++ *
++ * DNS Resolver definitions
++ *
++ * a Net::DNS like library for C
++ *
++ * (c) NLnet Labs, 2005-2006
++ *
++ * See the file LICENSE for the license
++ */
++
++#ifndef LDNS_NET_H
++#define LDNS_NET_H
++
++#include <ldns/ldns.h>
++#include <sys/socket.h>
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++#define LDNS_DEFAULT_TIMEOUT_SEC 5
++#define LDNS_DEFAULT_TIMEOUT_USEC 0
++
++/**
++ * \file
++ *
++ * Contains functions to send and receive packets over a network.
++ */
++
++/**
++ * Sends a buffer to an ip using udp and return the respons as a ldns_pkt
++ * \param[in] qbin the ldns_buffer to be send
++ * \param[in] to the ip addr to send to
++ * \param[in] tolen length of the ip addr
++ * \param[in] timeout the timeout value for the network
++ * \param[out] answersize size of the packet
++ * \param[out] result packet with the answer
++ * \return status
++ */
++ldns_status ldns_udp_send(uint8_t **result, ldns_buffer *qbin, const struct sockaddr_storage *to, socklen_t tolen, struct timeval timeout, size_t *answersize);
++
++/**
++ * Send an udp query and don't wait for an answer but return
++ * the socket
++ * \param[in] qbin the ldns_buffer to be send
++ * \param[in] to the ip addr to send to
++ * \param[in] tolen length of the ip addr
++ * \param[in] timeout *unused*, was the timeout value for the network
++ * \return the socket used
++ */
++int ldns_udp_bgsend(ldns_buffer *qbin, const struct sockaddr_storage *to, socklen_t tolen, struct timeval timeout);
++
++/**
++ * Send an tcp query and don't wait for an answer but return
++ * the socket
++ * \param[in] qbin the ldns_buffer to be send
++ * \param[in] to the ip addr to send to
++ * \param[in] tolen length of the ip addr
++ * \param[in] timeout the timeout value for the connect attempt
++ * \return the socket used
++ */
++int ldns_tcp_bgsend(ldns_buffer *qbin, const struct sockaddr_storage *to, socklen_t tolen, struct timeval timeout);
++
++/**
++ * Sends a buffer to an ip using tcp and return the respons as a ldns_pkt
++ * \param[in] qbin the ldns_buffer to be send
++ * \param[in] qbin the ldns_buffer to be send
++ * \param[in] to the ip addr to send to
++ * \param[in] tolen length of the ip addr
++ * \param[in] timeout the timeout value for the network
++ * \param[out] answersize size of the packet
++ * \param[out] result packet with the answer
++ * \return status
++ */
++ldns_status ldns_tcp_send(uint8_t **result, ldns_buffer *qbin, const struct sockaddr_storage *to, socklen_t tolen, struct timeval timeout, size_t *answersize);
++
++/**
++ * Sends ptk to the nameserver at the resolver object. Returns the data
++ * as a ldns_pkt
++ * 
++ * \param[out] pkt packet received from the nameserver
++ * \param[in] r the resolver to use 
++ * \param[in] query_pkt the query to send
++ * \return status
++ */
++ldns_status ldns_send(ldns_pkt **pkt, ldns_resolver *r, const ldns_pkt *query_pkt);
++
++/**
++ * Sends and ldns_buffer (presumably containing a packet to the nameserver at the resolver object. Returns the data
++ * as a ldns_pkt
++ * 
++ * \param[out] pkt packet received from the nameserver
++ * \param[in] r the resolver to use 
++ * \param[in] qb the buffer to send
++ * \param[in] tsig_mac the tsig MAC to authenticate the response with (NULL to do no TSIG authentication)
++ * \return status
++ */
++ldns_status ldns_send_buffer(ldns_pkt **pkt, ldns_resolver *r, ldns_buffer *qb, ldns_rdf *tsig_mac);
++
++/**
++ * Create a tcp socket to the specified address
++ * \param[in] to ip and family
++ * \param[in] tolen length of to
++ * \param[in] timeout timeout for the connect attempt
++ * \return a socket descriptor
++ */
++int ldns_tcp_connect(const struct sockaddr_storage *to, socklen_t tolen, struct timeval timeout);
++
++/**
++ * Create a udp socket to the specified address
++ * \param[in] to ip and family
++ * \param[in] timeout *unused*, was timeout for the socket
++ * \return a socket descriptor
++ */
++int ldns_udp_connect(const struct sockaddr_storage *to, struct timeval timeout);
++
++/**
++ * send a query via tcp to a server. Don't want for the answer
++ *
++ * \param[in] qbin the buffer to send
++ * \param[in] sockfd the socket to use
++ * \param[in] to which ip to send it
++ * \param[in] tolen socketlen
++ * \return number of bytes sent
++ */
++ssize_t ldns_tcp_send_query(ldns_buffer *qbin, int sockfd, const struct sockaddr_storage *to, socklen_t tolen);
++
++/**
++ * send a query via udp to a server. Don;t want for the answer
++ *
++ * \param[in] qbin the buffer to send
++ * \param[in] sockfd the socket to use
++ * \param[in] to which ip to send it
++ * \param[in] tolen socketlen
++ * \return number of bytes sent
++ */
++ssize_t ldns_udp_send_query(ldns_buffer *qbin, int sockfd, const struct sockaddr_storage *to, socklen_t tolen);
++
++/**
++ * Gives back a raw packet from the wire and reads the header data from the given
++ * socket. Allocates the data (of size size) itself, so don't forget to free
++ *
++ * \param[in] sockfd the socket to read from
++ * \param[out] size the number of bytes that are read
++ * \param[in] timeout the time allowed between packets.
++ * \return the data read
++ */
++uint8_t *ldns_tcp_read_wire_timeout(int sockfd, size_t *size, struct timeval timeout);
++
++/**
++ * This routine may block. Use ldns_tcp_read_wire_timeout, it checks timeouts.
++ * Gives back a raw packet from the wire and reads the header data from the given
++ * socket. Allocates the data (of size size) itself, so don't forget to free
++ *
++ * \param[in] sockfd the socket to read from
++ * \param[out] size the number of bytes that are read
++ * \return the data read
++ */
++uint8_t *ldns_tcp_read_wire(int sockfd, size_t *size);
++
++/**
++ * Gives back a raw packet from the wire and reads the header data from the given
++ * socket. Allocates the data (of size size) itself, so don't forget to free
++ *
++ * \param[in] sockfd the socket to read from
++ * \param[in] fr the address of the client (if applicable)
++ * \param[in] *frlen the lenght of the client's addr (if applicable)
++ * \param[out] size the number of bytes that are read
++ * \return the data read
++ */
++uint8_t *ldns_udp_read_wire(int sockfd, size_t *size, struct sockaddr_storage *fr, socklen_t *frlen);
++
++/**
++ * returns the native sockaddr representation from the rdf.
++ * \param[in] rd the ldns_rdf to operate on
++ * \param[in] port what port to use. 0 means; use default (53)
++ * \param[out] size what is the size of the sockaddr_storage
++ * \return struct sockaddr* the address in the format so other
++ * functions can use it (sendto)
++ */
++struct sockaddr_storage * ldns_rdf2native_sockaddr_storage(const ldns_rdf *rd, uint16_t port, size_t *size);
++
++/**
++ * returns an rdf with the sockaddr info. works for ip4 and ip6
++ * \param[in] sock the struct sockaddr_storage to convert
++ * \param[in] port what port was used. When NULL this is not set
++ * \return ldns_rdf* wth the address
++ */
++ldns_rdf * ldns_sockaddr_storage2rdf(struct sockaddr_storage *sock, uint16_t *port);
++
++/**
++ * Prepares the resolver for an axfr query
++ * The query is sent and the answers can be read with ldns_axfr_next
++ * \param[in] resolver the resolver to use
++ * \param[in] domain the domain to exfr
++ * \param[in] c the class to use
++ * \return ldns_status the status of the transfer
++ */
++ldns_status ldns_axfr_start(ldns_resolver *resolver, ldns_rdf *domain, ldns_rr_class c);
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif  /* LDNS_NET_H */
+diff --git a/ldns/include/ldns/packet.h b/ldns/include/ldns/packet.h
+new file mode 100644
+index 0000000..e66aa34
+--- /dev/null
++++ b/ldns/include/ldns/packet.h
+@@ -0,0 +1,891 @@
++/*
++ * packet.h
++ *
++ * DNS packet definitions
++ *
++ * a Net::DNS like library for C
++ *
++ * (c) NLnet Labs, 2005-2006
++ *
++ * See the file LICENSE for the license
++ */
++
++/**
++ * \file
++ *
++ * Contains the definition of ldns_pkt and its parts, as well
++ * as functions to manipulate those.
++ */
++
++
++#ifndef LDNS_PACKET_H
++#define LDNS_PACKET_H
++
++#define LDNS_MAX_PACKETLEN         65535
++
++/* allow flags to be given to mk_query */
++#define LDNS_QR		1       /* QueRy - query flag */
++#define LDNS_AA		2       /* Authoritative Answer - server flag */
++#define LDNS_TC		4       /* TrunCated - server flag */
++#define LDNS_RD		8       /* Recursion Desired - query flag */
++#define LDNS_CD		16      /* Checking Disabled - query flag */
++#define LDNS_RA		32      /* Recursion Available - server flag */
++#define LDNS_AD		64      /* Authenticated Data - server flag */
++
++#include <ldns/error.h>
++#include <ldns/common.h>
++#include <ldns/rr.h>
++#include <sys/time.h>
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/* opcodes for pkt's */
++enum ldns_enum_pkt_opcode {
++	LDNS_PACKET_QUERY = 0,
++	LDNS_PACKET_IQUERY = 1,
++	LDNS_PACKET_STATUS = 2, /* there is no 3?? DNS is weird */
++	LDNS_PACKET_NOTIFY = 4,
++	LDNS_PACKET_UPDATE = 5
++};
++typedef enum ldns_enum_pkt_opcode ldns_pkt_opcode;
++
++/* rcodes for pkts */
++enum ldns_enum_pkt_rcode {
++	LDNS_RCODE_NOERROR = 0,
++	LDNS_RCODE_FORMERR = 1,
++	LDNS_RCODE_SERVFAIL = 2,
++	LDNS_RCODE_NXDOMAIN = 3,
++	LDNS_RCODE_NOTIMPL = 4,
++	LDNS_RCODE_REFUSED = 5,
++	LDNS_RCODE_YXDOMAIN = 6,
++	LDNS_RCODE_YXRRSET = 7,
++	LDNS_RCODE_NXRRSET = 8,
++	LDNS_RCODE_NOTAUTH = 9,
++	LDNS_RCODE_NOTZONE = 10
++};
++typedef enum ldns_enum_pkt_rcode ldns_pkt_rcode;
++
++/**
++ *  Header of a dns packet
++ *
++ * Contains the information about the packet itself, as specified in RFC1035
++<pre>
++4.1.1. Header section format
++
++The header contains the following fields:
++
++                                    1  1  1  1  1  1
++      0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
++    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
++    |                      ID                       |
++    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
++    |QR|   Opcode  |AA|TC|RD|RA|   Z    |   RCODE   |
++    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
++    |                    QDCOUNT                    |
++    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
++    |                    ANCOUNT                    |
++    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
++    |                    NSCOUNT                    |
++    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
++    |                    ARCOUNT                    |
++    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
++
++where:
++
++ID              A 16 bit identifier assigned by the program that
++                generates any kind of query.  This identifier is copied
++                the corresponding reply and can be used by the requester
++                to match up replies to outstanding queries.
++
++QR              A one bit field that specifies whether this message is a
++                query (0), or a response (1).
++
++OPCODE          A four bit field that specifies kind of query in this
++                message.  This value is set by the originator of a query
++                and copied into the response.  The values are:
++
++                0               a standard query (QUERY)
++
++                1               an inverse query (IQUERY)
++
++                2               a server status request (STATUS)
++
++                3-15            reserved for future use
++
++AA              Authoritative Answer - this bit is valid in responses,
++                and specifies that the responding name server is an
++                authority for the domain name in question section.
++
++                Note that the contents of the answer section may have
++                multiple owner names because of aliases.  The AA bit
++
++                corresponds to the name which matches the query name, or
++                the first owner name in the answer section.
++
++TC              TrunCation - specifies that this message was truncated
++                due to length greater than that permitted on the
++                transmission channel.
++
++RD              Recursion Desired - this bit may be set in a query and
++                is copied into the response.  If RD is set, it directs
++                the name server to pursue the query recursively.
++                Recursive query support is optional.
++
++RA              Recursion Available - this be is set or cleared in a
++                response, and denotes whether recursive query support is
++                available in the name server.
++
++Z               Reserved for future use.  Must be zero in all queries
++                and responses.
++
++RCODE           Response code - this 4 bit field is set as part of
++                responses.  The values have the following
++                interpretation:
++
++                0               No error condition
++
++                1               Format error - The name server was
++                                unable to interpret the query.
++
++                2               Server failure - The name server was
++                                unable to process this query due to a
++                                problem with the name server.
++
++                3               Name Error - Meaningful only for
++                                responses from an authoritative name
++                                server, this code signifies that the
++                                domain name referenced in the query does
++                                not exist.
++
++                4               Not Implemented - The name server does
++                                not support the requested kind of query.
++
++                5               Refused - The name server refuses to
++                                perform the specified operation for
++                                policy reasons.  For example, a name
++                                server may not wish to provide the
++                                information to the particular requester,
++                                or a name server may not wish to perform
++                                a particular operation (e.g., zone
++
++                                transfer) for particular data.
++
++                6-15            Reserved for future use.
++
++QDCOUNT         an unsigned 16 bit integer specifying the number of
++                entries in the question section.
++
++ANCOUNT         an unsigned 16 bit integer specifying the number of
++                resource records in the answer section.
++
++NSCOUNT         an unsigned 16 bit integer specifying the number of name
++                server resource records in the authority records
++                section.
++
++ARCOUNT         an unsigned 16 bit integer specifying the number of
++                resource records in the additional records section.
++
++</pre>
++ */
++struct ldns_struct_hdr
++{
++	/**  Id of a packet */
++	uint16_t _id;
++	/**  Query bit (0=query, 1=answer) */
++	bool _qr;
++	/**  Authoritative answer */
++	bool _aa;
++	/**  Packet truncated */
++	bool _tc;
++	/**  Recursion desired */
++	bool _rd;
++	/**  Checking disabled */
++	bool _cd;
++	/**  Recursion available */
++	bool _ra;
++	/**  Authentic data */
++	bool _ad;
++	/**  Query type */
++	ldns_pkt_opcode _opcode;	 /* XXX 8 bits? */
++	/**  Response code */
++	uint8_t _rcode;
++	/**  question sec */
++	uint16_t _qdcount;
++	/**  answer sec */
++	uint16_t _ancount;
++	/**  auth sec */
++	uint16_t _nscount;
++	/**  add sec */
++	uint16_t _arcount;
++};
++typedef struct ldns_struct_hdr ldns_hdr;
++
++/**
++ * DNS packet
++ *
++ * This structure contains a complete DNS packet (either a query or an answer)
++ *
++ * It is the complete representation of what you actually send to a
++ * nameserver, and what it sends back (assuming you are the client here).
++ */
++struct ldns_struct_pkt
++{
++	/** Header section */
++	ldns_hdr *_header;
++	/* extra items needed in a packet */
++	/** The size of the wire format of the packet in octets */
++	ldns_rdf *_answerfrom;
++        /** Timestamp of the time the packet was sent or created */
++	struct timeval timestamp;
++	/** The duration of the query this packet is an answer to */
++	uint32_t _querytime;
++	/** The size of the wire format of the packet in octets */
++	size_t _size;
++	/** Optional tsig rr */
++	ldns_rr *_tsig_rr;
++	/** EDNS0 available buffer size, see RFC2671 */
++	uint16_t _edns_udp_size;
++	/** EDNS0 Extended rcode */
++	uint8_t _edns_extended_rcode;
++	/** EDNS Version */
++	uint8_t _edns_version;
++        /* OPT pseudo-RR presence flag */
++        uint8_t _edns_present;
++	/** Reserved EDNS data bits */
++	uint16_t _edns_z;
++	/** Arbitrary EDNS rdata */
++	ldns_rdf *_edns_data;
++	/**  Question section */
++	ldns_rr_list	*_question;
++	/**  Answer section */
++	ldns_rr_list	*_answer;
++	/**  Authority section */
++	ldns_rr_list	*_authority;
++	/**  Additional section */
++	ldns_rr_list	*_additional;
++};
++typedef struct ldns_struct_pkt ldns_pkt;
++
++/**
++ * The sections of a packet
++ */
++enum ldns_enum_pkt_section {
++	LDNS_SECTION_QUESTION = 0,
++	LDNS_SECTION_ANSWER = 1,
++	LDNS_SECTION_AUTHORITY = 2,
++	LDNS_SECTION_ADDITIONAL = 3,
++	/** bogus section, if not interested */
++	LDNS_SECTION_ANY = 4,
++	/** used to get all non-question rrs from a packet */
++	LDNS_SECTION_ANY_NOQUESTION = 5
++};
++typedef enum ldns_enum_pkt_section ldns_pkt_section;	
++
++/**
++ * The different types of packets
++ */
++enum ldns_enum_pkt_type {
++	LDNS_PACKET_QUESTION,
++	LDNS_PACKET_REFERRAL,
++	LDNS_PACKET_ANSWER,
++	LDNS_PACKET_NXDOMAIN,
++	LDNS_PACKET_NODATA,
++	LDNS_PACKET_UNKNOWN
++};
++typedef enum ldns_enum_pkt_type ldns_pkt_type;
++
++/* prototypes */
++
++/* read */
++
++/**
++ * Read the packet id
++ * \param[in] p the packet
++ * \return the packet id
++ */
++uint16_t ldns_pkt_id(const ldns_pkt *p);
++/**
++ * Read the packet's qr bit
++ * \param[in] p the packet
++ * \return value of the bit
++ */
++bool ldns_pkt_qr(const ldns_pkt *p);
++/**
++ * Read the packet's aa bit
++ * \param[in] p the packet
++ * \return value of the bit
++ */
++bool ldns_pkt_aa(const ldns_pkt *p);
++/**
++ * Read the packet's tc bit
++ * \param[in] p the packet
++ * \return value of the bit
++ */
++bool ldns_pkt_tc(const ldns_pkt *p);
++/**
++ * Read the packet's rd bit
++ * \param[in] p the packet
++ * \return value of the bit
++ */
++bool ldns_pkt_rd(const ldns_pkt *p);
++/**
++ * Read the packet's cd bit
++ * \param[in] p the packet
++ * \return value of the bit
++ */
++bool ldns_pkt_cd(const ldns_pkt *p);
++/**
++ * Read the packet's ra bit
++ * \param[in] p the packet
++ * \return value of the bit
++ */
++bool ldns_pkt_ra(const ldns_pkt *p);
++/**
++ * Read the packet's ad bit
++ * \param[in] p the packet
++ * \return value of the bit
++ */
++bool ldns_pkt_ad(const ldns_pkt *p);
++/**
++ * Read the packet's code
++ * \param[in] p the packet
++ * \return the opcode
++ */
++ldns_pkt_opcode ldns_pkt_get_opcode(const ldns_pkt *p);
++/**
++ * Return the packet's respons code
++ * \param[in] p the packet
++ * \return the respons code
++ */
++ldns_pkt_rcode ldns_pkt_get_rcode(const ldns_pkt *p);
++/**
++ * Return the packet's qd count 
++ * \param[in] p the packet
++ * \return the qd count
++ */
++uint16_t ldns_pkt_qdcount(const ldns_pkt *p);
++/**
++ * Return the packet's an count
++ * \param[in] p the packet
++ * \return the an count
++ */
++uint16_t ldns_pkt_ancount(const ldns_pkt *p);
++/**
++ * Return the packet's ns count
++ * \param[in] p the packet
++ * \return the ns count
++ */
++uint16_t ldns_pkt_nscount(const ldns_pkt *p);
++/**
++ * Return the packet's ar count
++ * \param[in] p the packet
++ * \return the ar count
++ */
++uint16_t ldns_pkt_arcount(const ldns_pkt *p);
++
++/** 
++ * Return the packet's answerfrom
++ * \param[in] p packet
++ * \return the name of the server
++ */
++ldns_rdf *ldns_pkt_answerfrom(const ldns_pkt *p);
++
++/**
++ * Return the packet's timestamp
++ * \param[in] p the packet
++ * \return the timestamp
++ */
++struct timeval ldns_pkt_timestamp(const ldns_pkt *p);
++/**
++ * Return the packet's querytime
++ * \param[in] p the packet
++ * \return the querytime
++ */
++uint32_t ldns_pkt_querytime(const ldns_pkt *p);
++
++/**
++ * Return the packet's size in bytes
++ * \param[in] p the packet
++ * \return the size
++ */
++size_t ldns_pkt_size(const ldns_pkt *p);
++
++/**
++ * Return the number of RRs in the given section.
++ * Returns the sum of all RRs when LDNS_SECTION_ANY is given.
++ * Returns the sum of all non-question RRs when LDNS_SECTION_ANY_NOQUESTION
++ * is given.
++ * \param[in] p the packet
++ * \param[in] s the section
++ * \return the number of RRs in the given section
++ */
++uint16_t ldns_pkt_section_count(const ldns_pkt *p, ldns_pkt_section s);
++
++/**
++ * Return the packet's tsig pseudo rr's
++ * \param[in] p the packet
++ * \return the tsig rr
++ */
++ldns_rr *ldns_pkt_tsig(const ldns_pkt *p);
++
++/**
++ * Return the packet's question section
++ * \param[in] p the packet
++ * \return the section
++ */
++ldns_rr_list *ldns_pkt_question(const ldns_pkt *p);
++/**
++ * Return the packet's answer section
++ * \param[in] p the packet
++ * \return the section
++ */
++ldns_rr_list *ldns_pkt_answer(const ldns_pkt *p);
++/**
++ * Return the packet's authority section
++ * \param[in] p the packet
++ * \return the section
++ */
++ldns_rr_list *ldns_pkt_authority(const ldns_pkt *p);
++/**
++ * Return the packet's additional section
++ * \param[in] p the packet
++ * \return the section
++ */
++ldns_rr_list *ldns_pkt_additional(const ldns_pkt *p);
++/**
++ * Return the packet's question, answer, authority and additional sections
++ * concatenated, in a new rr_list clone.
++ * \param[in] p the packet
++ * \return the rrs
++ */
++ldns_rr_list *ldns_pkt_all(const ldns_pkt *p);
++/**
++ * Return the packet's answer, authority and additional sections concatenated, 
++ * in a new rr_list clone.  Like ldns_pkt_all but without the questions.
++ * \param[in] p the packet
++ * \return the rrs except the question rrs
++ */
++ldns_rr_list *ldns_pkt_all_noquestion(const ldns_pkt *p);
++
++/**
++ * return all the rr_list's in the packet. Clone the lists, instead
++ * of returning pointers. 
++ * \param[in] p the packet to look in
++ * \param[in] s what section(s) to return
++ * \return ldns_rr_list with the rr's or NULL if none were found
++ */
++ldns_rr_list *ldns_pkt_get_section_clone(const ldns_pkt *p, ldns_pkt_section s);
++
++/**
++ * return all the rr with a specific name from a packet. Optionally
++ * specify from which section in the packet
++ * \param[in] p the packet
++ * \param[in] r the name
++ * \param[in] s the packet's section
++ * \return a list with the rr's or NULL if none were found
++ */
++ldns_rr_list *ldns_pkt_rr_list_by_name(ldns_pkt *p, ldns_rdf *r, ldns_pkt_section s);
++/**
++ * return all the rr with a specific type from a packet. Optionally
++ * specify from which section in the packet
++ * \param[in] p the packet
++ * \param[in] t the type
++ * \param[in] s the packet's section
++ * \return a list with the rr's or NULL if none were found
++ */
++ldns_rr_list *ldns_pkt_rr_list_by_type(const ldns_pkt *p, ldns_rr_type t, ldns_pkt_section s);
++/**
++ * return all the rr with a specific type and type from a packet. Optionally
++ * specify from which section in the packet
++ * \param[in] packet the packet
++ * \param[in] ownername the name
++ * \param[in] type the type
++ * \param[in] sec the packet's section
++ * \return a list with the rr's or NULL if none were found
++ */
++ldns_rr_list *ldns_pkt_rr_list_by_name_and_type(const ldns_pkt *packet, const ldns_rdf *ownername, ldns_rr_type type, ldns_pkt_section sec);
++
++
++/**
++ * check to see if an rr exist in the packet
++ * \param[in] pkt the packet to examine
++ * \param[in] sec in which section to look
++ * \param[in] rr the rr to look for
++ */
++bool ldns_pkt_rr(ldns_pkt *pkt, ldns_pkt_section sec, ldns_rr *rr);
++
++
++/**
++ * sets the flags in a packet.
++ * \param[in] pkt the packet to operate on
++ * \param[in] flags ORed values: LDNS_QR| LDNS_AR for instance
++ * \return true on success otherwise false
++ */
++bool ldns_pkt_set_flags(ldns_pkt *pkt, uint16_t flags);
++
++/**
++ * Set the packet's id
++ * \param[in] p the packet
++ * \param[in] id the id to set
++ */
++void ldns_pkt_set_id(ldns_pkt *p, uint16_t id);
++/**
++ * Set the packet's id to a random value
++ * \param[in] p the packet
++ */
++void ldns_pkt_set_random_id(ldns_pkt *p);
++/**
++ * Set the packet's qr bit
++ * \param[in] p the packet
++ * \param[in] b the value to set (boolean)
++ */
++void ldns_pkt_set_qr(ldns_pkt *p, bool b);
++/**
++ * Set the packet's aa bit
++ * \param[in] p the packet
++ * \param[in] b the value to set (boolean)
++ */
++void ldns_pkt_set_aa(ldns_pkt *p, bool b);
++/**
++ * Set the packet's tc bit
++ * \param[in] p the packet
++ * \param[in] b the value to set (boolean)
++ */
++void ldns_pkt_set_tc(ldns_pkt *p, bool b);
++/**
++ * Set the packet's rd bit
++ * \param[in] p the packet
++ * \param[in] b the value to set (boolean)
++ */
++void ldns_pkt_set_rd(ldns_pkt *p, bool b);
++/**
++ * Set the packet's cd bit
++ * \param[in] p the packet
++ * \param[in] b the value to set (boolean)
++ */
++void ldns_pkt_set_cd(ldns_pkt *p, bool b);
++/**
++ * Set the packet's ra bit
++ * \param[in] p the packet
++ * \param[in] b the value to set (boolean)
++ */
++void ldns_pkt_set_ra(ldns_pkt *p, bool b);
++/**
++ * Set the packet's ad bit
++ * \param[in] p the packet
++ * \param[in] b the value to set (boolean)
++ */
++void ldns_pkt_set_ad(ldns_pkt *p, bool b);
++
++/**
++ * Set the packet's opcode
++ * \param[in] p the packet
++ * \param[in] c the opcode
++ */
++void ldns_pkt_set_opcode(ldns_pkt *p, ldns_pkt_opcode c);
++/**
++ * Set the packet's respons code
++ * \param[in] p the packet
++ * \param[in] c the rcode
++ */
++void ldns_pkt_set_rcode(ldns_pkt *p, uint8_t c);
++/**
++ * Set the packet's qd count
++ * \param[in] p the packet
++ * \param[in] c the count
++ */
++void ldns_pkt_set_qdcount(ldns_pkt *p, uint16_t c);
++/**
++ * Set the packet's an count
++ * \param[in] p the packet
++ * \param[in] c the count
++ */
++void ldns_pkt_set_ancount(ldns_pkt *p, uint16_t c);
++/**
++ * Set the packet's ns count
++ * \param[in] p the packet
++ * \param[in] c the count
++ */
++void ldns_pkt_set_nscount(ldns_pkt *p, uint16_t c);
++/**
++ * Set the packet's arcount
++ * \param[in] p the packet
++ * \param[in] c the count
++ */
++void ldns_pkt_set_arcount(ldns_pkt *p, uint16_t c);
++/**
++ * Set the packet's answering server
++ * \param[in] p the packet
++ * \param[in] r the address
++ */
++void ldns_pkt_set_answerfrom(ldns_pkt *p, ldns_rdf *r);
++/**
++ * Set the packet's query time
++ * \param[in] p the packet
++ * \param[in] t the querytime in msec
++ */
++void ldns_pkt_set_querytime(ldns_pkt *p, uint32_t t);
++/**
++ * Set the packet's size
++ * \param[in] p the packet
++ * \param[in] s the size
++ */
++void ldns_pkt_set_size(ldns_pkt *p, size_t s);
++
++/**
++ * Set the packet's timestamp
++ * \param[in] p the packet
++ * \param[in] timeval the timestamp
++ */
++void ldns_pkt_set_timestamp(ldns_pkt *p, struct timeval timeval);
++/**
++ * Set a packet's section count to x
++ * \param[in] p the packet
++ * \param[in] s the section
++ * \param[in] x the section count
++ */
++void ldns_pkt_set_section_count(ldns_pkt *p, ldns_pkt_section s, uint16_t x);
++/**
++ * Set the packet's tsig rr
++ * \param[in] p the packet
++ * \param[in] t the tsig rr
++ */
++void ldns_pkt_set_tsig(ldns_pkt *p, ldns_rr *t);
++
++/**
++ * looks inside the packet to determine
++ * what kind of packet it is, AUTH, NXDOMAIN, REFERRAL, etc.
++ * \param[in] p the packet to examine
++ * \return the type of packet
++ */
++ldns_pkt_type ldns_pkt_reply_type(ldns_pkt *p);
++
++/**
++ * return the packet's edns udp size
++ * \param[in] packet the packet
++ * \return the size
++ */
++uint16_t ldns_pkt_edns_udp_size(const ldns_pkt *packet);
++/**
++ * return the packet's edns extended rcode
++ * \param[in] packet the packet
++ * \return the rcode
++ */
++uint8_t ldns_pkt_edns_extended_rcode(const ldns_pkt *packet);
++/**
++ * return the packet's edns version
++ * \param[in] packet the packet
++ * \return the version
++ */
++uint8_t ldns_pkt_edns_version(const ldns_pkt *packet);
++/**
++ * return the packet's edns z value
++ * \param[in] packet the packet
++ * \return the z value
++ */
++uint16_t ldns_pkt_edns_z(const ldns_pkt *packet);
++/**
++ * return the packet's edns data
++ * \param[in] packet the packet
++ * \return the data
++ */
++ldns_rdf *ldns_pkt_edns_data(const ldns_pkt *packet);
++
++/**
++ * return the packet's edns do bit
++ * \param[in] packet the packet
++ * \return the bit's value
++ */
++bool ldns_pkt_edns_do(const ldns_pkt *packet);
++/**
++ * Set the packet's edns do bit
++ * \param[in] packet the packet
++ * \param[in] value the bit's new value
++ */
++void ldns_pkt_set_edns_do(ldns_pkt *packet, bool value);
++
++/**
++ * returns true if this packet needs and EDNS rr to be sent.
++ * At the moment the only reason is an expected packet
++ * size larger than 512 bytes, but for instance dnssec would
++ * be a good reason too.
++ *
++ * \param[in] packet the packet to check
++ * \return true if packet needs edns rr
++ */
++bool ldns_pkt_edns(const ldns_pkt *packet);
++
++/**
++ * Set the packet's edns udp size
++ * \param[in] packet the packet
++ * \param[in] s the size
++ */
++void ldns_pkt_set_edns_udp_size(ldns_pkt *packet, uint16_t s);
++/**
++ * Set the packet's edns extended rcode
++ * \param[in] packet the packet
++ * \param[in] c the code
++ */
++void ldns_pkt_set_edns_extended_rcode(ldns_pkt *packet, uint8_t c);
++/**
++ * Set the packet's edns version
++ * \param[in] packet the packet
++ * \param[in] v the version
++ */
++void ldns_pkt_set_edns_version(ldns_pkt *packet, uint8_t v);
++/**
++ * Set the packet's edns z value
++ * \param[in] packet the packet
++ * \param[in] z the value
++ */
++void ldns_pkt_set_edns_z(ldns_pkt *packet, uint16_t z);
++/**
++ * Set the packet's edns data
++ * \param[in] packet the packet
++ * \param[in] data the data
++ */
++void ldns_pkt_set_edns_data(ldns_pkt *packet, ldns_rdf *data);
++
++/**
++ * allocates and initializes a ldns_pkt structure.
++ * \return pointer to the new packet
++ */
++ldns_pkt *ldns_pkt_new(void);
++
++/**
++ * frees the packet structure and all data that it contains.
++ * \param[in] packet The packet structure to free
++ * \return void
++ */
++void ldns_pkt_free(ldns_pkt *packet);
++
++/**
++ * creates a query packet for the given name, type, class.
++ * \param[out] p the packet to be returned
++ * \param[in] rr_name the name to query for (as string)
++ * \param[in] rr_type the type to query for
++ * \param[in] rr_class the class to query for
++ * \param[in] flags packet flags
++ * \return LDNS_STATUS_OK or a ldns_status mesg with the error
++ */
++ldns_status ldns_pkt_query_new_frm_str(ldns_pkt **p, const char *rr_name, ldns_rr_type rr_type, ldns_rr_class rr_class , uint16_t flags);
++
++/**
++ * creates an IXFR request packet for the given name, class.
++ * adds the SOA record to the authority section.
++ * \param[out] p the packet to be returned
++ * \param[in] rr_name the name to query for (as string)
++ * \param[in] rr_class the class to query for
++ * \param[in] flags packet flags
++ * \param[in] soa soa record to be added to the authority section
++ * \return LDNS_STATUS_OK or a ldns_status mesg with the error
++ */
++ldns_status ldns_pkt_ixfr_request_new_frm_str(ldns_pkt **p, const char *rr_name, ldns_rr_class rr_class, uint16_t flags, ldns_rr* soa);
++
++/**
++ * creates a packet with a query in it for the given name, type and class.
++ * \param[in] rr_name the name to query for
++ * \param[in] rr_type the type to query for
++ * \param[in] rr_class the class to query for
++ * \param[in] flags packet flags
++ * \return ldns_pkt* a pointer to the new pkt
++ */
++ldns_pkt *ldns_pkt_query_new(ldns_rdf *rr_name, ldns_rr_type rr_type, ldns_rr_class rr_class, uint16_t flags);
++
++/**
++ * creates an IXFR request packet for the given name, type and class.
++ * adds the SOA record to the authority section.
++ * \param[in] rr_name the name to query for
++ * \param[in] rr_class the class to query for
++ * \param[in] flags packet flags
++ * \param[in] soa soa record to be added to the authority section
++ * \return ldns_pkt* a pointer to the new pkt
++ */
++ldns_pkt *ldns_pkt_ixfr_request_new(ldns_rdf *rr_name, ldns_rr_class rr_class, uint16_t flags, ldns_rr* soa);
++
++/**
++ * clones the given packet, creating a fully allocated copy
++ *
++ * \param[in] pkt the packet to clone
++ * \return ldns_pkt* pointer to the new packet
++ */
++ldns_pkt *ldns_pkt_clone(const ldns_pkt *pkt);
++
++/**
++ * directly set the additional section
++ * \param[in] p packet to operate on
++ * \param[in] rr rrlist to set
++ */
++void ldns_pkt_set_additional(ldns_pkt *p, ldns_rr_list *rr);
++
++/**
++ * directly set the answer section
++ * \param[in] p packet to operate on
++ * \param[in] rr rrlist to set
++ */
++void ldns_pkt_set_answer(ldns_pkt *p, ldns_rr_list *rr);
++
++/**
++ * directly set the question section
++ * \param[in] p packet to operate on
++ * \param[in] rr rrlist to set
++ */
++void ldns_pkt_set_question(ldns_pkt *p, ldns_rr_list *rr);
++
++/**
++ * directly set the auhority section
++ * \param[in] p packet to operate on
++ * \param[in] rr rrlist to set
++ */
++void ldns_pkt_set_authority(ldns_pkt *p, ldns_rr_list *rr);
++
++/**
++ * push an rr on a packet
++ * \param[in] packet packet to operate on
++ * \param[in] section where to put it
++ * \param[in] rr rr to push
++ * \return a boolean which is true when the rr was added
++ */
++bool ldns_pkt_push_rr(ldns_pkt *packet, ldns_pkt_section section, ldns_rr *rr);
++
++/**
++ * push an rr on a packet, provided the RR is not there.
++ * \param[in] pkt packet to operate on
++ * \param[in] sec where to put it
++ * \param[in] rr rr to push
++ * \return a boolean which is true when the rr was added
++ */
++bool ldns_pkt_safe_push_rr(ldns_pkt *pkt, ldns_pkt_section sec, ldns_rr *rr);
++
++/**
++ * push a rr_list on a packet
++ * \param[in] packet packet to operate on
++ * \param[in] section where to put it
++ * \param[in] list the rr_list to push
++ * \return a boolean which is true when the rr was added
++ */
++bool ldns_pkt_push_rr_list(ldns_pkt *packet, ldns_pkt_section section, ldns_rr_list *list);
++
++/**
++ * push an rr_list to a packet, provided the RRs are not already there.
++ * \param[in] pkt packet to operate on
++ * \param[in] sec where to put it
++ * \param[in] list the rr_list to push
++ * \return a boolean which is true when the rr was added
++ */
++bool ldns_pkt_safe_push_rr_list(ldns_pkt *pkt, ldns_pkt_section sec, ldns_rr_list *list);
++
++/**
++ * check if a packet is empty
++ * \param[in] p packet
++ * \return true: empty, false: not empty
++ */
++bool ldns_pkt_empty(ldns_pkt *p);
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif  /* LDNS_PACKET_H */
+diff --git a/ldns/include/ldns/parse.h b/ldns/include/ldns/parse.h
+new file mode 100644
+index 0000000..0e9034c
+--- /dev/null
++++ b/ldns/include/ldns/parse.h
+@@ -0,0 +1,167 @@
++/*
++ * parse.h 
++ *
++ * a Net::DNS like library for C
++ * LibDNS Team @ NLnet Labs
++ * (c) NLnet Labs, 2005-2006
++ * See the file LICENSE for the license
++ */
++
++#ifndef LDNS_PARSE_H
++#define LDNS_PARSE_H
++
++#include <ldns/common.h>
++#include <ldns/buffer.h>
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++#define LDNS_PARSE_SKIP_SPACE		"\f\n\r\v"
++#define LDNS_PARSE_NORMAL		" \f\n\r\t\v"
++#define LDNS_PARSE_NO_NL		" \t"
++#define LDNS_MAX_LINELEN		10230
++#define LDNS_MAX_KEYWORDLEN		32
++
++
++/**
++ * \file
++ *
++ * Contains some low-level parsing functions, mostly used in the _frm_str
++ * family of functions.
++ */
++ 
++/**
++ * different type of directives in zone files
++ * We now deal with $TTL, $ORIGIN and $INCLUDE.
++ * The latter is not implemented in ldns (yet)
++ */
++enum ldns_enum_directive
++{
++	LDNS_DIR_TTL,
++	LDNS_DIR_ORIGIN,
++	LDNS_DIR_INCLUDE
++};
++typedef enum ldns_enum_directive ldns_directive;
++
++/** 
++ * returns a token/char from the stream F.
++ * This function deals with ( and ) in the stream,
++ * and ignores them when encountered
++ * \param[in] *f the file to read from
++ * \param[out] *token the read token is put here
++ * \param[in] *delim chars at which the parsing should stop
++ * \param[in] *limit how much to read. If 0 the builtin maximum is used
++ * \return 0 on error of EOF of the stream F.  Otherwise return the length of what is read
++ */
++ssize_t ldns_fget_token(FILE *f, char *token, const char *delim, size_t limit);
++
++/** 
++ * returns a token/char from the stream F.
++ * This function deals with ( and ) in the stream,
++ * and ignores when it finds them.
++ * \param[in] *f the file to read from
++ * \param[out] *token the token is put here
++ * \param[in] *delim chars at which the parsing should stop
++ * \param[in] *limit how much to read. If 0 use builtin maximum
++ * \param[in] line_nr pointer to an integer containing the current line number (for debugging purposes)
++ * \return 0 on error of EOF of F otherwise return the length of what is read
++ */
++ssize_t ldns_fget_token_l(FILE *f, char *token, const char *delim, size_t limit, int *line_nr);
++
++/**
++ * returns a token/char from the buffer b.
++ * This function deals with ( and ) in the buffer,
++ * and ignores when it finds them.
++ * \param[in] *b the buffer to read from
++ * \param[out] *token the token is put here
++ * \param[in] *delim chars at which the parsing should stop
++ * \param[in] *limit how much to read. If 0 the builtin maximum is used
++ * \returns 0 on error of EOF of b. Otherwise return the length of what is read
++ */
++ssize_t ldns_bget_token(ldns_buffer *b, char *token, const char *delim, size_t limit);
++
++/*
++ * searches for keyword and delim in a file. Gives everything back
++ * after the keyword + k_del until we hit d_del
++ * \param[in] f file pointer to read from
++ * \param[in] keyword keyword to look for
++ * \param[in] k_del keyword delimeter 
++ * \param[out] data the data found 
++ * \param[in] d_del the data delimeter
++ * \param[in] data_limit maximum size the the data buffer
++ * \return the number of character read
++ */
++ssize_t ldns_fget_keyword_data(FILE *f, const char *keyword, const char *k_del, char *data, const char *d_del, size_t data_limit);
++
++/*
++ * searches for keyword and delim. Gives everything back
++ * after the keyword + k_del until we hit d_del
++ * \param[in] f file pointer to read from
++ * \param[in] keyword keyword to look for
++ * \param[in] k_del keyword delimeter 
++ * \param[out] data the data found 
++ * \param[in] d_del the data delimeter
++ * \param[in] data_limit maximum size the the data buffer
++ * \param[in] line_nr pointer to an integer containing the current line number (for
++debugging purposes)
++ * \return the number of character read
++ */
++ssize_t ldns_fget_keyword_data_l(FILE *f, const char *keyword, const char *k_del, char *data, const char *d_del, size_t data_limit, int *line_nr);
++
++/*
++ * searches for keyword and delim in a buffer. Gives everything back
++ * after the keyword + k_del until we hit d_del
++ * \param[in] b buffer pointer to read from
++ * \param[in] keyword keyword to look for
++ * \param[in] k_del keyword delimeter 
++ * \param[out] data the data found 
++ * \param[in] d_del the data delimeter
++ * \param[in] data_limit maximum size the the data buffer
++ * \return the number of character read
++ */
++ssize_t ldns_bget_keyword_data(ldns_buffer *b, const char *keyword, const char *k_del, char *data, const char *d_del, size_t data_limit);
++
++/**
++ * returns the next character from a buffer. Advances the position pointer with 1.
++ * When end of buffer is reached returns EOF. This is the buffer's equivalent
++ * for getc().
++ * \param[in] *buffer buffer to read from
++ * \return EOF on failure otherwise return the character
++ */
++int ldns_bgetc(ldns_buffer *buffer);
++
++/**
++ * skips all of the characters in the given string in the buffer, moving
++ * the position to the first character that is not in *s.
++ * \param[in] *buffer buffer to use
++ * \param[in] *s characters to skip
++ * \return void
++ */
++void ldns_bskipcs(ldns_buffer *buffer, const char *s);
++
++/**
++ * skips all of the characters in the given string in the fp, moving
++ * the position to the first character that is not in *s.
++ * \param[in] *fp file to use
++ * \param[in] *s characters to skip
++ * \return void
++ */
++void ldns_fskipcs(FILE *fp, const char *s);
++
++
++/**
++ * skips all of the characters in the given string in the fp, moving
++ * the position to the first character that is not in *s.
++ * \param[in] *fp file to use
++ * \param[in] *s characters to skip
++ * \param[in] line_nr pointer to an integer containing the current line number (for debugging purposes)
++ * \return void
++ */
++void ldns_fskipcs_l(FILE *fp, const char *s, int *line_nr);
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* LDNS_PARSE_H */
+diff --git a/ldns/include/ldns/radix.h b/ldns/include/ldns/radix.h
+new file mode 100644
+index 0000000..1885959
+--- /dev/null
++++ b/ldns/include/ldns/radix.h
+@@ -0,0 +1,240 @@
++/*
++ * radix.h -- generic radix tree
++ *
++ * Copyright (c) 2012, NLnet Labs. All rights reserved.
++ *
++ * This software is open source.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright notice,
++ * this list of conditions and the following disclaimer in the documentation
++ * and/or other materials provided with the distribution.
++ *
++ * Neither the name of the NLNET LABS nor the names of its contributors may
++ * be used to endorse or promote products derived from this software without
++ * specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
++ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
++ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
++ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
++ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ *
++ */
++
++/**
++ * \file
++ * Radix tree. Implementation taken from NSD 4, adjusted for use in ldns.
++ *
++ */
++
++#ifndef LDNS_RADIX_H_
++#define	LDNS_RADIX_H_
++
++#include <ldns/error.h>
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++typedef uint16_t radix_strlen_t;
++typedef struct ldns_radix_array_t ldns_radix_array_t;
++typedef struct ldns_radix_node_t ldns_radix_node_t;
++typedef struct ldns_radix_t ldns_radix_t;
++
++/** Radix node select edge array */
++struct ldns_radix_array_t {
++	/** Additional string after the selection byte for this edge. */
++	uint8_t* str;
++	/** Length of additional string for this edge. */
++	radix_strlen_t len;
++	/** Node that deals with byte+str. */
++	ldns_radix_node_t* edge;
++};
++
++/** A node in a radix tree */
++struct ldns_radix_node_t {
++	/** Key corresponding to this node. */
++	uint8_t* key;
++	/** Key length corresponding to this node. */
++	radix_strlen_t klen;
++	/** Data corresponding to this node. */
++	void* data;
++	/** Parent node. */
++	ldns_radix_node_t* parent;
++	/** Index in the the parent node select edge array. */
++	uint8_t parent_index;
++	/** Length of the array. */
++	uint16_t len;
++	/** Offset of the array. */
++	uint16_t offset;
++	/** Capacity of the array. */
++	uint16_t capacity;
++	/** Select edge array. */
++	ldns_radix_array_t* array;
++};
++
++/** An entire radix tree */
++struct ldns_radix_t {
++	/** Root. */
++	ldns_radix_node_t* root;
++	/** Number of nodes in tree. */
++	size_t count;
++};
++
++/**
++ * Create a new radix tree.
++ * @return: new radix tree.
++ *
++ */
++ldns_radix_t* ldns_radix_create(void);
++
++/**
++ * Initialize radix tree.
++ * @param tree: uninitialized radix tree.
++ *
++ */
++void ldns_radix_init(ldns_radix_t* tree);
++
++/**
++ * Free the radix tree.
++ * @param tree: radix tree.
++ *
++ */
++void ldns_radix_free(ldns_radix_t* tree);
++
++/**
++ * Insert data into the tree.
++ * @param tree: tree to insert to.
++ * @param key:  key.
++ * @param len:  length of key.
++ * @param data: data.
++ * @return: status.
++ *
++ */
++ldns_status ldns_radix_insert(ldns_radix_t* tree, uint8_t* key,
++	radix_strlen_t len, void* data);
++
++/**
++ * Delete data from the tree.
++ * @param tree: tree to insert to.
++ * @param key:  key.
++ * @param len:  length of key.
++ * @return: unlinked data or NULL if not present.
++ *
++ */
++void* ldns_radix_delete(ldns_radix_t* tree, uint8_t* key, radix_strlen_t len);
++
++/**
++ * Search data in the tree.
++ * @param tree: tree to insert to.
++ * @param key:  key.
++ * @param len:  length of key.
++ * @return: the radix node or NULL if not found.
++ *
++ */
++ldns_radix_node_t* ldns_radix_search(ldns_radix_t* tree, uint8_t* key,
++	radix_strlen_t len);
++
++/**
++ * Search data in the tree, and if not found, find the closest smaller
++ * element in the tree.
++ * @param tree: tree to insert to.
++ * @param key:  key.
++ * @param len:  length of key.
++ * @param result: the radix node with the exact or closest match. NULL if
++ *                the key is smaller than the smallest key in the tree.
++ * @return 1 if exact match, 0 otherwise.
++ *
++ */
++int ldns_radix_find_less_equal(ldns_radix_t* tree, uint8_t* key,
++	radix_strlen_t len, ldns_radix_node_t** result);
++
++/**
++ * Get the first element in the tree.
++ * @param tree: tree.
++ * @return: the radix node with the first element.
++ *
++ */
++ldns_radix_node_t* ldns_radix_first(ldns_radix_t* tree);
++
++/**
++ * Get the last element in the tree.
++ * @param tree: tree.
++ * @return: the radix node with the last element.
++ *
++ */
++ldns_radix_node_t* ldns_radix_last(ldns_radix_t* tree);
++
++/**
++ * Next element.
++ * @param node: node.
++ * @return: node with next element.
++ *
++ */
++ldns_radix_node_t* ldns_radix_next(ldns_radix_node_t* node);
++
++/**
++ * Previous element.
++ * @param node: node.
++ * @return: node with previous element.
++ *
++ */
++ldns_radix_node_t* ldns_radix_prev(ldns_radix_node_t* node);
++
++/**
++ * Split radix tree intwo.
++ * @param tree1: one tree.
++ * @param num: number of elements to split off.
++ * @param tree2: another tree.
++ * @return: status.
++ *
++ */
++ldns_status ldns_radix_split(ldns_radix_t* tree1, size_t num,
++	ldns_radix_t** tree2);
++
++/**
++ * Join two radix trees.
++ * @param tree1: one tree.
++ * @param tree2: another tree.
++ * @return: status.
++ *
++ */
++ldns_status ldns_radix_join(ldns_radix_t* tree1, ldns_radix_t* tree2);
++
++/**
++ * Call function for all nodes in the tree, such that leaf nodes are
++ * called before parent nodes.
++ * @param node: start node.
++ * @param func: function.
++ * @param arg: user argument.
++ *
++ */
++void ldns_radix_traverse_postorder(ldns_radix_node_t* node,
++        void (*func)(ldns_radix_node_t*, void*), void* arg);
++
++/**
++ * Print radix tree (for debugging purposes).
++ * @param fd: file descriptor.
++ * @param tree: tree.
++ *
++ */
++void ldns_radix_printf(FILE* fd, ldns_radix_t* tree);
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* LDNS_RADIX_H_ */
+diff --git a/ldns/include/ldns/rbtree.h b/ldns/include/ldns/rbtree.h
+new file mode 100644
+index 0000000..c891934
+--- /dev/null
++++ b/ldns/include/ldns/rbtree.h
+@@ -0,0 +1,230 @@
++/*
++ * rbtree.h -- generic red-black tree
++ *
++ * Copyright (c) 2001-2008, NLnet Labs. All rights reserved.
++ *
++ * This software is open source.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright notice,
++ * this list of conditions and the following disclaimer in the documentation
++ * and/or other materials provided with the distribution.
++ *
++ * Neither the name of the NLNET LABS nor the names of its contributors may
++ * be used to endorse or promote products derived from this software without
++ * specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
++ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
++ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
++ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
++ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ *
++ */
++
++/**
++ * \file
++ * Red black tree. Implementation taken from NSD 3.0.5, adjusted for use
++ * in unbound (memory allocation, logging and so on).
++ */
++
++#ifndef LDNS_RBTREE_H_
++#define	LDNS_RBTREE_H_
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/**
++ * This structure must be the first member of the data structure in
++ * the rbtree.  This allows easy casting between an rbnode_t and the
++ * user data (poor man's inheritance).
++ * Or you can use the data pointer member to get to your data item.
++ */
++typedef struct ldns_rbnode_t ldns_rbnode_t;
++/**
++ * The rbnode_t struct definition.
++ */
++struct ldns_rbnode_t {
++	/** parent in rbtree, RBTREE_NULL for root */
++	ldns_rbnode_t   *parent;
++	/** left node (smaller items) */
++	ldns_rbnode_t   *left;
++	/** right node (larger items) */
++	ldns_rbnode_t   *right;
++	/** pointer to sorting key */
++	const void *key;
++	/** pointer to data */
++	const void *data;
++	/** colour of this node */
++	uint8_t	    color;
++};
++
++/** The nullpointer, points to empty node */
++#define	LDNS_RBTREE_NULL &ldns_rbtree_null_node
++/** the global empty node */
++extern	ldns_rbnode_t	ldns_rbtree_null_node;
++
++/** An entire red black tree */
++typedef struct ldns_rbtree_t ldns_rbtree_t;
++/** definition for tree struct */
++struct ldns_rbtree_t {
++	/** The root of the red-black tree */
++	ldns_rbnode_t    *root;
++
++	/** The number of the nodes in the tree */
++	size_t       count;
++
++	/**
++	 * Key compare function. <0,0,>0 like strcmp.
++	 * Return 0 on two NULL ptrs.
++	 */
++	int (*cmp) (const void *, const void *);
++};
++
++/**
++ * Create new tree (malloced) with given key compare function.
++ * @param cmpf: compare function (like strcmp) takes pointers to two keys.
++ * @return: new tree, empty.
++ */
++ldns_rbtree_t *ldns_rbtree_create(int (*cmpf)(const void *, const void *));
++
++/**
++ * Free the complete tree (but not its keys)
++ * @param rbtree The tree to free
++ */
++void ldns_rbtree_free(ldns_rbtree_t *rbtree);
++
++/**
++ * Init a new tree (malloced by caller) with given key compare function.
++ * @param rbtree: uninitialised memory for new tree, returned empty.
++ * @param cmpf: compare function (like strcmp) takes pointers to two keys.
++ */
++void ldns_rbtree_init(ldns_rbtree_t *rbtree, int (*cmpf)(const void *, const void *));
++
++/**
++ * Insert data into the tree.
++ * @param rbtree: tree to insert to.
++ * @param data: element to insert.
++ * @return: data ptr or NULL if key already present.
++ */
++ldns_rbnode_t *ldns_rbtree_insert(ldns_rbtree_t *rbtree, ldns_rbnode_t *data);
++
++/**
++ * Insert data into the tree (reversed arguments, for use as callback)
++ * \param[in] data element to insert
++ * \param[out] rbtree tree to insert in to
++ * \return data ptr or NULL if key is already present
++ */
++void ldns_rbtree_insert_vref(ldns_rbnode_t *data, void *rbtree);
++
++/**
++ * Delete element from tree.
++ * @param rbtree: tree to delete from.
++ * @param key: key of item to delete.
++ * @return: node that is now unlinked from the tree. User to delete it.
++ * returns 0 if node not present
++ */
++ldns_rbnode_t *ldns_rbtree_delete(ldns_rbtree_t *rbtree, const void *key);
++
++/**
++ * Find key in tree. Returns NULL if not found.
++ * @param rbtree: tree to find in.
++ * @param key: key that must match.
++ * @return: node that fits or NULL.
++ */
++ldns_rbnode_t *ldns_rbtree_search(ldns_rbtree_t *rbtree, const void *key);
++
++/**
++ * Find, but match does not have to be exact.
++ * @param rbtree: tree to find in.
++ * @param key: key to find position of.
++ * @param result: set to the exact node if present, otherwise to element that
++ *   precedes the position of key in the tree. NULL if no smaller element.
++ * @return: true if exact match in result. Else result points to <= element,
++ * or NULL if key is smaller than the smallest key.
++ */
++int ldns_rbtree_find_less_equal(ldns_rbtree_t *rbtree, const void *key,
++	ldns_rbnode_t **result);
++
++/**
++ * Returns first (smallest) node in the tree
++ * @param rbtree: tree
++ * @return: smallest element or NULL if tree empty.
++ */
++ldns_rbnode_t *ldns_rbtree_first(ldns_rbtree_t *rbtree);
++
++/**
++ * Returns last (largest) node in the tree
++ * @param rbtree: tree
++ * @return: largest element or NULL if tree empty.
++ */
++ldns_rbnode_t *ldns_rbtree_last(ldns_rbtree_t *rbtree);
++
++/**
++ * Returns next larger node in the tree
++ * @param rbtree: tree
++ * @return: next larger element or NULL if no larger in tree.
++ */
++ldns_rbnode_t *ldns_rbtree_next(ldns_rbnode_t *rbtree);
++
++/**
++ * Returns previous smaller node in the tree
++ * @param rbtree: tree
++ * @return: previous smaller element or NULL if no previous in tree.
++ */
++ldns_rbnode_t *ldns_rbtree_previous(ldns_rbnode_t *rbtree);
++
++/**
++ * split off 'elements' number of elements from the start
++ * of the name tree and return a new tree containing those
++ * elements
++ */
++ldns_rbtree_t *ldns_rbtree_split(ldns_rbtree_t *tree, size_t elements);
++
++/**
++ * add all node from the second tree to the first (removing them from the
++ * second), and fix up nsec(3)s if present
++ */
++void ldns_rbtree_join(ldns_rbtree_t *tree1, ldns_rbtree_t *tree2);
++
++/**
++ * Call with node=variable of struct* with rbnode_t as first element.
++ * with type is the type of a pointer to that struct.
++ */
++#define LDNS_RBTREE_FOR(node, type, rbtree) \
++	for(node=(type)ldns_rbtree_first(rbtree); \
++		(ldns_rbnode_t*)node != LDNS_RBTREE_NULL; \
++		node = (type)ldns_rbtree_next((ldns_rbnode_t*)node))
++
++/**
++ * Call function for all elements in the redblack tree, such that
++ * leaf elements are called before parent elements. So that all
++ * elements can be safely free()d.
++ * Note that your function must not remove the nodes from the tree.
++ * Since that may trigger rebalances of the rbtree.
++ * @param tree: the tree
++ * @param func: function called with element and user arg.
++ * 	The function must not alter the rbtree.
++ * @param arg: user argument.
++ */
++void ldns_traverse_postorder(ldns_rbtree_t* tree,
++	void (*func)(ldns_rbnode_t*, void*), void* arg);
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* UTIL_RBTREE_H_ */
+diff --git a/ldns/include/ldns/rdata.h b/ldns/include/ldns/rdata.h
+new file mode 100644
+index 0000000..22665b1
+--- /dev/null
++++ b/ldns/include/ldns/rdata.h
+@@ -0,0 +1,451 @@
++/*
++ * rdata.h
++ *
++ * rdata definitions
++ *
++ * a Net::DNS like library for C
++ *
++ * (c) NLnet Labs, 2005-2006
++ *
++ * See the file LICENSE for the license
++ */
++
++
++/**
++ * \file
++ *
++ * Defines ldns_rdf and functions to manipulate those.
++ */
++
++
++#ifndef LDNS_RDATA_H
++#define LDNS_RDATA_H
++
++#include <ldns/common.h>
++#include <ldns/error.h>
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++#define LDNS_MAX_RDFLEN	65535
++
++#define LDNS_RDF_SIZE_BYTE              1
++#define LDNS_RDF_SIZE_WORD              2
++#define LDNS_RDF_SIZE_DOUBLEWORD        4
++#define LDNS_RDF_SIZE_6BYTES            6
++#define LDNS_RDF_SIZE_8BYTES            8
++#define LDNS_RDF_SIZE_16BYTES           16
++
++#define LDNS_NSEC3_VARS_OPTOUT_MASK 0x01
++
++/**
++ * The different types of RDATA fields.
++ */
++enum ldns_enum_rdf_type
++{
++	/** none */
++	LDNS_RDF_TYPE_NONE,
++	/** domain name */
++	LDNS_RDF_TYPE_DNAME,
++	/** 8 bits */
++	LDNS_RDF_TYPE_INT8,
++	/** 16 bits */
++	LDNS_RDF_TYPE_INT16,
++	/** 32 bits */
++	LDNS_RDF_TYPE_INT32,
++	/** A record */
++	LDNS_RDF_TYPE_A,
++	/** AAAA record */
++	LDNS_RDF_TYPE_AAAA,
++	/** txt string */
++	LDNS_RDF_TYPE_STR,
++	/** apl data */
++	LDNS_RDF_TYPE_APL,
++	/** b32 string */
++	LDNS_RDF_TYPE_B32_EXT,
++	/** b64 string */
++	LDNS_RDF_TYPE_B64,
++	/** hex string */
++	LDNS_RDF_TYPE_HEX,
++	/** nsec type codes */
++	LDNS_RDF_TYPE_NSEC,
++	/** a RR type */
++	LDNS_RDF_TYPE_TYPE,
++	/** a class */
++	LDNS_RDF_TYPE_CLASS,
++	/** certificate algorithm */
++	LDNS_RDF_TYPE_CERT_ALG,
++	/** a key algorithm */
++	LDNS_RDF_TYPE_ALG,
++	/** unknown types */
++	LDNS_RDF_TYPE_UNKNOWN,
++	/** time (32 bits) */
++	LDNS_RDF_TYPE_TIME,
++	/** period */
++	LDNS_RDF_TYPE_PERIOD,
++	/** tsig time 48 bits */
++	LDNS_RDF_TYPE_TSIGTIME,
++	/** Represents the Public Key Algorithm, HIT and Public Key fields
++	    for the HIP RR types.  A HIP specific rdf type is used because of
++	    the unusual layout in wireformat (see RFC 5205 Section 5) */
++	LDNS_RDF_TYPE_HIP,
++	/** variable length any type rdata where the length
++	    is specified by the first 2 bytes */
++	LDNS_RDF_TYPE_INT16_DATA,
++	/** protocol and port bitmaps */
++	LDNS_RDF_TYPE_SERVICE,
++	/** location data */
++	LDNS_RDF_TYPE_LOC,
++	/** well known services */
++	LDNS_RDF_TYPE_WKS,
++	/** NSAP */
++	LDNS_RDF_TYPE_NSAP,
++	/** ATMA */
++	LDNS_RDF_TYPE_ATMA,
++	/** IPSECKEY */
++	LDNS_RDF_TYPE_IPSECKEY,
++	/** nsec3 hash salt */
++	LDNS_RDF_TYPE_NSEC3_SALT,
++	/** nsec3 base32 string (with length byte on wire */
++	LDNS_RDF_TYPE_NSEC3_NEXT_OWNER,
++
++	/** 4 shorts represented as 4 * 16 bit hex numbers
++	 *  separated by colons. For NID and L64.
++	 */
++	LDNS_RDF_TYPE_ILNP64,
++
++	/** 6 * 8 bit hex numbers separated by dashes. For EUI48. */
++	LDNS_RDF_TYPE_EUI48,
++	/** 8 * 8 bit hex numbers separated by dashes. For EUI64. */
++	LDNS_RDF_TYPE_EUI64,
++
++	/** A non-zero sequence of US-ASCII letters and numbers in lower case.
++	 *  For CAA.
++	 */
++	LDNS_RDF_TYPE_TAG,
++
++	/** A <character-string> encoding of the value field as specified 
++	 * [RFC1035], Section 5.1., encoded as remaining rdata.
++	 * For CAA.
++	 */
++	LDNS_RDF_TYPE_LONG_STR,
++
++	/** Since RFC7218 TLSA records can be given with mnemonics,
++	 * hence these rdata field types.  But as with DNSKEYs, the output
++	 * is always numeric.
++	 */
++	LDNS_RDF_TYPE_CERTIFICATE_USAGE,
++	LDNS_RDF_TYPE_SELECTOR,
++	LDNS_RDF_TYPE_MATCHING_TYPE,
++
++	/* Aliases */
++	LDNS_RDF_TYPE_BITMAP = LDNS_RDF_TYPE_NSEC
++};
++typedef enum ldns_enum_rdf_type ldns_rdf_type;
++
++/**
++ * algorithms used in CERT rrs
++ */
++enum ldns_enum_cert_algorithm
++{
++        LDNS_CERT_PKIX		= 1,
++        LDNS_CERT_SPKI		= 2,
++        LDNS_CERT_PGP		= 3,
++        LDNS_CERT_IPKIX         = 4,
++        LDNS_CERT_ISPKI         = 5,
++        LDNS_CERT_IPGP          = 6,
++        LDNS_CERT_ACPKIX        = 7,
++        LDNS_CERT_IACPKIX       = 8,
++        LDNS_CERT_URI		= 253,
++        LDNS_CERT_OID		= 254
++};
++typedef enum ldns_enum_cert_algorithm ldns_cert_algorithm;
++
++
++
++/**
++ * Resource record data field.
++ *
++ * The data is a network ordered array of bytes, which size is specified by
++ * the (16-bit) size field. To correctly parse it, use the type
++ * specified in the (16-bit) type field with a value from \ref ldns_rdf_type.
++ */
++struct ldns_struct_rdf
++{
++	/** The size of the data (in octets) */
++	size_t _size;
++	/** The type of the data */
++	ldns_rdf_type _type;
++	/** Pointer to the data (raw octets) */
++	void  *_data;
++};
++typedef struct ldns_struct_rdf ldns_rdf;
++
++/* prototypes */
++
++/* write access functions */
++
++/**
++ * sets the size of the rdf.
++ * \param[in] *rd the rdf to operate on
++ * \param[in] size the new size
++ * \return void
++ */
++void ldns_rdf_set_size(ldns_rdf *rd, size_t size);
++
++/**
++ * sets the size of the rdf.
++ * \param[in] *rd the rdf to operate on
++ * \param[in] type the new type
++ * \return void
++ */
++void ldns_rdf_set_type(ldns_rdf *rd, ldns_rdf_type type);
++
++/**
++ * sets the size of the rdf.
++ * \param[in] *rd the rdf to operate on
++ * \param[in] *data pointer to the new data
++ * \return void
++ */
++void ldns_rdf_set_data(ldns_rdf *rd, void *data);
++
++/* read access */
++
++/**
++ * returns the size of the rdf.
++ * \param[in] *rd the rdf to read from
++ * \return uint16_t with the size
++ */
++size_t ldns_rdf_size(const ldns_rdf *rd);
++
++/**
++ * returns the type of the rdf. We need to insert _get_
++ * here to prevent conflict the the rdf_type TYPE.
++ * \param[in] *rd the rdf to read from
++ * \return ldns_rdf_type with the type
++ */
++ldns_rdf_type ldns_rdf_get_type(const ldns_rdf *rd);
++
++/**
++ * returns the data of the rdf.
++ * \param[in] *rd the rdf to read from
++ *
++ * \return uint8_t* pointer to the rdf's data
++ */
++uint8_t *ldns_rdf_data(const ldns_rdf *rd);
++
++/* creator functions */
++
++/**
++ * allocates a new rdf structure and fills it.
++ * This function DOES NOT copy the contents from
++ * the buffer, unlinke ldns_rdf_new_frm_data()
++ * \param[in] type type of the rdf
++ * \param[in] size size of the buffer
++ * \param[in] data pointer to the buffer to be copied
++ * \return the new rdf structure or NULL on failure
++ */
++ldns_rdf *ldns_rdf_new(ldns_rdf_type type, size_t size, void *data);
++
++/**
++ * allocates a new rdf structure and fills it.
++ * This function _does_ copy the contents from
++ * the buffer, unlinke ldns_rdf_new()
++ * \param[in] type type of the rdf
++ * \param[in] size size of the buffer
++ * \param[in] data pointer to the buffer to be copied
++ * \return the new rdf structure or NULL on failure
++ */
++ldns_rdf *ldns_rdf_new_frm_data(ldns_rdf_type type, size_t size, const void *data);
++
++/**
++ * creates a new rdf from a string.
++ * \param[in] type   type to use
++ * \param[in] str string to use
++ * \return ldns_rdf* or NULL in case of an error
++ */
++ldns_rdf *ldns_rdf_new_frm_str(ldns_rdf_type type, const char *str);
++
++/**
++ * creates a new rdf from a file containing a string.
++ * \param[out] r the new rdf
++ * \param[in] type   type to use
++ * \param[in] fp the file pointer  to use
++ * \return LDNS_STATUS_OK or the error
++ */
++ldns_status ldns_rdf_new_frm_fp(ldns_rdf **r, ldns_rdf_type type, FILE *fp);
++
++/**
++ * creates a new rdf from a file containing a string.
++ * \param[out] r the new rdf
++ * \param[in] type   type to use
++ * \param[in] fp the file pointer  to use
++ * \param[in] line_nr pointer to an integer containing the current line number (for debugging purposes)
++ * \return LDNS_STATUS_OK or the error
++ */
++ldns_status ldns_rdf_new_frm_fp_l(ldns_rdf **r, ldns_rdf_type type, FILE *fp, int *line_nr);
++
++/* destroy functions */
++
++/**
++ * frees a rdf structure, leaving the
++ * data pointer intact.
++ * \param[in] rd the pointer to be freed
++ * \return void
++ */
++void ldns_rdf_free(ldns_rdf *rd);
++
++/**
++ * frees a rdf structure _and_ frees the
++ * data. rdf should be created with _new_frm_data
++ * \param[in] rd the rdf structure to be freed
++ * \return void
++ */
++void ldns_rdf_deep_free(ldns_rdf *rd);
++
++/* conversion functions */
++
++/**
++ * returns the rdf containing the native uint8_t repr.
++ * \param[in] type the ldns_rdf type to use
++ * \param[in] value the uint8_t to use
++ * \return ldns_rdf* with the converted value
++ */
++ldns_rdf *ldns_native2rdf_int8(ldns_rdf_type type, uint8_t value);
++
++/**
++ * returns the rdf containing the native uint16_t representation.
++ * \param[in] type the ldns_rdf type to use
++ * \param[in] value the uint16_t to use
++ * \return ldns_rdf* with the converted value
++ */
++ldns_rdf *ldns_native2rdf_int16(ldns_rdf_type type, uint16_t value);
++
++/**
++ * returns an rdf that contains the given int32 value.
++ *
++ * Because multiple rdf types can contain an int32, the
++ * type must be specified
++ * \param[in] type the ldns_rdf type to use
++ * \param[in] value the uint32_t to use
++ * \return ldns_rdf* with the converted value
++ */
++ldns_rdf *ldns_native2rdf_int32(ldns_rdf_type type, uint32_t value);
++
++/**
++ * returns an int16_data rdf that contains the data in the
++ * given array, preceded by an int16 specifying the length.
++ *
++ * The memory is copied, and an LDNS_RDF_TYPE_INT16DATA is returned
++ * \param[in] size the size of the data
++ * \param[in] *data pointer to the actual data
++ *
++ * \return ldns_rd* the rdf with the data
++ */
++ldns_rdf *ldns_native2rdf_int16_data(size_t size, uint8_t *data);
++
++/**
++ * reverses an rdf, only actually useful for AAAA and A records.
++ * The returned rdf has the type LDNS_RDF_TYPE_DNAME!
++ * \param[in] *rd rdf to be reversed
++ * \return the reversed rdf (a newly created rdf)
++ */
++ldns_rdf *ldns_rdf_address_reverse(ldns_rdf *rd);
++
++/**
++ * returns the native uint8_t representation from the rdf.
++ * \param[in] rd the ldns_rdf to operate on
++ * \return uint8_t the value extracted
++ */
++uint8_t 	ldns_rdf2native_int8(const ldns_rdf *rd);
++
++/**
++ * returns the native uint16_t representation from the rdf.
++ * \param[in] rd the ldns_rdf to operate on
++ * \return uint16_t the value extracted
++ */
++uint16_t	ldns_rdf2native_int16(const ldns_rdf *rd);
++
++/**
++ * returns the native uint32_t representation from the rdf.
++ * \param[in] rd the ldns_rdf to operate on
++ * \return uint32_t the value extracted
++ */
++uint32_t ldns_rdf2native_int32(const ldns_rdf *rd);
++
++/**
++ * returns the native time_t representation from the rdf.
++ * \param[in] rd the ldns_rdf to operate on
++ * \return time_t the value extracted (32 bits currently)
++ */
++time_t ldns_rdf2native_time_t(const ldns_rdf *rd);
++
++/**
++ * converts a ttl value (like 5d2h) to a long.
++ * \param[in] nptr the start of the string
++ * \param[out] endptr points to the last char in case of error
++ * \return the convert duration value
++ */
++uint32_t ldns_str2period(const char *nptr, const char **endptr);
++
++/**
++ * removes \\DDD, \\[space] and other escapes from the input.
++ * See RFC 1035, section 5.1.
++ * \param[in] word what to check
++ * \param[in] length the string
++ * \return ldns_status mesg
++ */
++ldns_status ldns_octet(char *word, size_t *length);
++
++/**
++ * clones a rdf structure. The data is copied.
++ * \param[in] rd rdf to be copied
++ * \return a new rdf structure
++ */
++ldns_rdf *ldns_rdf_clone(const ldns_rdf *rd);
++
++/**
++ * compares two rdf's on their wire formats.
++ * (To order dnames according to rfc4034, use ldns_dname_compare)
++ * \param[in] rd1 the first one
++ * \param[in] rd2 the second one
++ * \return 0 if equal
++ * \return -1 if rd1 comes before rd2
++ * \return +1 if rd2 comes before rd1
++ */
++int ldns_rdf_compare(const ldns_rdf *rd1, const ldns_rdf *rd2);
++
++/**
++ * Gets the algorithm value, the HIT and Public Key data from the rdf with
++ * type LDNS_RDF_TYPE_HIP.
++ * \param[in] rdf the rdf with type LDNS_RDF_TYPE_HIP
++ * \param[out] alg      the algorithm
++ * \param[out] hit_size the size of the HIT data
++ * \param[out] hit      the hit data
++ * \param[out] pk_size  the size of the Public Key data
++ * \param[out] pk       the  Public Key data
++ * \return LDNS_STATUS_OK on success, and the error otherwise
++ */
++ldns_status ldns_rdf_hip_get_alg_hit_pk(ldns_rdf *rdf, uint8_t* alg,
++		uint8_t *hit_size, uint8_t** hit,
++		uint16_t *pk_size, uint8_t** pk);
++
++/**
++ * Creates a new LDNS_RDF_TYPE_HIP rdf from given data.
++ * \param[out] rdf      the newly created LDNS_RDF_TYPE_HIP rdf
++ * \param[in]  alg      the algorithm
++ * \param[in]  hit_size the size of the HIT data
++ * \param[in]  hit      the hit data
++ * \param[in]  pk_size  the size of the Public Key data
++ * \param[in]  pk       the  Public Key data
++ * \return LDNS_STATUS_OK on success, and the error otherwise
++ */
++ldns_status ldns_rdf_hip_new_frm_alg_hit_pk(ldns_rdf** rdf, uint8_t alg,
++		uint8_t hit_size, uint8_t *hit, uint16_t pk_size, uint8_t *pk);
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif	/* LDNS_RDATA_H */
+diff --git a/ldns/include/ldns/resolver.h b/ldns/include/ldns/resolver.h
+new file mode 100644
+index 0000000..228485c
+--- /dev/null
++++ b/ldns/include/ldns/resolver.h
+@@ -0,0 +1,805 @@
++/*
++ * resolver.h
++ *
++ * DNS Resolver definitions
++ *
++ * a Net::DNS like library for C
++ *
++ * (c) NLnet Labs, 2005-2006
++ *
++ * See the file LICENSE for the license
++ */
++
++/**
++ * \file
++ *
++ * Defines the  ldns_resolver structure, a stub resolver that can send queries and parse answers.
++ *
++ */
++
++#ifndef LDNS_RESOLVER_H
++#define LDNS_RESOLVER_H
++
++#include <ldns/error.h>
++#include <ldns/common.h>
++#include <ldns/rr.h>
++#include <ldns/tsig.h>
++#include <ldns/rdata.h>
++#include <ldns/packet.h>
++#include <sys/time.h>
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/** Default location of the resolv.conf file */
++#define LDNS_RESOLV_CONF	"/etc/resolv.conf"
++/** Default location of the hosts file */
++#define LDNS_RESOLV_HOSTS	"/etc/hosts"
++
++#define LDNS_RESOLV_KEYWORD     -1
++#define LDNS_RESOLV_DEFDOMAIN	0
++#define LDNS_RESOLV_NAMESERVER	1
++#define LDNS_RESOLV_SEARCH	2
++#define LDNS_RESOLV_SORTLIST	3
++#define LDNS_RESOLV_OPTIONS	4
++#define LDNS_RESOLV_ANCHOR	5
++#define LDNS_RESOLV_KEYWORDS    6
++
++#define LDNS_RESOLV_INETANY		0
++#define LDNS_RESOLV_INET		1
++#define LDNS_RESOLV_INET6		2
++
++#define LDNS_RESOLV_RTT_INF             0       /* infinity */
++#define LDNS_RESOLV_RTT_MIN             1       /* reachable */
++
++/**
++ * DNS stub resolver structure
++ */
++struct ldns_struct_resolver
++{
++	/**  Port to send queries to */
++	uint16_t _port;
++
++	/** Array of nameservers to query (IP addresses or dnames) */
++	ldns_rdf **_nameservers;
++	/** Number of nameservers in \c _nameservers */
++	size_t _nameserver_count; /* how many do we have */
++
++	/**  Round trip time; 0 -> infinity. Unit: ms? */
++	size_t *_rtt;
++
++	/**  Whether or not to be recursive */
++	bool _recursive;
++
++	/**  Print debug information */
++	bool _debug;
++
++	/**  Default domain to add to non fully qualified domain names */
++	ldns_rdf *_domain;
++
++	/**  Searchlist array, add the names in this array if a query cannot be found */
++	ldns_rdf **_searchlist;
++
++	/** Number of entries in the searchlist array */
++	size_t _searchlist_count;
++
++	/**  Number of times to retry before giving up */
++	uint8_t _retry;
++	/**  Time to wait before retrying */
++	uint8_t _retrans;
++	/**  Use new fallback mechanism (try EDNS, then do TCP) */
++	bool _fallback;
++
++	/**  Whether to do DNSSEC */
++	bool _dnssec;
++	/**  Whether to set the CD bit on DNSSEC requests */
++	bool _dnssec_cd;
++	/** Optional trust anchors for complete DNSSEC validation */
++	ldns_rr_list * _dnssec_anchors;
++	/**  Whether to use tcp or udp (tcp if the value is true)*/
++	bool _usevc;
++	/**  Whether to ignore the tc bit */
++	bool _igntc;
++	/**  Whether to use ip6: 0->does not matter, 1 is IPv4, 2 is IPv6 */
++	uint8_t _ip6;
++	/**  If true append the default domain */
++	bool _defnames;
++	/**  If true apply the search list */
++	bool _dnsrch;
++	/**  Timeout for socket connections */
++	struct timeval _timeout;
++	/**  Only try the first nameserver, and return with an error directly if it fails */
++	bool _fail;
++	/**  Randomly choose a nameserver */
++	bool _random;
++	/** Keep some things to make AXFR possible */
++	int _socket;
++	/** Count the number of LDNS_RR_TYPE_SOA RRs we have seen so far
++	 * (the second one signifies the end of the AXFR)
++	 */
++	int _axfr_soa_count;
++	/* when axfring we get complete packets from the server
++	   but we want to give the caller 1 rr at a time, so
++	   keep the current pkt */
++        /** Packet currently handled when doing part of an AXFR */
++	ldns_pkt *_cur_axfr_pkt;
++	/** Counter for within the AXFR packets */
++	uint16_t _axfr_i;
++	/* EDNS0 available buffer size */
++	uint16_t _edns_udp_size;
++	/* serial for IXFR */
++	uint32_t _serial;
++
++	/* Optional tsig key for signing queries,
++	outgoing messages are signed if and only if both are set
++	*/
++	/** Name of the key to use with TSIG, if _tsig_keyname and _tsig_keydata both contain values, outgoing messages are automatically signed with TSIG. */
++	char *_tsig_keyname;
++	/** Secret key data to use with TSIG, if _tsig_keyname and _tsig_keydata both contain values, outgoing messages are automatically signed with TSIG. */
++	char *_tsig_keydata;
++	/** TSIG signing algorithm */
++	char *_tsig_algorithm;
++
++	/** Source address to query from */
++	ldns_rdf *_source;
++};
++typedef struct ldns_struct_resolver ldns_resolver;
++
++/* prototypes */
++/* read access functions */
++
++/**
++ * Get the port the resolver should use
++ * \param[in] r the resolver
++ * \return the port number
++ */
++uint16_t ldns_resolver_port(const ldns_resolver *r);
++
++/**
++ * Get the source address the resolver should use
++ * \param[in] r the resolver
++ * \return the source rdf
++ */
++ldns_rdf *ldns_resolver_source(const ldns_resolver *r);
++
++/**
++ * Is the resolver set to recurse
++ * \param[in] r the resolver
++ * \return true if so, otherwise false
++ */
++bool ldns_resolver_recursive(const ldns_resolver *r);
++
++/**
++ * Get the debug status of the resolver
++ * \param[in] r the resolver
++ * \return true if so, otherwise false
++ */
++bool ldns_resolver_debug(const ldns_resolver *r);
++
++/**
++ * Get the number of retries
++ * \param[in] r the resolver
++ * \return the number of retries
++ */
++uint8_t ldns_resolver_retry(const ldns_resolver *r);
++
++/**
++ * Get the retransmit interval
++ * \param[in] r the resolver
++ * \return the retransmit interval
++ */
++uint8_t ldns_resolver_retrans(const ldns_resolver *r);
++
++/**
++ * Get the truncation fallback status
++ * \param[in] r the resolver
++ * \return whether the truncation fallback mechanism is used
++ */
++bool ldns_resolver_fallback(const ldns_resolver *r);
++
++/**
++ * Does the resolver use ip6 or ip4
++ * \param[in] r the resolver
++ * \return 0: both, 1: ip4, 2:ip6
++ */
++uint8_t ldns_resolver_ip6(const ldns_resolver *r);
++
++/**
++ * Get the resolver's udp size
++ * \param[in] r the resolver
++ * \return the udp mesg size
++ */
++uint16_t ldns_resolver_edns_udp_size(const ldns_resolver *r);
++/**
++ * Does the resolver use tcp or udp
++ * \param[in] r the resolver
++ * \return true: tcp, false: udp
++ */
++bool ldns_resolver_usevc(const ldns_resolver *r);
++/**
++ * Does the resolver only try the first nameserver
++ * \param[in] r the resolver
++ * \return true: yes, fail, false: no, try the others
++ */
++bool ldns_resolver_fail(const ldns_resolver *r);
++/**
++ * Does the resolver apply default domain name
++ * \param[in] r the resolver
++ * \return true: yes, false: no
++ */
++bool ldns_resolver_defnames(const ldns_resolver *r);
++/**
++ * Does the resolver apply search list
++ * \param[in] r the resolver
++ * \return true: yes, false: no
++ */
++bool ldns_resolver_dnsrch(const ldns_resolver *r);
++/**
++ * Does the resolver do DNSSEC
++ * \param[in] r the resolver
++ * \return true: yes, false: no
++ */
++bool ldns_resolver_dnssec(const ldns_resolver *r);
++/**
++ * Does the resolver set the CD bit
++ * \param[in] r the resolver
++ * \return true: yes, false: no
++ */
++bool ldns_resolver_dnssec_cd(const ldns_resolver *r);
++/**
++ * Get the resolver's DNSSEC anchors
++ * \param[in] r the resolver
++ * \return an rr_list containg trusted DNSSEC anchors
++ */
++ldns_rr_list * ldns_resolver_dnssec_anchors(const ldns_resolver *r);
++/**
++ * Does the resolver ignore the TC bit (truncated)
++ * \param[in] r the resolver
++ * \return true: yes, false: no
++ */
++bool ldns_resolver_igntc(const ldns_resolver *r);
++/**
++ * Does the resolver randomize the nameserver before usage
++ * \param[in] r the resolver
++ * \return true: yes, false: no
++ */
++bool ldns_resolver_random(const ldns_resolver *r);
++/**
++ * How many nameserver are configured in the resolver
++ * \param[in] r the resolver
++ * \return number of nameservers
++ */
++size_t ldns_resolver_nameserver_count(const ldns_resolver *r);
++/**
++ * What is the default dname to add to relative queries
++ * \param[in] r the resolver
++ * \return the dname which is added
++ */
++ldns_rdf *ldns_resolver_domain(const ldns_resolver *r);
++/**
++ * What is the timeout on socket connections
++ * \param[in] r the resolver
++ * \return the timeout as struct timeval
++ */
++struct timeval ldns_resolver_timeout(const ldns_resolver *r);
++/**
++ * What is the searchlist as used by the resolver
++ * \param[in] r the resolver
++ * \return a ldns_rdf pointer to a list of the addresses
++ */
++ldns_rdf** ldns_resolver_searchlist(const ldns_resolver *r);
++/**
++ * Return the configured nameserver ip address
++ * \param[in] r the resolver
++ * \return a ldns_rdf pointer to a list of the addresses
++ */
++ldns_rdf** ldns_resolver_nameservers(const ldns_resolver *r);
++/**
++ * Return the used round trip times for the nameservers
++ * \param[in] r the resolver
++ * \return a size_t* pointer to the list.
++ * yet)
++ */
++size_t * ldns_resolver_rtt(const ldns_resolver *r);
++/**
++ * Return the used round trip time for a specific nameserver
++ * \param[in] r the resolver
++ * \param[in] pos the index to the nameserver
++ * \return the rrt, 0: infinite, >0: undefined (as of * yet)
++ */
++size_t ldns_resolver_nameserver_rtt(const ldns_resolver *r, size_t pos);
++/**
++ * Return the tsig keyname as used by the nameserver
++ * \param[in] r the resolver
++ * \return the name used.
++ */
++char *ldns_resolver_tsig_keyname(const ldns_resolver *r);
++/**
++ * Return the tsig algorithm as used by the nameserver
++ * \param[in] r the resolver
++ * \return the algorithm used.
++ */
++char *ldns_resolver_tsig_algorithm(const ldns_resolver *r);
++/**
++ * Return the tsig keydata as used by the nameserver
++ * \param[in] r the resolver
++ * \return the keydata used.
++ */
++char *ldns_resolver_tsig_keydata(const ldns_resolver *r);
++/**
++ * pop the last nameserver from the resolver.
++ * \param[in] r the resolver
++ * \return the popped address or NULL if empty
++ */
++ldns_rdf* ldns_resolver_pop_nameserver(ldns_resolver *r);
++
++/**
++ * Return the resolver's searchlist count
++ * \param[in] r the resolver
++ * \return the searchlist count
++ */
++size_t ldns_resolver_searchlist_count(const ldns_resolver *r);
++
++/* write access function */
++/**
++ * Set the port the resolver should use
++ * \param[in] r the resolver
++ * \param[in] p the port number
++ */
++void ldns_resolver_set_port(ldns_resolver *r, uint16_t p);
++
++/**
++ * Set the source rdf (address) the resolver should use
++ * \param[in] r the resolver
++ * \param[in] s the source address
++ */
++void ldns_resolver_set_source(ldns_resolver *r, ldns_rdf *s);
++
++/**
++ * Set the resolver recursion
++ * \param[in] r the resolver
++ * \param[in] b true: set to recurse, false: unset
++ */
++void ldns_resolver_set_recursive(ldns_resolver *r, bool b);
++
++/**
++ * Set the resolver debugging
++ * \param[in] r the resolver
++ * \param[in] b true: debug on: false debug off
++ */
++void ldns_resolver_set_debug(ldns_resolver *r, bool b);
++
++/**
++ * Incremental the resolver's nameserver count.
++ * \param[in] r the resolver
++ */
++void ldns_resolver_incr_nameserver_count(ldns_resolver *r);
++
++/**
++ * Decrement the resolver's nameserver count.
++ * \param[in] r the resolver
++ */
++void ldns_resolver_dec_nameserver_count(ldns_resolver *r);
++
++/**
++ * Set the resolver's nameserver count directly.
++ * \param[in] r the resolver
++ * \param[in] c the nameserver count
++ */
++void ldns_resolver_set_nameserver_count(ldns_resolver *r, size_t c);
++
++/**
++ * Set the resolver's nameserver count directly by using an rdf list
++ * \param[in] r the resolver
++ * \param[in] rd the resolver addresses
++ */
++void ldns_resolver_set_nameservers(ldns_resolver *r, ldns_rdf **rd);
++
++/**
++ * Set the resolver's default domain. This gets appended when no
++ * absolute name is given
++ * \param[in] r the resolver
++ * \param[in] rd the name to append
++ */
++void ldns_resolver_set_domain(ldns_resolver *r, ldns_rdf *rd);
++
++/**
++ * Set the resolver's socket time out when talking to remote hosts
++ * \param[in] r the resolver
++ * \param[in] timeout the timeout to use
++ */
++void ldns_resolver_set_timeout(ldns_resolver *r, struct timeval timeout);
++
++/**
++ * Push a new rd to the resolver's searchlist
++ * \param[in] r the resolver
++ * \param[in] rd to push
++ */
++void ldns_resolver_push_searchlist(ldns_resolver *r, ldns_rdf *rd);
++
++/**
++ * Whether the resolver uses the name set with _set_domain
++ * \param[in] r the resolver
++ * \param[in] b true: use the defaults, false: don't use them
++ */
++void ldns_resolver_set_defnames(ldns_resolver *r, bool b);
++
++/**
++ * Whether the resolver uses a virtual circuit (TCP)
++ * \param[in] r the resolver
++ * \param[in] b true: use TCP, false: don't use TCP
++ */
++void ldns_resolver_set_usevc(ldns_resolver *r, bool b);
++
++/**
++ * Whether the resolver uses the searchlist
++ * \param[in] r the resolver
++ * \param[in] b true: use the list, false: don't use the list
++ */
++void ldns_resolver_set_dnsrch(ldns_resolver *r, bool b);
++
++/**
++ * Whether the resolver uses DNSSEC
++ * \param[in] r the resolver
++ * \param[in] b true: use DNSSEC, false: don't use DNSSEC
++ */
++void ldns_resolver_set_dnssec(ldns_resolver *r, bool b);
++
++/**
++ * Whether the resolver uses the checking disable bit
++ * \param[in] r the resolver
++ * \param[in] b true: enable , false: don't use TCP
++ */
++void ldns_resolver_set_dnssec_cd(ldns_resolver *r, bool b);
++/**
++ * Set the resolver's DNSSEC anchor list directly. RRs should be of type DS or DNSKEY.
++ * \param[in] r the resolver
++ * \param[in] l the list of RRs to use as trust anchors
++ */
++void ldns_resolver_set_dnssec_anchors(ldns_resolver *r, ldns_rr_list * l);
++
++/**
++ * Push a new trust anchor to the resolver. It must be a DS or DNSKEY rr
++ * \param[in] r the resolver.
++ * \param[in] rr the RR to add as a trust anchor.
++ * \return a status
++ */
++ldns_status ldns_resolver_push_dnssec_anchor(ldns_resolver *r, ldns_rr *rr);
++
++/**
++ * Set the resolver retrans timeout (in seconds)
++ * \param[in] r the resolver
++ * \param[in] re the retransmission interval in seconds
++ */
++void ldns_resolver_set_retrans(ldns_resolver *r, uint8_t re);
++
++/**
++ * Set whether the resolvers truncation fallback mechanism is used
++ * when ldns_resolver_query() is called.
++ * \param[in] r the resolver
++ * \param[in] fallback whether to use the fallback mechanism
++ */
++void ldns_resolver_set_fallback(ldns_resolver *r, bool fallback);
++
++/**
++ * Set the number of times a resolver should retry a nameserver before the
++ * next one is tried.
++ * \param[in] r the resolver
++ * \param[in] re the number of retries
++ */
++void ldns_resolver_set_retry(ldns_resolver *r, uint8_t re);
++
++/**
++ * Whether the resolver uses ip6
++ * \param[in] r the resolver
++ * \param[in] i 0: no pref, 1: ip4, 2: ip6
++ */
++void ldns_resolver_set_ip6(ldns_resolver *r, uint8_t i);
++
++/**
++ * Whether or not to fail after one failed query
++ * \param[in] r the resolver
++ * \param[in] b true: yes fail, false: continue with next nameserver
++ */
++void ldns_resolver_set_fail(ldns_resolver *r, bool b);
++
++/**
++ * Whether or not to ignore the TC bit
++ * \param[in] r the resolver
++ * \param[in] b true: yes ignore, false: don't ignore
++ */
++void ldns_resolver_set_igntc(ldns_resolver *r, bool b);
++
++/**
++ * Set maximum udp size
++ * \param[in] r the resolver
++ * \param[in] s the udp max size
++ */
++void ldns_resolver_set_edns_udp_size(ldns_resolver *r, uint16_t s);
++
++/**
++ * Set the tsig key name
++ * \param[in] r the resolver
++ * \param[in] tsig_keyname the tsig key name
++ */
++void ldns_resolver_set_tsig_keyname(ldns_resolver *r, char *tsig_keyname);
++
++/**
++ * Set the tsig algorithm
++ * \param[in] r the resolver
++ * \param[in] tsig_algorithm the tsig algorithm
++ */
++void ldns_resolver_set_tsig_algorithm(ldns_resolver *r, char *tsig_algorithm);
++
++/**
++ * Set the tsig key data
++ * \param[in] r the resolver
++ * \param[in] tsig_keydata the key data
++ */
++void ldns_resolver_set_tsig_keydata(ldns_resolver *r, char *tsig_keydata);
++
++/**
++ * Set round trip time for all nameservers. Note this currently
++ * differentiates between: unreachable and reachable.
++ * \param[in] r the resolver
++ * \param[in] rtt a list with the times
++ */
++void ldns_resolver_set_rtt(ldns_resolver *r, size_t *rtt);
++
++/**
++ * Set round trip time for a specific nameserver. Note this
++ * currently differentiates between: unreachable and reachable.
++ * \param[in] r the resolver
++ * \param[in] pos the nameserver position
++ * \param[in] value the rtt
++ */
++void ldns_resolver_set_nameserver_rtt(ldns_resolver *r, size_t pos, size_t value);
++
++/**
++ * Should the nameserver list be randomized before each use
++ * \param[in] r the resolver
++ * \param[in] b: true: randomize, false: don't
++ */
++void ldns_resolver_set_random(ldns_resolver *r, bool b);
++
++/**
++ * Push a new nameserver to the resolver. It must be an IP
++ * address v4 or v6.
++ * \param[in] r the resolver
++ * \param[in] n the ip address
++ * \return ldns_status a status
++ */
++ldns_status ldns_resolver_push_nameserver(ldns_resolver *r, ldns_rdf *n);
++
++/**
++ * Push a new nameserver to the resolver. It must be an
++ * A or AAAA RR record type
++ * \param[in] r the resolver
++ * \param[in] rr the resource record
++ * \return ldns_status a status
++ */
++ldns_status ldns_resolver_push_nameserver_rr(ldns_resolver *r, ldns_rr *rr);
++
++/**
++ * Push a new nameserver rr_list to the resolver.
++ * \param[in] r the resolver
++ * \param[in] rrlist the rr_list to push
++ * \return ldns_status a status
++ */
++ldns_status ldns_resolver_push_nameserver_rr_list(ldns_resolver *r, ldns_rr_list *rrlist);
++
++/**
++ * Send the query for using the resolver and take the search list into account
++ * The search algorithm is as follows:
++ * If the name is absolute, try it as-is, otherwise apply the search list
++ * \param[in] *r operate using this resolver
++ * \param[in] *rdf query for this name
++ * \param[in] t query for this type (may be 0, defaults to A)
++ * \param[in] c query for this class (may be 0, default to IN)
++ * \param[in] flags the query flags
++ *
++ * \return ldns_pkt* a packet with the reply from the nameserver
++ */
++ldns_pkt* ldns_resolver_search(const ldns_resolver *r, const ldns_rdf *rdf, ldns_rr_type t, ldns_rr_class c, uint16_t flags);
++
++
++/**
++ * Send the query for using the resolver and take the search list into account
++ * The search algorithm is as follows:
++ * If the name is absolute, try it as-is, otherwise apply the search list
++ * \param[out] pkt a packet with the reply from the nameserver
++ * \param[in] *r operate using this resolver
++ * \param[in] *rdf query for this name
++ * \param[in] t query for this type (may be 0, defaults to A)
++ * \param[in] c query for this class (may be 0, default to IN)
++ * \param[in] flags the query flags
++ *
++ * \return ldns_status LDNS_STATUS_OK on success
++ */
++ldns_status ldns_resolver_search_status(ldns_pkt** pkt, ldns_resolver *r, const ldns_rdf *rdf, ldns_rr_type t, ldns_rr_class c, uint16_t flags);
++
++/**
++ * Form a query packet from a resolver and name/type/class combo
++ * \param[out] **q a pointer to a ldns_pkt pointer (initialized by this function)
++ * \param[in] *r operate using this resolver
++ * \param[in] *name query for this name
++ * \param[in] t query for this type (may be 0, defaults to A)
++ * \param[in] c query for this class (may be 0, default to IN)
++ * \param[in] f the query flags
++ *
++ * \return ldns_pkt* a packet with the reply from the nameserver
++ */
++ldns_status ldns_resolver_prepare_query_pkt(ldns_pkt **q, ldns_resolver *r, const  ldns_rdf *name, ldns_rr_type t, ldns_rr_class c, uint16_t f);
++
++/**
++ * Send the query for name as-is
++ * \param[out] **answer a pointer to a ldns_pkt pointer (initialized by this function)
++ * \param[in] *r operate using this resolver
++ * \param[in] *name query for this name
++ * \param[in] t query for this type (may be 0, defaults to A)
++ * \param[in] c query for this class (may be 0, default to IN)
++ * \param[in] flags the query flags
++ *
++ * \return ldns_pkt* a packet with the reply from the nameserver
++ */
++ldns_status ldns_resolver_send(ldns_pkt **answer, ldns_resolver *r, const ldns_rdf *name, ldns_rr_type t, ldns_rr_class c, uint16_t flags);
++
++/**
++ * Send the given packet to a nameserver
++ * \param[out] **answer a pointer to a ldns_pkt pointer (initialized by this function)
++ * \param[in] *r operate using this resolver
++ * \param[in] *query_pkt query
++ */
++ldns_status ldns_resolver_send_pkt(ldns_pkt **answer, ldns_resolver *r, ldns_pkt *query_pkt);
++
++/**
++ * Send a query to a nameserver
++ * \param[out] pkt a packet with the reply from the nameserver
++ * \param[in] *r operate using this resolver
++ * \param[in] *name query for this name
++ * \param[in] *t query for this type (may be 0, defaults to A)
++ * \param[in] *c query for this class (may be 0, default to IN)
++ * \param[in] flags the query flags
++ *
++ * \return ldns_status LDNS_STATUS_OK on success
++ * if _defnames is true the default domain will be added
++ */
++ldns_status ldns_resolver_query_status(ldns_pkt** pkt, ldns_resolver *r, const ldns_rdf *name, ldns_rr_type t, ldns_rr_class c, uint16_t flags);
++
++
++/**
++ * Send a query to a nameserver
++ * \param[in] *r operate using this resolver 
++ *               (despite the const in the declaration,
++ *                the struct is altered as a side-effect)
++ * \param[in] *name query for this name
++ * \param[in] *t query for this type (may be 0, defaults to A)
++ * \param[in] *c query for this class (may be 0, default to IN)
++ * \param[in] flags the query flags
++ *
++ * \return ldns_pkt* a packet with the reply from the nameserver
++ * if _defnames is true the default domain will be added
++ */
++ldns_pkt* ldns_resolver_query(const ldns_resolver *r, const ldns_rdf *name, ldns_rr_type t, ldns_rr_class c, uint16_t flags);
++
++
++/**
++ * Create a new resolver structure
++ * \return ldns_resolver* pointer to new structure
++ */
++ldns_resolver* ldns_resolver_new(void);
++
++/**
++ * Clone a resolver
++ * \param[in] r the resolver to clone
++ * \return ldns_resolver* pointer to new structure
++ */
++ldns_resolver* ldns_resolver_clone(ldns_resolver *r);
++
++/**
++ * Create a resolver structure from a file like /etc/resolv.conf
++ * \param[out] r the new resolver
++ * \param[in] fp file pointer to create new resolver from
++ *      if NULL use /etc/resolv.conf
++ * \return LDNS_STATUS_OK or the error
++ */
++ldns_status ldns_resolver_new_frm_fp(ldns_resolver **r, FILE *fp);
++
++/**
++ * Create a resolver structure from a file like /etc/resolv.conf
++ * \param[out] r the new resolver
++ * \param[in] fp file pointer to create new resolver from
++ *      if NULL use /etc/resolv.conf
++ * \param[in] line_nr pointer to an integer containing the current line number (for debugging purposes)
++ * \return LDNS_STATUS_OK or the error
++ */
++ldns_status ldns_resolver_new_frm_fp_l(ldns_resolver **r, FILE *fp, int *line_nr);
++
++/**
++ * Configure a resolver by means of a resolv.conf file
++ * The file may be NULL in which case there will  be
++ * looked the RESOLV_CONF (defaults to /etc/resolv.conf
++ * \param[out] r the new resolver
++ * \param[in] filename the filename to use
++ * \return LDNS_STATUS_OK or the error
++ */
++ldns_status ldns_resolver_new_frm_file(ldns_resolver **r, const char *filename);
++
++/**
++ * Frees the allocated space for this resolver. Only frees the resolver pionter! You should probably be using _deep_free.
++ * \param res resolver to free
++ */
++void ldns_resolver_free(ldns_resolver *res);
++
++/**
++ * Frees the allocated space for this resolver and all it's data
++ * \param res resolver to free
++ */
++void ldns_resolver_deep_free(ldns_resolver *res);
++
++/**
++ * Get the next stream of RRs in a AXFR
++ * \param[in] resolver the resolver to use. First ldns_axfr_start() must be
++ * called
++ * \return ldns_rr the next RR from the AXFR stream
++ * After you get this returned RR (not NULL: on error), then check if 
++ * ldns_axfr_complete() is true to see if the zone transfer has completed.
++ */
++ldns_rr* ldns_axfr_next(ldns_resolver *resolver);
++
++/**
++ * Abort a transfer that is in progress
++ * \param[in] resolver the resolver that is used
++ */
++void ldns_axfr_abort(ldns_resolver *resolver);
++
++/**
++ * Returns true if the axfr transfer has completed (i.e. 2 SOA RRs and no errors were encountered
++ * \param[in] resolver the resolver that is used
++ * \return bool true if axfr transfer was completed without error
++ */
++bool ldns_axfr_complete(const ldns_resolver *resolver);
++
++/**
++ * Returns a pointer to the last ldns_pkt that was sent by the server in the AXFR transfer
++ * uasable for instance to get the error code on failure
++ * \param[in] res the resolver that was used in the axfr transfer
++ * \return ldns_pkt the last packet sent
++ */
++ldns_pkt *ldns_axfr_last_pkt(const ldns_resolver *res);
++
++/**
++ * Get the serial for requesting IXFR.
++ * \param[in] r the resolver
++ * \param[in] serial serial
++ */
++void ldns_resolver_set_ixfr_serial(ldns_resolver *r, uint32_t serial);
++
++/**
++ * Get the serial for requesting IXFR.
++ * \param[in] res the resolver
++ * \return uint32_t serial
++ */
++uint32_t ldns_resolver_get_ixfr_serial(const ldns_resolver *res);
++
++/**
++ * Randomize the nameserver list in the resolver
++ * \param[in] r the resolver
++ */
++void ldns_resolver_nameservers_randomize(ldns_resolver *r);
++
++/**
++ * Returns true if at least one of the provided keys is a trust anchor
++ * \param[in] r the current resolver
++ * \param[in] keys the keyset to check
++ * \param[out] trusted_keys the subset of trusted keys in the 'keys' rrset
++ * \return true if at least one of the provided keys is a configured trust anchor
++ */
++bool ldns_resolver_trusted_key(const ldns_resolver *r, ldns_rr_list * keys, ldns_rr_list * trusted_keys);
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif  /* LDNS_RESOLVER_H */
+diff --git a/ldns/include/ldns/rr.h b/ldns/include/ldns/rr.h
+new file mode 100644
+index 0000000..75ac352
+--- /dev/null
++++ b/ldns/include/ldns/rr.h
+@@ -0,0 +1,929 @@
++/*
++ * rr.h -  resource record definitions
++ *
++ * a Net::DNS like library for C
++ *
++ * (c) NLnet Labs, 2005-2006
++ *
++ * See the file LICENSE for the license
++ */
++
++/**
++ * \file
++ *
++ * Contains the definition of ldns_rr and functions to manipulate those.
++ */
++
++
++#ifndef LDNS_RR_H
++#define LDNS_RR_H
++
++#include <ldns/common.h>
++#include <ldns/rdata.h>
++#include <ldns/buffer.h>
++#include <ldns/error.h>
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/** Maximum length of a dname label */
++#define LDNS_MAX_LABELLEN     63
++/** Maximum length of a complete dname */
++#define LDNS_MAX_DOMAINLEN    255
++/** Maximum number of pointers in 1 dname */
++#define LDNS_MAX_POINTERS	65535
++/** The bytes TTL, CLASS and length use up in an rr */
++#define LDNS_RR_OVERHEAD	10
++
++/* The first fields are contiguous and can be referenced instantly */
++#define LDNS_RDATA_FIELD_DESCRIPTORS_COMMON 258
++
++
++
++/**
++ *  The different RR classes.
++ */
++enum ldns_enum_rr_class
++{
++	/** the Internet */
++	LDNS_RR_CLASS_IN 	= 1,
++	/** Chaos class */
++	LDNS_RR_CLASS_CH	= 3,
++	/** Hesiod (Dyer 87) */
++	LDNS_RR_CLASS_HS	= 4,
++    /** None class, dynamic update */
++    LDNS_RR_CLASS_NONE      = 254,
++	/** Any class */
++	LDNS_RR_CLASS_ANY	= 255,
++
++	LDNS_RR_CLASS_FIRST     = 0,
++	LDNS_RR_CLASS_LAST      = 65535,
++	LDNS_RR_CLASS_COUNT     = LDNS_RR_CLASS_LAST - LDNS_RR_CLASS_FIRST + 1
++};
++typedef enum ldns_enum_rr_class ldns_rr_class;
++
++/**
++ *  Used to specify whether compression is allowed.
++ */
++enum ldns_enum_rr_compress
++{
++	/** compression is allowed */
++	LDNS_RR_COMPRESS,
++	LDNS_RR_NO_COMPRESS
++};
++typedef enum ldns_enum_rr_compress ldns_rr_compress;
++
++/**
++ * The different RR types.
++ */
++enum ldns_enum_rr_type
++{
++	/**  a host address */
++	LDNS_RR_TYPE_A = 1,
++	/**  an authoritative name server */
++	LDNS_RR_TYPE_NS = 2,
++	/**  a mail destination (Obsolete - use MX) */
++	LDNS_RR_TYPE_MD = 3,
++	/**  a mail forwarder (Obsolete - use MX) */
++	LDNS_RR_TYPE_MF = 4,
++	/**  the canonical name for an alias */
++	LDNS_RR_TYPE_CNAME = 5,
++	/**  marks the start of a zone of authority */
++	LDNS_RR_TYPE_SOA = 6,
++	/**  a mailbox domain name (EXPERIMENTAL) */
++	LDNS_RR_TYPE_MB = 7,
++	/**  a mail group member (EXPERIMENTAL) */
++	LDNS_RR_TYPE_MG = 8,
++	/**  a mail rename domain name (EXPERIMENTAL) */
++	LDNS_RR_TYPE_MR = 9,
++	/**  a null RR (EXPERIMENTAL) */
++	LDNS_RR_TYPE_NULL = 10,
++	/**  a well known service description */
++	LDNS_RR_TYPE_WKS = 11,
++	/**  a domain name pointer */
++	LDNS_RR_TYPE_PTR = 12,
++	/**  host information */
++	LDNS_RR_TYPE_HINFO = 13,
++	/**  mailbox or mail list information */
++	LDNS_RR_TYPE_MINFO = 14,
++	/**  mail exchange */
++	LDNS_RR_TYPE_MX = 15,
++	/**  text strings */
++	LDNS_RR_TYPE_TXT = 16,
++	/**  RFC1183 */
++	LDNS_RR_TYPE_RP = 17,
++	/**  RFC1183 */
++	LDNS_RR_TYPE_AFSDB = 18,
++	/**  RFC1183 */
++	LDNS_RR_TYPE_X25 = 19,
++	/**  RFC1183 */
++	LDNS_RR_TYPE_ISDN = 20,
++	/**  RFC1183 */
++	LDNS_RR_TYPE_RT = 21,
++	/**  RFC1706 */
++	LDNS_RR_TYPE_NSAP = 22,
++	/**  RFC1348 */
++	LDNS_RR_TYPE_NSAP_PTR = 23,
++	/**  2535typecode */
++	LDNS_RR_TYPE_SIG = 24,
++	/**  2535typecode */
++	LDNS_RR_TYPE_KEY = 25,
++	/**  RFC2163 */
++	LDNS_RR_TYPE_PX = 26,
++	/**  RFC1712 */
++	LDNS_RR_TYPE_GPOS = 27,
++	/**  ipv6 address */
++	LDNS_RR_TYPE_AAAA = 28,
++	/**  LOC record  RFC1876 */
++	LDNS_RR_TYPE_LOC = 29,
++	/**  2535typecode */
++	LDNS_RR_TYPE_NXT = 30,
++	/**  draft-ietf-nimrod-dns-01.txt */
++	LDNS_RR_TYPE_EID = 31,
++	/**  draft-ietf-nimrod-dns-01.txt */
++	LDNS_RR_TYPE_NIMLOC = 32,
++	/**  SRV record RFC2782 */
++	LDNS_RR_TYPE_SRV = 33,
++	/**  http://www.jhsoft.com/rfc/af-saa-0069.000.rtf */
++	LDNS_RR_TYPE_ATMA = 34,
++	/**  RFC2915 */
++	LDNS_RR_TYPE_NAPTR = 35,
++	/**  RFC2230 */
++	LDNS_RR_TYPE_KX = 36,
++	/**  RFC2538 */
++	LDNS_RR_TYPE_CERT = 37,
++	/**  RFC2874 */
++	LDNS_RR_TYPE_A6 = 38,
++	/**  RFC2672 */
++	LDNS_RR_TYPE_DNAME = 39,
++	/**  dnsind-kitchen-sink-02.txt */
++	LDNS_RR_TYPE_SINK = 40,
++	/**  Pseudo OPT record... */
++	LDNS_RR_TYPE_OPT = 41,
++	/**  RFC3123 */
++	LDNS_RR_TYPE_APL = 42,
++	/**  RFC4034, RFC3658 */
++	LDNS_RR_TYPE_DS = 43,
++	/**  SSH Key Fingerprint */
++	LDNS_RR_TYPE_SSHFP = 44, /* RFC 4255 */
++	/**  IPsec Key */
++	LDNS_RR_TYPE_IPSECKEY = 45, /* RFC 4025 */
++	/**  DNSSEC */
++	LDNS_RR_TYPE_RRSIG = 46, /* RFC 4034 */
++	LDNS_RR_TYPE_NSEC = 47, /* RFC 4034 */
++	LDNS_RR_TYPE_DNSKEY = 48, /* RFC 4034 */
++
++	LDNS_RR_TYPE_DHCID = 49, /* RFC 4701 */
++	/* NSEC3 */
++	LDNS_RR_TYPE_NSEC3 = 50, /* RFC 5155 */
++	LDNS_RR_TYPE_NSEC3PARAM = 51, /* RFC 5155 */
++	LDNS_RR_TYPE_NSEC3PARAMS = 51,
++	LDNS_RR_TYPE_TLSA = 52, /* RFC 6698 */
++
++	LDNS_RR_TYPE_HIP = 55, /* RFC 5205 */
++
++	/** draft-reid-dnsext-zs */
++	LDNS_RR_TYPE_NINFO = 56,
++	/** draft-reid-dnsext-rkey */
++	LDNS_RR_TYPE_RKEY = 57,
++        /** draft-ietf-dnsop-trust-history */
++        LDNS_RR_TYPE_TALINK = 58,
++	LDNS_RR_TYPE_CDS = 59, /* RFC 7344 */
++	LDNS_RR_TYPE_CDNSKEY = 60, /* RFC 7344 */
++	/** draft-ietf-dane-openpgpkey */
++	LDNS_RR_TYPE_OPENPGPKEY = 61,
++
++	LDNS_RR_TYPE_SPF = 99, /* RFC 4408 */
++
++	LDNS_RR_TYPE_UINFO = 100,
++	LDNS_RR_TYPE_UID = 101,
++	LDNS_RR_TYPE_GID = 102,
++	LDNS_RR_TYPE_UNSPEC = 103,
++
++	LDNS_RR_TYPE_NID = 104, /* RFC 6742 */
++	LDNS_RR_TYPE_L32 = 105, /* RFC 6742 */
++	LDNS_RR_TYPE_L64 = 106, /* RFC 6742 */
++	LDNS_RR_TYPE_LP = 107, /* RFC 6742 */
++
++	LDNS_RR_TYPE_EUI48 = 108, /* RFC 7043 */
++	LDNS_RR_TYPE_EUI64 = 109, /* RFC 7043 */
++
++	LDNS_RR_TYPE_TKEY = 249, /* RFC 2930 */
++	LDNS_RR_TYPE_TSIG = 250,
++	LDNS_RR_TYPE_IXFR = 251,
++	LDNS_RR_TYPE_AXFR = 252,
++	/**  A request for mailbox-related records (MB, MG or MR) */
++	LDNS_RR_TYPE_MAILB = 253,
++	/**  A request for mail agent RRs (Obsolete - see MX) */
++	LDNS_RR_TYPE_MAILA = 254,
++	/**  any type (wildcard) */
++	LDNS_RR_TYPE_ANY = 255,
++	/** draft-faltstrom-uri-06 */
++	LDNS_RR_TYPE_URI = 256,
++	LDNS_RR_TYPE_CAA = 257, /* RFC 6844 */
++
++	/** DNSSEC Trust Authorities */
++	LDNS_RR_TYPE_TA = 32768,
++	/* RFC 4431, 5074, DNSSEC Lookaside Validation */
++	LDNS_RR_TYPE_DLV = 32769,
++
++	/* type codes from nsec3 experimental phase
++	LDNS_RR_TYPE_NSEC3 = 65324,
++	LDNS_RR_TYPE_NSEC3PARAMS = 65325, */
++	LDNS_RR_TYPE_FIRST = 0,
++	LDNS_RR_TYPE_LAST  = 65535,
++	LDNS_RR_TYPE_COUNT = LDNS_RR_TYPE_LAST - LDNS_RR_TYPE_FIRST + 1
++};
++typedef enum ldns_enum_rr_type ldns_rr_type;
++
++/**
++ * Resource Record
++ *
++ * This is the basic DNS element that contains actual data
++ *
++ * From RFC1035:
++ * <pre>
++3.2.1. Format
++
++All RRs have the same top level format shown below:
++
++                                    1  1  1  1  1  1
++      0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
++    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
++    |                                               |
++    /                                               /
++    /                      NAME                     /
++    |                                               |
++    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
++    |                      TYPE                     |
++    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
++    |                     CLASS                     |
++    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
++    |                      TTL                      |
++    |                                               |
++    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
++    |                   RDLENGTH                    |
++    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--|
++    /                     RDATA                     /
++    /                                               /
++    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
++
++where:
++
++NAME            an owner name, i.e., the name of the node to which this
++                resource record pertains.
++
++TYPE            two octets containing one of the RR TYPE codes.
++
++CLASS           two octets containing one of the RR CLASS codes.
++
++TTL             a 32 bit signed integer that specifies the time interval
++                that the resource record may be cached before the source
++                of the information should again be consulted.  Zero
++                values are interpreted to mean that the RR can only be
++                used for the transaction in progress, and should not be
++                cached.  For example, SOA records are always distributed
++                with a zero TTL to prohibit caching.  Zero values can
++                also be used for extremely volatile data.
++
++RDLENGTH        an unsigned 16 bit integer that specifies the length in
++                octets of the RDATA field.
++
++RDATA           a variable length string of octets that describes the
++                resource.  The format of this information varies
++                according to the TYPE and CLASS of the resource record.
++ * </pre>
++ *
++ * The actual amount and type of rdata fields depend on the RR type of the
++ * RR, and can be found by using \ref ldns_rr_descriptor functions.
++ */
++struct ldns_struct_rr
++{
++	/**  Owner name, uncompressed */
++	ldns_rdf	*_owner;
++	/**  Time to live  */
++	uint32_t	_ttl;
++	/**  Number of data fields */
++	size_t	        _rd_count;
++	/**  the type of the RR. A, MX etc. */
++	ldns_rr_type	_rr_type;
++	/**  Class of the resource record.  */
++	ldns_rr_class	_rr_class;
++	/* everything in the rdata is in network order */
++	/**  The array of rdata's */
++	ldns_rdf	 **_rdata_fields;
++	/**  question rr [it would be nicer if thous is after _rd_count]
++		 ABI change: Fix this in next major release
++	 */
++	bool		_rr_question;
++};
++typedef struct ldns_struct_rr ldns_rr;
++
++/**
++ * List or Set of Resource Records
++ *
++ * Contains a list of rr's <br>
++ * No official RFC-like checks are made
++ */
++struct ldns_struct_rr_list
++{
++	size_t _rr_count;
++	size_t _rr_capacity;
++	ldns_rr **_rrs;
++};
++typedef struct ldns_struct_rr_list ldns_rr_list;
++
++/**
++ * Contains all information about resource record types.
++ *
++ * This structure contains, for all rr types, the rdata fields that are defined.
++ */
++struct ldns_struct_rr_descriptor
++{
++	/** Type of the RR that is described here */
++	ldns_rr_type    _type;
++	/** Textual name of the RR type.  */
++	const char *_name;
++	/** Minimum number of rdata fields in the RRs of this type.  */
++	uint8_t     _minimum;
++	/** Maximum number of rdata fields in the RRs of this type.  */
++	uint8_t     _maximum;
++	/** Wireformat specification for the rr, i.e. the types of rdata fields in their respective order. */
++	const ldns_rdf_type *_wireformat;
++	/** Special rdf types */
++	ldns_rdf_type _variable;
++	/** Specifies whether compression can be used for dnames in this RR type. */
++	ldns_rr_compress _compress;
++	/** The number of DNAMEs in the _wireformat string, for parsing. */
++	uint8_t _dname_count;
++};
++typedef struct ldns_struct_rr_descriptor ldns_rr_descriptor;
++
++
++/**
++ * Create a rr type bitmap rdf providing enough space to set all 
++ * known (to ldns) rr types.
++ * \param[out] rdf the constructed rdf
++ * \return LDNS_STATUS_OK if all went well.
++ */
++ldns_status ldns_rdf_bitmap_known_rr_types_space(ldns_rdf** rdf);
++
++/**
++ * Create a rr type bitmap rdf with at least all known (to ldns) rr types set.
++ * \param[out] rdf the constructed rdf
++ * \return LDNS_STATUS_OK if all went well.
++ */
++ldns_status ldns_rdf_bitmap_known_rr_types(ldns_rdf** rdf);
++
++
++/**
++ * creates a new rr structure.
++ * \return ldns_rr *
++ */
++ldns_rr* ldns_rr_new(void);
++
++/**
++ * creates a new rr structure, based on the given type.
++ * alloc enough space to hold all the rdf's
++ */
++ldns_rr* ldns_rr_new_frm_type(ldns_rr_type t);
++
++/**
++ * frees an RR structure
++ * \param[in] *rr the RR to be freed
++ * \return void
++ */
++void ldns_rr_free(ldns_rr *rr);
++
++/**
++ * creates an rr from a string.
++ * The string should be a fully filled-in rr, like
++ * ownername <space> TTL <space> CLASS <space>
++ * TYPE <space> RDATA.
++ * \param[out] n the rr to return
++ * \param[in] str the string to convert
++ * \param[in] default_ttl default ttl value for the rr.
++ *            If 0 DEF_TTL will be used
++ * \param[in] origin when the owner is relative add this.
++ *	The caller must ldns_rdf_deep_free it.
++ * \param[out] prev the previous ownername. if this value is not NULL,
++ * the function overwrites this with the ownername found in this
++ * string. The caller must then ldns_rdf_deep_free it.
++ * \return a status msg describing an error or LDNS_STATUS_OK
++ */
++ldns_status ldns_rr_new_frm_str(ldns_rr **n, const char *str,
++                                uint32_t default_ttl, ldns_rdf *origin,
++                                ldns_rdf **prev);
++
++/**
++ * creates an rr for the question section from a string, i.e.
++ * without RDATA fields
++ * Origin and previous RR functionality are the same as in
++ * ldns_rr_new_frm_str()
++ * \param[out] n the rr to return
++ * \param[in] str the string to convert
++ * \param[in] origin when the owner is relative add this.
++ *	The caller must ldns_rdf_deep_free it.
++ * \param prev the previous ownername. the function overwrite this with
++ * the current found ownername. The caller must ldns_rdf_deep_free it.
++ * \return a status msg describing an error or LDNS_STATUS_OK
++ */
++ldns_status ldns_rr_new_question_frm_str(ldns_rr **n, const char *str,
++                                ldns_rdf *origin, ldns_rdf **prev);
++
++/**
++ * creates a new rr from a file containing a string.
++ * \param[out] rr the new rr
++ * \param[in] fp the file pointer to use
++ * \param[in] default_ttl pointer to a default ttl for the rr. If NULL DEF_TTL will be used
++ *            the pointer will be updated if the file contains a $TTL directive
++ * \param[in] origin when the owner is relative add this
++ * 	      the pointer will be updated if the file contains a $ORIGIN directive
++ *	      The caller must ldns_rdf_deep_free it.
++ * \param[in] prev when the owner is whitespaces use this as the * ownername
++ *            the pointer will be updated after the call
++ *	      The caller must ldns_rdf_deep_free it.
++ * \return a ldns_status with an error or LDNS_STATUS_OK
++ */
++ldns_status ldns_rr_new_frm_fp(ldns_rr **rr, FILE *fp, uint32_t *default_ttl, ldns_rdf **origin, ldns_rdf **prev);
++
++/**
++ * creates a new rr from a file containing a string.
++ * \param[out] rr the new rr
++ * \param[in] fp the file pointer to use
++ * \param[in] default_ttl a default ttl for the rr. If NULL DEF_TTL will be used
++ *            the pointer will be updated if the file contains a $TTL directive
++ * \param[in] origin when the owner is relative add this
++ * 	      the pointer will be updated if the file contains a $ORIGIN directive
++ *	      The caller must ldns_rdf_deep_free it.
++ * \param[in] line_nr pointer to an integer containing the current line number (for debugging purposes)
++ * \param[in] prev when the owner is whitespaces use this as the * ownername
++ *            the pointer will be updated after the call
++ *	      The caller must ldns_rdf_deep_free it.
++ * \return a ldns_status with an error or LDNS_STATUS_OK
++ */
++ldns_status ldns_rr_new_frm_fp_l(ldns_rr **rr, FILE *fp, uint32_t *default_ttl, ldns_rdf **origin, ldns_rdf **prev, int *line_nr);
++
++/**
++ * sets the owner in the rr structure.
++ * \param[in] *rr rr to operate on
++ * \param[in] *owner set to this owner
++ * \return void
++ */
++void ldns_rr_set_owner(ldns_rr *rr, ldns_rdf *owner);
++
++/**
++ * sets the question flag in the rr structure.
++ * \param[in] *rr rr to operate on
++ * \param[in] question question flag
++ * \return void
++ */
++void ldns_rr_set_question(ldns_rr *rr, bool question);
++
++/**
++ * sets the ttl in the rr structure.
++ * \param[in] *rr rr to operate on
++ * \param[in] ttl set to this ttl
++ * \return void
++ */
++void ldns_rr_set_ttl(ldns_rr *rr, uint32_t ttl);
++
++/**
++ * sets the rd_count in the rr.
++ * \param[in] *rr rr to operate on
++ * \param[in] count set to this count
++ * \return void
++ */
++void ldns_rr_set_rd_count(ldns_rr *rr, size_t count);
++
++/**
++ * sets the type in the rr.
++ * \param[in] *rr rr to operate on
++ * \param[in] rr_type set to this type
++ * \return void
++ */
++void ldns_rr_set_type(ldns_rr *rr, ldns_rr_type rr_type);
++
++/**
++ * sets the class in the rr.
++ * \param[in] *rr rr to operate on
++ * \param[in] rr_class set to this class
++ * \return void
++ */
++void ldns_rr_set_class(ldns_rr *rr, ldns_rr_class rr_class);
++
++/**
++ * sets a rdf member, it will be set on the
++ * position given. The old value is returned, like pop.
++ * \param[in] *rr the rr to operate on
++ * \param[in] *f the rdf to set
++ * \param[in] position the position the set the rdf
++ * \return  the old value in the rr, NULL on failyre
++ */
++ldns_rdf* ldns_rr_set_rdf(ldns_rr *rr, const ldns_rdf *f, size_t position);
++
++/**
++ * sets rd_field member, it will be
++ * placed in the next available spot.
++ * \param[in] *rr rr to operate on
++ * \param[in] *f the data field member to set
++ * \return bool
++ */
++bool ldns_rr_push_rdf(ldns_rr *rr, const ldns_rdf *f);
++
++/**
++ * removes a rd_field member, it will be
++ * popped from the last position.
++ * \param[in] *rr rr to operate on
++ * \return rdf which was popped (null if nothing)
++ */
++ldns_rdf* ldns_rr_pop_rdf(ldns_rr *rr);
++
++/**
++ * returns the rdata field member counter.
++ * \param[in] *rr rr to operate on
++ * \param[in] nr the number of the rdf to return
++ * \return ldns_rdf *
++ */
++ldns_rdf* ldns_rr_rdf(const ldns_rr *rr, size_t nr);
++
++/**
++ * returns the owner name of an rr structure.
++ * \param[in] *rr rr to operate on
++ * \return ldns_rdf *
++ */
++ldns_rdf* ldns_rr_owner(const ldns_rr *rr);
++
++/**
++ * returns the question flag of an rr structure.
++ * \param[in] *rr rr to operate on
++ * \return bool true if question
++ */
++bool ldns_rr_is_question(const ldns_rr *rr);
++
++/**
++ * returns the ttl of an rr structure.
++ * \param[in] *rr the rr to read from
++ * \return the ttl of the rr
++ */
++uint32_t ldns_rr_ttl(const ldns_rr *rr);
++
++/**
++ * returns the rd_count of an rr structure.
++ * \param[in] *rr the rr to read from
++ * \return the rd count of the rr
++ */
++size_t ldns_rr_rd_count(const ldns_rr *rr);
++
++/**
++ * returns the type of the rr.
++ * \param[in] *rr the rr to read from
++ * \return the type of the rr
++ */
++ldns_rr_type ldns_rr_get_type(const ldns_rr *rr);
++
++/**
++ * returns the class of the rr.
++ * \param[in] *rr the rr to read from
++ * \return the class of the rr
++ */
++ldns_rr_class ldns_rr_get_class(const ldns_rr *rr);
++
++/* rr_lists */
++
++/**
++ * returns the number of rr's in an rr_list.
++ * \param[in] rr_list  the rr_list to read from
++ * \return the number of rr's
++ */
++size_t ldns_rr_list_rr_count(const ldns_rr_list *rr_list);
++
++/**
++ * sets the number of rr's in an rr_list.
++ * \param[in] rr_list the rr_list to set the count on
++ * \param[in] count the number of rr in this list
++ * \return void
++ */
++void ldns_rr_list_set_rr_count(ldns_rr_list *rr_list, size_t count);
++
++/**
++ * set a rr on a specific index in a ldns_rr_list
++ * \param[in] rr_list the rr_list to use
++ * \param[in] r the rr to set
++ * \param[in] count index into the rr_list
++ * \return the old rr which was stored in the rr_list, or
++ * NULL is the index was too large
++ * set a specific rr */
++ldns_rr * ldns_rr_list_set_rr(ldns_rr_list *rr_list, const ldns_rr *r, size_t count);
++
++/**
++ * returns a specific rr of an rrlist.
++ * \param[in] rr_list the rr_list to read from
++ * \param[in] nr return this rr
++ * \return the rr at position nr
++ */
++ldns_rr* ldns_rr_list_rr(const ldns_rr_list *rr_list, size_t nr);
++
++/**
++ * creates a new rr_list structure.
++ * \return a new rr_list structure
++ */
++ldns_rr_list* ldns_rr_list_new(void);
++
++/**
++ * frees an rr_list structure.
++ * \param[in] rr_list the list to free
++ */
++void ldns_rr_list_free(ldns_rr_list *rr_list);
++
++/**
++ * frees an rr_list structure and all rrs contained therein.
++ * \param[in] rr_list the list to free
++ */
++void ldns_rr_list_deep_free(ldns_rr_list *rr_list);
++
++/**
++ * concatenates two ldns_rr_lists together. This modifies
++ * *left (to extend it and add the pointers from *right).
++ * \param[in] left the leftside
++ * \param[in] right the rightside
++ * \return a left with right concatenated to it
++ */
++bool ldns_rr_list_cat(ldns_rr_list *left, ldns_rr_list *right);
++
++/**
++ * concatenates two ldns_rr_lists together, but makes clones of the rr's 
++ * (instead of pointer copying).
++ * \param[in] left the leftside
++ * \param[in] right the rightside
++ * \return a new rr_list with leftside/rightside concatenated
++ */
++ldns_rr_list* ldns_rr_list_cat_clone(ldns_rr_list *left, ldns_rr_list *right);
++
++/**
++ * pushes an rr to an rrlist.
++ * \param[in] rr_list the rr_list to push to 
++ * \param[in] rr the rr to push 
++ * \return false on error, otherwise true
++ */
++bool ldns_rr_list_push_rr(ldns_rr_list *rr_list, const ldns_rr *rr);
++
++/**
++ * pushes an rr_list to an rrlist.
++ * \param[in] rr_list the rr_list to push to 
++ * \param[in] push_list the rr_list to push 
++ * \return false on error, otherwise true
++ */
++bool ldns_rr_list_push_rr_list(ldns_rr_list *rr_list, const ldns_rr_list *push_list);
++
++/**
++ * pops the last rr from an rrlist.
++ * \param[in] rr_list the rr_list to pop from
++ * \return NULL if nothing to pop. Otherwise the popped RR
++ */
++ldns_rr* ldns_rr_list_pop_rr(ldns_rr_list *rr_list);
++
++/**
++ * pops an  rr_list of size s from an rrlist.
++ * \param[in] rr_list the rr_list to pop from
++ * \param[in] size the number of rr's to pop 
++ * \return NULL if nothing to pop. Otherwise the popped rr_list
++ */
++ldns_rr_list* ldns_rr_list_pop_rr_list(ldns_rr_list *rr_list, size_t size);
++
++/**
++ * returns true if the given rr is one of the rrs in the
++ * list, or if it is equal to one
++ * \param[in] rr_list the rr_list to check
++ * \param[in] rr the rr to check
++ * \return true if rr_list contains rr, false otherwise
++ */
++bool ldns_rr_list_contains_rr(const ldns_rr_list *rr_list, ldns_rr *rr); 
++
++/**
++ * checks if an rr_list is a rrset.
++ * \param[in] rr_list the rr_list to check
++ * \return true if it is an rrset otherwise false
++ */
++bool ldns_is_rrset(ldns_rr_list *rr_list);
++
++/**
++ * pushes an rr to an rrset (which really are rr_list's).
++ * \param[in] *rr_list the rrset to push the rr to
++ * \param[in] *rr the rr to push
++ * \return true if the push succeeded otherwise false
++ */
++bool ldns_rr_set_push_rr(ldns_rr_list *rr_list, ldns_rr *rr);
++
++/**
++ * pops the last rr from an rrset. This function is there only
++ * for the symmetry.
++ * \param[in] rr_list the rr_list to pop from
++ * \return NULL if nothing to pop. Otherwise the popped RR
++ *
++ */
++ldns_rr* ldns_rr_set_pop_rr(ldns_rr_list *rr_list);
++
++/**
++ * pops the first rrset from the list,
++ * the list must be sorted, so that all rr's from each rrset
++ * are next to each other
++ */
++ldns_rr_list *ldns_rr_list_pop_rrset(ldns_rr_list *rr_list);
++
++
++/**
++ * retrieves a rrtype by looking up its name.
++ * \param[in] name a string with the name
++ * \return the type which corresponds with the name
++ */
++ldns_rr_type ldns_get_rr_type_by_name(const char *name);
++
++/**
++ * retrieves a class by looking up its name.
++ * \param[in] name string with the name
++ * \return the cass which corresponds with the name
++ */
++ldns_rr_class ldns_get_rr_class_by_name(const char *name);
++
++/**
++ * clones a rr and all its data
++ * \param[in] rr the rr to clone
++ * \return the new rr or NULL on failure
++ */
++ldns_rr* ldns_rr_clone(const ldns_rr *rr);
++
++/**
++ * clones an rrlist.
++ * \param[in] rrlist the rrlist to clone
++ * \return the cloned rr list
++ */
++ldns_rr_list* ldns_rr_list_clone(const ldns_rr_list *rrlist);
++
++/**
++ * sorts an rr_list (canonical wire format). the sorting is done inband.
++ * \param[in] unsorted the rr_list to be sorted
++ * \return void
++ */
++void ldns_rr_list_sort(ldns_rr_list *unsorted);
++
++/**
++ * compares two rrs. The TTL is not looked at.
++ * \param[in] rr1 the first one
++ * \param[in] rr2 the second one
++ * \return 0 if equal
++ *         -1 if rr1 comes before rr2
++ *         +1 if rr2 comes before rr1
++ */
++int ldns_rr_compare(const ldns_rr *rr1, const ldns_rr *rr2);
++
++/**
++ * compares two rrs, up to the rdata.
++ * \param[in] rr1 the first one
++ * \param[in] rr2 the second one
++ * \return 0 if equal
++ *         -1 if rr1 comes before rr2
++ *         +1 if rr2 comes before rr1
++ */
++int ldns_rr_compare_no_rdata(const ldns_rr *rr1, const ldns_rr *rr2);
++
++/**
++ * compares the wireformat of two rrs, contained in the given buffers.
++ * \param[in] rr1_buf the first one
++ * \param[in] rr2_buf the second one
++ * \return 0 if equal
++ *         -1 if rr1_buf comes before rr2_buf
++ *         +1 if rr2_buf comes before rr1_buf
++ */
++int ldns_rr_compare_wire(ldns_buffer *rr1_buf, ldns_buffer *rr2_buf);
++
++/**
++ * returns true of the given rr's are equal.
++ * Also returns true if one record is a DS that represents the
++ * same DNSKEY record as the other record
++ * \param[in] rr1 the first rr
++ * \param[in] rr2 the second rr
++ * \return true if equal otherwise false
++ */
++bool ldns_rr_compare_ds(const ldns_rr *rr1, const ldns_rr *rr2);
++
++/**
++ * compares two rr listss.
++ * \param[in] rrl1 the first one
++ * \param[in] rrl2 the second one
++ * \return 0 if equal
++ *         -1 if rrl1 comes before rrl2
++ *         +1 if rrl2 comes before rrl1
++ */
++int ldns_rr_list_compare(const ldns_rr_list *rrl1, const ldns_rr_list *rrl2);
++
++/** 
++ * calculates the uncompressed size of an RR.
++ * \param[in] r the rr to operate on
++ * \return size of the rr
++ */
++size_t ldns_rr_uncompressed_size(const ldns_rr *r);
++
++/** 
++ * converts each dname in a rr to its canonical form.
++ * \param[in] rr the rr to work on
++ * \return void
++ */
++void ldns_rr2canonical(ldns_rr *rr);
++
++/** 
++ * converts each dname in each rr in a rr_list to its canonical form.
++ * \param[in] rr_list the rr_list to work on
++ * \return void
++ */
++void ldns_rr_list2canonical(ldns_rr_list *rr_list);
++
++/** 
++ * counts the number of labels of the ownername.
++ * \param[in] rr count the labels of this rr
++ * \return the number of labels
++ */
++uint8_t ldns_rr_label_count(ldns_rr *rr);
++
++/**
++ * returns the resource record descriptor for the given rr type.
++ *
++ * \param[in] type the type value of the rr type
++ *\return the ldns_rr_descriptor for this type
++ */
++const ldns_rr_descriptor *ldns_rr_descript(uint16_t type);
++
++/**
++ * returns the minimum number of rdata fields of the rr type this descriptor describes.
++ *
++ * \param[in]  descriptor for an rr type
++ * \return the minimum number of rdata fields
++ */
++size_t ldns_rr_descriptor_minimum(const ldns_rr_descriptor *descriptor);
++
++/**
++ * returns the maximum number of rdata fields of the rr type this descriptor describes.
++ *
++ * \param[in]  descriptor for an rr type
++ * \return the maximum number of rdata fields
++ */
++size_t ldns_rr_descriptor_maximum(const ldns_rr_descriptor *descriptor);
++
++/**
++ * returns the rdf type for the given rdata field number of the rr type for the given descriptor.
++ *
++ * \param[in] descriptor for an rr type
++ * \param[in] field the field number
++ * \return the rdf type for the field
++ */
++ldns_rdf_type ldns_rr_descriptor_field_type(const ldns_rr_descriptor *descriptor, size_t field);
++
++/**
++ * Return the rr_list which matches the rdf at position field. Think
++ * type-covered stuff for RRSIG
++ * 
++ * \param[in] l the rr_list to look in
++ * \param[in] r the rdf to use for the comparison
++ * \param[in] pos at which position can we find the rdf
++ * 
++ * \return a new rr list with only the RRs that match 
++ *
++ */
++ldns_rr_list *ldns_rr_list_subtype_by_rdf(ldns_rr_list *l, ldns_rdf *r, size_t pos);
++
++/**
++ * convert an rdf of type LDNS_RDF_TYPE_TYPE to an actual
++ * LDNS_RR_TYPE. This is usefull in the case when inspecting
++ * the rrtype covered field of an RRSIG.
++ * \param[in] rd the rdf to look at
++ * \return a ldns_rr_type with equivalent LDNS_RR_TYPE
++ *
++ */
++ldns_rr_type    ldns_rdf2rr_type(const ldns_rdf *rd);
++
++/**
++ * Returns the type of the first element of the RR
++ * If there are no elements present, 0 is returned
++ * 
++ * \param[in] rr_list The rr list
++ * \return rr_type of the first element, or 0 if the list is empty
++ */
++ldns_rr_type
++ldns_rr_list_type(const ldns_rr_list *rr_list);
++
++/**
++ * Returns the owner domain name rdf of the first element of the RR
++ * If there are no elements present, NULL is returned
++ * 
++ * \param[in] rr_list The rr list
++ * \return dname of the first element, or NULL if the list is empty
++ */
++ldns_rdf *
++ldns_rr_list_owner(const ldns_rr_list *rr_list);
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* LDNS_RR_H */
+diff --git a/ldns/include/ldns/rr_functions.h b/ldns/include/ldns/rr_functions.h
+new file mode 100644
+index 0000000..09a28dd
+--- /dev/null
++++ b/ldns/include/ldns/rr_functions.h
+@@ -0,0 +1,363 @@
++/*
++ * rr_functions.h
++ *
++ * the .h file with defs for the per rr
++ * functions
++ *
++ * a Net::DNS like library for C
++ * 
++ * (c) NLnet Labs, 2005-2006
++ * 
++ * See the file LICENSE for the license
++ */
++#ifndef LDNS_RR_FUNCTIONS_H
++#define LDNS_RR_FUNCTIONS_H
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/**
++ * \file
++ *
++ * Defines some extra convenience functions for ldns_rr structures
++ */
++
++/* A / AAAA */
++/**
++ * returns the address of a LDNS_RR_TYPE_A rr
++ * \param[in] r the resource record
++ * \return a ldns_rdf* with the address or NULL on failure
++ */
++ldns_rdf* ldns_rr_a_address(const ldns_rr *r);
++
++/**
++ * sets the address of a LDNS_RR_TYPE_A rr
++ * \param[in] r the rr to use
++ * \param[in] f the address to set
++ * \return true on success, false otherwise
++ */
++bool ldns_rr_a_set_address(ldns_rr *r, ldns_rdf *f);
++
++/* NS */
++/**
++ * returns the name of a LDNS_RR_TYPE_NS rr
++ * \param[in] r the resource record
++ * \return a ldns_rdf* with the name or NULL on failure
++ */
++ldns_rdf* ldns_rr_ns_nsdname(const ldns_rr *r);
++
++/* MX */
++/**
++ * returns the mx pref. of a LDNS_RR_TYPE_MX rr
++ * \param[in] r the resource record
++ * \return a ldns_rdf* with the preference or NULL on failure
++ */
++ldns_rdf* ldns_rr_mx_preference(const ldns_rr *r);
++/**
++ * returns the mx host of a LDNS_RR_TYPE_MX rr
++ * \param[in] r the resource record
++ * \return a ldns_rdf* with the name of the MX host or NULL on failure
++ */
++ldns_rdf* ldns_rr_mx_exchange(const ldns_rr *r);
++
++/* RRSIG */
++/**
++ * returns the type covered of a LDNS_RR_TYPE_RRSIG rr
++ * \param[in] r the resource record
++ * \return a ldns_rdf* with the type covered or NULL on failure
++ */
++ldns_rdf* ldns_rr_rrsig_typecovered(const ldns_rr *r);
++/**
++ * sets the typecovered of a LDNS_RR_TYPE_RRSIG rr
++ * \param[in] r the rr to use
++ * \param[in] f the typecovered to set
++ * \return true on success, false otherwise
++ */
++bool ldns_rr_rrsig_set_typecovered(ldns_rr *r, ldns_rdf *f);
++/**
++ * returns the algorithm of a LDNS_RR_TYPE_RRSIG RR
++ * \param[in] r the resource record
++ * \return a ldns_rdf* with the algorithm or NULL on failure
++ */
++ldns_rdf* ldns_rr_rrsig_algorithm(const ldns_rr *r);
++/**
++ * sets the algorithm of a LDNS_RR_TYPE_RRSIG rr
++ * \param[in] r the rr to use
++ * \param[in] f the algorithm to set
++ * \return true on success, false otherwise
++ */
++bool ldns_rr_rrsig_set_algorithm(ldns_rr *r, ldns_rdf *f);
++/**
++ * returns the number of labels of a LDNS_RR_TYPE_RRSIG RR
++ * \param[in] r the resource record
++ * \return a ldns_rdf* with the number of labels or NULL on failure
++ */
++ldns_rdf *ldns_rr_rrsig_labels(const ldns_rr *r);
++/**
++ * sets the number of labels of a LDNS_RR_TYPE_RRSIG rr
++ * \param[in] r the rr to use
++ * \param[in] f the number of labels to set
++ * \return true on success, false otherwise
++ */
++bool ldns_rr_rrsig_set_labels(ldns_rr *r, ldns_rdf *f);
++/**
++ * returns the original TTL of a LDNS_RR_TYPE_RRSIG RR
++ * \param[in] r the resource record
++ * \return a ldns_rdf* with the original TTL or NULL on failure
++ */
++ldns_rdf* ldns_rr_rrsig_origttl(const ldns_rr *r);
++/**
++ * sets the original TTL of a LDNS_RR_TYPE_RRSIG rr
++ * \param[in] r the rr to use
++ * \param[in] f the original TTL to set
++ * \return true on success, false otherwise
++ */
++bool ldns_rr_rrsig_set_origttl(ldns_rr *r, ldns_rdf *f);
++/**
++ * returns the expiration time of a LDNS_RR_TYPE_RRSIG RR
++ * \param[in] r the resource record
++ * \return a ldns_rdf* with the expiration time or NULL on failure
++ */
++ldns_rdf* ldns_rr_rrsig_expiration(const ldns_rr *r);
++/**
++ * sets the expireation date of a LDNS_RR_TYPE_RRSIG rr
++ * \param[in] r the rr to use
++ * \param[in] f the expireation date to set
++ * \return true on success, false otherwise
++ */
++bool ldns_rr_rrsig_set_expiration(ldns_rr *r, ldns_rdf *f);
++/**
++ * returns the inception time of a LDNS_RR_TYPE_RRSIG RR
++ * \param[in] r the resource record
++ * \return a ldns_rdf* with the inception time or NULL on failure
++ */
++ldns_rdf* ldns_rr_rrsig_inception(const ldns_rr *r);
++/**
++ * sets the inception date of a LDNS_RR_TYPE_RRSIG rr
++ * \param[in] r the rr to use
++ * \param[in] f the inception date to set
++ * \return true on success, false otherwise
++ */
++bool ldns_rr_rrsig_set_inception(ldns_rr *r, ldns_rdf *f);
++/**
++ * returns the keytag of a LDNS_RR_TYPE_RRSIG RR
++ * \param[in] r the resource record
++ * \return a ldns_rdf* with the keytag or NULL on failure
++ */
++ldns_rdf* ldns_rr_rrsig_keytag(const ldns_rr *r);
++/**
++ * sets the keytag of a LDNS_RR_TYPE_RRSIG rr
++ * \param[in] r the rr to use
++ * \param[in] f the keytag to set
++ * \return true on success, false otherwise
++ */
++bool ldns_rr_rrsig_set_keytag(ldns_rr *r, ldns_rdf *f);
++/**
++ * returns the signers name of a LDNS_RR_TYPE_RRSIG RR
++ * \param[in] r the resource record
++ * \return a ldns_rdf* with the signers name or NULL on failure
++ */
++ldns_rdf* ldns_rr_rrsig_signame(const ldns_rr *r);
++/**
++ * sets the signers name of a LDNS_RR_TYPE_RRSIG rr
++ * \param[in] r the rr to use
++ * \param[in] f the signers name to set
++ * \return true on success, false otherwise
++ */
++bool ldns_rr_rrsig_set_signame(ldns_rr *r, ldns_rdf *f);
++/**
++ * returns the signature data of a LDNS_RR_TYPE_RRSIG RR
++ * \param[in] r the resource record
++ * \return a ldns_rdf* with the signature data or NULL on failure
++ */
++ldns_rdf* ldns_rr_rrsig_sig(const ldns_rr *r);
++/**
++ * sets the signature data of a LDNS_RR_TYPE_RRSIG rr
++ * \param[in] r the rr to use
++ * \param[in] f the signature data to set
++ * \return true on success, false otherwise
++ */
++bool ldns_rr_rrsig_set_sig(ldns_rr *r, ldns_rdf *f);
++
++/* DNSKEY */
++/**
++ * returns the flags of a LDNS_RR_TYPE_DNSKEY rr
++ * \param[in] r the resource record
++ * \return a ldns_rdf* with the flags or NULL on failure
++ */
++ldns_rdf* ldns_rr_dnskey_flags(const ldns_rr *r);
++/**
++ * sets the flags of a LDNS_RR_TYPE_DNSKEY rr
++ * \param[in] r the rr to use
++ * \param[in] f the flags to set
++ * \return true on success, false otherwise
++ */
++bool ldns_rr_dnskey_set_flags(ldns_rr *r, ldns_rdf *f);
++/**
++ * returns the protocol of a LDNS_RR_TYPE_DNSKEY rr
++ * \param[in] r the resource record
++ * \return a ldns_rdf* with the protocol or NULL on failure
++ */
++ldns_rdf* ldns_rr_dnskey_protocol(const ldns_rr *r);
++/**
++ * sets the protocol of a LDNS_RR_TYPE_DNSKEY rr
++ * \param[in] r the rr to use
++ * \param[in] f the protocol to set
++ * \return true on success, false otherwise
++ */
++bool ldns_rr_dnskey_set_protocol(ldns_rr *r, ldns_rdf *f);
++/**
++ * returns the algorithm of a LDNS_RR_TYPE_DNSKEY rr
++ * \param[in] r the resource record
++ * \return a ldns_rdf* with the algorithm or NULL on failure
++ */
++ldns_rdf* ldns_rr_dnskey_algorithm(const ldns_rr *r);
++/**
++ * sets the algorithm of a LDNS_RR_TYPE_DNSKEY rr
++ * \param[in] r the rr to use
++ * \param[in] f the algorithm to set
++ * \return true on success, false otherwise
++ */
++bool ldns_rr_dnskey_set_algorithm(ldns_rr *r, ldns_rdf *f);
++/**
++ * returns the key data of a LDNS_RR_TYPE_DNSKEY rr
++ * \param[in] r the resource record
++ * \return a ldns_rdf* with the key data or NULL on failure
++ */
++ldns_rdf* ldns_rr_dnskey_key(const ldns_rr *r);
++/**
++ * sets the key data of a LDNS_RR_TYPE_DNSKEY rr
++ * \param[in] r the rr to use
++ * \param[in] f the key data to set
++ * \return true on success, false otherwise
++ */
++bool ldns_rr_dnskey_set_key(ldns_rr *r, ldns_rdf *f);
++
++/**
++ * get the length of the keydata in bits
++ * \param[in] keydata the raw key data
++ * \param[in] len the length of the keydata
++ * \param[in] alg the cryptographic algorithm this is a key for
++ * \return the keysize in bits, or 0 on error
++ */
++size_t ldns_rr_dnskey_key_size_raw(const unsigned char *keydata,
++                                   const size_t len,
++                                   const ldns_algorithm alg);
++
++/**
++ * get the length of the keydata in bits
++ * \param[in] key the key rr to use
++ * \return the keysize in bits
++ */
++size_t ldns_rr_dnskey_key_size(const ldns_rr *key);
++
++/**
++ * The type of function to be passed to ldns_rr_soa_increment_func,
++ * ldns_rr_soa_increment_func_data or ldns_rr_soa_increment_int.
++ * The function will be called with as the first argument the current serial
++ * number of the SOA RR to be updated, and as the second argument a value
++ * given when calling ldns_rr_soa_increment_func_data or 
++ * ldns_rr_soa_increment_int. With ldns_rr_soa_increment_int the pointer
++ * value holds the integer value passed to ldns_rr_soa_increment_int,
++ * and it should be cast to intptr_t to be used as an integer by the
++ * serial modifying function.
++ */
++typedef uint32_t (*ldns_soa_serial_increment_func_t)(uint32_t, void*);
++
++/**
++ * Function to be used with dns_rr_soa_increment_func_int, to set the soa
++ * serial number. 
++ * \param[in] unused the (unused) current serial number.
++ * \param[in] data the serial number to be set.
++ */
++uint32_t ldns_soa_serial_identity(uint32_t unused, void *data);
++
++/**
++ * Function to be used with dns_rr_soa_increment_func, to increment the soa
++ * serial number with one. 
++ * \param[in] s the current serial number.
++ * \param[in] unused unused.
++ */
++uint32_t ldns_soa_serial_increment(uint32_t s, void *unused);
++
++/**
++ * Function to be used with dns_rr_soa_increment_func_int, to increment the soa
++ * serial number with a certain amount. 
++ * \param[in] s the current serial number.
++ * \param[in] data the amount to add to the current serial number.
++ */
++uint32_t ldns_soa_serial_increment_by(uint32_t s, void *data);
++
++/**
++ * Function to be used with ldns_rr_soa_increment_func or 
++ * ldns_rr_soa_increment_func_int to set the soa serial to the number of 
++ * seconds since unix epoch (1-1-1970 00:00). 
++ * When data is given (i.e. the function is called via
++ * ldns_rr_soa_increment_func_int), it is used as the current time. 
++ * When the resulting serial number is smaller than the current serial number,
++ * the current serial number is increased by one.
++ * \param[in] s the current serial number.
++ * \param[in] data the time in seconds since 1-1-1970 00:00
++ */
++uint32_t ldns_soa_serial_unixtime(uint32_t s, void *data);
++
++/**
++ * Function to be used with ldns_rr_soa_increment_func or 
++ * ldns_rr_soa_increment_func_int to set the soa serial to the current date
++ * succeeded by a two digit iteration (datecounter).
++ * When data is given (i.e. the function is called via
++ * ldns_rr_soa_increment_func_int), it is used as the current time. 
++ * When the resulting serial number is smaller than the current serial number,
++ * the current serial number is increased by one.
++ * \param[in] s the current serial number.
++ * \param[in] data the time in seconds since 1-1-1970 00:00
++ */
++uint32_t ldns_soa_serial_datecounter(uint32_t s, void *data);
++
++/**
++ * Increment the serial number of the given SOA by one.
++ * \param[in] soa The soa rr to be incremented
++ */
++void ldns_rr_soa_increment(
++		ldns_rr *soa);
++
++/**
++ * Increment the serial number of the given SOA with the given function.
++ * Included functions to be used here are: ldns_rr_soa_increment, 
++ * ldns_soa_serial_unixtime and ldns_soa_serial_datecounter.
++ * \param[in] soa The soa rr to be incremented
++ * \param[in] f the function to use to increment the soa rr.
++ */
++void ldns_rr_soa_increment_func(
++		ldns_rr *soa, ldns_soa_serial_increment_func_t f);
++
++/**
++ * Increment the serial number of the given SOA with the given function
++ * passing it the given data argument.
++ * \param[in] soa The soa rr to be incremented
++ * \param[in] f the function to use to increment the soa rr.
++ * \param[in] data this argument will be passed to f as the second argument.
++ */
++void ldns_rr_soa_increment_func_data(
++		ldns_rr *soa, ldns_soa_serial_increment_func_t f, void *data);
++
++/**
++ * Increment the serial number of the given SOA with the given function
++ * using data as an argument for the function.
++ * Included functions to be used here are: ldns_soa_serial_identity,
++ * ldns_rr_soa_increment_by, ldns_soa_serial_unixtime and 
++ * ldns_soa_serial_datecounter.
++ * \param[in] soa The soa rr to be incremented
++ * \param[in] f the function to use to increment the soa rr.
++ * \param[in] data this argument will be passed to f as the second argument
++ *                 (by casting it to void*).
++ */
++void ldns_rr_soa_increment_func_int(
++		ldns_rr *soa, ldns_soa_serial_increment_func_t f, int data);
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* LDNS_RR_FUNCTIONS_H */
+diff --git a/ldns/include/ldns/sha1.h b/ldns/include/ldns/sha1.h
+new file mode 100644
+index 0000000..d5b1082
+--- /dev/null
++++ b/ldns/include/ldns/sha1.h
+@@ -0,0 +1,38 @@
++#ifndef LDNS_SHA1_H
++#define LDNS_SHA1_H
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++ 
++#define LDNS_SHA1_BLOCK_LENGTH               64
++#define LDNS_SHA1_DIGEST_LENGTH              20
++
++typedef struct {
++        uint32_t       state[5];
++        uint64_t       count;
++        unsigned char   buffer[LDNS_SHA1_BLOCK_LENGTH];
++} ldns_sha1_ctx;
++  
++void ldns_sha1_init(ldns_sha1_ctx * context);
++void ldns_sha1_transform(uint32_t state[5], const unsigned char buffer[LDNS_SHA1_BLOCK_LENGTH]);
++void ldns_sha1_update(ldns_sha1_ctx *context, const unsigned char *data, unsigned int len);
++void ldns_sha1_final(unsigned char digest[LDNS_SHA1_DIGEST_LENGTH], ldns_sha1_ctx *context);
++
++/**
++ * Convenience function to digest a fixed block of data at once.
++ *
++ * \param[in] data the data to digest
++ * \param[in] data_len the length of data in bytes
++ * \param[out] digest the length of data in bytes
++ *             This pointer MUST have LDNS_SHA1_DIGEST_LENGTH bytes
++ *             available
++ * \return the SHA1 digest of the given data
++ */
++unsigned char *ldns_sha1(unsigned char *data, unsigned int data_len, unsigned char *digest);
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* LDNS_SHA1_H */
+diff --git a/ldns/include/ldns/sha2.h b/ldns/include/ldns/sha2.h
+new file mode 100644
+index 0000000..238767a
+--- /dev/null
++++ b/ldns/include/ldns/sha2.h
+@@ -0,0 +1,149 @@
++/*
++ * FILE:	sha2.h
++ * AUTHOR:	Aaron D. Gifford - http://www.aarongifford.com/
++ * 
++ * Copyright (c) 2000-2001, Aaron D. Gifford
++ * All rights reserved.
++ *
++ * Modified by Jelte Jansen to fit in ldns, and not clash with any
++ * system-defined SHA code.
++ * Changes:
++ *  - Renamed (external) functions and constants to fit ldns style
++ *  - Removed uintXX vs. u_intXX smartness, since ldns needs uintXX
++ *    anyway
++ *  - BYTE ORDER check replaced by simple ifdef as defined or not by
++ *    configure.ac
++ *  - Removed _End and _Data functions
++ *  - Added ldns_shaX(data, len, digest) functions
++ * 
++ * 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.
++ * 3. Neither the name of the copyright holder nor the names of contributors
++ *    may be used to endorse or promote products derived from this software
++ *    without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``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 OR CONTRIBUTOR(S) 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.
++ *
++ * $Id: sha2.h,v 1.1 2001/11/08 00:02:01 adg Exp adg $
++ */
++
++#ifndef __LDNS_SHA2_H__
++#define __LDNS_SHA2_H__
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++
++/*
++ * Import u_intXX_t size_t type definitions from system headers.  You
++ * may need to change this, or define these things yourself in this
++ * file.
++ */
++#include <sys/types.h>
++
++#if LDNS_BUILD_CONFIG_HAVE_INTTYPES_H
++
++#include <inttypes.h>
++
++#endif /* LDNS_BUILD_CONFIG_HAVE_INTTYPES_H */
++
++
++/*** SHA-256/384/512 Various Length Definitions ***********************/
++#define LDNS_SHA256_BLOCK_LENGTH		64
++#define LDNS_SHA256_DIGEST_LENGTH		32
++#define LDNS_SHA256_DIGEST_STRING_LENGTH	(LDNS_SHA256_DIGEST_LENGTH * 2 + 1)
++#define LDNS_SHA384_BLOCK_LENGTH		128
++#define LDNS_SHA384_DIGEST_LENGTH		48
++#define LDNS_SHA384_DIGEST_STRING_LENGTH	(LDNS_SHA384_DIGEST_LENGTH * 2 + 1)
++#define LDNS_SHA512_BLOCK_LENGTH		128
++#define LDNS_SHA512_DIGEST_LENGTH		64
++#define LDNS_SHA512_DIGEST_STRING_LENGTH	(LDNS_SHA512_DIGEST_LENGTH * 2 + 1)
++
++
++/*** SHA-256/384/512 Context Structures *******************************/
++
++typedef struct _ldns_sha256_CTX {
++	uint32_t	state[8];
++	uint64_t	bitcount;
++	uint8_t	buffer[LDNS_SHA256_BLOCK_LENGTH];
++} ldns_sha256_CTX;
++typedef struct _ldns_sha512_CTX {
++	uint64_t	state[8];
++	uint64_t	bitcount[2];
++	uint8_t	buffer[LDNS_SHA512_BLOCK_LENGTH];
++} ldns_sha512_CTX;
++
++typedef ldns_sha512_CTX ldns_sha384_CTX;
++
++
++/*** SHA-256/384/512 Function Prototypes ******************************/
++void ldns_sha256_init(ldns_sha256_CTX *);
++void ldns_sha256_update(ldns_sha256_CTX*, const uint8_t*, size_t);
++void ldns_sha256_final(uint8_t[LDNS_SHA256_DIGEST_LENGTH], ldns_sha256_CTX*);
++
++void ldns_sha384_init(ldns_sha384_CTX*);
++void ldns_sha384_update(ldns_sha384_CTX*, const uint8_t*, size_t);
++void ldns_sha384_final(uint8_t[LDNS_SHA384_DIGEST_LENGTH], ldns_sha384_CTX*);
++
++void ldns_sha512_init(ldns_sha512_CTX*);
++void ldns_sha512_update(ldns_sha512_CTX*, const uint8_t*, size_t);
++void ldns_sha512_final(uint8_t[LDNS_SHA512_DIGEST_LENGTH], ldns_sha512_CTX*);
++
++/**
++ * Convenience function to digest a fixed block of data at once.
++ *
++ * \param[in] data the data to digest
++ * \param[in] data_len the length of data in bytes
++ * \param[out] digest the length of data in bytes
++ *             This pointer MUST have LDNS_SHA256_DIGEST_LENGTH bytes
++ *             available
++ * \return the SHA1 digest of the given data
++ */
++unsigned char *ldns_sha256(unsigned char *data, unsigned int data_len, unsigned char *digest);
++
++/**
++ * Convenience function to digest a fixed block of data at once.
++ *
++ * \param[in] data the data to digest
++ * \param[in] data_len the length of data in bytes
++ * \param[out] digest the length of data in bytes
++ *             This pointer MUST have LDNS_SHA384_DIGEST_LENGTH bytes
++ *             available
++ * \return the SHA1 digest of the given data
++ */
++unsigned char *ldns_sha384(unsigned char *data, unsigned int data_len, unsigned char *digest);
++
++/**
++ * Convenience function to digest a fixed block of data at once.
++ *
++ * \param[in] data the data to digest
++ * \param[in] data_len the length of data in bytes
++ * \param[out] digest the length of data in bytes
++ *             This pointer MUST have LDNS_SHA512_DIGEST_LENGTH bytes
++ *             available
++ * \return the SHA1 digest of the given data
++ */
++unsigned char *ldns_sha512(unsigned char *data, unsigned int data_len, unsigned char *digest);
++
++#ifdef	__cplusplus
++}
++#endif /* __cplusplus */
++
++#endif /* __LDNS_SHA2_H__ */
+diff --git a/ldns/include/ldns/str2host.h b/ldns/include/ldns/str2host.h
+new file mode 100644
+index 0000000..d639970
+--- /dev/null
++++ b/ldns/include/ldns/str2host.h
+@@ -0,0 +1,319 @@
++/**
++ * str2host.h - conversion from str to the host fmt
++ *
++ * a Net::DNS like library for C
++ *
++ * (c) NLnet Labs, 2005-2006
++ *
++ * See the file LICENSE for the license
++ */
++
++#ifndef LDNS_2HOST_H
++#define LDNS_2HOST_H
++
++#include <ldns/common.h>
++#include <ldns/error.h>
++#include <ldns/rr.h>
++#include <ldns/rdata.h>
++#include <ldns/packet.h>
++#include <ldns/buffer.h>
++#include <ctype.h>
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/**
++ * \file
++ *
++ * Defines functions to convert dns data in presentation format or text files
++ * to internal structures.
++ */
++
++/**
++ * convert a byte into wireformat
++ * \param[in] rd the rdf where to put the data
++ * \param[in] bytestr the string to be converted
++ * \return ldns_status
++ */
++ldns_status ldns_str2rdf_int8(ldns_rdf **rd, const char *bytestr);
++
++/**
++ * convert a string to a int16 in wireformat
++ * \param[in] rd the rdf where to put the data
++ * \param[in] shortstr the string to be converted
++ * \return ldns_status
++ */
++ldns_status ldns_str2rdf_int16(ldns_rdf **rd, const char *shortstr);
++
++/**
++ * convert a strings into a 4 byte int in wireformat
++ * \param[in] rd the rdf where to put the data
++ * \param[in] longstr the string to be converted
++ * \return ldns_status
++ */
++ldns_status ldns_str2rdf_int32(ldns_rdf **rd, const char *longstr);
++
++/**
++ * convert a time string to a time value in wireformat
++ * \param[in] rd the rdf where to put the data
++ * \param[in] time the string to be converted
++ * \return ldns_status
++ */
++ldns_status ldns_str2rdf_time(ldns_rdf **rd, const char *time);
++
++/* convert string with NSEC3 salt to wireformat) 
++ * \param[in] rd the rdf where to put the data
++ * \param[in] str the string to be converted
++ * return ldns_status
++ */
++ldns_status ldns_str2rdf_nsec3_salt(ldns_rdf **rd, const char *nsec3_salt);
++
++/* convert a time period (think TTL's) to wireformat) 
++ * \param[in] rd the rdf where to put the data
++ * \param[in] str the string to be converted
++ * return ldns_status
++ */
++ldns_status ldns_str2rdf_period(ldns_rdf **rd, const char *str);
++
++/**
++ * convert str with an A record into wireformat
++ * \param[in] rd the rdf where to put the data
++ * \param[in] str the string to be converted
++ * \return ldns_status
++ */
++ldns_status ldns_str2rdf_a(ldns_rdf **rd, const char *str);
++
++/**
++ * convert the str with an AAAA record into wireformat
++ * \param[in] rd the rdf where to put the data
++ * \param[in] str the string to be converted
++ * \return ldns_status
++ */
++ldns_status ldns_str2rdf_aaaa(ldns_rdf **rd, const char *str);
++
++/**
++ * convert a string into wireformat (think txt record)
++ * \param[in] rd the rdf where to put the data
++ * \param[in] str the string to be converted (NULL terminated)
++ * \return ldns_status
++ */
++ldns_status ldns_str2rdf_str(ldns_rdf **rd, const char *str);
++
++/**
++ * convert str with the apl record into wireformat
++ * \param[in] rd the rdf where to put the data
++ * \param[in] str the string to be converted
++ * \return ldns_status
++ */
++ldns_status ldns_str2rdf_apl(ldns_rdf **rd, const char *str);
++
++/**
++ * convert the string with the b64 data into wireformat
++ * \param[in] rd the rdf where to put the data
++ * \param[in] str the string to be converted
++ * \return ldns_status
++ */
++ldns_status ldns_str2rdf_b64(ldns_rdf **rd, const char *str);
++
++/**
++ * convert the string with the b32 ext hex data into wireformat
++ * \param[in] rd the rdf where to put the data
++ * \param[in] str the string to be converted
++ * \return ldns_status
++ */
++ldns_status ldns_str2rdf_b32_ext(ldns_rdf **rd, const char *str);
++
++/**
++ * convert a hex value into wireformat
++ * \param[in] rd the rdf where to put the data
++ * \param[in] str the string to be converted
++ * \return ldns_status
++ */
++ldns_status ldns_str2rdf_hex(ldns_rdf **rd, const char *str);
++
++/**
++ * convert string with nsec into wireformat
++ * \param[in] rd the rdf where to put the data
++ * \param[in] str the string to be converted
++ * \return ldns_status
++ */
++ldns_status ldns_str2rdf_nsec(ldns_rdf **rd, const char *str);
++
++/**
++ * convert a rrtype into wireformat
++ * \param[in] rd the rdf where to put the data
++ * \param[in] str the string to be converted
++ * \return ldns_status
++ */
++ldns_status ldns_str2rdf_type(ldns_rdf **rd, const char *str);
++
++/**
++ * convert string with a classname into wireformat
++ * \param[in] rd the rdf where to put the data
++ * \param[in] str the string to be converted
++ * \return ldns_status
++ */
++ldns_status ldns_str2rdf_class(ldns_rdf **rd, const char *str);
++
++/**
++ * convert an certificate algorithm value into wireformat
++ * \param[in] rd the rdf where to put the data
++ * \param[in] str the string to be converted
++ * \return ldns_status
++ */
++ldns_status ldns_str2rdf_cert_alg(ldns_rdf **rd, const char *str);
++
++/**
++ * convert an algorithm value into wireformat
++ * \param[in] rd the rdf where to put the data
++ * \param[in] str the string to be converted
++ * \return ldns_status
++ */
++ldns_status ldns_str2rdf_alg(ldns_rdf **rd, const char *str);
++
++/**
++ * convert a tlsa certificate usage value into wireformat
++ * \param[in] rd the rdf where to put the data
++ * \param[in] str the string to be converted
++ * \return ldns_status
++ */
++ldns_status ldns_str2rdf_certificate_usage(ldns_rdf **rd, const char *str);
++
++/**
++ * convert a tlsa selector value into wireformat
++ * \param[in] rd the rdf where to put the data
++ * \param[in] str the string to be converted
++ * \return ldns_status
++ */
++ldns_status ldns_str2rdf_selector(ldns_rdf **rd, const char *str);
++
++/**
++ * convert a tlsa matching type value into wireformat
++ * \param[in] rd the rdf where to put the data
++ * \param[in] str the string to be converted
++ * \return ldns_status
++ */
++ldns_status ldns_str2rdf_matching_type(ldns_rdf **rd, const char *str);
++
++/**
++ * convert a string with a unknown RR into wireformat
++ * \param[in] rd the rdf where to put the data
++ * \param[in] str the string to be converted
++ * \return ldns_status
++ */
++ldns_status ldns_str2rdf_unknown(ldns_rdf **rd, const char *str);
++
++/**
++ * convert string with a protocol service into wireformat
++ * \param[in] rd the rdf where to put the data
++ * \param[in] str the string to be converted
++ * \return ldns_status
++ */
++ldns_status ldns_str2rdf_service(ldns_rdf **rd, const char *str);
++
++/**
++ * convert a string with a LOC RR into wireformat
++ * \param[in] rd the rdf where to put the data
++ * \param[in] str the string to be converted
++ * \return ldns_status
++ */
++ldns_status ldns_str2rdf_loc(ldns_rdf **rd, const char *str);
++
++/**
++ * convert string with a WKS RR into wireformat
++ * \param[in] rd the rdf where to put the data
++ * \param[in] str the string to be converted
++ * \return ldns_status
++ */
++ldns_status ldns_str2rdf_wks(ldns_rdf **rd, const char *str);
++
++/**
++ * convert a str with a NSAP RR into wireformat
++ * \param[in] rd the rdf where to put the data
++ * \param[in] str the string to be converted
++ * \return ldns_status
++ */
++ldns_status ldns_str2rdf_nsap(ldns_rdf **rd, const char *str);
++
++/**
++ * convert a str with a ATMA RR into wireformat
++ * \param[in] rd the rdf where to put the data
++ * \param[in] str the string to be converted
++ * \return ldns_status
++ */
++ldns_status ldns_str2rdf_atma(ldns_rdf **rd, const char *str);
++
++/**
++ * convert a str with a IPSECKEY RR into wireformat
++ * \param[in] rd the rdf where to put the data
++ * \param[in] str the string to be converted
++ * \return ldns_status
++ */
++ldns_status ldns_str2rdf_ipseckey(ldns_rdf **rd, const char *str);
++
++/**
++ * convert a dname string into wireformat
++ * \param[in] rd the rdf where to put the data
++ * \param[in] str the string to be converted
++ * \return ldns_status
++ */
++ldns_status ldns_str2rdf_dname(ldns_rdf **rd, const char *str);
++
++/**
++ * convert 4 * 16bit hex separated by colons into wireformat
++ * \param[in] rd the rdf where to put the data
++ * \param[in] str the string to be converted
++ * \return ldns_status
++ */
++ldns_status ldns_str2rdf_ilnp64(ldns_rdf **rd, const char *str);
++
++/**
++ * convert 6 hex bytes separated by dashes into wireformat
++ * \param[in] rd the rdf where to put the data
++ * \param[in] str the string to be converted
++ * \return ldns_status
++ */
++ldns_status ldns_str2rdf_eui48(ldns_rdf **rd, const char *str);
++
++/**
++ * convert 8 hex bytes separated by dashes into wireformat
++ * \param[in] rd the rdf where to put the data
++ * \param[in] str the string to be converted
++ * \return ldns_status
++ */
++ldns_status ldns_str2rdf_eui64(ldns_rdf **rd, const char *str);
++
++/**
++ * Convert a non-zero sequence of US-ASCII letters and numbers into wireformat
++ * \param[in] rd the rdf where to put the data
++ * \param[in] str the string to be converted
++ * \return ldns_status
++ */
++ldns_status ldns_str2rdf_tag(ldns_rdf **rd, const char *str);
++
++/**
++ * Convert a <character-string> encoding of the value field as specified 
++ * [RFC1035], Section 5.1., encoded as one bug chunk of data.
++ * \param[in] rd the rdf where to put the data
++ * \param[in] str the string to be converted
++ * \return ldns_status
++ */
++ldns_status ldns_str2rdf_long_str(ldns_rdf **rd, const char *str);
++
++/**
++ * Convert a "<algorithm> <hit> <pk>" encoding of the value field as specified 
++ * in Section 6. of [RFC5205], encoded as wireformat as specified in Section 5.
++ * of [RFC5205].
++ * \param[in] rd the rdf where to put the data
++ * \param[in] str the string to be converted
++ * \return ldns_status
++ */
++ldns_status ldns_str2rdf_hip(ldns_rdf **rd, const char *str);
++
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* LDNS_2HOST_H */
+diff --git a/ldns/include/ldns/tsig.h b/ldns/include/ldns/tsig.h
+new file mode 100644
+index 0000000..676045f
+--- /dev/null
++++ b/ldns/include/ldns/tsig.h
+@@ -0,0 +1,101 @@
++/*
++ * tsig.h -- defines for TSIG [RFC2845]
++ *
++ * Copyright (c) 2005-2008, NLnet Labs. All rights reserved.
++ *
++ * See LICENSE for the license.
++ */
++
++#ifndef LDNS_TSIG_H
++#define LDNS_TSIG_H
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/**
++ * \file
++ *
++ * Defines functions for TSIG usage
++ */
++
++
++/**
++ * Contains credentials for TSIG
++*/
++typedef struct ldns_tsig_credentials_struct
++{
++    char *algorithm;
++    char *keyname;
++    char *keydata;
++    /* XXX More eventually. */
++} ldns_tsig_credentials;
++
++char *ldns_tsig_algorithm(ldns_tsig_credentials *);
++char *ldns_tsig_keyname(ldns_tsig_credentials *);
++char *ldns_tsig_keydata(ldns_tsig_credentials *);
++char *ldns_tsig_keyname_clone(ldns_tsig_credentials *);
++char *ldns_tsig_keydata_clone(ldns_tsig_credentials *);
++
++/**
++ * verifies the tsig rr for the given packet and key.
++ * The wire must be given too because tsig does not sign normalized packets.
++ * \param[in] pkt the packet to verify
++ * \param[in] wire needed to verify the mac
++ * \param[in] wire_size size of wire
++ * \param[in] key_name the name of the shared key
++ * \param[in] key_data the key in base 64 format
++ * \param[in] mac original mac
++ * \return true if tsig is correct, false if not, or if tsig is not set
++ */
++bool ldns_pkt_tsig_verify(ldns_pkt *pkt, uint8_t *wire, size_t wire_size, const char *key_name, const char *key_data, ldns_rdf *mac);
++
++/**
++ * verifies the tsig rr for the given packet and key.
++ * The wire must be given too because tsig does not sign normalized packets.
++ * \param[in] pkt the packet to verify
++ * \param[in] wire needed to verify the mac
++ * \param[in] wire_size size of wire
++ * \param[in] key_name the name of the shared key
++ * \param[in] key_data the key in base 64 format
++ * \param[in] mac original mac
++ * \param[in] tsig_timers_only must be zero for the first packet and positive for subsequent packets. If zero, all digest
++   components are used to verify the _mac. If non-zero, only the TSIG timers are used to verify the mac.
++ * \return true if tsig is correct, false if not, or if tsig is not set
++ */
++bool ldns_pkt_tsig_verify_next(ldns_pkt *pkt, uint8_t *wire, size_t wire_size, const char *key_name, const char *key_data, ldns_rdf *mac,
++    int tsig_timers_only);
++
++/**
++ * creates a tsig rr for the given packet and key.
++ * \param[in] pkt the packet to sign
++ * \param[in] key_name the name of the shared key
++ * \param[in] key_data the key in base 64 format
++ * \param[in] fudge seconds of error permitted in time signed
++ * \param[in] algorithm_name the name of the algorithm used
++ * \param[in] query_mac is added to the digest if not NULL (so NULL is for signing queries, not NULL is for signing answers)
++ * \return status (OK if success)
++ */
++ldns_status ldns_pkt_tsig_sign(ldns_pkt *pkt, const char *key_name, const char *key_data, uint16_t fudge,
++    const char *algorithm_name, ldns_rdf *query_mac);
++
++/**
++ * creates a tsig rr for the given packet and key.
++ * \param[in] pkt the packet to sign
++ * \param[in] key_name the name of the shared key
++ * \param[in] key_data the key in base 64 format
++ * \param[in] fudge seconds of error permitted in time signed
++ * \param[in] algorithm_name the name of the algorithm used
++ * \param[in] query_mac is added to the digest if not NULL (so NULL is for signing queries, not NULL is for signing answers)
++ * \param[in] tsig_timers_only must be zero for the first packet and positive for subsequent packets. If zero, all digest
++   components are used to create the query_mac. If non-zero, only the TSIG timers are used to create the query_mac.
++ * \return status (OK if success)
++ */
++ldns_status ldns_pkt_tsig_sign_next(ldns_pkt *pkt, const char *key_name, const char *key_data, uint16_t fudge,
++    const char *algorithm_name, ldns_rdf *query_mac, int tsig_timers_only);
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* LDNS_TSIG_H */
+diff --git a/ldns/include/ldns/update.h b/ldns/include/ldns/update.h
+new file mode 100644
+index 0000000..d3459d3
+--- /dev/null
++++ b/ldns/include/ldns/update.h
+@@ -0,0 +1,115 @@
++/*
++ * update.h
++ *
++ * Functions for RFC 2136 Dynamic Update
++ *
++ * Copyright (c) 2005-2008, NLnet Labs. All rights reserved.
++ *
++ * See LICENSE for the license.
++ */
++
++/**
++ * \file
++ *
++ * Defines functions to perform UPDATE queries
++ */
++
++
++#ifndef LDNS_UPDATE_H
++#define LDNS_UPDATE_H
++
++#include <ldns/resolver.h>
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/**
++ * create an update packet from zone name, class and the rr lists
++ * \param[in] zone_rdf name of the zone
++ * \param[in] clas zone class
++ * \param[in] pr_rrlist list of Prerequisite Section RRs
++ * \param[in] up_rrlist list of Updates Section RRs
++ * \param[in] ad_rrlist list of Additional Data Section RRs (currently unused)
++ * \return the new packet
++ */
++ldns_pkt *ldns_update_pkt_new(ldns_rdf *zone_rdf, ldns_rr_class clas, ldns_rr_list *pr_rrlist, ldns_rr_list *up_rrlist, ldns_rr_list *ad_rrlist);
++
++/**
++ * add tsig credentials to
++ * a packet from a resolver
++ * \param[in] p packet to copy to
++ * \param[in] r resolver to copy from
++ *
++ * \return status wether successfull or not
++ */
++ldns_status ldns_update_pkt_tsig_add(ldns_pkt *p, ldns_resolver *r);
++
++/* access functions */
++
++/**
++ * Get the zo count
++ * \param[in] p the packet
++ * \return the zo count
++ */
++uint16_t ldns_update_zocount(const ldns_pkt *p);
++/**
++ * Get the zo count
++ * \param[in] p the packet
++ * \return the pr count
++ */
++uint16_t ldns_update_prcount(const ldns_pkt *p);
++/**
++ * Get the zo count
++ * \param[in] p the packet
++ * \return the up count
++ */
++uint16_t ldns_update_upcount(const ldns_pkt *p);
++/**
++ * Get the zo count
++ * \param[in] p the packet
++ * \return the ad count
++ */
++uint16_t ldns_update_ad(const ldns_pkt *p);
++/**
++ * Set the zo count
++ * \param[in] p the packet
++ * \param[in] c the zo count to set
++ */
++void ldns_update_set_zo(ldns_pkt *p, uint16_t c);
++/**
++ * Set the pr count
++ * \param[in] p the packet
++ * \param[in] c the pr count to set
++ */
++void ldns_update_set_prcount(ldns_pkt *p, uint16_t c);
++/**
++ * Set the up count
++ * \param[in] p the packet
++ * \param[in] c the up count to set
++ */
++void ldns_update_set_upcount(ldns_pkt *p, uint16_t c);
++/**
++ * Set the ad count
++ * \param[in] p the packet
++ * \param[in] c the ad count to set
++ */
++void ldns_update_set_adcount(ldns_pkt *p, uint16_t c);
++
++/* soa functions that need to be configured */
++/*
++ * Not sure if we want to keep these like this, therefore
++ * not documented
++ */
++ldns_status ldns_update_soa_mname(ldns_rdf *zone, ldns_resolver *r, ldns_rr_class c, ldns_rdf **mname);
++/* 
++ * Not sure if we want to keep these like this, therefore
++ * not documented
++ */
++ldns_status ldns_update_soa_zone_mname(const char *fqdn, ldns_resolver *r, ldns_rr_class c, ldns_rdf **zone_rdf, ldns_rdf **mname_rdf);
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif  /* LDNS_UPDATE_H */
+diff --git a/ldns/include/ldns/util.h b/ldns/include/ldns/util.h
+new file mode 100644
+index 0000000..86848eb
+--- /dev/null
++++ b/ldns/include/ldns/util.h
+@@ -0,0 +1,392 @@
++/*
++ * util.h
++ *  
++ * helper function header file
++ * 
++ * a Net::DNS like library for C
++ * 
++ * (c) NLnet Labs, 2004
++ * 
++ * See the file LICENSE for the license
++ */
++
++#ifndef _UTIL_H
++#define _UTIL_H
++
++#include "EXTERN.h"
++#include "perl.h"
++#include <ldns/common.h>
++#include <time.h>
++#include <stdio.h>
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++#define dprintf(X,Y) fprintf(stderr, (X), (Y))
++/* #define	dprintf(X, Y)  */
++
++#define LDNS_VERSION "1.6.18"
++#define LDNS_REVISION ((1<<16)|(6<<8)|(18))
++
++/**
++ * splint static inline workaround
++ */
++#ifdef S_SPLINT_S
++#  define INLINE 
++#else
++#  ifdef SWIG
++#    define INLINE static
++#  else
++#    define INLINE static inline
++#  endif
++#endif
++
++/**
++ * Memory management macros
++ */
++#define LDNS_MALLOC(type)		LDNS_XMALLOC(type, 1)
++
++#define LDNS_XMALLOC(type, count)	((type *) malloc((count) * sizeof(type)))
++
++#define LDNS_CALLOC(type, count)	((type *) calloc((count), sizeof(type)))
++
++#define LDNS_REALLOC(ptr, type)		LDNS_XREALLOC((ptr), type, 1)
++
++#define LDNS_XREALLOC(ptr, type, count)				\
++	((type *) realloc((ptr), (count) * sizeof(type)))
++
++#define LDNS_FREE(ptr) \
++	do { free((ptr)); (ptr) = NULL; } while (0)
++
++#define LDNS_DEP     printf("DEPRECATED FUNCTION!\n");
++
++/*
++ * Copy data allowing for unaligned accesses in network byte order
++ * (big endian).
++ */
++INLINE uint16_t
++ldns_read_uint16(const void *src)
++{
++#ifdef ALLOW_UNALIGNED_ACCESSES
++	return ntohs(*(const uint16_t *) src);
++#else
++	const uint8_t *p = (const uint8_t *) src;
++	return ((uint16_t) p[0] << 8) | (uint16_t) p[1];
++#endif
++}
++
++INLINE uint32_t
++ldns_read_uint32(const void *src)
++{
++#ifdef ALLOW_UNALIGNED_ACCESSES
++	return ntohl(*(const uint32_t *) src);
++#else
++	const uint8_t *p = (const uint8_t *) src;
++	return (  ((uint32_t) p[0] << 24)
++		| ((uint32_t) p[1] << 16)
++		| ((uint32_t) p[2] << 8)
++		|  (uint32_t) p[3]);
++#endif
++}
++
++/*
++ * Copy data allowing for unaligned accesses in network byte order
++ * (big endian).
++ */
++INLINE void
++ldns_write_uint16(void *dst, uint16_t data)
++{
++#ifdef ALLOW_UNALIGNED_ACCESSES
++	* (uint16_t *) dst = htons(data);
++#else
++	uint8_t *p = (uint8_t *) dst;
++	p[0] = (uint8_t) ((data >> 8) & 0xff);
++	p[1] = (uint8_t) (data & 0xff);
++#endif
++}
++
++INLINE void
++ldns_write_uint32(void *dst, uint32_t data)
++{
++#ifdef ALLOW_UNALIGNED_ACCESSES
++	* (uint32_t *) dst = htonl(data);
++#else
++	uint8_t *p = (uint8_t *) dst;
++	p[0] = (uint8_t) ((data >> 24) & 0xff);
++	p[1] = (uint8_t) ((data >> 16) & 0xff);
++	p[2] = (uint8_t) ((data >> 8) & 0xff);
++	p[3] = (uint8_t) (data & 0xff);
++#endif
++}
++
++/* warning. */
++INLINE void
++ldns_write_uint64_as_uint48(void *dst, uint64_t data)
++{
++	uint8_t *p = (uint8_t *) dst;
++	p[0] = (uint8_t) ((data >> 40) & 0xff);
++	p[1] = (uint8_t) ((data >> 32) & 0xff);
++	p[2] = (uint8_t) ((data >> 24) & 0xff);
++	p[3] = (uint8_t) ((data >> 16) & 0xff);
++	p[4] = (uint8_t) ((data >> 8) & 0xff);
++	p[5] = (uint8_t) (data & 0xff);
++}
++
++
++/**
++ * Structure to do a Schwartzian-like transformation, for instance when
++ * sorting. If you need a transformation on the objects that are sorted,
++ * you can sue this to store the transformed values, so you do not
++ * need to do the transformation again for each comparison
++ */
++struct ldns_schwartzian_compare_struct {
++	void *original_object;
++	void *transformed_object;
++};
++
++/** A general purpose lookup table
++ *  
++ *  Lookup tables are arrays of (id, name) pairs,
++ *  So you can for instance lookup the RCODE 3, which is "NXDOMAIN",
++ *  and vice versa. The lookup tables themselves are defined wherever needed,
++ *  for instance in \ref host2str.c
++ */
++struct ldns_struct_lookup_table {
++        int id;
++        const char *name;
++};
++typedef struct ldns_struct_lookup_table ldns_lookup_table;
++  
++/**
++ * Looks up the table entry by name, returns NULL if not found.
++ * \param[in] table the lookup table to search in
++ * \param[in] name what to search for
++ * \return the item found
++ */
++ldns_lookup_table *ldns_lookup_by_name(ldns_lookup_table table[],
++                                       const char *name);
++
++/**
++ * Looks up the table entry by id, returns NULL if not found.
++ * \param[in] table the lookup table to search in
++ * \param[in] id what to search for
++ * \return the item found
++ */
++ldns_lookup_table *ldns_lookup_by_id(ldns_lookup_table table[], int id);
++
++/**
++ * Returns the value of the specified bit
++ * The bits are counted from left to right, so bit #0 is the
++ * left most bit.
++ * \param[in] bits array holding the bits
++ * \param[in] index to the wanted bit
++ * \return 
++ */
++int ldns_get_bit(uint8_t bits[], size_t index);
++
++
++/**
++ * Returns the value of the specified bit
++ * The bits are counted from right to left, so bit #0 is the
++ * right most bit.
++ * \param[in] bits array holding the bits
++ * \param[in] index to the wanted bit
++ * \return 1 or 0 depending no the bit state
++ */
++int ldns_get_bit_r(uint8_t bits[], size_t index);
++
++/**
++ * sets the specified bit in the specified byte to
++ * 1 if value is true, 0 if false
++ * The bits are counted from right to left, so bit #0 is the
++ * right most bit.
++ * \param[in] byte the bit to set the bit in
++ * \param[in] bit_nr the bit to set (0 <= n <= 7)
++ * \param[in] value whether to set the bit to 1 or 0
++ * \return 1 or 0 depending no the bit state
++ */
++void ldns_set_bit(uint8_t *byte, int bit_nr, bool value);
++
++/**
++ * Returns the value of a to the power of b
++ * (or 1 of b < 1)
++ */
++/*@unused@*/
++INLINE long
++ldns_power(long a, long b) {
++	long result = 1;
++	while (b > 0) {
++		if (b & 1) {
++			result *= a;
++			if (b == 1) {
++				return result;
++			}
++		}
++		a *= a;
++		b /= 2;
++	}
++	return result;
++}
++
++/**
++ * Returns the int value of the given (hex) digit
++ * \param[in] ch the hex char to convert
++ * \return the converted decimal value
++ */
++int ldns_hexdigit_to_int(char ch);
++
++/**
++ * Returns the char (hex) representation of the given int
++ * \param[in] ch the int to convert
++ * \return the converted hex char
++ */
++char ldns_int_to_hexdigit(int ch);
++
++/**
++ * Converts a hex string to binary data
++ *
++ * \param[out] data The binary result is placed here.
++ * At least strlen(str)/2 bytes should be allocated
++ * \param[in] str The hex string to convert.
++ * This string should not contain spaces
++ * \return The number of bytes of converted data, or -1 if one of the arguments * is NULL, or -2 if the string length is not an even number
++ */
++int
++ldns_hexstring_to_data(uint8_t *data, const char *str);
++
++/**
++ * Show the internal library version
++ * \return a string with the version in it
++ */
++const char * ldns_version(void);
++
++/**
++ * Convert TM to seconds since epoch (midnight, January 1st, 1970).
++ * Like timegm(3), which is not always available.
++ * \param[in] tm a struct tm* with the date
++ * \return the seconds since epoch
++ */
++time_t ldns_mktime_from_utc(const struct tm *tm);
++
++time_t mktime_from_utc(const struct tm *tm);
++
++/**
++ * The function interprets time as the number of seconds since epoch
++ * with respect to now using serial arithmitics (rfc1982).
++ * That number of seconds is then converted to broken-out time information.
++ * This is especially usefull when converting the inception and expiration
++ * fields of RRSIG records.
++ *
++ * \param[in] time number of seconds since epoch (midnight, January 1st, 1970)
++ *            to be intepreted as a serial arithmitics number relative to now.
++ * \param[in] now number of seconds since epoch (midnight, January 1st, 1970)
++ *            to which the time value is compared to determine the final value.
++ * \param[out] result the struct with the broken-out time information
++ * \return result on success or NULL on error
++ */
++struct tm * ldns_serial_arithmitics_gmtime_r(int32_t time, time_t now, struct tm *result);
++ 
++/**
++ * Seed the random function.
++ * If the file descriptor is specified, the random generator is seeded with
++ * data from that file. If not, /dev/urandom is used.
++ *
++ * applications should call this if they need entropy data within ldns
++ * If openSSL is available, it is automatically seeded from /dev/urandom
++ * or /dev/random.
++ *
++ * If you need more entropy, or have no openssl available, this function
++ * MUST be called at the start of the program
++ *
++ * If openssl *is* available, this function just adds more entropy
++ *
++ * \param[in] fd a file providing entropy data for the seed
++ * \param[in] size the number of bytes to use as entropy data. If this is 0,
++ *            only the minimal amount is taken (usually 4 bytes)
++ * \return 0 if seeding succeeds, 1 if it fails
++ */
++int ldns_init_random(FILE *fd, unsigned int size);
++
++/**
++ * Get random number.
++ * \return random number.
++ *
++ */
++uint16_t ldns_get_random(void);
++
++/**
++ * Encode data as BubbleBabble
++ *
++ * \param[in] data a pointer to data to be encoded
++ * \param[in] len size the number of bytes of data
++ * \return a string of BubbleBabble
++ */
++char *ldns_bubblebabble(uint8_t *data, size_t len);
++
++
++INLINE time_t ldns_time(time_t *t) { return time(t); }
++
++
++/**
++ * calculates the size needed to store the result of b32_ntop
++ */
++/*@unused@*/
++INLINE size_t ldns_b32_ntop_calculate_size(size_t src_data_length)
++{
++	return src_data_length == 0 ? 0 : ((src_data_length - 1) / 5 + 1) * 8;
++}
++
++INLINE size_t ldns_b32_ntop_calculate_size_no_padding(size_t src_data_length)
++{
++	return ((src_data_length + 3) * 8 / 5) - 4;
++}
++
++int ldns_b32_ntop(const uint8_t* src_data, size_t src_data_length,
++	     char* target_text_buffer, size_t target_text_buffer_size);
++
++int ldns_b32_ntop_extended_hex(const uint8_t* src_data, size_t src_data_length,
++	     char* target_text_buffer, size_t target_text_buffer_size);
++
++#if ! LDNS_BUILD_CONFIG_HAVE_B32_NTOP
++
++int b32_ntop(const uint8_t* src_data, size_t src_data_length,
++	     char* target_text_buffer, size_t target_text_buffer_size);
++
++int b32_ntop_extended_hex(const uint8_t* src_data, size_t src_data_length,
++	     char* target_text_buffer, size_t target_text_buffer_size);
++
++#endif /* ! LDNS_BUILD_CONFIG_HAVE_B32_NTOP */
++
++
++/**
++ * calculates the size needed to store the result of b32_pton
++ */
++/*@unused@*/
++INLINE size_t ldns_b32_pton_calculate_size(size_t src_text_length)
++{
++	return src_text_length * 5 / 8;
++}
++
++int ldns_b32_pton(const char* src_text, size_t src_text_length,
++	       	uint8_t* target_data_buffer, size_t target_data_buffer_size);
++
++int ldns_b32_pton_extended_hex(const char* src_text, size_t src_text_length,
++		uint8_t* target_data_buffer, size_t target_data_buffer_size);
++
++#if ! LDNS_BUILD_CONFIG_HAVE_B32_PTON
++
++int b32_pton(const char* src_text, size_t src_text_length,
++	       	uint8_t* target_data_buffer, size_t target_data_buffer_size);
++
++int b32_pton_extended_hex(const char* src_text, size_t src_text_length,
++		uint8_t* target_data_buffer, size_t target_data_buffer_size);
++
++#endif /* ! LDNS_BUILD_CONFIG_HAVE_B32_PTON */
++
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* !_UTIL_H */
+diff --git a/ldns/include/ldns/wire2host.h b/ldns/include/ldns/wire2host.h
+new file mode 100644
+index 0000000..53155b3
+--- /dev/null
++++ b/ldns/include/ldns/wire2host.h
+@@ -0,0 +1,197 @@
++/*
++ * wire2host.h - from wire conversion routines
++ *
++ * a Net::DNS like library for C
++ *
++ * (c) NLnet Labs, 2005-2006
++ *
++ * See the file LICENSE for the license
++ */
++
++/**
++ * \file
++ *
++ * Contains functions that translate dns data from the wire format (as sent
++ * by servers and clients) to the internal structures.
++ */
++ 
++#ifndef LDNS_WIRE2HOST_H
++#define LDNS_WIRE2HOST_H
++
++#include <ldns/rdata.h>
++#include <ldns/common.h>
++#include <ldns/error.h>
++#include <ldns/rr.h>
++#include <ldns/packet.h>
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/* The length of the header */
++#define	LDNS_HEADER_SIZE	12
++
++/* First octet of flags */
++#define	LDNS_RD_MASK		0x01U
++#define	LDNS_RD_SHIFT	0
++#define	LDNS_RD_WIRE(wirebuf)	(*(wirebuf+2) & LDNS_RD_MASK)
++#define	LDNS_RD_SET(wirebuf)	(*(wirebuf+2) |= LDNS_RD_MASK)
++#define	LDNS_RD_CLR(wirebuf)	(*(wirebuf+2) &= ~LDNS_RD_MASK)
++
++#define LDNS_TC_MASK		0x02U
++#define LDNS_TC_SHIFT	1
++#define	LDNS_TC_WIRE(wirebuf)	(*(wirebuf+2) & LDNS_TC_MASK)
++#define	LDNS_TC_SET(wirebuf)	(*(wirebuf+2) |= LDNS_TC_MASK)
++#define	LDNS_TC_CLR(wirebuf)	(*(wirebuf+2) &= ~LDNS_TC_MASK)
++
++#define	LDNS_AA_MASK		0x04U
++#define	LDNS_AA_SHIFT	2
++#define	LDNS_AA_WIRE(wirebuf)	(*(wirebuf+2) & LDNS_AA_MASK)
++#define	LDNS_AA_SET(wirebuf)	(*(wirebuf+2) |= LDNS_AA_MASK)
++#define	LDNS_AA_CLR(wirebuf)	(*(wirebuf+2) &= ~LDNS_AA_MASK)
++
++#define	LDNS_OPCODE_MASK	0x78U
++#define	LDNS_OPCODE_SHIFT	3
++#define	LDNS_OPCODE_WIRE(wirebuf)	((*(wirebuf+2) & LDNS_OPCODE_MASK) >> LDNS_OPCODE_SHIFT)
++#define	LDNS_OPCODE_SET(wirebuf, opcode) \
++	(*(wirebuf+2) = ((*(wirebuf+2)) & ~LDNS_OPCODE_MASK) | ((opcode) << LDNS_OPCODE_SHIFT))
++
++#define	LDNS_QR_MASK		0x80U
++#define	LDNS_QR_SHIFT	7
++#define	LDNS_QR_WIRE(wirebuf)	(*(wirebuf+2) & LDNS_QR_MASK)
++#define	LDNS_QR_SET(wirebuf)	(*(wirebuf+2) |= LDNS_QR_MASK)
++#define	LDNS_QR_CLR(wirebuf)	(*(wirebuf+2) &= ~LDNS_QR_MASK)
++
++/* Second octet of flags */
++#define	LDNS_RCODE_MASK	0x0fU
++#define	LDNS_RCODE_SHIFT	0
++#define	LDNS_RCODE_WIRE(wirebuf)	(*(wirebuf+3) & LDNS_RCODE_MASK)
++#define	LDNS_RCODE_SET(wirebuf, rcode) \
++	(*(wirebuf+3) = ((*(wirebuf+3)) & ~LDNS_RCODE_MASK) | (rcode))
++
++#define	LDNS_CD_MASK		0x10U
++#define	LDNS_CD_SHIFT	4
++#define	LDNS_CD_WIRE(wirebuf)	(*(wirebuf+3) & LDNS_CD_MASK)
++#define	LDNS_CD_SET(wirebuf)	(*(wirebuf+3) |= LDNS_CD_MASK)
++#define	LDNS_CD_CLR(wirebuf)	(*(wirebuf+3) &= ~LDNS_CD_MASK)
++
++#define	LDNS_AD_MASK		0x20U
++#define	LDNS_AD_SHIFT	5
++#define	LDNS_AD_WIRE(wirebuf)	(*(wirebuf+3) & LDNS_AD_MASK)
++#define	LDNS_AD_SET(wirebuf)	(*(wirebuf+3) |= LDNS_AD_MASK)
++#define	LDNS_AD_CLR(wirebuf)	(*(wirebuf+3) &= ~LDNS_AD_MASK)
++
++#define	LDNS_Z_MASK		0x40U
++#define	LDNS_Z_SHIFT		6
++#define	LDNS_Z_WIRE(wirebuf)	(*(wirebuf+3) & LDNS_Z_MASK)
++#define	LDNS_Z_SET(wirebuf)	(*(wirebuf+3) |= LDNS_Z_MASK)
++#define	LDNS_Z_CLR(wirebuf)	(*(wirebuf+3) &= ~LDNS_Z_MASK)
++
++#define	LDNS_RA_MASK		0x80U
++#define	LDNS_RA_SHIFT	7
++#define	LDNS_RA_WIRE(wirebuf)	(*(wirebuf+3) & LDNS_RA_MASK)
++#define	LDNS_RA_SET(wirebuf)	(*(wirebuf+3) |= LDNS_RA_MASK)
++#define	LDNS_RA_CLR(wirebuf)	(*(wirebuf+3) &= ~LDNS_RA_MASK)
++
++/* Query ID */
++#define	LDNS_ID_WIRE(wirebuf)		(ldns_read_uint16(wirebuf))
++#define	LDNS_ID_SET(wirebuf, id)	(ldns_write_uint16(wirebuf, id))
++
++/* Counter of the question section */
++#define LDNS_QDCOUNT_OFF		4
++/*
++#define	QDCOUNT(wirebuf)		(ntohs(*(uint16_t *)(wirebuf+QDCOUNT_OFF)))
++*/
++#define	LDNS_QDCOUNT(wirebuf)		(ldns_read_uint16(wirebuf+LDNS_QDCOUNT_OFF))
++
++/* Counter of the answer section */
++#define LDNS_ANCOUNT_OFF		6
++#define	LDNS_ANCOUNT(wirebuf)		(ldns_read_uint16(wirebuf+LDNS_ANCOUNT_OFF))
++
++/* Counter of the authority section */
++#define LDNS_NSCOUNT_OFF		8
++#define	LDNS_NSCOUNT(wirebuf)		(ldns_read_uint16(wirebuf+LDNS_NSCOUNT_OFF))
++
++/* Counter of the additional section */
++#define LDNS_ARCOUNT_OFF		10
++#define	LDNS_ARCOUNT(wirebuf)		(ldns_read_uint16(wirebuf+LDNS_ARCOUNT_OFF))
++
++/**
++ * converts the data on the uint8_t bytearray (in wire format) to a DNS packet.
++ * This function will initialize and allocate memory space for the packet 
++ * structure.
++ * 
++ * \param[in] packet pointer to the structure to hold the packet
++ * \param[in] data pointer to the buffer with the data
++ * \param[in] len the length of the data buffer (in bytes)
++ * \return LDNS_STATUS_OK if everything succeeds, error otherwise
++ */
++ldns_status ldns_wire2pkt(ldns_pkt **packet, const uint8_t *data, size_t len);
++
++/**
++ * converts the data on the uint8_t bytearray (in wire format) to a DNS packet.
++ * This function will initialize and allocate memory space for the packet 
++ * structure.
++ * 
++ * \param[in] packet pointer to the structure to hold the packet
++ * \param[in] buffer the buffer with the data
++ * \return LDNS_STATUS_OK if everything succeeds, error otherwise
++ */
++ldns_status ldns_buffer2pkt_wire(ldns_pkt **packet, ldns_buffer *buffer);
++
++/**
++ * converts the data on the uint8_t bytearray (in wire format) to a DNS 
++ * dname rdata field. This function will initialize and allocate memory
++ * space for the dname structure. The length of the wiredata of this rdf 
++ * is added to the *pos value.
++ *
++ * \param[in] dname pointer to the structure to hold the rdata value
++ * \param[in] wire pointer to the buffer with the data
++ * \param[in] max the length of the data buffer (in bytes)
++ * \param[in] pos the position of the rdf in the buffer (ie. the number of bytes 
++ *            from the start of the buffer)
++ * \return LDNS_STATUS_OK if everything succeeds, error otherwise
++ */
++ldns_status ldns_wire2dname(ldns_rdf **dname, const uint8_t *wire, size_t max, size_t *pos);
++
++/**
++ * converts the data on the uint8_t bytearray (in wire format) to DNS 
++ * rdata fields, and adds them to the list of rdfs of the given rr.
++ * This function will initialize and allocate memory space for the dname
++ * structures.
++ * The length of the wiredata of these rdfs is added to the *pos value.
++ *
++ * All rdfs belonging to the RR are read; the rr should have no rdfs
++ * yet. An error is returned if the format cannot be parsed.
++ *
++ * \param[in] rr pointer to the ldns_rr structure to hold the rdata value
++ * \param[in] wire pointer to the buffer with the data
++ * \param[in] max the length of the data buffer (in bytes)
++ * \param[in] pos the position of the rdf in the buffer (ie. the number of bytes 
++ *            from the start of the buffer)
++ * \return LDNS_STATUS_OK if everything succeeds, error otherwise
++ */
++ldns_status ldns_wire2rdf(ldns_rr *rr, const uint8_t *wire, size_t max, size_t *pos);
++
++/**
++ * converts the data on the uint8_t bytearray (in wire format) to a DNS 
++ * resource record.
++ * This function will initialize and allocate memory space for the rr
++ * structure.
++ * The length of the wiredata of this rr is added to the *pos value.
++ * 
++ * \param[in] rr pointer to the structure to hold the rdata value
++ * \param[in] wire pointer to the buffer with the data
++ * \param[in] max the length of the data buffer (in bytes)
++ * \param[in] pos the position of the rr in the buffer (ie. the number of bytes 
++ *            from the start of the buffer)
++ * \param[in] section the section in the packet the rr is meant for
++ * \return LDNS_STATUS_OK if everything succeeds, error otherwise
++ */
++ldns_status ldns_wire2rr(ldns_rr **rr, const uint8_t *wire, size_t max, size_t *pos, ldns_pkt_section section);
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* LDNS_WIRE2HOST_H */
+diff --git a/ldns/include/ldns/zone.h b/ldns/include/ldns/zone.h
+new file mode 100644
+index 0000000..0d129a0
+--- /dev/null
++++ b/ldns/include/ldns/zone.h
+@@ -0,0 +1,176 @@
++/**
++ * zone.h
++ *
++ * zone definitions
++ *  - what is it
++ *  - get_glue function
++ *  - search etc
++ *
++ * a Net::DNS like library for C
++ *
++ * (c) NLnet Labs, 2005-2006
++ *
++ * See the file LICENSE for the license
++ */
++
++/**
++ * \file
++ *
++ * Defines the ldns_zone structure and functions to manipulate it.
++ */
++ 
++
++#ifndef LDNS_ZONE_H
++#define LDNS_ZONE_H
++
++#include <ldns/common.h>
++#include <ldns/rdata.h>
++#include <ldns/rr.h>
++#include <ldns/error.h>
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/** 
++ * DNS Zone
++ *
++ * A list of RR's with some
++ * extra information which comes from the SOA RR
++ * Note: nothing has been done to make this efficient (yet).
++ */
++struct ldns_struct_zone
++{
++	/** the soa defines a zone */
++	ldns_rr 	*_soa;
++	/* basicly a zone is a list of rr's */
++	ldns_rr_list 	*_rrs;
++	/* we could change this to be a b-tree etc etc todo */
++};
++typedef struct ldns_struct_zone ldns_zone;	
++	
++/**
++ * create a new ldns_zone structure
++ * \return a pointer to a ldns_zone structure
++ */
++ldns_zone * ldns_zone_new(void);
++
++/**
++ * Return the soa record of a zone
++ * \param[in] z the zone to read from
++ * \return the soa record in the zone
++ */
++ldns_rr * ldns_zone_soa(const ldns_zone *z);
++
++/**
++ * Returns the number of resource records in the zone, NOT counting the SOA record
++ * \param[in] z the zone to read from
++ * \return the number of rr's in the zone
++ */
++size_t ldns_zone_rr_count(const ldns_zone *z);
++
++/**
++ * Set the zone's soa record
++ * \param[in] z the zone to put the new soa in
++ * \param[in] soa the soa to set
++ */
++void ldns_zone_set_soa(ldns_zone *z, ldns_rr *soa);
++
++/**
++ * Get a list of a zone's content. Note that the SOA
++ * isn't included in this list. You need to get the 
++ * with ldns_zone_soa.
++ * \param[in] z the zone to read from
++ * \return the rrs from this zone
++ */
++ldns_rr_list * ldns_zone_rrs(const ldns_zone *z);
++
++/**
++ * Set the zone's contents
++ * \param[in] z the zone to put the new soa in
++ * \param[in] rrlist the rrlist to use
++ */
++void ldns_zone_set_rrs(ldns_zone *z, ldns_rr_list *rrlist);
++
++/**
++ * push an rrlist to a zone structure. This function use pointer
++ * copying, so the rr_list structure inside z is modified!
++ * \param[in] z the zone to add to
++ * \param[in] list the list to add
++ * \return a true on succes otherwise falsed
++ */
++bool ldns_zone_push_rr_list(ldns_zone *z, ldns_rr_list *list);
++
++/**
++ * push an single rr to a zone structure. This function use pointer
++ * copying, so the rr_list structure inside z is modified!
++ * \param[in] z the zone to add to
++ * \param[in] rr the rr to add
++ * \return a true on succes otherwise falsed
++ */
++bool ldns_zone_push_rr(ldns_zone *z, ldns_rr *rr);
++
++/**
++ * Retrieve all resource records from the zone that are glue
++ * records. The resulting list does are pointer references
++ * to the zone's data.
++ *
++ * Due to the current zone implementation (as a list of rr's), this
++ * function is extremely slow. Another (probably better) way to do this
++ * is to use an ldns_dnssec_zone structure and the 
++ * ldns_dnssec_mark_and_get_glue() function.
++ *
++ * \param[in] z the zone to look for glue
++ * \return the rr_list with the glue
++ */
++ldns_rr_list *ldns_zone_glue_rr_list(const ldns_zone *z);
++
++/**
++ * Create a new zone from a file
++ * \param[out] z the new zone
++ * \param[in] *fp the filepointer to use
++ * \param[in] *origin the zones' origin
++ * \param[in] ttl default ttl to use
++ * \param[in] c default class to use (IN)
++ *
++ * \return ldns_status mesg with an error or LDNS_STATUS_OK
++ */
++ldns_status ldns_zone_new_frm_fp(ldns_zone **z, FILE *fp, ldns_rdf *origin, uint32_t ttl, ldns_rr_class c);
++
++/**
++ * Create a new zone from a file, keep track of the line numbering
++ * \param[out] z the new zone
++ * \param[in] *fp the filepointer to use
++ * \param[in] *origin the zones' origin
++ * \param[in] ttl default ttl to use
++ * \param[in] c default class to use (IN)
++ * \param[out] line_nr used for error msg, to get to the line number
++ *
++ * \return ldns_status mesg with an error or LDNS_STATUS_OK
++ */
++ldns_status ldns_zone_new_frm_fp_l(ldns_zone **z, FILE *fp, ldns_rdf *origin, uint32_t ttl, ldns_rr_class c, int *line_nr);
++
++/**
++ * Frees the allocated memory for the zone, and the rr_list structure in it
++ * \param[in] zone the zone to free
++ */
++void ldns_zone_free(ldns_zone *zone);
++
++/**
++ * Frees the allocated memory for the zone, the soa rr in it, 
++ * and the rr_list structure in it, including the rr's in that. etc.
++ * \param[in] zone the zone to free
++ */
++void ldns_zone_deep_free(ldns_zone *zone);
++
++/**
++ * Sort the rrs in a zone, with the current impl. this is slow
++ * \param[in] zone the zone to sort
++ */
++void ldns_zone_sort(ldns_zone *zone);
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* LDNS_ZONE_H */
+diff --git a/ldns/src/buffer.c b/ldns/src/buffer.c
+new file mode 100644
+index 0000000..fc6c17e
+--- /dev/null
++++ b/ldns/src/buffer.c
+@@ -0,0 +1,177 @@
++/*
++ * buffer.c -- generic memory buffer .
++ *
++ * Copyright (c) 2001-2008, NLnet Labs. All rights reserved.
++ *
++ * See LICENSE for the license.
++ *
++ */
++
++#include <ldns/config.h>
++
++#include <ldns/ldns.h>
++#include <ldns/buffer.h>
++
++ldns_buffer *
++ldns_buffer_new(size_t capacity)
++{
++	ldns_buffer *buffer = LDNS_MALLOC(ldns_buffer);
++
++	if (!buffer) {
++		return NULL;
++	}
++	
++	buffer->_data = (uint8_t *) LDNS_XMALLOC(uint8_t, capacity);
++	if (!buffer->_data) {
++		LDNS_FREE(buffer);
++		return NULL;
++	}
++	
++	buffer->_position = 0;
++	buffer->_limit = buffer->_capacity = capacity;
++	buffer->_fixed = 0;
++	buffer->_status = LDNS_STATUS_OK;
++	
++	ldns_buffer_invariant(buffer);
++	
++	return buffer;
++}
++
++void
++ldns_buffer_new_frm_data(ldns_buffer *buffer, void *data, size_t size)
++{
++	assert(data != NULL);
++
++	buffer->_position = 0; 
++	buffer->_limit = buffer->_capacity = size;
++	buffer->_fixed = 0;
++	buffer->_data = LDNS_XMALLOC(uint8_t, size);
++	if(!buffer->_data) {
++		buffer->_status = LDNS_STATUS_MEM_ERR;
++		return;
++	}
++	memcpy(buffer->_data, data, size);
++	buffer->_status = LDNS_STATUS_OK;
++	
++	ldns_buffer_invariant(buffer);
++}
++
++bool
++ldns_buffer_set_capacity(ldns_buffer *buffer, size_t capacity)
++{
++	void *data;
++	
++	ldns_buffer_invariant(buffer);
++	assert(buffer->_position <= capacity);
++
++	data = (uint8_t *) LDNS_XREALLOC(buffer->_data, uint8_t, capacity);
++	if (!data) {
++		buffer->_status = LDNS_STATUS_MEM_ERR;
++		return false;
++	} else {
++		buffer->_data = data;
++		buffer->_limit = buffer->_capacity = capacity;
++		return true;
++	}
++}
++
++bool
++ldns_buffer_reserve(ldns_buffer *buffer, size_t amount)
++{
++	ldns_buffer_invariant(buffer);
++	assert(!buffer->_fixed);
++	if (buffer->_capacity < buffer->_position + amount) {
++		size_t new_capacity = buffer->_capacity * 3 / 2;
++
++		if (new_capacity < buffer->_position + amount) {
++			new_capacity = buffer->_position + amount;
++		}
++		if (!ldns_buffer_set_capacity(buffer, new_capacity)) {
++			buffer->_status = LDNS_STATUS_MEM_ERR;
++			return false;
++		}
++	}
++	buffer->_limit = buffer->_capacity;
++	return true;
++}
++
++int
++ldns_buffer_printf(ldns_buffer *buffer, const char *format, ...)
++{
++	va_list args;
++	int written = 0;
++	size_t remaining;
++	
++	if (ldns_buffer_status_ok(buffer)) {
++		ldns_buffer_invariant(buffer);
++		assert(buffer->_limit == buffer->_capacity);
++
++		remaining = ldns_buffer_remaining(buffer);
++		va_start(args, format);
++		written = vsnprintf((char *) ldns_buffer_current(buffer), remaining,
++				    format, args);
++		va_end(args);
++		if (written == -1) {
++			buffer->_status = LDNS_STATUS_INTERNAL_ERR;
++			return -1;
++		} else if ((size_t) written >= remaining) {
++			if (!ldns_buffer_reserve(buffer, (size_t) written + 1)) {
++				buffer->_status = LDNS_STATUS_MEM_ERR;
++				return -1;
++			}
++			va_start(args, format);
++			written = vsnprintf((char *) ldns_buffer_current(buffer),
++			    ldns_buffer_remaining(buffer), format, args);
++			va_end(args);
++			if (written == -1) {
++				buffer->_status = LDNS_STATUS_INTERNAL_ERR;
++				return -1;
++			}
++		}
++		buffer->_position += written;
++	}
++	return written;
++}
++
++void
++ldns_buffer_free(ldns_buffer *buffer)
++{
++	if (!buffer) {
++		return;
++	}
++
++	if (!buffer->_fixed)
++		LDNS_FREE(buffer->_data);
++
++	LDNS_FREE(buffer);
++}
++
++void *
++ldns_buffer_export(ldns_buffer *buffer)
++{
++	buffer->_fixed = 1;
++	return buffer->_data;
++}
++
++int
++ldns_bgetc(ldns_buffer *buffer)
++{
++	if (!ldns_buffer_available_at(buffer, buffer->_position, sizeof(uint8_t))) {
++		ldns_buffer_set_position(buffer, ldns_buffer_limit(buffer));
++		/* ldns_buffer_rewind(buffer);*/
++		return EOF;
++	}
++	return (int)ldns_buffer_read_u8(buffer);
++}
++
++void 
++ldns_buffer_copy(ldns_buffer* result, ldns_buffer* from)
++{
++	size_t tocopy = ldns_buffer_limit(from);
++
++	if(tocopy > ldns_buffer_capacity(result))
++		tocopy = ldns_buffer_capacity(result);
++	ldns_buffer_clear(result);
++	ldns_buffer_write(result, ldns_buffer_begin(from), tocopy);
++	ldns_buffer_flip(result);
++}
+diff --git a/ldns/src/compat/b64_ntop.c b/ldns/src/compat/b64_ntop.c
+new file mode 100644
+index 0000000..6895aca
+--- /dev/null
++++ b/ldns/src/compat/b64_ntop.c
+@@ -0,0 +1,185 @@
++/*
++ * Copyright (c) 1996, 1998 by Internet Software Consortium.
++ *
++ * Permission to use, copy, modify, and distribute this software for any
++ * purpose with or without fee is hereby granted, provided that the above
++ * copyright notice and this permission notice appear in all copies.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
++ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
++ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
++ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
++ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
++ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
++ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
++ * SOFTWARE.
++ */
++
++/*
++ * Portions Copyright (c) 1995 by International Business Machines, Inc.
++ *
++ * International Business Machines, Inc. (hereinafter called IBM) grants
++ * permission under its copyrights to use, copy, modify, and distribute this
++ * Software with or without fee, provided that the above copyright notice and
++ * all paragraphs of this notice appear in all copies, and that the name of IBM
++ * not be used in connection with the marketing of any product incorporating
++ * the Software or modifications thereof, without specific, written prior
++ * permission.
++ *
++ * To the extent it has a right to do so, IBM grants an immunity from suit
++ * under its patents, if any, for the use, sale or manufacture of products to
++ * the extent that such products are used for performing Domain Name System
++ * dynamic updates in TCP/IP networks by means of the Software.  No immunity is
++ * granted for any product per se or for any other function of any product.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
++ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
++ * PARTICULAR PURPOSE.  IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
++ * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
++ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
++ * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
++ */
++#include <ldns/config.h>
++#include <ctype.h>
++#include <stdlib.h>
++#include <string.h>
++
++static const char Base64[] =
++	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
++static const char Pad64 = '=';
++
++/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt)
++   The following encoding technique is taken from RFC 1521 by Borenstein
++   and Freed.  It is reproduced here in a slightly edited form for
++   convenience.
++
++   A 65-character subset of US-ASCII is used, enabling 6 bits to be
++   represented per printable character. (The extra 65th character, "=",
++   is used to signify a special processing function.)
++
++   The encoding process represents 24-bit groups of input bits as output
++   strings of 4 encoded characters. Proceeding from left to right, a
++   24-bit input group is formed by concatenating 3 8-bit input groups.
++   These 24 bits are then treated as 4 concatenated 6-bit groups, each
++   of which is translated into a single digit in the base64 alphabet.
++
++   Each 6-bit group is used as an index into an array of 64 printable
++   characters. The character referenced by the index is placed in the
++   output string.
++
++                         Table 1: The Base64 Alphabet
++
++      Value Encoding  Value Encoding  Value Encoding  Value Encoding
++          0 A            17 R            34 i            51 z
++          1 B            18 S            35 j            52 0
++          2 C            19 T            36 k            53 1
++          3 D            20 U            37 l            54 2
++          4 E            21 V            38 m            55 3
++          5 F            22 W            39 n            56 4
++          6 G            23 X            40 o            57 5
++          7 H            24 Y            41 p            58 6
++          8 I            25 Z            42 q            59 7
++          9 J            26 a            43 r            60 8
++         10 K            27 b            44 s            61 9
++         11 L            28 c            45 t            62 +
++         12 M            29 d            46 u            63 /
++         13 N            30 e            47 v
++         14 O            31 f            48 w         (pad) =
++         15 P            32 g            49 x
++         16 Q            33 h            50 y
++
++   Special processing is performed if fewer than 24 bits are available
++   at the end of the data being encoded.  A full encoding quantum is
++   always completed at the end of a quantity.  When fewer than 24 input
++   bits are available in an input group, zero bits are added (on the
++   right) to form an integral number of 6-bit groups.  Padding at the
++   end of the data is performed using the '=' character.
++
++   Since all base64 input is an integral number of octets, only the
++         -------------------------------------------------                       
++   following cases can arise:
++   
++       (1) the final quantum of encoding input is an integral
++           multiple of 24 bits; here, the final unit of encoded
++	   output will be an integral multiple of 4 characters
++	   with no "=" padding,
++       (2) the final quantum of encoding input is exactly 8 bits;
++           here, the final unit of encoded output will be two
++	   characters followed by two "=" padding characters, or
++       (3) the final quantum of encoding input is exactly 16 bits;
++           here, the final unit of encoded output will be three
++	   characters followed by one "=" padding character.
++   */
++
++int
++ldns_b64_ntop(uint8_t const *src, size_t srclength, char *target, size_t targsize) {
++	size_t datalength = 0;
++	uint8_t input[3];
++	uint8_t output[4];
++	size_t i;
++	
++	if (srclength == 0) {
++		if (targsize > 0) {
++			target[0] = '\0';
++			return 0;
++		} else {
++			return -1;
++		}
++	}
++
++	while (2 < srclength) {
++		input[0] = *src++;
++		input[1] = *src++;
++		input[2] = *src++;
++		srclength -= 3;
++
++		output[0] = input[0] >> 2;
++		output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
++		output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
++		output[3] = input[2] & 0x3f;
++		assert(output[0] < 64);
++		assert(output[1] < 64);
++		assert(output[2] < 64);
++		assert(output[3] < 64);
++
++		if (datalength + 4 > targsize) {
++			return (-1);
++		}
++		target[datalength++] = Base64[output[0]];
++		target[datalength++] = Base64[output[1]];
++		target[datalength++] = Base64[output[2]];
++		target[datalength++] = Base64[output[3]];
++	}
++    
++	/* Now we worry about padding. */
++	if (0 != srclength) {
++		/* Get what's left. */
++		input[0] = input[1] = input[2] = (uint8_t) '\0';
++		for (i = 0; i < srclength; i++)
++			input[i] = *src++;
++	
++		output[0] = input[0] >> 2;
++		output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
++		output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
++		assert(output[0] < 64);
++		assert(output[1] < 64);
++		assert(output[2] < 64);
++
++		if (datalength + 4 > targsize) {
++			return (-2);
++		}
++		target[datalength++] = Base64[output[0]];
++		target[datalength++] = Base64[output[1]];
++		if (srclength == 1) {
++			target[datalength++] = Pad64;
++		} else {
++			target[datalength++] = Base64[output[2]];
++		}
++		target[datalength++] = Pad64;
++	}
++	if (datalength >= targsize) {
++		return (-3);
++	}
++	target[datalength] = '\0';	/* Returned value doesn't count \0. */
++	return (int) (datalength);
++}
+diff --git a/ldns/src/compat/b64_pton.c b/ldns/src/compat/b64_pton.c
+new file mode 100644
+index 0000000..18d8c8e
+--- /dev/null
++++ b/ldns/src/compat/b64_pton.c
+@@ -0,0 +1,244 @@
++/*
++ * Copyright (c) 1996, 1998 by Internet Software Consortium.
++ *
++ * Permission to use, copy, modify, and distribute this software for any
++ * purpose with or without fee is hereby granted, provided that the above
++ * copyright notice and this permission notice appear in all copies.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
++ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
++ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
++ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
++ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
++ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
++ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
++ * SOFTWARE.
++ */
++
++/*
++ * Portions Copyright (c) 1995 by International Business Machines, Inc.
++ *
++ * International Business Machines, Inc. (hereinafter called IBM) grants
++ * permission under its copyrights to use, copy, modify, and distribute this
++ * Software with or without fee, provided that the above copyright notice and
++ * all paragraphs of this notice appear in all copies, and that the name of IBM
++ * not be used in connection with the marketing of any product incorporating
++ * the Software or modifications thereof, without specific, written prior
++ * permission.
++ *
++ * To the extent it has a right to do so, IBM grants an immunity from suit
++ * under its patents, if any, for the use, sale or manufacture of products to
++ * the extent that such products are used for performing Domain Name System
++ * dynamic updates in TCP/IP networks by means of the Software.  No immunity is
++ * granted for any product per se or for any other function of any product.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
++ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
++ * PARTICULAR PURPOSE.  IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
++ * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
++ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
++ * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
++ */
++#include <ldns/config.h>
++#include <ctype.h>
++#include <stdlib.h>
++#include <string.h>
++
++static const char Base64[] =
++	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
++static const char Pad64 = '=';
++
++/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt)
++   The following encoding technique is taken from RFC 1521 by Borenstein
++   and Freed.  It is reproduced here in a slightly edited form for
++   convenience.
++
++   A 65-character subset of US-ASCII is used, enabling 6 bits to be
++   represented per printable character. (The extra 65th character, "=",
++   is used to signify a special processing function.)
++
++   The encoding process represents 24-bit groups of input bits as output
++   strings of 4 encoded characters. Proceeding from left to right, a
++   24-bit input group is formed by concatenating 3 8-bit input groups.
++   These 24 bits are then treated as 4 concatenated 6-bit groups, each
++   of which is translated into a single digit in the base64 alphabet.
++
++   Each 6-bit group is used as an index into an array of 64 printable
++   characters. The character referenced by the index is placed in the
++   output string.
++
++                         Table 1: The Base64 Alphabet
++
++      Value Encoding  Value Encoding  Value Encoding  Value Encoding
++          0 A            17 R            34 i            51 z
++          1 B            18 S            35 j            52 0
++          2 C            19 T            36 k            53 1
++          3 D            20 U            37 l            54 2
++          4 E            21 V            38 m            55 3
++          5 F            22 W            39 n            56 4
++          6 G            23 X            40 o            57 5
++          7 H            24 Y            41 p            58 6
++          8 I            25 Z            42 q            59 7
++          9 J            26 a            43 r            60 8
++         10 K            27 b            44 s            61 9
++         11 L            28 c            45 t            62 +
++         12 M            29 d            46 u            63 /
++         13 N            30 e            47 v
++         14 O            31 f            48 w         (pad) =
++         15 P            32 g            49 x
++         16 Q            33 h            50 y
++
++   Special processing is performed if fewer than 24 bits are available
++   at the end of the data being encoded.  A full encoding quantum is
++   always completed at the end of a quantity.  When fewer than 24 input
++   bits are available in an input group, zero bits are added (on the
++   right) to form an integral number of 6-bit groups.  Padding at the
++   end of the data is performed using the '=' character.
++
++   Since all base64 input is an integral number of octets, only the
++         -------------------------------------------------                       
++   following cases can arise:
++   
++       (1) the final quantum of encoding input is an integral
++           multiple of 24 bits; here, the final unit of encoded
++	   output will be an integral multiple of 4 characters
++	   with no "=" padding,
++       (2) the final quantum of encoding input is exactly 8 bits;
++           here, the final unit of encoded output will be two
++	   characters followed by two "=" padding characters, or
++       (3) the final quantum of encoding input is exactly 16 bits;
++           here, the final unit of encoded output will be three
++	   characters followed by one "=" padding character.
++   */
++
++/* skips all whitespace anywhere.
++   converts characters, four at a time, starting at (or after)
++   src from base - 64 numbers into three 8 bit bytes in the target area.
++   it returns the number of data bytes stored at the target, or -1 on error.
++ */
++
++int
++ldns_b64_pton(char const *origsrc, uint8_t *target, size_t targsize)
++{
++	unsigned char const* src = (unsigned char*)origsrc;
++	int tarindex, state, ch;
++	char *pos;
++
++	state = 0;
++	tarindex = 0;
++
++	if (strlen(origsrc) == 0) {
++		return 0;
++	}
++
++	while ((ch = *src++) != '\0') {
++		if (isspace((unsigned char)ch))        /* Skip whitespace anywhere. */
++			continue;
++
++		if (ch == Pad64)
++			break;
++
++		pos = strchr(Base64, ch);
++		if (pos == 0) {
++			/* A non-base64 character. */
++			return (-1);
++		}
++
++		switch (state) {
++		case 0:
++			if (target) {
++				if ((size_t)tarindex >= targsize)
++					return (-1);
++				target[tarindex] = (pos - Base64) << 2;
++			}
++			state = 1;
++			break;
++		case 1:
++			if (target) {
++				if ((size_t)tarindex + 1 >= targsize)
++					return (-1);
++				target[tarindex]   |=  (pos - Base64) >> 4;
++				target[tarindex+1]  = ((pos - Base64) & 0x0f)
++							<< 4 ;
++			}
++			tarindex++;
++			state = 2;
++			break;
++		case 2:
++			if (target) {
++				if ((size_t)tarindex + 1 >= targsize)
++					return (-1);
++				target[tarindex]   |=  (pos - Base64) >> 2;
++				target[tarindex+1]  = ((pos - Base64) & 0x03)
++							<< 6;
++			}
++			tarindex++;
++			state = 3;
++			break;
++		case 3:
++			if (target) {
++				if ((size_t)tarindex >= targsize)
++					return (-1);
++				target[tarindex] |= (pos - Base64);
++			}
++			tarindex++;
++			state = 0;
++			break;
++		default:
++			abort();
++		}
++	}
++
++	/*
++	 * We are done decoding Base-64 chars.  Let's see if we ended
++	 * on a byte boundary, and/or with erroneous trailing characters.
++	 */
++
++	if (ch == Pad64) {		/* We got a pad char. */
++		ch = *src++;		/* Skip it, get next. */
++		switch (state) {
++		case 0:		/* Invalid = in first position */
++		case 1:		/* Invalid = in second position */
++			return (-1);
++
++		case 2:		/* Valid, means one byte of info */
++			/* Skip any number of spaces. */
++			for ((void)NULL; ch != '\0'; ch = *src++)
++				if (!isspace((unsigned char)ch))
++					break;
++			/* Make sure there is another trailing = sign. */
++			if (ch != Pad64)
++				return (-1);
++			ch = *src++;		/* Skip the = */
++			/* Fall through to "single trailing =" case. */
++			/* FALLTHROUGH */
++
++		case 3:		/* Valid, means two bytes of info */
++			/*
++			 * We know this char is an =.  Is there anything but
++			 * whitespace after it?
++			 */
++			for ((void)NULL; ch != '\0'; ch = *src++)
++				if (!isspace((unsigned char)ch))
++					return (-1);
++
++			/*
++			 * Now make sure for cases 2 and 3 that the "extra"
++			 * bits that slopped past the last full byte were
++			 * zeros.  If we don't check them, they become a
++			 * subliminal channel.
++			 */
++			if (target && target[tarindex] != 0)
++				return (-1);
++		}
++	} else {
++		/*
++		 * We ended by seeing the end of the string.  Make sure we
++		 * have no partial bytes lying around.
++		 */
++		if (state != 0)
++			return (-1);
++	}
++
++	return (tarindex);
++}
+diff --git a/ldns/src/compat/strlcpy.c b/ldns/src/compat/strlcpy.c
+new file mode 100644
+index 0000000..d6c34c1
+--- /dev/null
++++ b/ldns/src/compat/strlcpy.c
+@@ -0,0 +1,57 @@
++/* from openssh 4.3p2 compat/strlcpy.c */
++/*
++ * Copyright (c) 1998 Todd C. Miller <Todd.Miller at courtesan.com>
++ *
++ * Permission to use, copy, modify, and distribute this software for any
++ * purpose with or without fee is hereby granted, provided that the above
++ * copyright notice and this permission notice appear in all copies.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
++ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
++ */
++
++/* OPENBSD ORIGINAL: lib/libc/string/strlcpy.c */
++
++#include <ldns/config.h>
++#ifndef HAVE_STRLCPY
++
++#include <sys/types.h>
++#include <string.h>
++
++/*
++ * Copy src to string dst of size siz.  At most siz-1 characters
++ * will be copied.  Always NUL terminates (unless siz == 0).
++ * Returns strlen(src); if retval >= siz, truncation occurred.
++ */
++size_t
++strlcpy(char *dst, const char *src, size_t siz)
++{
++	char *d = dst;
++	const char *s = src;
++	size_t n = siz;
++
++	/* Copy as many bytes as will fit */
++	if (n != 0 && --n != 0) {
++		do {
++			if ((*d++ = *s++) == 0)
++				break;
++		} while (--n != 0);
++	}
++
++	/* Not enough room in dst, add NUL and traverse rest of src */
++	if (n == 0) {
++		if (siz != 0)
++			*d = '\0';		/* NUL-terminate dst */
++		while (*s++)
++			;
++	}
++
++	return(s - src - 1);	/* count does not include NUL */
++}
++
++#endif /* !HAVE_STRLCPY */
+diff --git a/ldns/src/dane.c b/ldns/src/dane.c
+new file mode 100644
+index 0000000..675dfa8
+--- /dev/null
++++ b/ldns/src/dane.c
+@@ -0,0 +1,748 @@
++/*
++ * Verify or create TLS authentication with DANE (RFC6698)
++ *
++ * (c) NLnetLabs 2012
++ *
++ * See the file LICENSE for the license.
++ *
++ */
++
++#include <ldns/config.h>
++#ifdef USE_DANE
++
++#include <ldns/ldns.h>
++#include <ldns/dane.h>
++
++#include <unistd.h>
++#include <stdlib.h>
++#include <sys/types.h>
++#ifdef HAVE_SYS_SOCKET_H
++#include <sys/socket.h>
++#endif
++#ifdef HAVE_NETDB_H
++#include <netdb.h>
++#endif
++
++#ifdef HAVE_SSL
++#include <openssl/ssl.h>
++#include <openssl/err.h>
++#include <openssl/x509v3.h>
++#endif
++
++ldns_status
++ldns_dane_create_tlsa_owner(ldns_rdf** tlsa_owner, const ldns_rdf* name,
++		uint16_t port, ldns_dane_transport transport)
++{
++	char buf[LDNS_MAX_DOMAINLEN];
++	size_t s;
++
++	assert(tlsa_owner != NULL);
++	assert(name != NULL);
++	assert(ldns_rdf_get_type(name) == LDNS_RDF_TYPE_DNAME);
++
++	s = (size_t)snprintf(buf, LDNS_MAX_DOMAINLEN, "X_%d", (int)port);
++	buf[0] = (char)(s - 1);
++
++	switch(transport) {
++	case LDNS_DANE_TRANSPORT_TCP:
++		s += snprintf(buf + s, LDNS_MAX_DOMAINLEN - s, "\004_tcp");
++		break;
++	
++	case LDNS_DANE_TRANSPORT_UDP:
++		s += snprintf(buf + s, LDNS_MAX_DOMAINLEN - s, "\004_udp");
++		break;
++
++	case LDNS_DANE_TRANSPORT_SCTP:
++		s += snprintf(buf + s, LDNS_MAX_DOMAINLEN - s, "\005_sctp");
++		break;
++	
++	default:
++		return LDNS_STATUS_DANE_UNKNOWN_TRANSPORT;
++	}
++	if (s + ldns_rdf_size(name) > LDNS_MAX_DOMAINLEN) {
++		return LDNS_STATUS_DOMAINNAME_OVERFLOW;
++	}
++	memcpy(buf + s, ldns_rdf_data(name), ldns_rdf_size(name));
++	*tlsa_owner = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_DNAME,
++			s + ldns_rdf_size(name), buf);
++	if (*tlsa_owner == NULL) {
++		return LDNS_STATUS_MEM_ERR;
++	}
++	return LDNS_STATUS_OK;
++}
++
++
++#ifdef HAVE_SSL
++ldns_status
++ldns_dane_cert2rdf(ldns_rdf** rdf, X509* cert,
++		ldns_tlsa_selector      selector,
++		ldns_tlsa_matching_type matching_type)
++{
++	unsigned char* buf = NULL;
++	size_t len;
++
++	X509_PUBKEY* xpubkey;
++	EVP_PKEY* epubkey;
++
++	unsigned char* digest;
++
++	assert(rdf != NULL);
++	assert(cert != NULL);
++
++	switch(selector) {
++	case LDNS_TLSA_SELECTOR_FULL_CERTIFICATE:
++
++		len = (size_t)i2d_X509(cert, &buf);
++		break;
++
++	case LDNS_TLSA_SELECTOR_SUBJECTPUBLICKEYINFO:
++
++#ifndef S_SPLINT_S
++		xpubkey = X509_get_X509_PUBKEY(cert);
++#endif
++		if (! xpubkey) {
++			return LDNS_STATUS_SSL_ERR;
++		}
++		epubkey = X509_PUBKEY_get(xpubkey);
++		if (! epubkey) {
++			return LDNS_STATUS_SSL_ERR;
++		}
++		len = (size_t)i2d_PUBKEY(epubkey, &buf);
++		break;
++	
++	default:
++		return LDNS_STATUS_DANE_UNKNOWN_SELECTOR;
++	}
++
++	switch(matching_type) {
++	case LDNS_TLSA_MATCHING_TYPE_NO_HASH_USED:
++
++		*rdf = ldns_rdf_new(LDNS_RDF_TYPE_HEX, len, buf);
++		
++		return *rdf ? LDNS_STATUS_OK : LDNS_STATUS_MEM_ERR;
++		break;
++	
++	case LDNS_TLSA_MATCHING_TYPE_SHA256:
++
++		digest = LDNS_XMALLOC(unsigned char, LDNS_SHA256_DIGEST_LENGTH);
++		if (digest == NULL) {
++			LDNS_FREE(buf);
++			return LDNS_STATUS_MEM_ERR;
++		}
++		(void) ldns_sha256(buf, (unsigned int)len, digest);
++		*rdf = ldns_rdf_new(LDNS_RDF_TYPE_HEX, LDNS_SHA256_DIGEST_LENGTH,
++				digest);
++		LDNS_FREE(buf);
++
++		return *rdf ? LDNS_STATUS_OK : LDNS_STATUS_MEM_ERR;
++		break;
++
++	case LDNS_TLSA_MATCHING_TYPE_SHA512:
++
++		digest = LDNS_XMALLOC(unsigned char, LDNS_SHA512_DIGEST_LENGTH);
++		if (digest == NULL) {
++			LDNS_FREE(buf);
++			return LDNS_STATUS_MEM_ERR;
++		}
++		(void) ldns_sha512(buf, (unsigned int)len, digest);
++		*rdf = ldns_rdf_new(LDNS_RDF_TYPE_HEX, LDNS_SHA512_DIGEST_LENGTH,
++				digest);
++		LDNS_FREE(buf);
++
++		return *rdf ? LDNS_STATUS_OK : LDNS_STATUS_MEM_ERR;
++		break;
++	
++	default:
++		LDNS_FREE(buf);
++		return LDNS_STATUS_DANE_UNKNOWN_MATCHING_TYPE;
++	}
++}
++
++
++/* Ordinary PKIX validation of cert (with extra_certs to help)
++ * against the CA's in store
++ */
++static ldns_status
++ldns_dane_pkix_validate(X509* cert, STACK_OF(X509)* extra_certs,
++		X509_STORE* store)
++{
++	X509_STORE_CTX* vrfy_ctx;
++	ldns_status s;
++
++	if (! store) {
++		return LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE;
++	}
++	vrfy_ctx = X509_STORE_CTX_new();
++	if (! vrfy_ctx) {
++
++		return LDNS_STATUS_SSL_ERR;
++
++	} else if (X509_STORE_CTX_init(vrfy_ctx, store,
++				cert, extra_certs) != 1) {
++		s = LDNS_STATUS_SSL_ERR;
++
++	} else if (X509_verify_cert(vrfy_ctx) == 1) {
++
++		s = LDNS_STATUS_OK;
++
++	} else {
++		s = LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE;
++	}
++	X509_STORE_CTX_free(vrfy_ctx);
++	return s;
++}
++
++
++/* Orinary PKIX validation of cert (with extra_certs to help)
++ * against the CA's in store, but also return the validation chain.
++ */
++static ldns_status
++ldns_dane_pkix_validate_and_get_chain(STACK_OF(X509)** chain, X509* cert,
++		STACK_OF(X509)* extra_certs, X509_STORE* store)
++{
++	ldns_status s;
++	X509_STORE* empty_store = NULL;
++	X509_STORE_CTX* vrfy_ctx;
++
++	assert(chain != NULL);
++
++	if (! store) {
++		store = empty_store = X509_STORE_new();
++	}
++	s = LDNS_STATUS_SSL_ERR;
++	vrfy_ctx = X509_STORE_CTX_new();
++	if (! vrfy_ctx) {
++
++		goto exit_free_empty_store;
++
++	} else if (X509_STORE_CTX_init(vrfy_ctx, store,
++					cert, extra_certs) != 1) {
++		goto exit_free_vrfy_ctx;
++
++	} else if (X509_verify_cert(vrfy_ctx) == 1) {
++
++		s = LDNS_STATUS_OK;
++
++	} else {
++		s = LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE;
++	}
++	*chain = X509_STORE_CTX_get1_chain(vrfy_ctx);
++	if (! *chain) {
++		s = LDNS_STATUS_SSL_ERR;
++	}
++
++exit_free_vrfy_ctx:
++	X509_STORE_CTX_free(vrfy_ctx);
++
++exit_free_empty_store:
++	if (empty_store) {
++		X509_STORE_free(empty_store);
++	}
++	return s;
++}
++
++
++/* Return the validation chain that can be build out of cert, with extra_certs.
++ */
++static ldns_status
++ldns_dane_pkix_get_chain(STACK_OF(X509)** chain,
++		X509* cert, STACK_OF(X509)* extra_certs)
++{
++	ldns_status s;
++	X509_STORE* empty_store = NULL;
++	X509_STORE_CTX* vrfy_ctx;
++
++	assert(chain != NULL);
++
++	empty_store = X509_STORE_new();
++	s = LDNS_STATUS_SSL_ERR;
++	vrfy_ctx = X509_STORE_CTX_new();
++	if (! vrfy_ctx) {
++
++		goto exit_free_empty_store;
++
++	} else if (X509_STORE_CTX_init(vrfy_ctx, empty_store,
++					cert, extra_certs) != 1) {
++		goto exit_free_vrfy_ctx;
++	}
++	(void) X509_verify_cert(vrfy_ctx);
++	*chain = X509_STORE_CTX_get1_chain(vrfy_ctx);
++	if (! *chain) {
++		s = LDNS_STATUS_SSL_ERR;
++	} else {
++		s = LDNS_STATUS_OK;
++	}
++exit_free_vrfy_ctx:
++	X509_STORE_CTX_free(vrfy_ctx);
++
++exit_free_empty_store:
++	X509_STORE_free(empty_store);
++	return s;
++}
++
++
++/* Pop n+1 certs and return the last popped.
++ */
++static ldns_status
++ldns_dane_get_nth_cert_from_validation_chain(
++		X509** cert, STACK_OF(X509)* chain, int n, bool ca)
++{
++	if (n >= sk_X509_num(chain) || n < 0) {
++		return LDNS_STATUS_DANE_OFFSET_OUT_OF_RANGE;
++	}
++	*cert = sk_X509_pop(chain);
++	while (n-- > 0) {
++		X509_free(*cert);
++		*cert = sk_X509_pop(chain);
++	}
++	if (ca && ! X509_check_ca(*cert)) {
++		return LDNS_STATUS_DANE_NON_CA_CERTIFICATE;
++	}
++	return LDNS_STATUS_OK;
++}
++
++
++/* Create validation chain with cert and extra_certs and returns the last
++ * self-signed (if present).
++ */
++static ldns_status
++ldns_dane_pkix_get_last_self_signed(X509** out_cert,
++		X509* cert, STACK_OF(X509)* extra_certs)
++{
++	ldns_status s;
++	X509_STORE* empty_store = NULL;
++	X509_STORE_CTX* vrfy_ctx;
++
++	assert(out_cert != NULL);
++
++	empty_store = X509_STORE_new();
++	s = LDNS_STATUS_SSL_ERR;
++	vrfy_ctx = X509_STORE_CTX_new();
++	if (! vrfy_ctx) {
++		goto exit_free_empty_store;
++
++	} else if (X509_STORE_CTX_init(vrfy_ctx, empty_store,
++					cert, extra_certs) != 1) {
++		goto exit_free_vrfy_ctx;
++
++	}
++	(void) X509_verify_cert(vrfy_ctx);
++	if (vrfy_ctx->error == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN ||
++	    vrfy_ctx->error == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT){
++
++		*out_cert = X509_STORE_CTX_get_current_cert( vrfy_ctx);
++		s = LDNS_STATUS_OK;
++	} else {
++		s = LDNS_STATUS_DANE_PKIX_NO_SELF_SIGNED_TRUST_ANCHOR;
++	}
++exit_free_vrfy_ctx:
++	X509_STORE_CTX_free(vrfy_ctx);
++
++exit_free_empty_store:
++	X509_STORE_free(empty_store);
++	return s;
++}
++
++
++ldns_status
++ldns_dane_select_certificate(X509** selected_cert,
++		X509* cert, STACK_OF(X509)* extra_certs,
++		X509_STORE* pkix_validation_store,
++		ldns_tlsa_certificate_usage cert_usage, int offset)
++{
++	ldns_status s;
++	STACK_OF(X509)* pkix_validation_chain = NULL;
++
++	assert(selected_cert != NULL);
++	assert(cert != NULL);
++
++	/* With PKIX validation explicitely turned off (pkix_validation_store
++	 *  == NULL), treat the "CA constraint" and "Service certificate
++	 * constraint" the same as "Trust anchor assertion" and "Domain issued
++	 * certificate" respectively.
++	 */
++	if (pkix_validation_store == NULL) {
++		switch (cert_usage) {
++
++		case LDNS_TLSA_USAGE_CA_CONSTRAINT:
++
++			cert_usage = LDNS_TLSA_USAGE_TRUST_ANCHOR_ASSERTION;
++			break;
++
++		case LDNS_TLSA_USAGE_SERVICE_CERTIFICATE_CONSTRAINT:
++
++			cert_usage = LDNS_TLSA_USAGE_DOMAIN_ISSUED_CERTIFICATE;
++			break;
++
++		default:
++			break;
++		}
++	}
++
++	/* Now what to do with each Certificate usage...
++	 */
++	switch (cert_usage) {
++
++	case LDNS_TLSA_USAGE_CA_CONSTRAINT:
++
++		s = ldns_dane_pkix_validate_and_get_chain(
++				&pkix_validation_chain,
++				cert, extra_certs,
++				pkix_validation_store);
++		if (! pkix_validation_chain) {
++			return s;
++		}
++		if (s == LDNS_STATUS_OK) {
++			if (offset == -1) {
++				offset = 0;
++			}
++			s = ldns_dane_get_nth_cert_from_validation_chain(
++					selected_cert, pkix_validation_chain,
++					offset, true);
++		}
++		sk_X509_pop_free(pkix_validation_chain, X509_free);
++		return s;
++		break;
++
++
++	case LDNS_TLSA_USAGE_SERVICE_CERTIFICATE_CONSTRAINT:
++
++		*selected_cert = cert;
++		return ldns_dane_pkix_validate(cert, extra_certs,
++				pkix_validation_store);
++		break;
++
++
++	case LDNS_TLSA_USAGE_TRUST_ANCHOR_ASSERTION:
++
++		if (offset == -1) {
++			s = ldns_dane_pkix_get_last_self_signed(
++					selected_cert, cert, extra_certs);
++			return s;
++		} else {
++			s = ldns_dane_pkix_get_chain(
++					&pkix_validation_chain,
++					cert, extra_certs);
++			if (s == LDNS_STATUS_OK) {
++				s =
++				ldns_dane_get_nth_cert_from_validation_chain(
++					selected_cert, pkix_validation_chain,
++					offset, false);
++			} else if (! pkix_validation_chain) {
++				return s;
++			}
++			sk_X509_pop_free(pkix_validation_chain, X509_free);
++			return s;
++		}
++		break;
++
++
++	case LDNS_TLSA_USAGE_DOMAIN_ISSUED_CERTIFICATE:
++
++		*selected_cert = cert;
++		return LDNS_STATUS_OK;
++		break;
++	
++	default:
++		return LDNS_STATUS_DANE_UNKNOWN_CERTIFICATE_USAGE;
++		break;
++	}
++}
++
++
++ldns_status
++ldns_dane_create_tlsa_rr(ldns_rr** tlsa,
++		ldns_tlsa_certificate_usage certificate_usage,
++		ldns_tlsa_selector          selector,
++		ldns_tlsa_matching_type     matching_type,
++		X509* cert)
++{
++	ldns_rdf* rdf;
++	ldns_status s;
++
++	assert(tlsa != NULL);
++	assert(cert != NULL);
++
++	/* create rr */
++	*tlsa = ldns_rr_new_frm_type(LDNS_RR_TYPE_TLSA);
++	if (*tlsa == NULL) {
++		return LDNS_STATUS_MEM_ERR;
++	}
++
++	rdf = ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8,
++			(uint8_t)certificate_usage);
++	if (rdf == NULL) {
++		goto memerror;
++	}
++	(void) ldns_rr_set_rdf(*tlsa, rdf, 0);
++
++	rdf = ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8, (uint8_t)selector);
++	if (rdf == NULL) {
++		goto memerror;
++	}
++	(void) ldns_rr_set_rdf(*tlsa, rdf, 1);
++
++	rdf = ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8, (uint8_t)matching_type);
++	if (rdf == NULL) {
++		goto memerror;
++	}
++	(void) ldns_rr_set_rdf(*tlsa, rdf, 2);
++
++	s = ldns_dane_cert2rdf(&rdf, cert, selector, matching_type);
++	if (s == LDNS_STATUS_OK) {
++		(void) ldns_rr_set_rdf(*tlsa, rdf, 3);
++		return LDNS_STATUS_OK;
++	}
++	ldns_rr_free(*tlsa);
++	*tlsa = NULL;
++	return s;
++
++memerror:
++	ldns_rr_free(*tlsa);
++	*tlsa = NULL;
++	return LDNS_STATUS_MEM_ERR;
++}
++
++
++/* Return tlsas that actually are TLSA resource records with known values
++ * for the Certificate usage, Selector and Matching type rdata fields.
++ */
++static ldns_rr_list*
++ldns_dane_filter_unusable_records(const ldns_rr_list* tlsas)
++{
++	size_t i;
++	ldns_rr_list* r = ldns_rr_list_new();
++	ldns_rr* tlsa_rr;
++
++	if (! r) {
++		return NULL;
++	}
++	for (i = 0; i < ldns_rr_list_rr_count(tlsas); i++) {
++		tlsa_rr = ldns_rr_list_rr(tlsas, i);
++		if (ldns_rr_get_type(tlsa_rr) == LDNS_RR_TYPE_TLSA &&
++		    ldns_rr_rd_count(tlsa_rr) == 4 &&
++		    ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr, 0)) <= 3 &&
++		    ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr, 1)) <= 1 &&
++		    ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr, 2)) <= 2) {
++
++			if (! ldns_rr_list_push_rr(r, tlsa_rr)) {
++				ldns_rr_list_free(r);
++				return NULL;
++			}
++		}
++	}
++	return r;
++}
++
++
++/* Return whether cert/selector/matching_type matches data.
++ */
++static ldns_status
++ldns_dane_match_cert_with_data(X509* cert, ldns_tlsa_selector selector,
++		ldns_tlsa_matching_type matching_type, ldns_rdf* data)
++{
++	ldns_status s;
++	ldns_rdf* match_data;
++
++	s = ldns_dane_cert2rdf(&match_data, cert, selector, matching_type);
++	if (s == LDNS_STATUS_OK) {
++		if (ldns_rdf_compare(data, match_data) != 0) {
++			s = LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH;
++		}
++		ldns_rdf_free(match_data);
++	}
++	return s;
++}
++
++
++/* Return whether any certificate from the chain with selector/matching_type
++ * matches data.
++ * ca should be true if the certificate has to be a CA certificate too.
++ */
++static ldns_status
++ldns_dane_match_any_cert_with_data(STACK_OF(X509)* chain,
++		ldns_tlsa_selector      selector,
++		ldns_tlsa_matching_type matching_type,
++		ldns_rdf* data, bool ca)
++{
++	ldns_status s = LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH;
++	size_t n, i;
++	X509* cert;
++
++	n = (size_t)sk_X509_num(chain);
++	for (i = 0; i < n; i++) {
++		cert = sk_X509_pop(chain);
++		if (! cert) {
++			s = LDNS_STATUS_SSL_ERR;
++			break;
++		}
++		s = ldns_dane_match_cert_with_data(cert,
++				selector, matching_type, data);
++		if (ca && s == LDNS_STATUS_OK && ! X509_check_ca(cert)) {
++			s = LDNS_STATUS_DANE_NON_CA_CERTIFICATE;
++		}
++		X509_free(cert);
++		if (s != LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH) {
++			break;
++		}
++		/* when s == LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH,
++		 * try to match the next certificate
++		 */
++	}
++	return s;
++}
++
++
++ldns_status
++ldns_dane_verify_rr(const ldns_rr* tlsa_rr,
++		X509* cert, STACK_OF(X509)* extra_certs,
++		X509_STORE* pkix_validation_store)
++{
++	ldns_status s;
++
++	STACK_OF(X509)* pkix_validation_chain = NULL;
++
++	ldns_tlsa_certificate_usage cert_usage;
++	ldns_tlsa_selector          selector;
++	ldns_tlsa_matching_type     matching_type;
++	ldns_rdf*                   data;
++
++	if (! tlsa_rr) {
++		/* No TLSA, so regular PKIX validation
++		 */
++		return ldns_dane_pkix_validate(cert, extra_certs,
++				pkix_validation_store);
++	}
++	cert_usage    = ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr, 0));
++	selector      = ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr, 1));
++	matching_type = ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr, 2));
++	data          =                      ldns_rr_rdf(tlsa_rr, 3) ;
++
++	switch (cert_usage) {
++	case LDNS_TLSA_USAGE_CA_CONSTRAINT:
++		s = ldns_dane_pkix_validate_and_get_chain(
++				&pkix_validation_chain, 
++				cert, extra_certs,
++				pkix_validation_store);
++		if (! pkix_validation_chain) {
++			return s;
++		}
++		if (s == LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE) {
++			/*
++			 * NO PKIX validation. We still try to match *any*
++			 * certificate from the chain, so we return
++			 * TLSA errors over PKIX errors.
++			 *
++			 * i.e. When the TLSA matches no certificate, we return
++			 * TLSA_DID_NOT_MATCH and not PKIX_DID_NOT_VALIDATE
++			 */
++			s = ldns_dane_match_any_cert_with_data(
++					pkix_validation_chain,
++					selector, matching_type, data, true);
++
++			if (s == LDNS_STATUS_OK) {
++				/* A TLSA record did match a cert from the
++				 * chain, thus the error is failed PKIX
++				 * validation.
++				 */
++				s = LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE;
++			}
++
++		} else if (s == LDNS_STATUS_OK) { 
++			/* PKIX validated, does the TLSA match too? */
++
++			s = ldns_dane_match_any_cert_with_data(
++					pkix_validation_chain,
++					selector, matching_type, data, true);
++		}
++		sk_X509_pop_free(pkix_validation_chain, X509_free);
++		return s;
++		break;
++
++	case LDNS_TLSA_USAGE_SERVICE_CERTIFICATE_CONSTRAINT:
++		s = ldns_dane_match_cert_with_data(cert,
++				selector, matching_type, data);
++
++		if (s == LDNS_STATUS_OK) {
++			return ldns_dane_pkix_validate(cert, extra_certs,
++					pkix_validation_store);
++		}
++		return s;
++		break;
++
++	case LDNS_TLSA_USAGE_TRUST_ANCHOR_ASSERTION:
++		s = ldns_dane_pkix_get_chain(&pkix_validation_chain,
++				cert, extra_certs);
++
++		if (s == LDNS_STATUS_OK) {
++			s = ldns_dane_match_any_cert_with_data(
++					pkix_validation_chain,
++					selector, matching_type, data, false);
++
++		} else if (! pkix_validation_chain) {
++			return s;
++		}
++		sk_X509_pop_free(pkix_validation_chain, X509_free);
++		return s;
++		break;
++
++	case LDNS_TLSA_USAGE_DOMAIN_ISSUED_CERTIFICATE:
++		return ldns_dane_match_cert_with_data(cert,
++				selector, matching_type, data);
++		break;
++
++	default:
++		break;
++	}
++	return LDNS_STATUS_DANE_UNKNOWN_CERTIFICATE_USAGE;
++}
++
++
++ldns_status
++ldns_dane_verify(ldns_rr_list* tlsas,
++		X509* cert, STACK_OF(X509)* extra_certs,
++		X509_STORE* pkix_validation_store)
++{
++	size_t i;
++	ldns_rr* tlsa_rr;
++	ldns_status s = LDNS_STATUS_OK, ps;
++
++	assert(cert != NULL);
++
++	if (tlsas && ldns_rr_list_rr_count(tlsas) > 0) {
++		tlsas = ldns_dane_filter_unusable_records(tlsas);
++		if (! tlsas) {
++			return LDNS_STATUS_MEM_ERR;
++		}
++	}
++	if (! tlsas || ldns_rr_list_rr_count(tlsas) == 0) {
++		/* No TLSA's, so regular PKIX validation
++		 */
++		return ldns_dane_pkix_validate(cert, extra_certs,
++				pkix_validation_store);
++	} else {
++		for (i = 0; i < ldns_rr_list_rr_count(tlsas); i++) {
++			tlsa_rr = ldns_rr_list_rr(tlsas, i);
++			ps = s;
++			s = ldns_dane_verify_rr(tlsa_rr, cert, extra_certs,
++					pkix_validation_store);
++
++			if (s != LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH &&
++			    s != LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE) {
++
++				/* which would be LDNS_STATUS_OK (match)
++				 * or some fatal error preventing use from
++				 * trying the next TLSA record.
++				 */
++				break;
++			}
++			s = (s > ps ? s : ps); /* prefer PKIX_DID_NOT_VALIDATE
++						* over   TLSA_DID_NOT_MATCH
++						*/
++		}
++		ldns_rr_list_free(tlsas);
++	}
++	return s;
++}
++#endif /* HAVE_SSL */
++#endif /* USE_DANE */
+diff --git a/ldns/src/dname.c b/ldns/src/dname.c
+new file mode 100644
+index 0000000..55aba5d
+--- /dev/null
++++ b/ldns/src/dname.c
+@@ -0,0 +1,598 @@
++/*
++ * dname.c
++ *
++ * dname specific rdata implementations
++ * A dname is a rdf structure with type LDNS_RDF_TYPE_DNAME
++ * It is not a /real/ type! All function must therefor check
++ * for LDNS_RDF_TYPE_DNAME.
++ *
++ * a Net::DNS like library for C
++ *
++ * (c) NLnet Labs, 2004-2006
++ *
++ * See the file LICENSE for the license
++ */
++
++#include <ldns/config.h>
++
++#include <ldns/ldns.h>
++
++#ifdef HAVE_NETINET_IN_H
++#include <netinet/in.h>
++#endif
++#ifdef HAVE_SYS_SOCKET_H
++#include <sys/socket.h>
++#endif
++#ifdef HAVE_NETDB_H
++#include <netdb.h>
++#endif
++#ifdef HAVE_ARPA_INET_H
++#include <arpa/inet.h>
++#endif
++
++/* Returns whether the last label in the name is a root label (a empty label).
++ * Note that it is not enough to just test the last character to be 0,
++ * because it may be part of the last label itself.
++ */
++static bool
++ldns_dname_last_label_is_root_label(const ldns_rdf* dname)
++{
++	size_t src_pos;
++	size_t len = 0;
++
++	for (src_pos = 0; src_pos < ldns_rdf_size(dname); src_pos += len + 1) {
++		len = ldns_rdf_data(dname)[src_pos];
++	}
++	assert(src_pos == ldns_rdf_size(dname));
++
++	return src_pos > 0 && len == 0;
++}
++
++ldns_rdf *
++ldns_dname_cat_clone(const ldns_rdf *rd1, const ldns_rdf *rd2)
++{
++	ldns_rdf *new;
++	uint16_t new_size;
++	uint8_t *buf;
++	uint16_t left_size;
++
++	if (ldns_rdf_get_type(rd1) != LDNS_RDF_TYPE_DNAME ||
++			ldns_rdf_get_type(rd2) != LDNS_RDF_TYPE_DNAME) {
++		return NULL;
++	}
++
++	/* remove root label if it is present at the end of the left
++	 * rd, by reducing the size with 1
++	 */
++	left_size = ldns_rdf_size(rd1);
++	if (ldns_dname_last_label_is_root_label(rd1)) {
++		left_size--;
++	}
++
++	/* we overwrite the nullbyte of rd1 */
++	new_size = left_size + ldns_rdf_size(rd2);
++	buf = LDNS_XMALLOC(uint8_t, new_size);
++	if (!buf) {
++		return NULL;
++	}
++
++	/* put the two dname's after each other */
++	memcpy(buf, ldns_rdf_data(rd1), left_size);
++	memcpy(buf + left_size, ldns_rdf_data(rd2), ldns_rdf_size(rd2));
++
++	new = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_DNAME, new_size, buf);
++
++	LDNS_FREE(buf);
++	return new;
++}
++
++ldns_status
++ldns_dname_cat(ldns_rdf *rd1, ldns_rdf *rd2)
++{
++	uint16_t left_size;
++	uint16_t size;
++	uint8_t* newd;
++
++	if (ldns_rdf_get_type(rd1) != LDNS_RDF_TYPE_DNAME ||
++			ldns_rdf_get_type(rd2) != LDNS_RDF_TYPE_DNAME) {
++		return LDNS_STATUS_ERR;
++	}
++
++	/* remove root label if it is present at the end of the left
++	 * rd, by reducing the size with 1
++	 */
++	left_size = ldns_rdf_size(rd1);
++	if (ldns_dname_last_label_is_root_label(rd1)) {
++		left_size--;
++	}
++
++	size = left_size + ldns_rdf_size(rd2);
++	newd = LDNS_XREALLOC(ldns_rdf_data(rd1), uint8_t, size);
++	if(!newd) {
++		return LDNS_STATUS_MEM_ERR;
++	}
++
++	ldns_rdf_set_data(rd1, newd);
++	memcpy(ldns_rdf_data(rd1) + left_size, ldns_rdf_data(rd2),
++			ldns_rdf_size(rd2));
++	ldns_rdf_set_size(rd1, size);
++
++	return LDNS_STATUS_OK;
++}
++
++ldns_rdf*
++ldns_dname_reverse(const ldns_rdf *dname)
++{
++	size_t rd_size;
++	uint8_t* buf;
++	ldns_rdf* new;
++	size_t src_pos;
++	size_t len ;
++
++	assert(ldns_rdf_get_type(dname) == LDNS_RDF_TYPE_DNAME);
++	
++	rd_size = ldns_rdf_size(dname);
++	buf = LDNS_XMALLOC(uint8_t, rd_size);
++	if (! buf) {
++		return NULL;
++	}
++	new = ldns_rdf_new(LDNS_RDF_TYPE_DNAME, rd_size, buf);
++	if (! new) {
++		LDNS_FREE(buf);
++		return NULL;
++	}
++	
++	/* If dname ends in a root label, the reverse should too.
++	 */
++	if (ldns_dname_last_label_is_root_label(dname)) {
++		buf[rd_size - 1] = 0;
++		rd_size -= 1;
++	}
++	for (src_pos = 0; src_pos < rd_size; src_pos += len + 1) {
++		len = ldns_rdf_data(dname)[src_pos];
++		memcpy(&buf[rd_size - src_pos - len - 1],
++				&ldns_rdf_data(dname)[src_pos], len + 1);
++	}
++	return new;
++}
++
++ldns_rdf *
++ldns_dname_clone_from(const ldns_rdf *d, uint16_t n)
++{
++	uint8_t *data;
++	uint8_t label_size;
++	size_t data_size;
++
++	if (!d ||
++	    ldns_rdf_get_type(d) != LDNS_RDF_TYPE_DNAME ||
++	    ldns_dname_label_count(d) < n) {
++		return NULL;
++	}
++
++	data = ldns_rdf_data(d);
++	data_size = ldns_rdf_size(d);
++	while (n > 0) {
++		label_size = data[0] + 1;
++		data += label_size;
++		if (data_size < label_size) {
++			/* this label is very broken */
++			return NULL;
++		}
++		data_size -= label_size;
++		n--;
++	}
++
++	return ldns_dname_new_frm_data(data_size, data);
++}
++
++ldns_rdf *
++ldns_dname_left_chop(const ldns_rdf *d)
++{
++	uint8_t label_pos;
++	ldns_rdf *chop;
++
++	if (!d) {
++		return NULL;
++	}
++
++	if (ldns_rdf_get_type(d) != LDNS_RDF_TYPE_DNAME) {
++		return NULL;
++	}
++	if (ldns_dname_label_count(d) == 0) {
++		/* root label */
++		return NULL;
++	}
++	/* 05blaat02nl00 */
++	label_pos = ldns_rdf_data(d)[0];
++
++	chop = ldns_dname_new_frm_data(ldns_rdf_size(d) - label_pos - 1,
++			ldns_rdf_data(d) + label_pos + 1);
++	return chop;
++}
++
++uint8_t
++ldns_dname_label_count(const ldns_rdf *r)
++{
++        uint16_t src_pos;
++        uint16_t len;
++        uint8_t i;
++        size_t r_size;
++
++	if (!r) {
++		return 0;
++	}
++
++	i = 0;
++	src_pos = 0;
++	r_size = ldns_rdf_size(r);
++
++	if (ldns_rdf_get_type(r) != LDNS_RDF_TYPE_DNAME) {
++		return 0;
++	} else {
++		len = ldns_rdf_data(r)[src_pos]; /* start of the label */
++
++		/* single root label */
++		if (1 == r_size) {
++			return 0;
++		} else {
++			while ((len > 0) && src_pos < r_size) {
++				src_pos++;
++				src_pos += len;
++				len = ldns_rdf_data(r)[src_pos];
++				i++;
++			}
++		}
++	}
++	return i;
++}
++
++ldns_rdf *
++ldns_dname_new(uint16_t s, void *d)
++{
++        ldns_rdf *rd;
++
++        rd = LDNS_MALLOC(ldns_rdf);
++        if (!rd) {
++                return NULL;
++        }
++        ldns_rdf_set_size(rd, s);
++        ldns_rdf_set_type(rd, LDNS_RDF_TYPE_DNAME);
++        ldns_rdf_set_data(rd, d);
++        return rd;
++}
++
++ldns_rdf *
++ldns_dname_new_frm_str(const char *str)
++{
++	return ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, str);
++}
++
++ldns_rdf *
++ldns_dname_new_frm_data(uint16_t size, const void *data)
++{
++	return ldns_rdf_new_frm_data(LDNS_RDF_TYPE_DNAME, size, data);
++}
++
++void
++ldns_dname2canonical(const ldns_rdf *rd)
++{
++	uint8_t *rdd;
++	uint16_t i;
++
++	if (ldns_rdf_get_type(rd) != LDNS_RDF_TYPE_DNAME) {
++		return;
++	}
++
++	rdd = (uint8_t*)ldns_rdf_data(rd);
++	for (i = 0; i < ldns_rdf_size(rd); i++, rdd++) {
++		*rdd = (uint8_t)LDNS_DNAME_NORMALIZE((int)*rdd);
++	}
++}
++
++bool
++ldns_dname_is_subdomain(const ldns_rdf *sub, const ldns_rdf *parent)
++{
++	uint8_t sub_lab;
++	uint8_t par_lab;
++	int8_t i, j;
++	ldns_rdf *tmp_sub = NULL;
++	ldns_rdf *tmp_par = NULL;
++    ldns_rdf *sub_clone;
++    ldns_rdf *parent_clone;
++    bool result = true;
++
++	if (ldns_rdf_get_type(sub) != LDNS_RDF_TYPE_DNAME ||
++			ldns_rdf_get_type(parent) != LDNS_RDF_TYPE_DNAME ||
++			ldns_rdf_compare(sub, parent) == 0) {
++		return false;
++	}
++
++    /* would be nicer if we do not have to clone... */
++    sub_clone = ldns_dname_clone_from(sub, 0);
++    parent_clone = ldns_dname_clone_from(parent, 0);
++    ldns_dname2canonical(sub_clone);
++    ldns_dname2canonical(parent_clone);
++
++	sub_lab = ldns_dname_label_count(sub_clone);
++	par_lab = ldns_dname_label_count(parent_clone);
++
++	/* if sub sits above parent, it cannot be a child/sub domain */
++	if (sub_lab < par_lab) {
++		result = false;
++	} else {
++		/* check all labels the from the parent labels, from right to left.
++		 * When they /all/ match we have found a subdomain
++		 */
++		j = sub_lab - 1; /* we count from zero, thank you */
++		for (i = par_lab -1; i >= 0; i--) {
++			tmp_sub = ldns_dname_label(sub_clone, j);
++			tmp_par = ldns_dname_label(parent_clone, i);
++			if (!tmp_sub || !tmp_par) {
++				/* deep free does null check */
++				ldns_rdf_deep_free(tmp_sub);
++				ldns_rdf_deep_free(tmp_par);
++				result = false;
++				break;
++			}
++
++			if (ldns_rdf_compare(tmp_sub, tmp_par) != 0) {
++				/* they are not equal */
++				ldns_rdf_deep_free(tmp_sub);
++				ldns_rdf_deep_free(tmp_par);
++				result = false;
++				break;
++			}
++			ldns_rdf_deep_free(tmp_sub);
++			ldns_rdf_deep_free(tmp_par);
++			j--;
++		}
++	}
++	ldns_rdf_deep_free(sub_clone);
++	ldns_rdf_deep_free(parent_clone);
++	return result;
++}
++
++int
++ldns_dname_compare(const ldns_rdf *dname1, const ldns_rdf *dname2)
++{
++	size_t lc1, lc2, lc1f, lc2f;
++	size_t i;
++	int result = 0;
++	uint8_t *lp1, *lp2;
++
++	/* see RFC4034 for this algorithm */
++	/* this algorithm assumes the names are normalized to case */
++
++        /* only when both are not NULL we can say anything about them */
++        if (!dname1 && !dname2) {
++                return 0;
++        }
++        if (!dname1 || !dname2) {
++                return -1;
++        }
++	/* asserts must happen later as we are looking in the
++	 * dname, which could be NULL. But this case is handled
++	 * above
++	 */
++	assert(ldns_rdf_get_type(dname1) == LDNS_RDF_TYPE_DNAME);
++	assert(ldns_rdf_get_type(dname2) == LDNS_RDF_TYPE_DNAME);
++
++	lc1 = ldns_dname_label_count(dname1);
++	lc2 = ldns_dname_label_count(dname2);
++
++	if (lc1 == 0 && lc2 == 0) {
++		return 0;
++	}
++	if (lc1 == 0) {
++		return -1;
++	}
++	if (lc2 == 0) {
++		return 1;
++	}
++	lc1--;
++	lc2--;
++	/* we start at the last label */
++	while (true) {
++		/* find the label first */
++		lc1f = lc1;
++		lp1 = ldns_rdf_data(dname1);
++		while (lc1f > 0) {
++			lp1 += *lp1 + 1;
++			lc1f--;
++		}
++
++		/* and find the other one */
++		lc2f = lc2;
++		lp2 = ldns_rdf_data(dname2);
++		while (lc2f > 0) {
++			lp2 += *lp2 + 1;
++			lc2f--;
++		}
++
++		/* now check the label character for character. */
++		for (i = 1; i < (size_t)(*lp1 + 1); i++) {
++			if (i > *lp2) {
++				/* apparently label 1 is larger */
++				result = 1;
++				goto done;
++			}
++			if (LDNS_DNAME_NORMALIZE((int) *(lp1 + i)) <
++			    LDNS_DNAME_NORMALIZE((int) *(lp2 + i))) {
++			    result = -1;
++			    goto done;
++			} else if (LDNS_DNAME_NORMALIZE((int) *(lp1 + i)) >
++			    LDNS_DNAME_NORMALIZE((int) *(lp2 + i))) {
++			    result = 1;
++			    goto done;
++			}
++		}
++		if (*lp1 < *lp2) {
++			/* apparently label 2 is larger */
++			result = -1;
++			goto done;
++		}
++		if (lc1 == 0 && lc2 > 0) {
++			result = -1;
++			goto done;
++		} else if (lc1 > 0 && lc2 == 0) {
++			result = 1;
++			goto done;
++		} else if (lc1 == 0 && lc2 == 0) {
++			result = 0;
++			goto done;
++		}
++		lc1--;
++		lc2--;
++	}
++
++	done:
++	return result;
++}
++
++int
++ldns_dname_is_wildcard(const ldns_rdf* dname)
++{
++	return ( ldns_dname_label_count(dname) > 0 &&
++		 ldns_rdf_data(dname)[0] == 1 &&
++		 ldns_rdf_data(dname)[1] == '*');
++}
++
++int
++ldns_dname_match_wildcard(const ldns_rdf *dname, const ldns_rdf *wildcard)
++{
++	ldns_rdf *wc_chopped;
++	int result;
++	/* check whether it really is a wildcard */
++	if (ldns_dname_is_wildcard(wildcard)) {
++		/* ok, so the dname needs to be a subdomain of the wildcard
++		 * without the *
++		 */
++		wc_chopped = ldns_dname_left_chop(wildcard);
++		result = (int) ldns_dname_is_subdomain(dname, wc_chopped);
++		ldns_rdf_deep_free(wc_chopped);
++	} else {
++		result = (ldns_dname_compare(dname, wildcard) == 0);
++	}
++	return result;
++}
++
++/* nsec test: does prev <= middle < next
++ * -1 = yes
++ * 0 = error/can't tell
++ * 1 = no
++ */
++int
++ldns_dname_interval(const ldns_rdf *prev, const ldns_rdf *middle,
++		const ldns_rdf *next)
++{
++	int prev_check, next_check;
++
++	assert(ldns_rdf_get_type(prev) == LDNS_RDF_TYPE_DNAME);
++	assert(ldns_rdf_get_type(middle) == LDNS_RDF_TYPE_DNAME);
++	assert(ldns_rdf_get_type(next) == LDNS_RDF_TYPE_DNAME);
++
++	prev_check = ldns_dname_compare(prev, middle);
++	next_check = ldns_dname_compare(middle, next);
++	/* <= next. This cannot be the case for nsec, because then we would
++	 * have gotten the nsec of next...
++	 */
++	if (next_check == 0) {
++		return 0;
++	}
++
++			/* <= */
++	if ((prev_check == -1 || prev_check == 0) &&
++			/* < */
++			next_check == -1) {
++		return -1;
++	} else {
++		return 1;
++	}
++}
++
++
++bool
++ldns_dname_str_absolute(const char *dname_str)
++{
++        const char* s;
++	if(dname_str && strcmp(dname_str, ".") == 0)
++		return 1;
++        if(!dname_str || strlen(dname_str) < 2)
++                return 0;
++        if(dname_str[strlen(dname_str) - 1] != '.')
++                return 0;
++        if(dname_str[strlen(dname_str) - 2] != '\\')
++                return 1; /* ends in . and no \ before it */
++        /* so we have the case of ends in . and there is \ before it */
++        for(s=dname_str; *s; s++) {
++                if(*s == '\\') {
++                        if(s[1] && s[2] && s[3] /* check length */
++                                && isdigit(s[1]) && isdigit(s[2]) && 
++                                isdigit(s[3]))
++                                s += 3;
++                        else if(!s[1] || isdigit(s[1])) /* escape of nul,0-9 */
++                                return 0; /* parse error */
++                        else s++; /* another character escaped */
++                }
++                else if(!*(s+1) && *s == '.')
++                        return 1; /* trailing dot, unescaped */
++        }
++        return 0;
++}
++
++bool
++ldns_dname_absolute(const ldns_rdf *rdf)
++{
++	char *str = ldns_rdf2str(rdf);
++	if (str) {
++		bool r = ldns_dname_str_absolute(str);
++		LDNS_FREE(str);
++		return r;
++	}
++	return false;
++}
++
++ldns_rdf *
++ldns_dname_label(const ldns_rdf *rdf, uint8_t labelpos)
++{
++	uint8_t labelcnt;
++	uint16_t src_pos;
++	uint16_t len;
++	ldns_rdf *tmpnew;
++	size_t s;
++	uint8_t *data;
++
++	if (ldns_rdf_get_type(rdf) != LDNS_RDF_TYPE_DNAME) {
++		return NULL;
++	}
++
++	labelcnt = 0;
++	src_pos = 0;
++	s = ldns_rdf_size(rdf);
++
++	len = ldns_rdf_data(rdf)[src_pos]; /* label start */
++	while ((len > 0) && src_pos < s) {
++		if (labelcnt == labelpos) {
++			/* found our label */
++			data = LDNS_XMALLOC(uint8_t, len + 2);
++			if (!data) {
++				return NULL;
++			}
++			memcpy(data, ldns_rdf_data(rdf) + src_pos, len + 1);
++			data[len + 2 - 1] = 0;
++
++			tmpnew = ldns_rdf_new( LDNS_RDF_TYPE_DNAME
++					     , len + 2, data);
++			if (!tmpnew) {
++				LDNS_FREE(data);
++				return NULL;
++			}
++			return tmpnew;
++		}
++		src_pos++;
++		src_pos += len;
++		len = ldns_rdf_data(rdf)[src_pos];
++		labelcnt++;
++	}
++	return NULL;
++}
+diff --git a/ldns/src/dnssec.c b/ldns/src/dnssec.c
+new file mode 100644
+index 0000000..a41a9f6
+--- /dev/null
++++ b/ldns/src/dnssec.c
+@@ -0,0 +1,1869 @@
++/*
++ * dnssec.c
++ *
++ * contains the cryptographic function needed for DNSSEC in ldns
++ * The crypto library used is openssl
++ *
++ * (c) NLnet Labs, 2004-2008
++ *
++ * See the file LICENSE for the license
++ */
++
++#include <ldns/config.h>
++
++#include <ldns/ldns.h>
++#include <ldns/dnssec.h>
++
++#include <strings.h>
++#include <time.h>
++
++#ifdef HAVE_SSL
++#include <openssl/ssl.h>
++#include <openssl/evp.h>
++#include <openssl/rand.h>
++#include <openssl/err.h>
++#include <openssl/md5.h>
++#endif
++
++ldns_rr *
++ldns_dnssec_get_rrsig_for_name_and_type(const ldns_rdf *name,
++                                        const ldns_rr_type type,
++                                        const ldns_rr_list *rrs)
++{
++	size_t i;
++	ldns_rr *candidate;
++
++	if (!name || !rrs) {
++		return NULL;
++	}
++
++	for (i = 0; i < ldns_rr_list_rr_count(rrs); i++) {
++		candidate = ldns_rr_list_rr(rrs, i);
++		if (ldns_rr_get_type(candidate) == LDNS_RR_TYPE_RRSIG) {
++			if (ldns_dname_compare(ldns_rr_owner(candidate),
++			                       name) == 0 &&
++			    ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(candidate))
++			    == type
++			    ) {
++				return candidate;
++			}
++		}
++	}
++
++	return NULL;
++}
++
++ldns_rr *
++ldns_dnssec_get_dnskey_for_rrsig(const ldns_rr *rrsig,
++						   const ldns_rr_list *rrs)
++{
++	size_t i;
++	ldns_rr *candidate;
++
++	if (!rrsig || !rrs) {
++		return NULL;
++	}
++
++	for (i = 0; i < ldns_rr_list_rr_count(rrs); i++) {
++		candidate = ldns_rr_list_rr(rrs, i);
++		if (ldns_rr_get_type(candidate) == LDNS_RR_TYPE_DNSKEY) {
++			if (ldns_dname_compare(ldns_rr_owner(candidate),
++			                       ldns_rr_rrsig_signame(rrsig)) == 0 &&
++			    ldns_rdf2native_int16(ldns_rr_rrsig_keytag(rrsig)) ==
++			    ldns_calc_keytag(candidate)
++			    ) {
++				return candidate;
++			}
++		}
++	}
++
++	return NULL;
++}
++
++ldns_rdf *
++ldns_nsec_get_bitmap(ldns_rr *nsec) {
++	if (ldns_rr_get_type(nsec) == LDNS_RR_TYPE_NSEC) {
++		return ldns_rr_rdf(nsec, 1);
++	} else if (ldns_rr_get_type(nsec) == LDNS_RR_TYPE_NSEC3) {
++		return ldns_rr_rdf(nsec, 5);
++	} else {
++		return NULL;
++	}
++}
++
++/*return the owner name of the closest encloser for name from the list of rrs */
++/* this is NOT the hash, but the original name! */
++ldns_rdf *
++ldns_dnssec_nsec3_closest_encloser(ldns_rdf *qname,
++                                   ATTR_UNUSED(ldns_rr_type qtype),
++                                   ldns_rr_list *nsec3s)
++{
++	/* remember parameters, they must match */
++	uint8_t algorithm;
++	uint32_t iterations;
++	uint8_t salt_length;
++	uint8_t *salt;
++
++	ldns_rdf *sname, *hashed_sname, *tmp;
++	bool flag;
++
++	bool exact_match_found;
++	bool in_range_found;
++
++	ldns_status status;
++	ldns_rdf *zone_name;
++
++	size_t nsec_i;
++	ldns_rr *nsec;
++	ldns_rdf *result = NULL;
++
++	if (!qname || !nsec3s || ldns_rr_list_rr_count(nsec3s) < 1) {
++		return NULL;
++	}
++
++	nsec = ldns_rr_list_rr(nsec3s, 0);
++	algorithm = ldns_nsec3_algorithm(nsec);
++	salt_length = ldns_nsec3_salt_length(nsec);
++	salt = ldns_nsec3_salt_data(nsec);
++	iterations = ldns_nsec3_iterations(nsec);
++
++	sname = ldns_rdf_clone(qname);
++
++	flag = false;
++
++	zone_name = ldns_dname_left_chop(ldns_rr_owner(nsec));
++
++	/* algorithm from nsec3-07 8.3 */
++	while (ldns_dname_label_count(sname) > 0) {
++		exact_match_found = false;
++		in_range_found = false;
++
++		hashed_sname = ldns_nsec3_hash_name(sname,
++									 algorithm,
++									 iterations,
++									 salt_length,
++									 salt);
++
++		status = ldns_dname_cat(hashed_sname, zone_name);
++                if(status != LDNS_STATUS_OK) {
++	                LDNS_FREE(salt);
++	                ldns_rdf_deep_free(zone_name);
++	                ldns_rdf_deep_free(sname);
++                        return NULL;
++                }
++
++		for (nsec_i = 0; nsec_i < ldns_rr_list_rr_count(nsec3s); nsec_i++) {
++			nsec = ldns_rr_list_rr(nsec3s, nsec_i);
++
++			/* check values of iterations etc! */
++
++			/* exact match? */
++			if (ldns_dname_compare(ldns_rr_owner(nsec), hashed_sname) == 0) {
++			 	exact_match_found = true;
++			} else if (ldns_nsec_covers_name(nsec, hashed_sname)) {
++				in_range_found = true;
++			}
++
++		}
++		if (!exact_match_found && in_range_found) {
++			flag = true;
++		} else if (exact_match_found && flag) {
++			result = ldns_rdf_clone(sname);
++			/* RFC 5155: 8.3. 2.** "The proof is complete" */
++			ldns_rdf_deep_free(hashed_sname);
++			goto done;
++		} else if (exact_match_found && !flag) {
++			/* error! */
++			ldns_rdf_deep_free(hashed_sname);
++			goto done;
++		} else {
++			flag = false;
++		}
++
++		ldns_rdf_deep_free(hashed_sname);
++		tmp = sname;
++		sname = ldns_dname_left_chop(sname);
++		ldns_rdf_deep_free(tmp);
++	}
++
++	done:
++	LDNS_FREE(salt);
++	ldns_rdf_deep_free(zone_name);
++	ldns_rdf_deep_free(sname);
++
++	return result;
++}
++
++bool
++ldns_dnssec_pkt_has_rrsigs(const ldns_pkt *pkt)
++{
++	size_t i;
++	for (i = 0; i < ldns_pkt_ancount(pkt); i++) {
++		if (ldns_rr_get_type(ldns_rr_list_rr(ldns_pkt_answer(pkt), i)) ==
++		    LDNS_RR_TYPE_RRSIG) {
++			return true;
++		}
++	}
++	for (i = 0; i < ldns_pkt_nscount(pkt); i++) {
++		if (ldns_rr_get_type(ldns_rr_list_rr(ldns_pkt_authority(pkt), i)) ==
++		    LDNS_RR_TYPE_RRSIG) {
++			return true;
++		}
++	}
++	return false;
++}
++
++ldns_rr_list *
++ldns_dnssec_pkt_get_rrsigs_for_name_and_type(const ldns_pkt *pkt,
++									ldns_rdf *name,
++									ldns_rr_type type)
++{
++	uint16_t t_netorder;
++	ldns_rr_list *sigs;
++	ldns_rr_list *sigs_covered;
++	ldns_rdf *rdf_t;
++	
++	sigs = ldns_pkt_rr_list_by_name_and_type(pkt,
++									 name,
++									 LDNS_RR_TYPE_RRSIG,
++									 LDNS_SECTION_ANY_NOQUESTION
++									 );
++
++	t_netorder = htons(type); /* rdf are in network order! */
++	rdf_t = ldns_rdf_new(LDNS_RDF_TYPE_TYPE, LDNS_RDF_SIZE_WORD, &t_netorder);
++	sigs_covered = ldns_rr_list_subtype_by_rdf(sigs, rdf_t, 0);
++	
++	ldns_rdf_free(rdf_t);
++	ldns_rr_list_deep_free(sigs);
++
++	return sigs_covered;
++
++}
++
++ldns_rr_list *
++ldns_dnssec_pkt_get_rrsigs_for_type(const ldns_pkt *pkt, ldns_rr_type type)
++{
++	uint16_t t_netorder;
++	ldns_rr_list *sigs;
++	ldns_rr_list *sigs_covered;
++	ldns_rdf *rdf_t;
++
++	sigs = ldns_pkt_rr_list_by_type(pkt,
++	                                LDNS_RR_TYPE_RRSIG,
++	                                LDNS_SECTION_ANY_NOQUESTION
++							  );
++
++	t_netorder = htons(type); /* rdf are in network order! */
++	rdf_t = ldns_rdf_new(LDNS_RDF_TYPE_TYPE,
++					 2,
++					 &t_netorder);
++	sigs_covered = ldns_rr_list_subtype_by_rdf(sigs, rdf_t, 0);
++
++	ldns_rdf_free(rdf_t);
++	ldns_rr_list_deep_free(sigs);
++
++	return sigs_covered;
++
++}
++
++/* used only on the public key RR */
++uint16_t
++ldns_calc_keytag(const ldns_rr *key)
++{
++	uint16_t ac16;
++	ldns_buffer *keybuf;
++	size_t keysize;
++
++	if (!key) {
++		return 0;
++	}
++
++	if (ldns_rr_get_type(key) != LDNS_RR_TYPE_DNSKEY &&
++	    ldns_rr_get_type(key) != LDNS_RR_TYPE_KEY
++	    ) {
++		return 0;
++	}
++
++	/* rdata to buf - only put the rdata in a buffer */
++	keybuf = ldns_buffer_new(LDNS_MIN_BUFLEN); /* grows */
++	if (!keybuf) {
++		return 0;
++	}
++	(void)ldns_rr_rdata2buffer_wire(keybuf, key);
++	/* the current pos in the buffer is the keysize */
++	keysize= ldns_buffer_position(keybuf);
++
++	ac16 = ldns_calc_keytag_raw(ldns_buffer_begin(keybuf), keysize);
++	ldns_buffer_free(keybuf);
++	return ac16;
++}
++
++uint16_t ldns_calc_keytag_raw(uint8_t* key, size_t keysize)
++{
++	unsigned int i;
++	uint32_t ac32;
++	uint16_t ac16;
++
++	if(keysize < 4) {
++		return 0;
++	}
++	/* look at the algorithm field, copied from 2535bis */
++	if (key[3] == LDNS_RSAMD5) {
++		ac16 = 0;
++		if (keysize > 4) {
++			memmove(&ac16, key + keysize - 3, 2);
++		}
++		ac16 = ntohs(ac16);
++		return (uint16_t) ac16;
++	} else {
++		ac32 = 0;
++		for (i = 0; (size_t)i < keysize; ++i) {
++			ac32 += (i & 1) ? key[i] : key[i] << 8;
++		}
++		ac32 += (ac32 >> 16) & 0xFFFF;
++		return (uint16_t) (ac32 & 0xFFFF);
++	}
++}
++
++#ifdef HAVE_SSL
++DSA *
++ldns_key_buf2dsa(ldns_buffer *key)
++{
++	return ldns_key_buf2dsa_raw((unsigned char*)ldns_buffer_begin(key),
++						   ldns_buffer_position(key));
++}
++
++DSA *
++ldns_key_buf2dsa_raw(unsigned char* key, size_t len)
++{
++	uint8_t T;
++	uint16_t length;
++	uint16_t offset;
++	DSA *dsa;
++	BIGNUM *Q; BIGNUM *P;
++	BIGNUM *G; BIGNUM *Y;
++
++	if(len == 0)
++		return NULL;
++	T = (uint8_t)key[0];
++	length = (64 + T * 8);
++	offset = 1;
++
++	if (T > 8) {
++		return NULL;
++	}
++	if(len < (size_t)1 + SHA_DIGEST_LENGTH + 3*length)
++		return NULL;
++
++	Q = BN_bin2bn(key+offset, SHA_DIGEST_LENGTH, NULL);
++	offset += SHA_DIGEST_LENGTH;
++
++	P = BN_bin2bn(key+offset, (int)length, NULL);
++	offset += length;
++
++	G = BN_bin2bn(key+offset, (int)length, NULL);
++	offset += length;
++
++	Y = BN_bin2bn(key+offset, (int)length, NULL);
++	offset += length;
++
++	/* create the key and set its properties */
++	if(!Q || !P || !G || !Y || !(dsa = DSA_new())) {
++		BN_free(Q);
++		BN_free(P);
++		BN_free(G);
++		BN_free(Y);
++		return NULL;
++	}
++#ifndef S_SPLINT_S
++	dsa->p = P;
++	dsa->q = Q;
++	dsa->g = G;
++	dsa->pub_key = Y;
++#endif /* splint */
++
++	return dsa;
++}
++
++RSA *
++ldns_key_buf2rsa(ldns_buffer *key)
++{
++	return ldns_key_buf2rsa_raw((unsigned char*)ldns_buffer_begin(key),
++						   ldns_buffer_position(key));
++}
++
++RSA *
++ldns_key_buf2rsa_raw(unsigned char* key, size_t len)
++{
++	uint16_t offset;
++	uint16_t exp;
++	uint16_t int16;
++	RSA *rsa;
++	BIGNUM *modulus;
++	BIGNUM *exponent;
++
++	if (len == 0)
++		return NULL;
++	if (key[0] == 0) {
++		if(len < 3)
++			return NULL;
++		/* need some smart comment here XXX*/
++		/* the exponent is too large so it's places
++		 * futher...???? */
++		memmove(&int16, key+1, 2);
++		exp = ntohs(int16);
++		offset = 3;
++	} else {
++		exp = key[0];
++		offset = 1;
++	}
++
++	/* key length at least one */
++	if(len < (size_t)offset + exp + 1)
++		return NULL;
++
++	/* Exponent */
++	exponent = BN_new();
++	if(!exponent) return NULL;
++	(void) BN_bin2bn(key+offset, (int)exp, exponent);
++	offset += exp;
++
++	/* Modulus */
++	modulus = BN_new();
++	if(!modulus) {
++		BN_free(exponent);
++		return NULL;
++	}
++	/* length of the buffer must match the key length! */
++	(void) BN_bin2bn(key+offset, (int)(len - offset), modulus);
++
++	rsa = RSA_new();
++	if(!rsa) {
++		BN_free(exponent);
++		BN_free(modulus);
++		return NULL;
++	}
++#ifndef S_SPLINT_S
++	rsa->n = modulus;
++	rsa->e = exponent;
++#endif /* splint */
++
++	return rsa;
++}
++
++int
++ldns_digest_evp(unsigned char* data, unsigned int len, unsigned char* dest,
++	const EVP_MD* md)
++{
++	EVP_MD_CTX* ctx;
++	ctx = EVP_MD_CTX_create();
++	if(!ctx)
++		return false;
++	if(!EVP_DigestInit_ex(ctx, md, NULL) ||
++		!EVP_DigestUpdate(ctx, data, len) ||
++		!EVP_DigestFinal_ex(ctx, dest, NULL)) {
++		EVP_MD_CTX_destroy(ctx);
++		return false;
++	}
++	EVP_MD_CTX_destroy(ctx);
++	return true;
++}
++#endif /* HAVE_SSL */
++
++ldns_rr *
++ldns_key_rr2ds(const ldns_rr *key, ldns_hash h)
++{
++	ldns_rdf *tmp;
++	ldns_rr *ds;
++	uint16_t keytag;
++	uint8_t  sha1hash;
++	uint8_t *digest;
++	ldns_buffer *data_buf;
++#ifdef USE_GOST
++	const EVP_MD* md = NULL;
++#endif
++
++	if (ldns_rr_get_type(key) != LDNS_RR_TYPE_DNSKEY) {
++		return NULL;
++	}
++
++	ds = ldns_rr_new();
++	if (!ds) {
++		return NULL;
++	}
++	ldns_rr_set_type(ds, LDNS_RR_TYPE_DS);
++	ldns_rr_set_owner(ds, ldns_rdf_clone(
++								  ldns_rr_owner(key)));
++	ldns_rr_set_ttl(ds, ldns_rr_ttl(key));
++	ldns_rr_set_class(ds, ldns_rr_get_class(key));
++
++	switch(h) {
++	default:
++	case LDNS_SHA1:
++		digest = LDNS_XMALLOC(uint8_t, LDNS_SHA1_DIGEST_LENGTH);
++		if (!digest) {
++			ldns_rr_free(ds);
++			return NULL;
++		}
++		break;
++	case LDNS_SHA256:
++		digest = LDNS_XMALLOC(uint8_t, LDNS_SHA256_DIGEST_LENGTH);
++		if (!digest) {
++			ldns_rr_free(ds);
++			return NULL;
++		}
++		break;
++	case LDNS_HASH_GOST:
++#ifdef USE_GOST
++		(void)ldns_key_EVP_load_gost_id();
++		md = EVP_get_digestbyname("md_gost94");
++		if(!md) {
++			ldns_rr_free(ds);
++			return NULL;
++		}
++		digest = LDNS_XMALLOC(uint8_t, EVP_MD_size(md));
++		if (!digest) {
++			ldns_rr_free(ds);
++			return NULL;
++		}
++                break;
++#else
++		/* not implemented */
++		ldns_rr_free(ds);
++		return NULL;
++#endif
++	case LDNS_SHA384:
++#ifdef USE_ECDSA
++		digest = LDNS_XMALLOC(uint8_t, SHA384_DIGEST_LENGTH);
++		if (!digest) {
++			ldns_rr_free(ds);
++			return NULL;
++		}
++                break;
++#else
++		/* not implemented */
++		ldns_rr_free(ds);
++		return NULL;
++#endif
++	}
++
++	data_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN);
++	if (!data_buf) {
++		LDNS_FREE(digest);
++		ldns_rr_free(ds);
++		return NULL;
++	}
++
++	/* keytag */
++	keytag = htons(ldns_calc_keytag((ldns_rr*)key));
++	tmp = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_INT16,
++						   sizeof(uint16_t),
++						   &keytag);
++	ldns_rr_push_rdf(ds, tmp);
++
++	/* copy the algorithm field */
++	if ((tmp = ldns_rr_rdf(key, 2)) == NULL) {
++		LDNS_FREE(digest);
++		ldns_buffer_free(data_buf);
++		ldns_rr_free(ds);
++		return NULL;
++	} else {
++		ldns_rr_push_rdf(ds, ldns_rdf_clone( tmp )); 
++	}
++
++	/* digest hash type */
++	sha1hash = (uint8_t)h;
++	tmp = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_INT8,
++						   sizeof(uint8_t),
++						   &sha1hash);
++	ldns_rr_push_rdf(ds, tmp);
++
++	/* digest */
++	/* owner name */
++	tmp = ldns_rdf_clone(ldns_rr_owner(key));
++	ldns_dname2canonical(tmp);
++	if (ldns_rdf2buffer_wire(data_buf, tmp) != LDNS_STATUS_OK) {
++		LDNS_FREE(digest);
++		ldns_buffer_free(data_buf);
++		ldns_rr_free(ds);
++		ldns_rdf_deep_free(tmp);
++		return NULL;
++	}
++	ldns_rdf_deep_free(tmp);
++
++	/* all the rdata's */
++	if (ldns_rr_rdata2buffer_wire(data_buf,
++							(ldns_rr*)key) != LDNS_STATUS_OK) {
++		LDNS_FREE(digest);
++		ldns_buffer_free(data_buf);
++		ldns_rr_free(ds);
++		return NULL;
++	}
++	switch(h) {
++	case LDNS_SHA1:
++		(void) ldns_sha1((unsigned char *) ldns_buffer_begin(data_buf),
++		                 (unsigned int) ldns_buffer_position(data_buf),
++		                 (unsigned char *) digest);
++
++		tmp = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_HEX,
++		                            LDNS_SHA1_DIGEST_LENGTH,
++		                            digest);
++		ldns_rr_push_rdf(ds, tmp);
++
++		break;
++	case LDNS_SHA256:
++		(void) ldns_sha256((unsigned char *) ldns_buffer_begin(data_buf),
++		                   (unsigned int) ldns_buffer_position(data_buf),
++		                   (unsigned char *) digest);
++		tmp = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_HEX,
++		                            LDNS_SHA256_DIGEST_LENGTH,
++		                            digest);
++		ldns_rr_push_rdf(ds, tmp);
++		break;
++	case LDNS_HASH_GOST:
++#ifdef USE_GOST
++		if(!ldns_digest_evp((unsigned char *) ldns_buffer_begin(data_buf),
++				(unsigned int) ldns_buffer_position(data_buf),
++				(unsigned char *) digest, md)) {
++			LDNS_FREE(digest);
++			ldns_buffer_free(data_buf);
++			ldns_rr_free(ds);
++			return NULL;
++		}
++		tmp = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_HEX,
++		                            (size_t)EVP_MD_size(md),
++		                            digest);
++		ldns_rr_push_rdf(ds, tmp);
++#endif
++		break;
++	case LDNS_SHA384:
++#ifdef USE_ECDSA
++		(void) SHA384((unsigned char *) ldns_buffer_begin(data_buf),
++		                 (unsigned int) ldns_buffer_position(data_buf),
++		                 (unsigned char *) digest);
++		tmp = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_HEX,
++		                            SHA384_DIGEST_LENGTH,
++		                            digest);
++		ldns_rr_push_rdf(ds, tmp);
++#endif
++		break;
++	}
++
++	LDNS_FREE(digest);
++	ldns_buffer_free(data_buf);
++	return ds;
++}
++
++/* From RFC3845:
++ *
++ * 2.1.2.  The List of Type Bit Map(s) Field
++ * 
++ *    The RR type space is split into 256 window blocks, each representing
++ *    the low-order 8 bits of the 16-bit RR type space.  Each block that
++ *    has at least one active RR type is encoded using a single octet
++ *    window number (from 0 to 255), a single octet bitmap length (from 1
++ *    to 32) indicating the number of octets used for the window block's
++ *    bitmap, and up to 32 octets (256 bits) of bitmap.
++ * 
++ *    Window blocks are present in the NSEC RR RDATA in increasing
++ *    numerical order.
++ * 
++ *    "|" denotes concatenation
++ * 
++ *    Type Bit Map(s) Field = ( Window Block # | Bitmap Length | Bitmap ) +
++ * 
++ *    <cut>
++ * 
++ *    Blocks with no types present MUST NOT be included.  Trailing zero
++ *    octets in the bitmap MUST be omitted.  The length of each block's
++ *    bitmap is determined by the type code with the largest numerical
++ *    value within that block, among the set of RR types present at the
++ *    NSEC RR's owner name.  Trailing zero octets not specified MUST be
++ *    interpreted as zero octets.
++ */
++ldns_rdf *
++ldns_dnssec_create_nsec_bitmap(ldns_rr_type rr_type_list[],
++                               size_t size,
++                               ldns_rr_type nsec_type)
++{
++	uint8_t  window;		/*  most significant octet of type */
++	uint8_t  subtype;		/* least significant octet of type */
++	uint16_t windows[256]		/* Max subtype per window */
++#ifndef S_SPLINT_S
++	                      = { 0 }	/* Initialize ALL elements with 0 */
++#endif
++	                             ;
++	ldns_rr_type* d;	/* used to traverse rr_type_list*/
++	size_t i;		/* used to traverse windows array */
++
++	size_t sz;			/* size needed for type bitmap rdf */
++	uint8_t* data = NULL;		/* rdf data */
++	uint8_t* dptr;			/* used to itraverse rdf data */
++	ldns_rdf* rdf;			/* bitmap rdf to return */
++
++	if (nsec_type != LDNS_RR_TYPE_NSEC &&
++	    nsec_type != LDNS_RR_TYPE_NSEC3) {
++		return NULL;
++	}
++
++	/* Which other windows need to be in the bitmap rdf?
++	 */
++	for (d = rr_type_list; d < rr_type_list + size; d++) {
++		window  = *d >> 8;
++		subtype = *d & 0xff;
++		if (windows[window] < subtype) {
++			windows[window] = subtype;
++		}
++	}
++
++	/* How much space do we need in the rdf for those windows?
++	 */
++	sz = 0;
++	for (i = 0; i < 256; i++) {
++		if (windows[i]) {
++			sz += windows[i] / 8 + 3;
++		}
++	}
++	if (sz > 0) {
++		/* Format rdf data according RFC3845 Section 2.1.2 (see above)
++		 */
++		dptr = data = LDNS_CALLOC(uint8_t, sz);
++		if (!data) {
++			return NULL;
++		}
++		for (i = 0; i < 256; i++) {
++			if (windows[i]) {
++				*dptr++ = (uint8_t)i;
++				*dptr++ = (uint8_t)(windows[i] / 8 + 1);
++
++				/* Now let windows[i] index the bitmap
++				 * within data
++				 */
++				windows[i] = (uint16_t)(dptr - data);
++
++				dptr += dptr[-1];
++			}
++		}
++	}
++
++	/* Set the bits?
++	 */
++	for (d = rr_type_list; d < rr_type_list + size; d++) {
++		subtype = *d & 0xff;
++		data[windows[*d >> 8] + subtype/8] |= (0x80 >> (subtype % 8));
++	}
++
++	/* Allocate and return rdf structure for the data
++	 */
++	rdf = ldns_rdf_new(LDNS_RDF_TYPE_BITMAP, sz, data);
++	if (!rdf) {
++		LDNS_FREE(data);
++		return NULL;
++	}
++	return rdf;
++}
++
++int
++ldns_dnssec_rrsets_contains_type(ldns_dnssec_rrsets *rrsets,
++                                 ldns_rr_type type)
++{
++	ldns_dnssec_rrsets *cur_rrset = rrsets;
++	while (cur_rrset) {
++		if (cur_rrset->type == type) {
++			return 1;
++		}
++		cur_rrset = cur_rrset->next;
++	}
++	return 0;
++}
++
++ldns_rr *
++ldns_dnssec_create_nsec(ldns_dnssec_name *from,
++                        ldns_dnssec_name *to,
++                        ldns_rr_type nsec_type)
++{
++	ldns_rr *nsec_rr;
++	ldns_rr_type types[65536];
++	size_t type_count = 0;
++	ldns_dnssec_rrsets *cur_rrsets;
++	int on_delegation_point;
++
++	if (!from || !to || (nsec_type != LDNS_RR_TYPE_NSEC)) {
++		return NULL;
++	}
++
++	nsec_rr = ldns_rr_new();
++	ldns_rr_set_type(nsec_rr, nsec_type);
++	ldns_rr_set_owner(nsec_rr, ldns_rdf_clone(ldns_dnssec_name_name(from)));
++	ldns_rr_push_rdf(nsec_rr, ldns_rdf_clone(ldns_dnssec_name_name(to)));
++
++	on_delegation_point = ldns_dnssec_rrsets_contains_type(
++			from->rrsets, LDNS_RR_TYPE_NS)
++		&& !ldns_dnssec_rrsets_contains_type(
++			from->rrsets, LDNS_RR_TYPE_SOA);
++
++	cur_rrsets = from->rrsets;
++	while (cur_rrsets) {
++		/* Do not include non-authoritative rrsets on the delegation point
++		 * in the type bitmap */
++		if ((on_delegation_point && (
++				cur_rrsets->type == LDNS_RR_TYPE_NS 
++			     || cur_rrsets->type == LDNS_RR_TYPE_DS))
++			|| (!on_delegation_point &&
++				cur_rrsets->type != LDNS_RR_TYPE_RRSIG
++			     && cur_rrsets->type != LDNS_RR_TYPE_NSEC)) {
++
++			types[type_count] = cur_rrsets->type;
++			type_count++;
++		}
++		cur_rrsets = cur_rrsets->next;
++
++	}
++	types[type_count] = LDNS_RR_TYPE_RRSIG;
++	type_count++;
++	types[type_count] = LDNS_RR_TYPE_NSEC;
++	type_count++;
++
++	ldns_rr_push_rdf(nsec_rr, ldns_dnssec_create_nsec_bitmap(types,
++	                               type_count,
++	                               nsec_type));
++
++	return nsec_rr;
++}
++
++ldns_rr *
++ldns_dnssec_create_nsec3(ldns_dnssec_name *from,
++					ldns_dnssec_name *to,
++					ldns_rdf *zone_name,
++					uint8_t algorithm,
++					uint8_t flags,
++					uint16_t iterations,
++					uint8_t salt_length,
++					uint8_t *salt)
++{
++	ldns_rr *nsec_rr;
++	ldns_rr_type types[65536];
++	size_t type_count = 0;
++	ldns_dnssec_rrsets *cur_rrsets;
++	ldns_status status;
++	int on_delegation_point;
++
++	if (!from) {
++		return NULL;
++	}
++
++	nsec_rr = ldns_rr_new_frm_type(LDNS_RR_TYPE_NSEC3);
++	ldns_rr_set_owner(nsec_rr,
++	                  ldns_nsec3_hash_name(ldns_dnssec_name_name(from),
++	                  algorithm,
++	                  iterations,
++	                  salt_length,
++	                  salt));
++	status = ldns_dname_cat(ldns_rr_owner(nsec_rr), zone_name);
++        if(status != LDNS_STATUS_OK) {
++                ldns_rr_free(nsec_rr);
++                return NULL;
++        }
++	ldns_nsec3_add_param_rdfs(nsec_rr,
++	                          algorithm,
++	                          flags,
++	                          iterations,
++	                          salt_length,
++	                          salt);
++
++	on_delegation_point = ldns_dnssec_rrsets_contains_type(
++			from->rrsets, LDNS_RR_TYPE_NS)
++		&& !ldns_dnssec_rrsets_contains_type(
++			from->rrsets, LDNS_RR_TYPE_SOA);
++	cur_rrsets = from->rrsets;
++	while (cur_rrsets) {
++		/* Do not include non-authoritative rrsets on the delegation point
++		 * in the type bitmap. Potentionally not skipping insecure
++		 * delegation should have been done earlier, in function
++		 * ldns_dnssec_zone_create_nsec3s, or even earlier in:
++		 * ldns_dnssec_zone_sign_nsec3_flg .
++		 */
++		if ((on_delegation_point && (
++				cur_rrsets->type == LDNS_RR_TYPE_NS
++			     || cur_rrsets->type == LDNS_RR_TYPE_DS))
++			|| (!on_delegation_point &&
++				cur_rrsets->type != LDNS_RR_TYPE_RRSIG)) {
++
++			types[type_count] = cur_rrsets->type;
++			type_count++;
++		}
++		cur_rrsets = cur_rrsets->next;
++	}
++	/* always add rrsig type if this is not an unsigned
++	 * delegation
++	 */
++	if (type_count > 0 &&
++	    !(type_count == 1 && types[0] == LDNS_RR_TYPE_NS)) {
++		types[type_count] = LDNS_RR_TYPE_RRSIG;
++		type_count++;
++	}
++
++	/* leave next rdata empty if they weren't precomputed yet */
++	if (to && to->hashed_name) {
++		(void) ldns_rr_set_rdf(nsec_rr,
++		                       ldns_rdf_clone(to->hashed_name),
++		                       4);
++	} else {
++		(void) ldns_rr_set_rdf(nsec_rr, NULL, 4);
++	}
++
++	ldns_rr_push_rdf(nsec_rr,
++	                 ldns_dnssec_create_nsec_bitmap(types,
++	                 type_count,
++	                 LDNS_RR_TYPE_NSEC3));
++
++	return nsec_rr;
++}
++
++ldns_rr *
++ldns_create_nsec(ldns_rdf *cur_owner, ldns_rdf *next_owner, ldns_rr_list *rrs)
++{
++	/* we do not do any check here - garbage in, garbage out */
++
++	/* the the start and end names - get the type from the
++	 * before rrlist */
++
++	/* inefficient, just give it a name, a next name, and a list of rrs */
++	/* we make 1 big uberbitmap first, then windows */
++	/* todo: make something more efficient :) */
++	uint16_t i;
++	ldns_rr *i_rr;
++	uint16_t i_type;
++
++	ldns_rr *nsec = NULL;
++	ldns_rr_type i_type_list[65536];
++	size_t type_count = 0;
++
++	nsec = ldns_rr_new();
++	ldns_rr_set_type(nsec, LDNS_RR_TYPE_NSEC);
++	ldns_rr_set_owner(nsec, ldns_rdf_clone(cur_owner));
++	ldns_rr_push_rdf(nsec, ldns_rdf_clone(next_owner));
++
++	for (i = 0; i < ldns_rr_list_rr_count(rrs); i++) {
++		i_rr = ldns_rr_list_rr(rrs, i);
++		if (ldns_rdf_compare(cur_owner,
++						 ldns_rr_owner(i_rr)) == 0) {
++			i_type = ldns_rr_get_type(i_rr);
++			if (i_type != LDNS_RR_TYPE_RRSIG && i_type != LDNS_RR_TYPE_NSEC) {
++				if (type_count == 0 || i_type_list[type_count-1] != i_type) {
++					i_type_list[type_count] = i_type;
++					type_count++;
++				}
++			}
++		}
++	}
++
++	i_type_list[type_count] = LDNS_RR_TYPE_RRSIG;
++	type_count++;
++	i_type_list[type_count] = LDNS_RR_TYPE_NSEC;
++	type_count++;
++
++	ldns_rr_push_rdf(nsec,
++				  ldns_dnssec_create_nsec_bitmap(i_type_list,
++						type_count, LDNS_RR_TYPE_NSEC));
++
++	return nsec;
++}
++
++ldns_rdf *
++ldns_nsec3_hash_name(ldns_rdf *name,
++				 uint8_t algorithm,
++				 uint16_t iterations,
++				 uint8_t salt_length,
++				 uint8_t *salt)
++{
++	size_t hashed_owner_str_len;
++	ldns_rdf *cann;
++	ldns_rdf *hashed_owner;
++	unsigned char *hashed_owner_str;
++	char *hashed_owner_b32;
++	size_t hashed_owner_b32_len;
++	uint32_t cur_it;
++	/* define to contain the largest possible hash, which is
++	 * sha1 at the moment */
++	unsigned char hash[LDNS_SHA1_DIGEST_LENGTH];
++	ldns_status status;
++
++	/* TODO: mnemonic list for hash algs SHA-1, default to 1 now (sha1) */
++	if (algorithm != LDNS_SHA1) {
++		return NULL;
++	}
++
++	/* prepare the owner name according to the draft section bla */
++	cann = ldns_rdf_clone(name);
++	if(!cann) {
++#ifdef STDERR_MSGS
++		fprintf(stderr, "Memory error\n");
++#endif
++		return NULL;
++	}
++	ldns_dname2canonical(cann);
++
++	hashed_owner_str_len = salt_length + ldns_rdf_size(cann);
++	hashed_owner_str = LDNS_XMALLOC(unsigned char, hashed_owner_str_len);
++        if(!hashed_owner_str) {
++	        ldns_rdf_deep_free(cann);
++                return NULL;
++        }
++	memcpy(hashed_owner_str, ldns_rdf_data(cann), ldns_rdf_size(cann));
++	memcpy(hashed_owner_str + ldns_rdf_size(cann), salt, salt_length);
++	ldns_rdf_deep_free(cann);
++
++	for (cur_it = iterations + 1; cur_it > 0; cur_it--) {
++		(void) ldns_sha1((unsigned char *) hashed_owner_str,
++		                 (unsigned int) hashed_owner_str_len, hash);
++
++		LDNS_FREE(hashed_owner_str);
++		hashed_owner_str_len = salt_length + LDNS_SHA1_DIGEST_LENGTH;
++		hashed_owner_str = LDNS_XMALLOC(unsigned char, hashed_owner_str_len);
++		if (!hashed_owner_str) {
++			return NULL;
++		}
++		memcpy(hashed_owner_str, hash, LDNS_SHA1_DIGEST_LENGTH);
++		memcpy(hashed_owner_str + LDNS_SHA1_DIGEST_LENGTH, salt, salt_length);
++		hashed_owner_str_len = LDNS_SHA1_DIGEST_LENGTH + salt_length;
++	}
++
++	LDNS_FREE(hashed_owner_str);
++	hashed_owner_str = hash;
++	hashed_owner_str_len = LDNS_SHA1_DIGEST_LENGTH;
++
++	hashed_owner_b32 = LDNS_XMALLOC(char,
++                  ldns_b32_ntop_calculate_size(hashed_owner_str_len) + 1);
++        if(!hashed_owner_b32) {
++                return NULL;
++        }
++        hashed_owner_b32_len = (size_t) ldns_b32_ntop_extended_hex(
++                (uint8_t *) hashed_owner_str,
++                hashed_owner_str_len,
++                hashed_owner_b32,
++                ldns_b32_ntop_calculate_size(hashed_owner_str_len)+1);
++	if (hashed_owner_b32_len < 1) {
++#ifdef STDERR_MSGS
++		fprintf(stderr, "Error in base32 extended hex encoding ");
++		fprintf(stderr, "of hashed owner name (name: ");
++		ldns_rdf_print(stderr, name);
++		fprintf(stderr, ", return code: %u)\n",
++		        (unsigned int) hashed_owner_b32_len);
++#endif
++		LDNS_FREE(hashed_owner_b32);
++		return NULL;
++	}
++	hashed_owner_b32[hashed_owner_b32_len] = '\0';
++
++	status = ldns_str2rdf_dname(&hashed_owner, hashed_owner_b32);
++	if (status != LDNS_STATUS_OK) {
++#ifdef STDERR_MSGS
++		fprintf(stderr, "Error creating rdf from %s\n", hashed_owner_b32);
++#endif
++		LDNS_FREE(hashed_owner_b32);
++		return NULL;
++	}
++
++	LDNS_FREE(hashed_owner_b32);
++	return hashed_owner;
++}
++
++void
++ldns_nsec3_add_param_rdfs(ldns_rr *rr,
++					 uint8_t algorithm,
++					 uint8_t flags,
++					 uint16_t iterations,
++					 uint8_t salt_length,
++					 uint8_t *salt)
++{
++	ldns_rdf *salt_rdf = NULL;
++	uint8_t *salt_data = NULL;
++	ldns_rdf *old;
++
++	old = ldns_rr_set_rdf(rr,
++	                      ldns_rdf_new_frm_data(LDNS_RDF_TYPE_INT8,
++	                                            1, (void*)&algorithm),
++	                      0);
++	if (old) ldns_rdf_deep_free(old);
++
++	old = ldns_rr_set_rdf(rr,
++	                      ldns_rdf_new_frm_data(LDNS_RDF_TYPE_INT8,
++	                                            1, (void*)&flags),
++	                      1);
++	if (old) ldns_rdf_deep_free(old);
++
++	old = ldns_rr_set_rdf(rr,
++                          ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16,
++                                                iterations),
++	                      2);
++	if (old) ldns_rdf_deep_free(old);
++
++	salt_data = LDNS_XMALLOC(uint8_t, salt_length + 1);
++        if(!salt_data) {
++                /* no way to return error */
++                return;
++        }
++	salt_data[0] = salt_length;
++	memcpy(salt_data + 1, salt, salt_length);
++	salt_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_NSEC3_SALT,
++							   salt_length + 1,
++							   salt_data);
++        if(!salt_rdf) {
++                LDNS_FREE(salt_data);
++                /* no way to return error */
++                return;
++        }
++
++	old = ldns_rr_set_rdf(rr, salt_rdf, 3);
++	if (old) ldns_rdf_deep_free(old);
++	LDNS_FREE(salt_data);
++}
++
++static int
++rr_list_delegation_only(ldns_rdf *origin, ldns_rr_list *rr_list)
++{
++	size_t i;
++	ldns_rr *cur_rr;
++	if (!origin || !rr_list) return 0;
++	for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
++		cur_rr = ldns_rr_list_rr(rr_list, i);
++		if (ldns_dname_compare(ldns_rr_owner(cur_rr), origin) == 0) {
++			return 0;
++		}
++		if (ldns_rr_get_type(cur_rr) != LDNS_RR_TYPE_NS) {
++			return 0;
++		}
++	}
++	return 1;
++}
++
++/* this will NOT return the NSEC3  completed, you will have to run the
++   finalize function on the rrlist later! */
++ldns_rr *
++ldns_create_nsec3(ldns_rdf *cur_owner,
++                  ldns_rdf *cur_zone,
++                  ldns_rr_list *rrs,
++                  uint8_t algorithm,
++                  uint8_t flags,
++                  uint16_t iterations,
++                  uint8_t salt_length,
++                  uint8_t *salt,
++                  bool emptynonterminal)
++{
++	size_t i;
++	ldns_rr *i_rr;
++	uint16_t i_type;
++
++	ldns_rr *nsec = NULL;
++	ldns_rdf *hashed_owner = NULL;
++
++	ldns_status status;
++
++    ldns_rr_type i_type_list[1024];
++	size_t type_count = 0;
++
++	hashed_owner = ldns_nsec3_hash_name(cur_owner,
++								 algorithm,
++								 iterations,
++								 salt_length,
++								 salt);
++	status = ldns_dname_cat(hashed_owner, cur_zone);
++        if(status != LDNS_STATUS_OK) {
++		ldns_rdf_deep_free(hashed_owner);
++                return NULL;
++	}
++	nsec = ldns_rr_new_frm_type(LDNS_RR_TYPE_NSEC3);
++        if(!nsec) {
++		ldns_rdf_deep_free(hashed_owner);
++                return NULL;
++	}
++	ldns_rr_set_type(nsec, LDNS_RR_TYPE_NSEC3);
++	ldns_rr_set_owner(nsec, hashed_owner);
++
++	ldns_nsec3_add_param_rdfs(nsec,
++						 algorithm,
++						 flags,
++						 iterations,
++						 salt_length,
++						 salt);
++	(void) ldns_rr_set_rdf(nsec, NULL, 4);
++
++
++	for (i = 0; i < ldns_rr_list_rr_count(rrs); i++) {
++		i_rr = ldns_rr_list_rr(rrs, i);
++		if (ldns_rdf_compare(cur_owner,
++						 ldns_rr_owner(i_rr)) == 0) {
++			i_type = ldns_rr_get_type(i_rr);
++			if (type_count == 0 || i_type_list[type_count-1] != i_type) {
++				i_type_list[type_count] = i_type;
++				type_count++;
++			}
++		}
++	}
++
++	/* add RRSIG anyway, but only if this is not an ENT or
++	 * an unsigned delegation */
++	if (!emptynonterminal && !rr_list_delegation_only(cur_zone, rrs)) {
++		i_type_list[type_count] = LDNS_RR_TYPE_RRSIG;
++		type_count++;
++	}
++
++	/* and SOA if owner == zone */
++	if (ldns_dname_compare(cur_zone, cur_owner) == 0) {
++		i_type_list[type_count] = LDNS_RR_TYPE_SOA;
++		type_count++;
++	}
++
++	ldns_rr_push_rdf(nsec,
++				  ldns_dnssec_create_nsec_bitmap(i_type_list,
++						type_count, LDNS_RR_TYPE_NSEC3));
++
++	return nsec;
++}
++
++uint8_t
++ldns_nsec3_algorithm(const ldns_rr *nsec3_rr)
++{
++	if (nsec3_rr && 
++	      (ldns_rr_get_type(nsec3_rr) == LDNS_RR_TYPE_NSEC3 ||
++	       ldns_rr_get_type(nsec3_rr) == LDNS_RR_TYPE_NSEC3PARAM)
++	    && (ldns_rr_rdf(nsec3_rr, 0) != NULL)
++	    && ldns_rdf_size(ldns_rr_rdf(nsec3_rr, 0)) > 0) {
++		return ldns_rdf2native_int8(ldns_rr_rdf(nsec3_rr, 0));
++	}
++	return 0;
++}
++
++uint8_t
++ldns_nsec3_flags(const ldns_rr *nsec3_rr)
++{
++	if (nsec3_rr && 
++	      (ldns_rr_get_type(nsec3_rr) == LDNS_RR_TYPE_NSEC3 ||
++	       ldns_rr_get_type(nsec3_rr) == LDNS_RR_TYPE_NSEC3PARAM)
++	    && (ldns_rr_rdf(nsec3_rr, 1) != NULL)
++	    && ldns_rdf_size(ldns_rr_rdf(nsec3_rr, 1)) > 0) {
++		return ldns_rdf2native_int8(ldns_rr_rdf(nsec3_rr, 1));
++	}
++	return 0;
++}
++
++bool
++ldns_nsec3_optout(const ldns_rr *nsec3_rr)
++{
++	return (ldns_nsec3_flags(nsec3_rr) & LDNS_NSEC3_VARS_OPTOUT_MASK);
++}
++
++uint16_t
++ldns_nsec3_iterations(const ldns_rr *nsec3_rr)
++{
++	if (nsec3_rr &&
++	      (ldns_rr_get_type(nsec3_rr) == LDNS_RR_TYPE_NSEC3 ||
++	       ldns_rr_get_type(nsec3_rr) == LDNS_RR_TYPE_NSEC3PARAM)
++	    && (ldns_rr_rdf(nsec3_rr, 2) != NULL)
++	    && ldns_rdf_size(ldns_rr_rdf(nsec3_rr, 2)) > 0) {
++		return ldns_rdf2native_int16(ldns_rr_rdf(nsec3_rr, 2));
++	}
++	return 0;
++	
++}
++
++ldns_rdf *
++ldns_nsec3_salt(const ldns_rr *nsec3_rr)
++{
++	if (nsec3_rr && 
++	      (ldns_rr_get_type(nsec3_rr) == LDNS_RR_TYPE_NSEC3 ||
++	       ldns_rr_get_type(nsec3_rr) == LDNS_RR_TYPE_NSEC3PARAM)
++	    ) {
++		return ldns_rr_rdf(nsec3_rr, 3);
++	}
++	return NULL;
++}
++
++uint8_t
++ldns_nsec3_salt_length(const ldns_rr *nsec3_rr)
++{
++	ldns_rdf *salt_rdf = ldns_nsec3_salt(nsec3_rr);
++	if (salt_rdf && ldns_rdf_size(salt_rdf) > 0) {
++		return (uint8_t) ldns_rdf_data(salt_rdf)[0];
++	}
++	return 0;
++}
++
++/* allocs data, free with LDNS_FREE() */
++uint8_t *
++ldns_nsec3_salt_data(const ldns_rr *nsec3_rr)
++{
++	uint8_t salt_length;
++	uint8_t *salt;
++
++	ldns_rdf *salt_rdf = ldns_nsec3_salt(nsec3_rr);
++	if (salt_rdf && ldns_rdf_size(salt_rdf) > 0) {
++	    	salt_length = ldns_rdf_data(salt_rdf)[0];
++		salt = LDNS_XMALLOC(uint8_t, salt_length);
++                if(!salt) return NULL;
++		memcpy(salt, &ldns_rdf_data(salt_rdf)[1], salt_length);
++		return salt;
++	}
++	return NULL;
++}
++
++ldns_rdf *
++ldns_nsec3_next_owner(const ldns_rr *nsec3_rr)
++{
++	if (!nsec3_rr || ldns_rr_get_type(nsec3_rr) != LDNS_RR_TYPE_NSEC3) {
++		return NULL;
++	} else {
++		return ldns_rr_rdf(nsec3_rr, 4);
++	}
++}
++
++ldns_rdf *
++ldns_nsec3_bitmap(const ldns_rr *nsec3_rr)
++{
++	if (!nsec3_rr || ldns_rr_get_type(nsec3_rr) != LDNS_RR_TYPE_NSEC3) {
++		return NULL;
++	} else {
++		return ldns_rr_rdf(nsec3_rr, 5);
++	}
++}
++
++ldns_rdf *
++ldns_nsec3_hash_name_frm_nsec3(const ldns_rr *nsec, ldns_rdf *name)
++{
++	uint8_t algorithm;
++	uint16_t iterations;
++	uint8_t salt_length;
++	uint8_t *salt = 0;
++
++	ldns_rdf *hashed_owner;
++
++	algorithm = ldns_nsec3_algorithm(nsec);
++	salt_length = ldns_nsec3_salt_length(nsec);
++	salt = ldns_nsec3_salt_data(nsec);
++	iterations = ldns_nsec3_iterations(nsec);
++
++	hashed_owner = ldns_nsec3_hash_name(name,
++								 algorithm,
++								 iterations,
++								 salt_length,
++								 salt);
++
++	LDNS_FREE(salt);
++	return hashed_owner;
++}
++
++bool
++ldns_nsec_bitmap_covers_type(const  ldns_rdf* bitmap, ldns_rr_type type)
++{
++	uint8_t* dptr;
++	uint8_t* dend;
++
++	/* From RFC3845 Section 2.1.2:
++	 *
++	 *	"The RR type space is split into 256 window blocks, each re-
++	 *	 presenting the low-order 8 bits of the 16-bit RR type space."
++	 */
++	uint8_t  window = type >> 8;
++	uint8_t subtype = type & 0xff;
++
++	if (! bitmap) {
++		return false;
++	}
++	assert(ldns_rdf_get_type(bitmap) == LDNS_RDF_TYPE_BITMAP);
++
++	dptr = ldns_rdf_data(bitmap);
++	dend = ldns_rdf_data(bitmap) + ldns_rdf_size(bitmap);
++
++	/* Type Bitmap = ( Window Block # | Bitmap Length | Bitmap ) +
++	 *                 dptr[0]          dptr[1]         dptr[2:]
++	 */
++	while (dptr < dend && dptr[0] <= window) {
++
++		if (dptr[0] == window && subtype / 8 < dptr[1] &&
++				dptr + dptr[1] + 2 <= dend) {
++
++			return dptr[2 + subtype / 8] & (0x80 >> (subtype % 8));
++		}
++		dptr += dptr[1] + 2; /* next window */
++	}
++	return false;
++}
++
++ldns_status
++ldns_nsec_bitmap_set_type(ldns_rdf* bitmap, ldns_rr_type type)
++{
++	uint8_t* dptr;
++	uint8_t* dend;
++
++	/* From RFC3845 Section 2.1.2:
++	 *
++	 *	"The RR type space is split into 256 window blocks, each re-
++	 *	 presenting the low-order 8 bits of the 16-bit RR type space."
++	 */
++	uint8_t  window = type >> 8;
++	uint8_t subtype = type & 0xff;
++
++	if (! bitmap) {
++		return false;
++	}
++	assert(ldns_rdf_get_type(bitmap) == LDNS_RDF_TYPE_BITMAP);
++
++	dptr = ldns_rdf_data(bitmap);
++	dend = ldns_rdf_data(bitmap) + ldns_rdf_size(bitmap);
++
++	/* Type Bitmap = ( Window Block # | Bitmap Length | Bitmap ) +
++	 *                 dptr[0]          dptr[1]         dptr[2:]
++	 */
++	while (dptr < dend && dptr[0] <= window) {
++
++		if (dptr[0] == window && subtype / 8 < dptr[1] &&
++				dptr + dptr[1] + 2 <= dend) {
++
++			dptr[2 + subtype / 8] |= (0x80 >> (subtype % 8));
++			return LDNS_STATUS_OK;
++		}
++		dptr += dptr[1] + 2; /* next window */
++	}
++	return LDNS_STATUS_TYPE_NOT_IN_BITMAP;
++}
++
++ldns_status
++ldns_nsec_bitmap_clear_type(ldns_rdf* bitmap, ldns_rr_type type)
++{
++	uint8_t* dptr;
++	uint8_t* dend;
++
++	/* From RFC3845 Section 2.1.2:
++	 *
++	 *	"The RR type space is split into 256 window blocks, each re-
++	 *	 presenting the low-order 8 bits of the 16-bit RR type space."
++	 */
++	uint8_t  window = type >> 8;
++	uint8_t subtype = type & 0xff;
++
++	if (! bitmap) {
++		return false;
++	}
++
++	assert(ldns_rdf_get_type(bitmap) == LDNS_RDF_TYPE_BITMAP);
++
++	dptr = ldns_rdf_data(bitmap);
++	dend = ldns_rdf_data(bitmap) + ldns_rdf_size(bitmap);
++
++	/* Type Bitmap = ( Window Block # | Bitmap Length | Bitmap ) +
++	 *                 dptr[0]          dptr[1]         dptr[2:]
++	 */
++	while (dptr < dend && dptr[0] <= window) {
++
++		if (dptr[0] == window && subtype / 8 < dptr[1] &&
++				dptr + dptr[1] + 2 <= dend) {
++
++			dptr[2 + subtype / 8] &= ~(0x80 >> (subtype % 8));
++			return LDNS_STATUS_OK;
++		}
++		dptr += dptr[1] + 2; /* next window */
++	}
++	return LDNS_STATUS_TYPE_NOT_IN_BITMAP;
++}
++
++
++bool
++ldns_nsec_covers_name(const ldns_rr *nsec, const ldns_rdf *name)
++{
++	ldns_rdf *nsec_owner = ldns_rr_owner(nsec);
++	ldns_rdf *hash_next;
++	char *next_hash_str;
++	ldns_rdf *nsec_next = NULL;
++	ldns_status status;
++	ldns_rdf *chopped_dname;
++	bool result;
++
++	if (ldns_rr_get_type(nsec) == LDNS_RR_TYPE_NSEC) {
++		if (ldns_rr_rdf(nsec, 0) != NULL) {
++			nsec_next = ldns_rdf_clone(ldns_rr_rdf(nsec, 0));
++		} else {
++			return false;
++		}
++	} else if (ldns_rr_get_type(nsec) == LDNS_RR_TYPE_NSEC3) {
++		hash_next = ldns_nsec3_next_owner(nsec);
++		next_hash_str = ldns_rdf2str(hash_next);
++		nsec_next = ldns_dname_new_frm_str(next_hash_str);
++		LDNS_FREE(next_hash_str);
++		chopped_dname = ldns_dname_left_chop(nsec_owner);
++		status = ldns_dname_cat(nsec_next, chopped_dname);
++		ldns_rdf_deep_free(chopped_dname);
++		if (status != LDNS_STATUS_OK) {
++			printf("error catting: %s\n", ldns_get_errorstr_by_id(status));
++		}
++	} else {
++		ldns_rdf_deep_free(nsec_next);
++		return false;
++	}
++
++	/* in the case of the last nsec */
++	if(ldns_dname_compare(nsec_owner, nsec_next) > 0) {
++		result = (ldns_dname_compare(nsec_owner, name) <= 0 ||
++				ldns_dname_compare(name, nsec_next) < 0);
++	} else if(ldns_dname_compare(nsec_owner, nsec_next) < 0) {
++		result = (ldns_dname_compare(nsec_owner, name) <= 0 &&
++		          ldns_dname_compare(name, nsec_next) < 0);
++	} else {
++		result = true;
++	}
++
++	ldns_rdf_deep_free(nsec_next);
++	return result;
++}
++
++#ifdef HAVE_SSL
++/* sig may be null - if so look in the packet */
++
++ldns_status
++ldns_pkt_verify_time(ldns_pkt *p, ldns_rr_type t, ldns_rdf *o, 
++		ldns_rr_list *k, ldns_rr_list *s, 
++		time_t check_time, ldns_rr_list *good_keys)
++{
++	ldns_rr_list *rrset;
++	ldns_rr_list *sigs;
++	ldns_rr_list *sigs_covered;
++	ldns_rdf *rdf_t;
++	ldns_rr_type t_netorder;
++
++	if (!k) {
++		return LDNS_STATUS_ERR;
++		/* return LDNS_STATUS_CRYPTO_NO_DNSKEY; */
++	}
++
++	if (t == LDNS_RR_TYPE_RRSIG) {
++		/* we don't have RRSIG(RRSIG) (yet? ;-) ) */
++		return LDNS_STATUS_ERR;
++	}
++
++	if (s) {
++		/* if s is not NULL, the sigs are given to use */
++		sigs = s;
++	} else {
++		/* otherwise get them from the packet */
++		sigs = ldns_pkt_rr_list_by_name_and_type(p, o,
++				LDNS_RR_TYPE_RRSIG,
++				LDNS_SECTION_ANY_NOQUESTION);
++		if (!sigs) {
++			/* no sigs */
++			return LDNS_STATUS_ERR;
++			/* return LDNS_STATUS_CRYPTO_NO_RRSIG; */
++		}
++	}
++
++	/* rrsig are subtyped, so now we need to find the correct
++	 * sigs for the type t
++	 */
++	t_netorder = htons(t); /* rdf are in network order! */
++	/* a type identifier is a 16-bit number, so the size is 2 bytes */
++	rdf_t = ldns_rdf_new(LDNS_RDF_TYPE_TYPE, 2, &t_netorder);
++
++	sigs_covered = ldns_rr_list_subtype_by_rdf(sigs, rdf_t, 0);
++	ldns_rdf_free(rdf_t);
++	if (! sigs_covered) {
++		if (! s) {
++			ldns_rr_list_deep_free(sigs);
++		}
++		return LDNS_STATUS_ERR;
++	}
++	ldns_rr_list_deep_free(sigs_covered);
++
++	rrset = ldns_pkt_rr_list_by_name_and_type(p, o, t,
++			LDNS_SECTION_ANY_NOQUESTION);
++	if (!rrset) {
++		if (! s) {
++			ldns_rr_list_deep_free(sigs);
++		}
++		return LDNS_STATUS_ERR;
++	}
++	return ldns_verify_time(rrset, sigs, k, check_time, good_keys);
++}
++
++ldns_status
++ldns_pkt_verify(ldns_pkt *p, ldns_rr_type t, ldns_rdf *o, 
++		ldns_rr_list *k, ldns_rr_list *s, ldns_rr_list *good_keys)
++{
++	return ldns_pkt_verify_time(p, t, o, k, s, ldns_time(NULL), good_keys);
++}
++#endif /* HAVE_SSL */
++
++ldns_status
++ldns_dnssec_chain_nsec3_list(ldns_rr_list *nsec3_rrs)
++{
++	size_t i;
++	char *next_nsec_owner_str;
++	ldns_rdf *next_nsec_owner_label;
++	ldns_rdf *next_nsec_rdf;
++	ldns_status status = LDNS_STATUS_OK;
++
++	for (i = 0; i < ldns_rr_list_rr_count(nsec3_rrs); i++) {
++		if (i == ldns_rr_list_rr_count(nsec3_rrs) - 1) {
++			next_nsec_owner_label =
++				ldns_dname_label(ldns_rr_owner(ldns_rr_list_rr(nsec3_rrs,
++													  0)), 0);
++			next_nsec_owner_str = ldns_rdf2str(next_nsec_owner_label);
++			if (next_nsec_owner_str[strlen(next_nsec_owner_str) - 1]
++			    == '.') {
++				next_nsec_owner_str[strlen(next_nsec_owner_str) - 1]
++					= '\0';
++			}
++			status = ldns_str2rdf_b32_ext(&next_nsec_rdf,
++									next_nsec_owner_str);
++			if (!ldns_rr_set_rdf(ldns_rr_list_rr(nsec3_rrs, i),
++							 next_nsec_rdf, 4)) {
++				/* todo: error */
++			}
++
++			ldns_rdf_deep_free(next_nsec_owner_label);
++			LDNS_FREE(next_nsec_owner_str);
++		} else {
++			next_nsec_owner_label =
++				ldns_dname_label(ldns_rr_owner(ldns_rr_list_rr(nsec3_rrs,
++													  i + 1)),
++							  0);
++			next_nsec_owner_str = ldns_rdf2str(next_nsec_owner_label);
++			if (next_nsec_owner_str[strlen(next_nsec_owner_str) - 1]
++			    == '.') {
++				next_nsec_owner_str[strlen(next_nsec_owner_str) - 1]
++					= '\0';
++			}
++			status = ldns_str2rdf_b32_ext(&next_nsec_rdf,
++									next_nsec_owner_str);
++			ldns_rdf_deep_free(next_nsec_owner_label);
++			LDNS_FREE(next_nsec_owner_str);
++			if (!ldns_rr_set_rdf(ldns_rr_list_rr(nsec3_rrs, i),
++							 next_nsec_rdf, 4)) {
++				/* todo: error */
++			}
++		}
++	}
++	return status;
++}
++
++int
++qsort_rr_compare_nsec3(const void *a, const void *b)
++{
++	const ldns_rr *rr1 = * (const ldns_rr **) a;
++	const ldns_rr *rr2 = * (const ldns_rr **) b;
++	if (rr1 == NULL && rr2 == NULL) {
++		return 0;
++	}
++	if (rr1 == NULL) {
++		return -1;
++	}
++	if (rr2 == NULL) {
++		return 1;
++	}
++	return ldns_rdf_compare(ldns_rr_owner(rr1), ldns_rr_owner(rr2));
++}
++
++void
++ldns_rr_list_sort_nsec3(ldns_rr_list *unsorted)
++{
++	qsort(unsorted->_rrs,
++	      ldns_rr_list_rr_count(unsorted),
++	      sizeof(ldns_rr *),
++	      qsort_rr_compare_nsec3);
++}
++
++int
++ldns_dnssec_default_add_to_signatures( ATTR_UNUSED(ldns_rr *sig)
++				     , ATTR_UNUSED(void *n)
++				     )
++{
++	return LDNS_SIGNATURE_LEAVE_ADD_NEW;
++}
++
++int
++ldns_dnssec_default_leave_signatures( ATTR_UNUSED(ldns_rr *sig)
++				    , ATTR_UNUSED(void *n)
++				    )
++{
++	return LDNS_SIGNATURE_LEAVE_NO_ADD;
++}
++
++int
++ldns_dnssec_default_delete_signatures( ATTR_UNUSED(ldns_rr *sig)
++				     , ATTR_UNUSED(void *n)
++				     )
++{
++	return LDNS_SIGNATURE_REMOVE_NO_ADD;
++}
++
++int
++ldns_dnssec_default_replace_signatures( ATTR_UNUSED(ldns_rr *sig)
++				      , ATTR_UNUSED(void *n)
++				      )
++{
++	return LDNS_SIGNATURE_REMOVE_ADD_NEW;
++}
++
++#ifdef HAVE_SSL
++ldns_rdf *
++ldns_convert_dsa_rrsig_asn12rdf(const ldns_buffer *sig,
++						  const long sig_len)
++{
++	ldns_rdf *sigdata_rdf;
++	DSA_SIG *dsasig;
++	unsigned char *dsasig_data = (unsigned char*)ldns_buffer_begin(sig);
++	size_t byte_offset;
++
++	dsasig = d2i_DSA_SIG(NULL,
++					 (const unsigned char **)&dsasig_data,
++					 sig_len);
++	if (!dsasig) {
++                DSA_SIG_free(dsasig);
++		return NULL;
++	}
++
++	dsasig_data = LDNS_XMALLOC(unsigned char, 41);
++        if(!dsasig_data) {
++                DSA_SIG_free(dsasig);
++                return NULL;
++        }
++	dsasig_data[0] = 0;
++	byte_offset = (size_t) (20 - BN_num_bytes(dsasig->r));
++	if (byte_offset > 20) {
++                DSA_SIG_free(dsasig);
++                LDNS_FREE(dsasig_data);
++		return NULL;
++	}
++	memset(&dsasig_data[1], 0, byte_offset);
++	BN_bn2bin(dsasig->r, &dsasig_data[1 + byte_offset]);
++	byte_offset = (size_t) (20 - BN_num_bytes(dsasig->s));
++	if (byte_offset > 20) {
++                DSA_SIG_free(dsasig);
++                LDNS_FREE(dsasig_data);
++		return NULL;
++	}
++	memset(&dsasig_data[21], 0, byte_offset);
++	BN_bn2bin(dsasig->s, &dsasig_data[21 + byte_offset]);
++
++	sigdata_rdf = ldns_rdf_new(LDNS_RDF_TYPE_B64, 41, dsasig_data);
++        if(!sigdata_rdf) {
++                LDNS_FREE(dsasig_data);
++        }
++	DSA_SIG_free(dsasig);
++
++	return sigdata_rdf;
++}
++
++ldns_status
++ldns_convert_dsa_rrsig_rdf2asn1(ldns_buffer *target_buffer,
++						  const ldns_rdf *sig_rdf)
++{
++	/* the EVP api wants the DER encoding of the signature... */
++	BIGNUM *R, *S;
++	DSA_SIG *dsasig;
++	unsigned char *raw_sig = NULL;
++	int raw_sig_len;
++
++        if(ldns_rdf_size(sig_rdf) < 1 + 2*SHA_DIGEST_LENGTH)
++                return LDNS_STATUS_SYNTAX_RDATA_ERR;
++	/* extract the R and S field from the sig buffer */
++	R = BN_new();
++	if(!R) return LDNS_STATUS_MEM_ERR;
++	(void) BN_bin2bn((unsigned char *) ldns_rdf_data(sig_rdf) + 1,
++	                 SHA_DIGEST_LENGTH, R);
++	S = BN_new();
++	if(!S) {
++		BN_free(R);
++		return LDNS_STATUS_MEM_ERR;
++	}
++	(void) BN_bin2bn((unsigned char *) ldns_rdf_data(sig_rdf) + 21,
++	                 SHA_DIGEST_LENGTH, S);
++
++	dsasig = DSA_SIG_new();
++	if (!dsasig) {
++		BN_free(R);
++		BN_free(S);
++		return LDNS_STATUS_MEM_ERR;
++	}
++
++	dsasig->r = R;
++	dsasig->s = S;
++
++	raw_sig_len = i2d_DSA_SIG(dsasig, &raw_sig);
++	if (raw_sig_len < 0) {
++		DSA_SIG_free(dsasig);
++		free(raw_sig);
++		return LDNS_STATUS_SSL_ERR;
++	}
++	if (ldns_buffer_reserve(target_buffer, (size_t) raw_sig_len)) {
++		ldns_buffer_write(target_buffer, raw_sig, (size_t)raw_sig_len);
++	}
++
++	DSA_SIG_free(dsasig);
++	free(raw_sig);
++
++	return ldns_buffer_status(target_buffer);
++}
++
++#ifdef USE_ECDSA
++#ifndef S_SPLINT_S
++ldns_rdf *
++ldns_convert_ecdsa_rrsig_asn12rdf(const ldns_buffer *sig, const long sig_len)
++{
++        ECDSA_SIG* ecdsa_sig;
++	unsigned char *data = (unsigned char*)ldns_buffer_begin(sig);
++        ldns_rdf* rdf;
++	ecdsa_sig = d2i_ECDSA_SIG(NULL, (const unsigned char **)&data, sig_len);
++        if(!ecdsa_sig) return NULL;
++
++        /* "r | s". */
++        data = LDNS_XMALLOC(unsigned char,
++                BN_num_bytes(ecdsa_sig->r) + BN_num_bytes(ecdsa_sig->s));
++        if(!data) {
++                ECDSA_SIG_free(ecdsa_sig);
++                return NULL;
++        }
++        BN_bn2bin(ecdsa_sig->r, data);
++        BN_bn2bin(ecdsa_sig->s, data+BN_num_bytes(ecdsa_sig->r));
++	rdf = ldns_rdf_new(LDNS_RDF_TYPE_B64, (size_t)(
++		BN_num_bytes(ecdsa_sig->r) + BN_num_bytes(ecdsa_sig->s)), data);
++        ECDSA_SIG_free(ecdsa_sig);
++        return rdf;
++}
++
++ldns_status
++ldns_convert_ecdsa_rrsig_rdf2asn1(ldns_buffer *target_buffer,
++        const ldns_rdf *sig_rdf)
++{
++        ECDSA_SIG* sig;
++	int raw_sig_len;
++        long bnsize = (long)ldns_rdf_size(sig_rdf) / 2;
++        /* if too short, or not even length, do not bother */
++        if(bnsize < 16 || (size_t)bnsize*2 != ldns_rdf_size(sig_rdf))
++                return LDNS_STATUS_ERR;
++        
++        /* use the raw data to parse two evenly long BIGNUMs, "r | s". */
++        sig = ECDSA_SIG_new();
++        if(!sig) return LDNS_STATUS_MEM_ERR;
++        sig->r = BN_bin2bn((const unsigned char*)ldns_rdf_data(sig_rdf),
++                bnsize, sig->r);
++        sig->s = BN_bin2bn((const unsigned char*)ldns_rdf_data(sig_rdf)+bnsize,
++                bnsize, sig->s);
++        if(!sig->r || !sig->s) {
++                ECDSA_SIG_free(sig);
++                return LDNS_STATUS_MEM_ERR;
++        }
++
++	raw_sig_len = i2d_ECDSA_SIG(sig, NULL);
++	if (ldns_buffer_reserve(target_buffer, (size_t) raw_sig_len)) {
++                unsigned char* pp = (unsigned char*)
++			ldns_buffer_current(target_buffer);
++	        raw_sig_len = i2d_ECDSA_SIG(sig, &pp);
++                ldns_buffer_skip(target_buffer, (ssize_t) raw_sig_len);
++	}
++        ECDSA_SIG_free(sig);
++
++	return ldns_buffer_status(target_buffer);
++}
++
++#endif /* S_SPLINT_S */
++#endif /* USE_ECDSA */
++#endif /* HAVE_SSL */
+diff --git a/ldns/src/dnssec_sign.c b/ldns/src/dnssec_sign.c
+new file mode 100644
+index 0000000..4af882a
+--- /dev/null
++++ b/ldns/src/dnssec_sign.c
+@@ -0,0 +1,1456 @@
++#include <ldns/config.h>
++
++#include <ldns/ldns.h>
++
++#include <ldns/dnssec.h>
++#include <ldns/dnssec_sign.h>
++
++#include <strings.h>
++#include <time.h>
++
++#ifdef HAVE_SSL
++/* this entire file is rather useless when you don't have
++ * crypto...
++ */
++#include <openssl/ssl.h>
++#include <openssl/evp.h>
++#include <openssl/rand.h>
++#include <openssl/err.h>
++#include <openssl/md5.h>
++#endif /* HAVE_SSL */
++
++ldns_rr *
++ldns_create_empty_rrsig(ldns_rr_list *rrset,
++                        ldns_key *current_key)
++{
++	uint32_t orig_ttl;
++	ldns_rr_class orig_class;
++	time_t now;
++	ldns_rr *current_sig;
++	uint8_t label_count;
++	ldns_rdf *signame;
++
++	label_count = ldns_dname_label_count(ldns_rr_owner(ldns_rr_list_rr(rrset,
++	                                                   0)));
++        /* RFC4035 2.2: not counting the leftmost label if it is a wildcard */
++        if(ldns_dname_is_wildcard(ldns_rr_owner(ldns_rr_list_rr(rrset, 0))))
++                label_count --;
++
++	current_sig = ldns_rr_new_frm_type(LDNS_RR_TYPE_RRSIG);
++
++	/* set the type on the new signature */
++	orig_ttl = ldns_rr_ttl(ldns_rr_list_rr(rrset, 0));
++	orig_class = ldns_rr_get_class(ldns_rr_list_rr(rrset, 0));
++
++	ldns_rr_set_ttl(current_sig, orig_ttl);
++	ldns_rr_set_class(current_sig, orig_class);
++	ldns_rr_set_owner(current_sig,
++			  ldns_rdf_clone(
++			       ldns_rr_owner(
++				    ldns_rr_list_rr(rrset,
++						    0))));
++
++	/* fill in what we know of the signature */
++
++	/* set the orig_ttl */
++	(void)ldns_rr_rrsig_set_origttl(
++		   current_sig,
++		   ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32,
++					 orig_ttl));
++	/* the signers name */
++	signame = ldns_rdf_clone(ldns_key_pubkey_owner(current_key));
++	ldns_dname2canonical(signame);
++	(void)ldns_rr_rrsig_set_signame(
++			current_sig,
++			signame);
++	/* label count - get it from the first rr in the rr_list */
++	(void)ldns_rr_rrsig_set_labels(
++			current_sig,
++			ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8,
++			                     label_count));
++	/* inception, expiration */
++	now = time(NULL);
++	if (ldns_key_inception(current_key) != 0) {
++		(void)ldns_rr_rrsig_set_inception(
++				current_sig,
++				ldns_native2rdf_int32(
++				    LDNS_RDF_TYPE_TIME,
++				    ldns_key_inception(current_key)));
++	} else {
++		(void)ldns_rr_rrsig_set_inception(
++				current_sig,
++				ldns_native2rdf_int32(LDNS_RDF_TYPE_TIME, now));
++	}
++	if (ldns_key_expiration(current_key) != 0) {
++		(void)ldns_rr_rrsig_set_expiration(
++				current_sig,
++				ldns_native2rdf_int32(
++				    LDNS_RDF_TYPE_TIME,
++				    ldns_key_expiration(current_key)));
++	} else {
++		(void)ldns_rr_rrsig_set_expiration(
++			     current_sig,
++				ldns_native2rdf_int32(
++				    LDNS_RDF_TYPE_TIME,
++				    now + LDNS_DEFAULT_EXP_TIME));
++	}
++
++	(void)ldns_rr_rrsig_set_keytag(
++		   current_sig,
++		   ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16,
++		                         ldns_key_keytag(current_key)));
++
++	(void)ldns_rr_rrsig_set_algorithm(
++			current_sig,
++			ldns_native2rdf_int8(
++			    LDNS_RDF_TYPE_ALG,
++			    ldns_key_algorithm(current_key)));
++
++	(void)ldns_rr_rrsig_set_typecovered(
++			current_sig,
++			ldns_native2rdf_int16(
++			    LDNS_RDF_TYPE_TYPE,
++			    ldns_rr_get_type(ldns_rr_list_rr(rrset,
++			                                     0))));
++	return current_sig;
++}
++
++#ifdef HAVE_SSL
++ldns_rdf *
++ldns_sign_public_buffer(ldns_buffer *sign_buf, ldns_key *current_key)
++{
++	ldns_rdf *b64rdf = NULL;
++
++	switch(ldns_key_algorithm(current_key)) {
++	case LDNS_SIGN_DSA:
++	case LDNS_SIGN_DSA_NSEC3:
++		b64rdf = ldns_sign_public_evp(
++				   sign_buf,
++				   ldns_key_evp_key(current_key),
++				   EVP_dss1());
++		break;
++	case LDNS_SIGN_RSASHA1:
++	case LDNS_SIGN_RSASHA1_NSEC3:
++		b64rdf = ldns_sign_public_evp(
++				   sign_buf,
++				   ldns_key_evp_key(current_key),
++				   EVP_sha1());
++		break;
++#ifdef USE_SHA2
++	case LDNS_SIGN_RSASHA256:
++		b64rdf = ldns_sign_public_evp(
++				   sign_buf,
++				   ldns_key_evp_key(current_key),
++				   EVP_sha256());
++		break;
++	case LDNS_SIGN_RSASHA512:
++		b64rdf = ldns_sign_public_evp(
++				   sign_buf,
++				   ldns_key_evp_key(current_key),
++				   EVP_sha512());
++		break;
++#endif /* USE_SHA2 */
++#ifdef USE_GOST
++	case LDNS_SIGN_ECC_GOST:
++		b64rdf = ldns_sign_public_evp(
++				   sign_buf,
++				   ldns_key_evp_key(current_key),
++				   EVP_get_digestbyname("md_gost94"));
++		break;
++#endif /* USE_GOST */
++#ifdef USE_ECDSA
++        case LDNS_SIGN_ECDSAP256SHA256:
++       		b64rdf = ldns_sign_public_evp(
++				   sign_buf,
++				   ldns_key_evp_key(current_key),
++				   EVP_sha256());
++                break;
++        case LDNS_SIGN_ECDSAP384SHA384:
++       		b64rdf = ldns_sign_public_evp(
++				   sign_buf,
++				   ldns_key_evp_key(current_key),
++				   EVP_sha384());
++                break;
++#endif
++	case LDNS_SIGN_RSAMD5:
++		b64rdf = ldns_sign_public_evp(
++				   sign_buf,
++				   ldns_key_evp_key(current_key),
++				   EVP_md5());
++		break;
++	default:
++		/* do _you_ know this alg? */
++		printf("unknown algorithm, ");
++		printf("is the one used available on this system?\n");
++		break;
++	}
++
++	return b64rdf;
++}
++
++/**
++ * use this function to sign with a public/private key alg
++ * return the created signatures
++ */
++ldns_rr_list *
++ldns_sign_public(ldns_rr_list *rrset, ldns_key_list *keys)
++{
++	ldns_rr_list *signatures;
++	ldns_rr_list *rrset_clone;
++	ldns_rr *current_sig;
++	ldns_rdf *b64rdf;
++	ldns_key *current_key;
++	size_t key_count;
++	uint16_t i;
++	ldns_buffer *sign_buf;
++	ldns_rdf *new_owner;
++
++	if (!rrset || ldns_rr_list_rr_count(rrset) < 1 || !keys) {
++		return NULL;
++	}
++
++	new_owner = NULL;
++
++	signatures = ldns_rr_list_new();
++
++	/* prepare a signature and add all the know data
++	 * prepare the rrset. Sign this together.  */
++	rrset_clone = ldns_rr_list_clone(rrset);
++	if (!rrset_clone) {
++		return NULL;
++	}
++
++	/* make it canonical */
++	for(i = 0; i < ldns_rr_list_rr_count(rrset_clone); i++) {
++		ldns_rr_set_ttl(ldns_rr_list_rr(rrset_clone, i), 
++			ldns_rr_ttl(ldns_rr_list_rr(rrset, 0)));
++		ldns_rr2canonical(ldns_rr_list_rr(rrset_clone, i));
++	}
++	/* sort */
++	ldns_rr_list_sort(rrset_clone);
++
++	for (key_count = 0;
++		key_count < ldns_key_list_key_count(keys);
++		key_count++) {
++		if (!ldns_key_use(ldns_key_list_key(keys, key_count))) {
++			continue;
++		}
++		sign_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN);
++		if (!sign_buf) {
++			ldns_rr_list_free(rrset_clone);
++			ldns_rr_list_free(signatures);
++			ldns_rdf_free(new_owner);
++			return NULL;
++		}
++		b64rdf = NULL;
++
++		current_key = ldns_key_list_key(keys, key_count);
++		/* sign all RRs with keys that have ZSKbit, !SEPbit.
++		   sign DNSKEY RRs with keys that have ZSKbit&SEPbit */
++		if (ldns_key_flags(current_key) & LDNS_KEY_ZONE_KEY) {
++			current_sig = ldns_create_empty_rrsig(rrset_clone,
++			                                      current_key);
++
++			/* right now, we have: a key, a semi-sig and an rrset. For
++			 * which we can create the sig and base64 encode that and
++			 * add that to the signature */
++
++			if (ldns_rrsig2buffer_wire(sign_buf, current_sig)
++			    != LDNS_STATUS_OK) {
++				ldns_buffer_free(sign_buf);
++				/* ERROR */
++				ldns_rr_list_deep_free(rrset_clone);
++				ldns_rr_free(current_sig);
++				ldns_rr_list_deep_free(signatures);
++				return NULL;
++			}
++
++			/* add the rrset in sign_buf */
++			if (ldns_rr_list2buffer_wire(sign_buf, rrset_clone)
++			    != LDNS_STATUS_OK) {
++				ldns_buffer_free(sign_buf);
++				ldns_rr_list_deep_free(rrset_clone);
++				ldns_rr_free(current_sig);
++				ldns_rr_list_deep_free(signatures);
++				return NULL;
++			}
++
++			b64rdf = ldns_sign_public_buffer(sign_buf, current_key);
++
++			if (!b64rdf) {
++				/* signing went wrong */
++				ldns_rr_list_deep_free(rrset_clone);
++				ldns_rr_free(current_sig);
++				ldns_rr_list_deep_free(signatures);
++				return NULL;
++			}
++
++			ldns_rr_rrsig_set_sig(current_sig, b64rdf);
++
++			/* push the signature to the signatures list */
++			ldns_rr_list_push_rr(signatures, current_sig);
++		}
++		ldns_buffer_free(sign_buf); /* restart for the next key */
++	}
++	ldns_rr_list_deep_free(rrset_clone);
++
++	return signatures;
++}
++
++/**
++ * Sign data with DSA
++ *
++ * \param[in] to_sign The ldns_buffer containing raw data that is
++ *                    to be signed
++ * \param[in] key The DSA key structure to sign with
++ * \return ldns_rdf for the RRSIG ldns_rr
++ */
++ldns_rdf *
++ldns_sign_public_dsa(ldns_buffer *to_sign, DSA *key)
++{
++	unsigned char *sha1_hash;
++	ldns_rdf *sigdata_rdf;
++	ldns_buffer *b64sig;
++
++	DSA_SIG *sig;
++	uint8_t *data;
++	size_t pad;
++
++	b64sig = ldns_buffer_new(LDNS_MAX_PACKETLEN);
++	if (!b64sig) {
++		return NULL;
++	}
++
++	sha1_hash = SHA1((unsigned char*)ldns_buffer_begin(to_sign),
++				  ldns_buffer_position(to_sign), NULL);
++	if (!sha1_hash) {
++		ldns_buffer_free(b64sig);
++		return NULL;
++	}
++
++	sig = DSA_do_sign(sha1_hash, SHA_DIGEST_LENGTH, key);
++        if(!sig) {
++		ldns_buffer_free(b64sig);
++		return NULL;
++        }
++
++	data = LDNS_XMALLOC(uint8_t, 1 + 2 * SHA_DIGEST_LENGTH);
++        if(!data) {
++		ldns_buffer_free(b64sig);
++                DSA_SIG_free(sig);
++		return NULL;
++        }
++
++	data[0] = 1;
++	pad = 20 - (size_t) BN_num_bytes(sig->r);
++	if (pad > 0) {
++		memset(data + 1, 0, pad);
++	}
++	BN_bn2bin(sig->r, (unsigned char *) (data + 1) + pad);
++
++	pad = 20 - (size_t) BN_num_bytes(sig->s);
++	if (pad > 0) {
++		memset(data + 1 + SHA_DIGEST_LENGTH, 0, pad);
++	}
++	BN_bn2bin(sig->s, (unsigned char *) (data + 1 + SHA_DIGEST_LENGTH + pad));
++
++	sigdata_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64,
++								 1 + 2 * SHA_DIGEST_LENGTH,
++								 data);
++
++	ldns_buffer_free(b64sig);
++	LDNS_FREE(data);
++        DSA_SIG_free(sig);
++
++	return sigdata_rdf;
++}
++
++#ifdef USE_ECDSA
++#ifndef S_SPLINT_S
++static int
++ldns_pkey_is_ecdsa(EVP_PKEY* pkey)
++{
++        EC_KEY* ec;
++        const EC_GROUP* g;
++        if(EVP_PKEY_type(pkey->type) != EVP_PKEY_EC)
++                return 0;
++        ec = EVP_PKEY_get1_EC_KEY(pkey);
++        g = EC_KEY_get0_group(ec);
++        if(!g) {
++                EC_KEY_free(ec);
++                return 0;
++        }
++        if(EC_GROUP_get_curve_name(g) == NID_secp224r1 ||
++                EC_GROUP_get_curve_name(g) == NID_X9_62_prime256v1 ||
++                EC_GROUP_get_curve_name(g) == NID_secp384r1) {
++                EC_KEY_free(ec);
++                return 1;
++        }
++        /* downref the eckey, the original is still inside the pkey */
++        EC_KEY_free(ec);
++        return 0;
++}
++#endif /* splint */
++#endif /* USE_ECDSA */
++
++ldns_rdf *
++ldns_sign_public_evp(ldns_buffer *to_sign,
++				 EVP_PKEY *key,
++				 const EVP_MD *digest_type)
++{
++	unsigned int siglen;
++	ldns_rdf *sigdata_rdf;
++	ldns_buffer *b64sig;
++	EVP_MD_CTX ctx;
++	const EVP_MD *md_type;
++	int r;
++
++	siglen = 0;
++	b64sig = ldns_buffer_new(LDNS_MAX_PACKETLEN);
++	if (!b64sig) {
++		return NULL;
++	}
++
++	/* initializes a signing context */
++	md_type = digest_type;
++	if(!md_type) {
++		/* unknown message difest */
++		ldns_buffer_free(b64sig);
++		return NULL;
++	}
++
++	EVP_MD_CTX_init(&ctx);
++	r = EVP_SignInit(&ctx, md_type);
++	if(r == 1) {
++		r = EVP_SignUpdate(&ctx, (unsigned char*)
++					    ldns_buffer_begin(to_sign),
++					    ldns_buffer_position(to_sign));
++	} else {
++		ldns_buffer_free(b64sig);
++		return NULL;
++	}
++	if(r == 1) {
++		r = EVP_SignFinal(&ctx, (unsigned char*)
++					   ldns_buffer_begin(b64sig), &siglen, key);
++	} else {
++		ldns_buffer_free(b64sig);
++		return NULL;
++	}
++	if(r != 1) {
++		ldns_buffer_free(b64sig);
++		return NULL;
++	}
++
++	/* unfortunately, OpenSSL output is differenct from DNS DSA format */
++#ifndef S_SPLINT_S
++	if (EVP_PKEY_type(key->type) == EVP_PKEY_DSA) {
++		sigdata_rdf = ldns_convert_dsa_rrsig_asn12rdf(b64sig, siglen);
++#ifdef USE_ECDSA
++        } else if(EVP_PKEY_type(key->type) == EVP_PKEY_EC &&
++                ldns_pkey_is_ecdsa(key)) {
++                sigdata_rdf = ldns_convert_ecdsa_rrsig_asn12rdf(b64sig, siglen);
++#endif
++	} else {
++		/* ok output for other types is the same */
++		sigdata_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, siglen,
++									 ldns_buffer_begin(b64sig));
++	}
++#endif /* splint */
++	ldns_buffer_free(b64sig);
++	EVP_MD_CTX_cleanup(&ctx);
++	return sigdata_rdf;
++}
++
++ldns_rdf *
++ldns_sign_public_rsasha1(ldns_buffer *to_sign, RSA *key)
++{
++	unsigned char *sha1_hash;
++	unsigned int siglen;
++	ldns_rdf *sigdata_rdf;
++	ldns_buffer *b64sig;
++	int result;
++
++	siglen = 0;
++	b64sig = ldns_buffer_new(LDNS_MAX_PACKETLEN);
++	if (!b64sig) {
++		return NULL;
++	}
++
++	sha1_hash = SHA1((unsigned char*)ldns_buffer_begin(to_sign),
++				  ldns_buffer_position(to_sign), NULL);
++	if (!sha1_hash) {
++		ldns_buffer_free(b64sig);
++		return NULL;
++	}
++
++	result = RSA_sign(NID_sha1, sha1_hash, SHA_DIGEST_LENGTH,
++				   (unsigned char*)ldns_buffer_begin(b64sig),
++				   &siglen, key);
++	if (result != 1) {
++		ldns_buffer_free(b64sig);
++		return NULL;
++	}
++
++	sigdata_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, siglen, 
++								 ldns_buffer_begin(b64sig));
++	ldns_buffer_free(b64sig); /* can't free this buffer ?? */
++	return sigdata_rdf;
++}
++
++ldns_rdf *
++ldns_sign_public_rsamd5(ldns_buffer *to_sign, RSA *key)
++{
++	unsigned char *md5_hash;
++	unsigned int siglen;
++	ldns_rdf *sigdata_rdf;
++	ldns_buffer *b64sig;
++
++	b64sig = ldns_buffer_new(LDNS_MAX_PACKETLEN);
++	if (!b64sig) {
++		return NULL;
++	}
++
++	md5_hash = MD5((unsigned char*)ldns_buffer_begin(to_sign),
++				ldns_buffer_position(to_sign), NULL);
++	if (!md5_hash) {
++		ldns_buffer_free(b64sig);
++		return NULL;
++	}
++
++	RSA_sign(NID_md5, md5_hash, MD5_DIGEST_LENGTH,
++		    (unsigned char*)ldns_buffer_begin(b64sig),
++		    &siglen, key);
++
++	sigdata_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, siglen,
++								 ldns_buffer_begin(b64sig));
++	ldns_buffer_free(b64sig);
++	return sigdata_rdf;
++}
++#endif /* HAVE_SSL */
++
++/**
++ * Pushes all rrs from the rrsets of type A and AAAA on gluelist.
++ */
++static ldns_status
++ldns_dnssec_addresses_on_glue_list(
++		ldns_dnssec_rrsets *cur_rrset,
++		ldns_rr_list *glue_list)
++{
++	ldns_dnssec_rrs *cur_rrs;
++	while (cur_rrset) {
++		if (cur_rrset->type == LDNS_RR_TYPE_A 
++				|| cur_rrset->type == LDNS_RR_TYPE_AAAA) {
++			for (cur_rrs = cur_rrset->rrs; 
++					cur_rrs; 
++					cur_rrs = cur_rrs->next) {
++				if (cur_rrs->rr) {
++					if (!ldns_rr_list_push_rr(glue_list, 
++							cur_rrs->rr)) {
++						return LDNS_STATUS_MEM_ERR; 
++						/* ldns_rr_list_push_rr()
++						 * returns false when unable
++						 * to increase the capacity
++						 * of the ldsn_rr_list
++						 */
++					}
++				}
++			}
++		}
++		cur_rrset = cur_rrset->next;
++	}
++	return LDNS_STATUS_OK;
++}
++
++/**
++ * Marks the names in the zone that are occluded. Those names will be skipped
++ * when walking the tree with the ldns_dnssec_name_node_next_nonglue()
++ * function. But watch out! Names that are partially occluded (like glue with
++ * the same name as the delegation) will not be marked and should specifically 
++ * be taken into account separately.
++ *
++ * When glue_list is given (not NULL), in the process of marking the names, all
++ * glue resource records will be pushed to that list, even glue at delegation names.
++ *
++ * \param[in] zone the zone in which to mark the names
++ * \param[in] glue_list the list to which to push the glue rrs
++ * \return LDNS_STATUS_OK on success, an error code otherwise
++ */
++ldns_status
++ldns_dnssec_zone_mark_and_get_glue(ldns_dnssec_zone *zone, 
++	ldns_rr_list *glue_list)
++{
++	ldns_rbnode_t    *node;
++	ldns_dnssec_name *name;
++	ldns_rdf         *owner;
++	ldns_rdf         *cut = NULL; /* keeps track of zone cuts */
++	/* When the cut is caused by a delegation, below_delegation will be 1.
++	 * When caused by a DNAME, below_delegation will be 0.
++	 */
++	int below_delegation = -1; /* init suppresses comiler warning */
++	ldns_status s;
++
++	if (!zone || !zone->names) {
++		return LDNS_STATUS_NULL;
++	}
++	for (node = ldns_rbtree_first(zone->names); 
++			node != LDNS_RBTREE_NULL; 
++			node = ldns_rbtree_next(node)) {
++		name = (ldns_dnssec_name *) node->data;
++		owner = ldns_dnssec_name_name(name);
++
++		if (cut) { 
++			/* The previous node was a zone cut, or a subdomain
++			 * below a zone cut. Is this node (still) a subdomain
++			 * below the cut? Then the name is occluded. Unless
++			 * the name contains a SOA, after which we are 
++			 * authoritative again.
++			 *
++			 * FIXME! If there are labels in between the SOA and
++			 * the cut, going from the authoritative space (below
++			 * the SOA) up into occluded space again, will not be
++			 * detected with the contruct below!
++			 */
++			if (ldns_dname_is_subdomain(owner, cut) &&
++					!ldns_dnssec_rrsets_contains_type(
++					name->rrsets, LDNS_RR_TYPE_SOA)) {
++
++				if (below_delegation && glue_list) {
++					s = ldns_dnssec_addresses_on_glue_list(
++						name->rrsets, glue_list);
++					if (s != LDNS_STATUS_OK) {
++						return s;
++					}
++				}
++				name->is_glue = true; /* Mark occluded name! */
++				continue;
++			} else {
++				cut = NULL;
++			}
++		}
++
++		/* The node is not below a zone cut. Is it a zone cut itself?
++		 * Everything below a SOA is authoritative of course; Except
++		 * when the name also contains a DNAME :).
++		 */
++		if (ldns_dnssec_rrsets_contains_type(
++				name->rrsets, LDNS_RR_TYPE_NS)
++			    && !ldns_dnssec_rrsets_contains_type(
++				name->rrsets, LDNS_RR_TYPE_SOA)) {
++			cut = owner;
++			below_delegation = 1;
++			if (glue_list) { /* record glue on the zone cut */
++				s = ldns_dnssec_addresses_on_glue_list(
++					name->rrsets, glue_list);
++				if (s != LDNS_STATUS_OK) {
++					return s;
++				}
++			}
++		} else if (ldns_dnssec_rrsets_contains_type(
++				name->rrsets, LDNS_RR_TYPE_DNAME)) {
++			cut = owner;
++			below_delegation = 0;
++		}
++	}
++	return LDNS_STATUS_OK;
++}
++
++/**
++ * Marks the names in the zone that are occluded. Those names will be skipped
++ * when walking the tree with the ldns_dnssec_name_node_next_nonglue()
++ * function. But watch out! Names that are partially occluded (like glue with
++ * the same name as the delegation) will not be marked and should specifically 
++ * be taken into account separately.
++ *
++ * \param[in] zone the zone in which to mark the names
++ * \return LDNS_STATUS_OK on success, an error code otherwise
++ */
++ldns_status
++ldns_dnssec_zone_mark_glue(ldns_dnssec_zone *zone)
++{
++	return ldns_dnssec_zone_mark_and_get_glue(zone, NULL);
++}
++
++ldns_rbnode_t *
++ldns_dnssec_name_node_next_nonglue(ldns_rbnode_t *node)
++{
++	ldns_rbnode_t *next_node = NULL;
++	ldns_dnssec_name *next_name = NULL;
++	bool done = false;
++
++	if (node == LDNS_RBTREE_NULL) {
++		return NULL;
++	}
++	next_node = node;
++	while (!done) {
++		if (next_node == LDNS_RBTREE_NULL) {
++			return NULL;
++		} else {
++			next_name = (ldns_dnssec_name *)next_node->data;
++			if (!next_name->is_glue) {
++				done = true;
++			} else {
++				next_node = ldns_rbtree_next(next_node);
++			}
++		}
++	}
++	return next_node;
++}
++
++ldns_status
++ldns_dnssec_zone_create_nsecs(ldns_dnssec_zone *zone,
++                              ldns_rr_list *new_rrs)
++{
++
++	ldns_rbnode_t *first_node, *cur_node, *next_node;
++	ldns_dnssec_name *cur_name, *next_name;
++	ldns_rr *nsec_rr;
++	uint32_t nsec_ttl;
++	ldns_dnssec_rrsets *soa;
++
++	/* the TTL of NSEC rrs should be set to the minimum TTL of
++	 * the zone SOA (RFC4035 Section 2.3)
++	 */
++	soa = ldns_dnssec_name_find_rrset(zone->soa, LDNS_RR_TYPE_SOA);
++
++	/* did the caller actually set it? if not,
++	 * fall back to default ttl
++	 */
++	if (soa && soa->rrs && soa->rrs->rr
++			&& (ldns_rr_rdf(soa->rrs->rr, 6) != NULL)) {
++		nsec_ttl = ldns_rdf2native_int32(ldns_rr_rdf(soa->rrs->rr, 6));
++	} else {
++		nsec_ttl = LDNS_DEFAULT_TTL;
++	}
++
++	first_node = ldns_dnssec_name_node_next_nonglue(
++			       ldns_rbtree_first(zone->names));
++	cur_node = first_node;
++	if (cur_node) {
++		next_node = ldns_dnssec_name_node_next_nonglue(
++			           ldns_rbtree_next(cur_node));
++	} else {
++		next_node = NULL;
++	}
++
++	while (cur_node && next_node) {
++		cur_name = (ldns_dnssec_name *)cur_node->data;
++		next_name = (ldns_dnssec_name *)next_node->data;
++		nsec_rr = ldns_dnssec_create_nsec(cur_name,
++		                                  next_name,
++		                                  LDNS_RR_TYPE_NSEC);
++		ldns_rr_set_ttl(nsec_rr, nsec_ttl);
++		if(ldns_dnssec_name_add_rr(cur_name, nsec_rr)!=LDNS_STATUS_OK){
++			ldns_rr_free(nsec_rr);
++			return LDNS_STATUS_ERR;
++		}
++		ldns_rr_list_push_rr(new_rrs, nsec_rr);
++		cur_node = next_node;
++		if (cur_node) {
++			next_node = ldns_dnssec_name_node_next_nonglue(
++                               ldns_rbtree_next(cur_node));
++		}
++	}
++
++	if (cur_node && !next_node) {
++		cur_name = (ldns_dnssec_name *)cur_node->data;
++		next_name = (ldns_dnssec_name *)first_node->data;
++		nsec_rr = ldns_dnssec_create_nsec(cur_name,
++		                                  next_name,
++		                                  LDNS_RR_TYPE_NSEC);
++		ldns_rr_set_ttl(nsec_rr, nsec_ttl);
++		if(ldns_dnssec_name_add_rr(cur_name, nsec_rr)!=LDNS_STATUS_OK){
++			ldns_rr_free(nsec_rr);
++			return LDNS_STATUS_ERR;
++		}
++		ldns_rr_list_push_rr(new_rrs, nsec_rr);
++	} else {
++		printf("error\n");
++	}
++
++	return LDNS_STATUS_OK;
++}
++
++#ifdef HAVE_SSL
++static void
++ldns_hashed_names_node_free(ldns_rbnode_t *node, void *arg) {
++	(void) arg;
++	LDNS_FREE(node);
++}
++
++static ldns_status
++ldns_dnssec_zone_create_nsec3s_mkmap(ldns_dnssec_zone *zone,
++		ldns_rr_list *new_rrs,
++		uint8_t algorithm,
++		uint8_t flags,
++		uint16_t iterations,
++		uint8_t salt_length,
++		uint8_t *salt,
++		ldns_rbtree_t **map)
++{
++	ldns_rbnode_t *first_name_node;
++	ldns_rbnode_t *current_name_node;
++	ldns_dnssec_name *current_name;
++	ldns_status result = LDNS_STATUS_OK;
++	ldns_rr *nsec_rr;
++	ldns_rr_list *nsec3_list;
++	uint32_t nsec_ttl;
++	ldns_dnssec_rrsets *soa;
++	ldns_rbnode_t *hashmap_node;
++
++	if (!zone || !new_rrs || !zone->names) {
++		return LDNS_STATUS_ERR;
++	}
++
++	/* the TTL of NSEC rrs should be set to the minimum TTL of
++	 * the zone SOA (RFC4035 Section 2.3)
++	 */
++	soa = ldns_dnssec_name_find_rrset(zone->soa, LDNS_RR_TYPE_SOA);
++
++	/* did the caller actually set it? if not,
++	 * fall back to default ttl
++	 */
++	if (soa && soa->rrs && soa->rrs->rr
++			&& ldns_rr_rdf(soa->rrs->rr, 6) != NULL) {
++		nsec_ttl = ldns_rdf2native_int32(ldns_rr_rdf(soa->rrs->rr, 6));
++	} else {
++		nsec_ttl = LDNS_DEFAULT_TTL;
++	}
++
++	if (zone->hashed_names) {
++		ldns_traverse_postorder(zone->hashed_names,
++				ldns_hashed_names_node_free, NULL);
++		LDNS_FREE(zone->hashed_names);
++	}
++	zone->hashed_names = ldns_rbtree_create(ldns_dname_compare_v);
++	if (zone->hashed_names && map) {
++		*map = zone->hashed_names;
++	}
++
++	first_name_node = ldns_dnssec_name_node_next_nonglue(
++					  ldns_rbtree_first(zone->names));
++
++	current_name_node = first_name_node;
++
++	while (current_name_node && current_name_node != LDNS_RBTREE_NULL &&
++			result == LDNS_STATUS_OK) {
++
++		current_name = (ldns_dnssec_name *) current_name_node->data;
++		nsec_rr = ldns_dnssec_create_nsec3(current_name,
++		                                   NULL,
++		                                   zone->soa->name,
++		                                   algorithm,
++		                                   flags,
++		                                   iterations,
++		                                   salt_length,
++		                                   salt);
++		/* by default, our nsec based generator adds rrsigs
++		 * remove the bitmap for empty nonterminals */
++		if (!current_name->rrsets) {
++			ldns_rdf_deep_free(ldns_rr_pop_rdf(nsec_rr));
++		}
++		ldns_rr_set_ttl(nsec_rr, nsec_ttl);
++		result = ldns_dnssec_name_add_rr(current_name, nsec_rr);
++		ldns_rr_list_push_rr(new_rrs, nsec_rr);
++		if (ldns_rr_owner(nsec_rr)) {
++			hashmap_node = LDNS_MALLOC(ldns_rbnode_t);
++			if (hashmap_node == NULL) {
++				return LDNS_STATUS_MEM_ERR;
++			}
++			current_name->hashed_name = 
++				ldns_dname_label(ldns_rr_owner(nsec_rr), 0);
++
++			if (current_name->hashed_name == NULL) {
++				LDNS_FREE(hashmap_node);
++				return LDNS_STATUS_MEM_ERR;
++			}
++			hashmap_node->key  = current_name->hashed_name;
++			hashmap_node->data = current_name;
++
++			if (! ldns_rbtree_insert(zone->hashed_names
++						, hashmap_node)) {
++				LDNS_FREE(hashmap_node);
++			}
++		}
++		current_name_node = ldns_dnssec_name_node_next_nonglue(
++		                   ldns_rbtree_next(current_name_node));
++	}
++	if (result != LDNS_STATUS_OK) {
++		return result;
++	}
++
++	/* Make sorted list of nsec3s (via zone->hashed_names)
++	 */
++	nsec3_list = ldns_rr_list_new();
++	if (nsec3_list == NULL) {
++		return LDNS_STATUS_MEM_ERR;
++	}
++	for ( hashmap_node  = ldns_rbtree_first(zone->hashed_names)
++	    ; hashmap_node != LDNS_RBTREE_NULL
++	    ; hashmap_node  = ldns_rbtree_next(hashmap_node)
++	    ) {
++		current_name = (ldns_dnssec_name *) hashmap_node->data;
++		nsec_rr = ((ldns_dnssec_name *) hashmap_node->data)->nsec;
++		if (nsec_rr) {
++			ldns_rr_list_push_rr(nsec3_list, nsec_rr);
++		}
++	}
++	result = ldns_dnssec_chain_nsec3_list(nsec3_list);
++	ldns_rr_list_free(nsec3_list);
++
++	return result;
++}
++
++ldns_status
++ldns_dnssec_zone_create_nsec3s(ldns_dnssec_zone *zone,
++		ldns_rr_list *new_rrs,
++		uint8_t algorithm,
++		uint8_t flags,
++		uint16_t iterations,
++		uint8_t salt_length,
++		uint8_t *salt)
++{
++	return ldns_dnssec_zone_create_nsec3s_mkmap(zone, new_rrs, algorithm,
++		       	flags, iterations, salt_length, salt, NULL);
++
++}
++#endif /* HAVE_SSL */
++
++ldns_dnssec_rrs *
++ldns_dnssec_remove_signatures( ldns_dnssec_rrs *signatures
++			     , ATTR_UNUSED(ldns_key_list *key_list)
++			     , int (*func)(ldns_rr *, void *)
++			     , void *arg
++			     )
++{
++	ldns_dnssec_rrs *base_rrs = signatures;
++	ldns_dnssec_rrs *cur_rr = base_rrs;
++	ldns_dnssec_rrs *prev_rr = NULL;
++	ldns_dnssec_rrs *next_rr;
++
++	uint16_t keytag;
++	size_t i;
++
++	if (!cur_rr) {
++		switch(func(NULL, arg)) {
++		case LDNS_SIGNATURE_LEAVE_ADD_NEW:
++		case LDNS_SIGNATURE_REMOVE_ADD_NEW:
++		break;
++		case LDNS_SIGNATURE_LEAVE_NO_ADD:
++		case LDNS_SIGNATURE_REMOVE_NO_ADD:
++		ldns_key_list_set_use(key_list, false);
++		break;
++		default:
++#ifdef STDERR_MSGS
++			fprintf(stderr, "[XX] unknown return value from callback\n");
++#endif
++			break;
++		}
++		return NULL;
++	}
++	(void)func(cur_rr->rr, arg);
++
++	while (cur_rr) {
++		next_rr = cur_rr->next;
++
++		switch (func(cur_rr->rr, arg)) {
++		case  LDNS_SIGNATURE_LEAVE_ADD_NEW:
++			prev_rr = cur_rr;
++			break;
++		case LDNS_SIGNATURE_LEAVE_NO_ADD:
++			keytag = ldns_rdf2native_int16(
++					   ldns_rr_rrsig_keytag(cur_rr->rr));
++			for (i = 0; i < ldns_key_list_key_count(key_list); i++) {
++				if (ldns_key_keytag(ldns_key_list_key(key_list, i)) ==
++				    keytag) {
++					ldns_key_set_use(ldns_key_list_key(key_list, i),
++								  false);
++				}
++			}
++			prev_rr = cur_rr;
++			break;
++		case LDNS_SIGNATURE_REMOVE_NO_ADD:
++			keytag = ldns_rdf2native_int16(
++					   ldns_rr_rrsig_keytag(cur_rr->rr));
++			for (i = 0; i < ldns_key_list_key_count(key_list); i++) {
++				if (ldns_key_keytag(ldns_key_list_key(key_list, i))
++				    == keytag) {
++					ldns_key_set_use(ldns_key_list_key(key_list, i),
++								  false);
++				}
++			}
++			if (prev_rr) {
++				prev_rr->next = next_rr;
++			} else {
++				base_rrs = next_rr;
++			}
++			LDNS_FREE(cur_rr);
++			break;
++		case LDNS_SIGNATURE_REMOVE_ADD_NEW:
++			if (prev_rr) {
++				prev_rr->next = next_rr;
++			} else {
++				base_rrs = next_rr;
++			}
++			LDNS_FREE(cur_rr);
++			break;
++		default:
++#ifdef STDERR_MSGS
++			fprintf(stderr, "[XX] unknown return value from callback\n");
++#endif
++			break;
++		}
++		cur_rr = next_rr;
++	}
++
++	return base_rrs;
++}
++
++#ifdef HAVE_SSL
++ldns_status
++ldns_dnssec_zone_create_rrsigs(ldns_dnssec_zone *zone,
++                               ldns_rr_list *new_rrs,
++                               ldns_key_list *key_list,
++                               int (*func)(ldns_rr *, void*),
++                               void *arg)
++{
++	return ldns_dnssec_zone_create_rrsigs_flg(zone, new_rrs, key_list,
++		func, arg, 0);
++}
++
++/** If there are KSKs use only them and mark ZSKs unused */
++static void
++ldns_key_list_filter_for_dnskey(ldns_key_list *key_list)
++{
++	int saw_ksk = 0;
++	size_t i;
++	for(i=0; i<ldns_key_list_key_count(key_list); i++)
++		if((ldns_key_flags(ldns_key_list_key(key_list, i))&LDNS_KEY_SEP_KEY)) {
++			saw_ksk = 1;
++			break;
++		}
++	if(!saw_ksk)
++		return;
++	for(i=0; i<ldns_key_list_key_count(key_list); i++)
++		if(!(ldns_key_flags(ldns_key_list_key(key_list, i))&LDNS_KEY_SEP_KEY))
++			ldns_key_set_use(ldns_key_list_key(key_list, i), 0);
++}
++
++/** If there are no ZSKs use KSK as ZSK */
++static void
++ldns_key_list_filter_for_non_dnskey(ldns_key_list *key_list)
++{
++	int saw_zsk = 0;
++	size_t i;
++	for(i=0; i<ldns_key_list_key_count(key_list); i++)
++		if(!(ldns_key_flags(ldns_key_list_key(key_list, i))&LDNS_KEY_SEP_KEY)) {
++			saw_zsk = 1;
++			break;
++		}
++	if(!saw_zsk)
++		return;
++	/* else filter all KSKs */
++	for(i=0; i<ldns_key_list_key_count(key_list); i++)
++		if((ldns_key_flags(ldns_key_list_key(key_list, i))&LDNS_KEY_SEP_KEY))
++			ldns_key_set_use(ldns_key_list_key(key_list, i), 0);
++}
++
++ldns_status
++ldns_dnssec_zone_create_rrsigs_flg( ldns_dnssec_zone *zone
++				  , ldns_rr_list *new_rrs
++				  , ldns_key_list *key_list
++				  , int (*func)(ldns_rr *, void*)
++				  , void *arg
++				  , int flags
++				  )
++{
++	ldns_status result = LDNS_STATUS_OK;
++
++	ldns_rbnode_t *cur_node;
++	ldns_rr_list *rr_list;
++
++	ldns_dnssec_name *cur_name;
++	ldns_dnssec_rrsets *cur_rrset;
++	ldns_dnssec_rrs *cur_rr;
++
++	ldns_rr_list *siglist;
++
++	size_t i;
++
++	int on_delegation_point = 0; /* handle partially occluded names */
++
++	ldns_rr_list *pubkey_list = ldns_rr_list_new();
++	for (i = 0; i<ldns_key_list_key_count(key_list); i++) {
++		ldns_rr_list_push_rr( pubkey_list
++				    , ldns_key2rr(ldns_key_list_key(
++							key_list, i))
++				    );
++	}
++	/* TODO: callback to see is list should be signed */
++	/* TODO: remove 'old' signatures from signature list */
++	cur_node = ldns_rbtree_first(zone->names);
++	while (cur_node != LDNS_RBTREE_NULL) {
++		cur_name = (ldns_dnssec_name *) cur_node->data;
++
++		if (!cur_name->is_glue) {
++			on_delegation_point = ldns_dnssec_rrsets_contains_type(
++					cur_name->rrsets, LDNS_RR_TYPE_NS)
++				&& !ldns_dnssec_rrsets_contains_type(
++					cur_name->rrsets, LDNS_RR_TYPE_SOA);
++			cur_rrset = cur_name->rrsets;
++			while (cur_rrset) {
++				/* reset keys to use */
++				ldns_key_list_set_use(key_list, true);
++
++				/* walk through old sigs, remove the old,
++				   and mark which keys (not) to use) */
++				cur_rrset->signatures =
++					ldns_dnssec_remove_signatures(cur_rrset->signatures,
++											key_list,
++											func,
++											arg);
++				if(!(flags&LDNS_SIGN_DNSKEY_WITH_ZSK) &&
++					cur_rrset->type == LDNS_RR_TYPE_DNSKEY)
++					ldns_key_list_filter_for_dnskey(key_list);
++
++				if(cur_rrset->type != LDNS_RR_TYPE_DNSKEY)
++					ldns_key_list_filter_for_non_dnskey(key_list);
++
++				/* TODO: just set count to zero? */
++				rr_list = ldns_rr_list_new();
++
++				cur_rr = cur_rrset->rrs;
++				while (cur_rr) {
++					ldns_rr_list_push_rr(rr_list, cur_rr->rr);
++					cur_rr = cur_rr->next;
++				}
++
++				/* only sign non-delegation RRsets */
++				/* (glue should have been marked earlier, 
++				 *  except on the delegation points itself) */
++				if (!on_delegation_point ||
++						ldns_rr_list_type(rr_list) 
++							== LDNS_RR_TYPE_DS ||
++						ldns_rr_list_type(rr_list) 
++							== LDNS_RR_TYPE_NSEC ||
++						ldns_rr_list_type(rr_list) 
++							== LDNS_RR_TYPE_NSEC3) {
++					siglist = ldns_sign_public(rr_list, key_list);
++					for (i = 0; i < ldns_rr_list_rr_count(siglist); i++) {
++						if (cur_rrset->signatures) {
++							result = ldns_dnssec_rrs_add_rr(cur_rrset->signatures,
++											   ldns_rr_list_rr(siglist,
++														    i));
++						} else {
++							cur_rrset->signatures = ldns_dnssec_rrs_new();
++							cur_rrset->signatures->rr =
++								ldns_rr_list_rr(siglist, i);
++						}
++						if (new_rrs) {
++							ldns_rr_list_push_rr(new_rrs,
++												 ldns_rr_list_rr(siglist,
++															  i));
++						}
++					}
++					ldns_rr_list_free(siglist);
++				}
++
++				ldns_rr_list_free(rr_list);
++
++				cur_rrset = cur_rrset->next;
++			}
++
++			/* sign the nsec */
++			ldns_key_list_set_use(key_list, true);
++			cur_name->nsec_signatures =
++				ldns_dnssec_remove_signatures(cur_name->nsec_signatures,
++										key_list,
++										func,
++										arg);
++			ldns_key_list_filter_for_non_dnskey(key_list);
++
++			rr_list = ldns_rr_list_new();
++			ldns_rr_list_push_rr(rr_list, cur_name->nsec);
++			siglist = ldns_sign_public(rr_list, key_list);
++
++			for (i = 0; i < ldns_rr_list_rr_count(siglist); i++) {
++				if (cur_name->nsec_signatures) {
++					result = ldns_dnssec_rrs_add_rr(cur_name->nsec_signatures,
++									   ldns_rr_list_rr(siglist, i));
++				} else {
++					cur_name->nsec_signatures = ldns_dnssec_rrs_new();
++					cur_name->nsec_signatures->rr =
++						ldns_rr_list_rr(siglist, i);
++				}
++				if (new_rrs) {
++					ldns_rr_list_push_rr(new_rrs,
++								 ldns_rr_list_rr(siglist, i));
++				}
++			}
++
++			ldns_rr_list_free(siglist);
++			ldns_rr_list_free(rr_list);
++		}
++		cur_node = ldns_rbtree_next(cur_node);
++	}
++
++	ldns_rr_list_deep_free(pubkey_list);
++	return result;
++}
++
++ldns_status
++ldns_dnssec_zone_sign(ldns_dnssec_zone *zone,
++				  ldns_rr_list *new_rrs,
++				  ldns_key_list *key_list,
++				  int (*func)(ldns_rr *, void *),
++				  void *arg)
++{
++	return ldns_dnssec_zone_sign_flg(zone, new_rrs, key_list, func, arg, 0);
++}
++
++ldns_status
++ldns_dnssec_zone_sign_flg(ldns_dnssec_zone *zone,
++				  ldns_rr_list *new_rrs,
++				  ldns_key_list *key_list,
++				  int (*func)(ldns_rr *, void *),
++				  void *arg,
++				  int flags)
++{
++	ldns_status result = LDNS_STATUS_OK;
++
++	if (!zone || !new_rrs || !key_list) {
++		return LDNS_STATUS_ERR;
++	}
++
++	/* zone is already sorted */
++	result = ldns_dnssec_zone_mark_glue(zone);
++	if (result != LDNS_STATUS_OK) {
++		return result;
++	}
++
++	/* check whether we need to add nsecs */
++	if (zone->names && !((ldns_dnssec_name *)zone->names->root->data)->nsec) {
++		result = ldns_dnssec_zone_create_nsecs(zone, new_rrs);
++		if (result != LDNS_STATUS_OK) {
++			return result;
++		}
++	}
++
++	result = ldns_dnssec_zone_create_rrsigs_flg(zone,
++					new_rrs,
++					key_list,
++					func,
++					arg,
++					flags);
++
++	return result;
++}
++
++ldns_status
++ldns_dnssec_zone_sign_nsec3(ldns_dnssec_zone *zone,
++					   ldns_rr_list *new_rrs,
++					   ldns_key_list *key_list,
++					   int (*func)(ldns_rr *, void *),
++					   void *arg,
++					   uint8_t algorithm,
++					   uint8_t flags,
++					   uint16_t iterations,
++					   uint8_t salt_length,
++					   uint8_t *salt)
++{
++	return ldns_dnssec_zone_sign_nsec3_flg_mkmap(zone, new_rrs, key_list,
++		func, arg, algorithm, flags, iterations, salt_length, salt, 0,
++	       	NULL);
++}
++
++ldns_status
++ldns_dnssec_zone_sign_nsec3_flg_mkmap(ldns_dnssec_zone *zone,
++		ldns_rr_list *new_rrs,
++		ldns_key_list *key_list,
++		int (*func)(ldns_rr *, void *),
++		void *arg,
++		uint8_t algorithm,
++		uint8_t flags,
++		uint16_t iterations,
++		uint8_t salt_length,
++		uint8_t *salt,
++		int signflags,
++		ldns_rbtree_t **map)
++{
++	ldns_rr *nsec3, *nsec3param;
++	ldns_status result = LDNS_STATUS_OK;
++
++	/* zone is already sorted */
++	result = ldns_dnssec_zone_mark_glue(zone);
++	if (result != LDNS_STATUS_OK) {
++		return result;
++	}
++
++	/* TODO if there are already nsec3s presents and their
++	 * parameters are the same as these, we don't have to recreate
++	 */
++	if (zone->names) {
++		/* add empty nonterminals */
++		result = ldns_dnssec_zone_add_empty_nonterminals(zone);
++		if (result != LDNS_STATUS_OK) {
++			return result;
++		}
++
++		nsec3 = ((ldns_dnssec_name *)zone->names->root->data)->nsec;
++		if (nsec3 && ldns_rr_get_type(nsec3) == LDNS_RR_TYPE_NSEC3) {
++			/* no need to recreate */
++		} else {
++			if (!ldns_dnssec_zone_find_rrset(zone,
++									   zone->soa->name,
++									   LDNS_RR_TYPE_NSEC3PARAM)) {
++				/* create and add the nsec3param rr */
++				nsec3param =
++					ldns_rr_new_frm_type(LDNS_RR_TYPE_NSEC3PARAM);
++				ldns_rr_set_owner(nsec3param,
++							   ldns_rdf_clone(zone->soa->name));
++				ldns_nsec3_add_param_rdfs(nsec3param,
++									 algorithm,
++									 flags,
++									 iterations,
++									 salt_length,
++									 salt);
++				/* always set bit 7 of the flags to zero, according to
++				 * rfc5155 section 11. The bits are counted from right to left,
++				 * so bit 7 in rfc5155 is bit 0 in ldns */
++				ldns_set_bit(ldns_rdf_data(ldns_rr_rdf(nsec3param, 1)), 0, 0);
++				result = ldns_dnssec_zone_add_rr(zone, nsec3param);
++				if (result != LDNS_STATUS_OK) {
++					return result;
++				}
++				ldns_rr_list_push_rr(new_rrs, nsec3param);
++			}
++			result = ldns_dnssec_zone_create_nsec3s_mkmap(zone,
++											new_rrs,
++											algorithm,
++											flags,
++											iterations,
++											salt_length,
++											salt,
++											map);
++			if (result != LDNS_STATUS_OK) {
++				return result;
++			}
++		}
++
++		result = ldns_dnssec_zone_create_rrsigs_flg(zone,
++						new_rrs,
++						key_list,
++						func,
++						arg,
++						signflags);
++	}
++
++	return result;
++}
++
++ldns_status
++ldns_dnssec_zone_sign_nsec3_flg(ldns_dnssec_zone *zone,
++		ldns_rr_list *new_rrs,
++		ldns_key_list *key_list,
++		int (*func)(ldns_rr *, void *),
++		void *arg,
++		uint8_t algorithm,
++		uint8_t flags,
++		uint16_t iterations,
++		uint8_t salt_length,
++		uint8_t *salt,
++		int signflags)
++{
++	return ldns_dnssec_zone_sign_nsec3_flg_mkmap(zone, new_rrs, key_list,
++		func, arg, algorithm, flags, iterations, salt_length, salt,
++		signflags, NULL);
++}
++
++ldns_zone *
++ldns_zone_sign(const ldns_zone *zone, ldns_key_list *key_list)
++{
++	ldns_dnssec_zone *dnssec_zone;
++	ldns_zone *signed_zone;
++	ldns_rr_list *new_rrs;
++	size_t i;
++
++	signed_zone = ldns_zone_new();
++	dnssec_zone = ldns_dnssec_zone_new();
++
++	(void) ldns_dnssec_zone_add_rr(dnssec_zone, ldns_zone_soa(zone));
++	ldns_zone_set_soa(signed_zone, ldns_rr_clone(ldns_zone_soa(zone)));
++
++	for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(zone)); i++) {
++		(void) ldns_dnssec_zone_add_rr(dnssec_zone,
++								 ldns_rr_list_rr(ldns_zone_rrs(zone),
++											  i));
++		ldns_zone_push_rr(signed_zone,
++					   ldns_rr_clone(ldns_rr_list_rr(ldns_zone_rrs(zone),
++											   i)));
++	}
++
++	new_rrs = ldns_rr_list_new();
++	(void) ldns_dnssec_zone_sign(dnssec_zone,
++						    new_rrs,
++						    key_list,
++						    ldns_dnssec_default_replace_signatures,
++						    NULL);
++
++    	for (i = 0; i < ldns_rr_list_rr_count(new_rrs); i++) {
++		ldns_rr_list_push_rr(ldns_zone_rrs(signed_zone),
++						 ldns_rr_clone(ldns_rr_list_rr(new_rrs, i)));
++	}
++
++	ldns_rr_list_deep_free(new_rrs);
++	ldns_dnssec_zone_free(dnssec_zone);
++
++	return signed_zone;
++}
++
++ldns_zone *
++ldns_zone_sign_nsec3(ldns_zone *zone, ldns_key_list *key_list, uint8_t algorithm, uint8_t flags, uint16_t iterations, uint8_t salt_length, uint8_t *salt)
++{
++	ldns_dnssec_zone *dnssec_zone;
++	ldns_zone *signed_zone;
++	ldns_rr_list *new_rrs;
++	size_t i;
++
++	signed_zone = ldns_zone_new();
++	dnssec_zone = ldns_dnssec_zone_new();
++
++	(void) ldns_dnssec_zone_add_rr(dnssec_zone, ldns_zone_soa(zone));
++	ldns_zone_set_soa(signed_zone, ldns_rr_clone(ldns_zone_soa(zone)));
++
++	for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(zone)); i++) {
++		(void) ldns_dnssec_zone_add_rr(dnssec_zone,
++								 ldns_rr_list_rr(ldns_zone_rrs(zone),
++											  i));
++		ldns_zone_push_rr(signed_zone, 
++					   ldns_rr_clone(ldns_rr_list_rr(ldns_zone_rrs(zone),
++											   i)));
++	}
++
++	new_rrs = ldns_rr_list_new();
++	(void) ldns_dnssec_zone_sign_nsec3(dnssec_zone,
++								new_rrs,
++								key_list,
++								ldns_dnssec_default_replace_signatures,
++								NULL,
++								algorithm,
++								flags,
++								iterations,
++								salt_length,
++								salt);
++
++    	for (i = 0; i < ldns_rr_list_rr_count(new_rrs); i++) {
++		ldns_rr_list_push_rr(ldns_zone_rrs(signed_zone),
++						 ldns_rr_clone(ldns_rr_list_rr(new_rrs, i)));
++	}
++
++	ldns_rr_list_deep_free(new_rrs);
++	ldns_dnssec_zone_free(dnssec_zone);
++
++	return signed_zone;
++}
++#endif /* HAVE_SSL */
++
++
+diff --git a/ldns/src/dnssec_verify.c b/ldns/src/dnssec_verify.c
+new file mode 100644
+index 0000000..1af6635
+--- /dev/null
++++ b/ldns/src/dnssec_verify.c
+@@ -0,0 +1,2684 @@
++#include <ldns/config.h>
++
++#include <ldns/ldns.h>
++
++#include <strings.h>
++#include <time.h>
++
++#ifdef HAVE_SSL
++/* this entire file is rather useless when you don't have
++ * crypto...
++ */
++#include <openssl/ssl.h>
++#include <openssl/evp.h>
++#include <openssl/rand.h>
++#include <openssl/err.h>
++#include <openssl/md5.h>
++
++ldns_dnssec_data_chain *
++ldns_dnssec_data_chain_new(void)
++{
++	ldns_dnssec_data_chain *nc = LDNS_CALLOC(ldns_dnssec_data_chain, 1);
++        if(!nc) return NULL;
++	/* 
++	 * not needed anymore because CALLOC initalizes everything to zero.
++
++	nc->rrset = NULL;
++	nc->parent_type = 0;
++	nc->parent = NULL;
++	nc->signatures = NULL;
++	nc->packet_rcode = 0;
++	nc->packet_qtype = 0;
++	nc->packet_nodata = false;
++
++	 */
++	return nc;
++}
++
++void
++ldns_dnssec_data_chain_free(ldns_dnssec_data_chain *chain)
++{
++	LDNS_FREE(chain);
++}
++
++void
++ldns_dnssec_data_chain_deep_free(ldns_dnssec_data_chain *chain)
++{
++	ldns_rr_list_deep_free(chain->rrset);
++	ldns_rr_list_deep_free(chain->signatures);
++	if (chain->parent) {
++		ldns_dnssec_data_chain_deep_free(chain->parent);
++	}
++	LDNS_FREE(chain);
++}
++
++void
++ldns_dnssec_data_chain_print_fmt(FILE *out, const ldns_output_format *fmt,
++		const ldns_dnssec_data_chain *chain)
++{
++	ldns_lookup_table *rcode;
++	const ldns_rr_descriptor *rr_descriptor;
++	if (chain) {
++		ldns_dnssec_data_chain_print_fmt(out, fmt, chain->parent);
++		if (ldns_rr_list_rr_count(chain->rrset) > 0) {
++			rcode = ldns_lookup_by_id(ldns_rcodes,
++								 (int) chain->packet_rcode);
++			if (rcode) {
++				fprintf(out, ";; rcode: %s\n", rcode->name);
++			}
++
++			rr_descriptor = ldns_rr_descript(chain->packet_qtype);
++			if (rr_descriptor && rr_descriptor->_name) {
++				fprintf(out, ";; qtype: %s\n", rr_descriptor->_name);
++			} else if (chain->packet_qtype != 0) {
++				fprintf(out, "TYPE%u", 
++					   chain->packet_qtype);
++			}
++			if (chain->packet_nodata) {
++				fprintf(out, ";; NODATA response\n");
++			}
++			fprintf(out, "rrset:\n");
++			ldns_rr_list_print_fmt(out, fmt, chain->rrset);
++			fprintf(out, "sigs:\n");
++			ldns_rr_list_print_fmt(out, fmt, chain->signatures);
++			fprintf(out, "---\n");
++		} else {
++			fprintf(out, "<no data>\n");
++		}
++	}
++}
++void
++ldns_dnssec_data_chain_print(FILE *out, const ldns_dnssec_data_chain *chain)
++{
++	ldns_dnssec_data_chain_print_fmt(
++			out, ldns_output_format_default, chain);
++}
++
++
++static void
++ldns_dnssec_build_data_chain_dnskey(ldns_resolver *res,
++					    uint16_t qflags,
++					    const ldns_pkt *pkt,
++					    ldns_rr_list *signatures,
++						ldns_dnssec_data_chain *new_chain,
++						ldns_rdf *key_name,
++						ldns_rr_class c) {
++	ldns_rr_list *keys;
++	ldns_pkt *my_pkt;
++	if (signatures && ldns_rr_list_rr_count(signatures) > 0) {
++		new_chain->signatures = ldns_rr_list_clone(signatures);
++		new_chain->parent_type = 0;
++
++		keys = ldns_pkt_rr_list_by_name_and_type(
++				  pkt,
++				 key_name,
++				 LDNS_RR_TYPE_DNSKEY,
++				 LDNS_SECTION_ANY_NOQUESTION
++			  );
++		if (!keys) {
++			my_pkt = ldns_resolver_query(res,
++									key_name,
++									LDNS_RR_TYPE_DNSKEY,
++									c,
++									qflags);
++			if (my_pkt) {
++			keys = ldns_pkt_rr_list_by_name_and_type(
++					  my_pkt,
++					 key_name,
++					 LDNS_RR_TYPE_DNSKEY,
++					 LDNS_SECTION_ANY_NOQUESTION
++				  );
++			new_chain->parent = ldns_dnssec_build_data_chain(res,
++													qflags,
++													keys,
++													my_pkt,
++													NULL);
++			new_chain->parent->packet_qtype = LDNS_RR_TYPE_DNSKEY;
++			ldns_pkt_free(my_pkt);
++			}
++		} else {
++			new_chain->parent = ldns_dnssec_build_data_chain(res,
++													qflags,
++													keys,
++													pkt,
++													NULL);
++			new_chain->parent->packet_qtype = LDNS_RR_TYPE_DNSKEY;
++		}
++		ldns_rr_list_deep_free(keys);
++	}
++}
++
++static void
++ldns_dnssec_build_data_chain_other(ldns_resolver *res,
++					    uint16_t qflags,
++						ldns_dnssec_data_chain *new_chain,
++						ldns_rdf *key_name,
++						ldns_rr_class c,
++						ldns_rr_list *dss)
++{
++	/* 'self-signed', parent is a DS */
++	
++	/* okay, either we have other keys signing the current one,
++	 * or the current
++	 * one should have a DS record in the parent zone.
++	 * How do we find this out? Try both?
++	 *
++	 * request DNSKEYS for current zone,
++	 * add all signatures to current level
++	 */
++	ldns_pkt *my_pkt;
++	ldns_rr_list *signatures2;
++	
++	new_chain->parent_type = 1;
++
++	my_pkt = ldns_resolver_query(res,
++							key_name,
++							LDNS_RR_TYPE_DS,
++							c,
++							qflags);
++	if (my_pkt) {
++	dss = ldns_pkt_rr_list_by_name_and_type(my_pkt,
++									key_name,
++									LDNS_RR_TYPE_DS,
++									LDNS_SECTION_ANY_NOQUESTION
++									);
++	if (dss) {
++		new_chain->parent = ldns_dnssec_build_data_chain(res,
++												qflags,
++												dss,
++												my_pkt,
++												NULL);
++		new_chain->parent->packet_qtype = LDNS_RR_TYPE_DS;
++		ldns_rr_list_deep_free(dss);
++	}
++	ldns_pkt_free(my_pkt);
++	}
++
++	my_pkt = ldns_resolver_query(res,
++							key_name,
++							LDNS_RR_TYPE_DNSKEY,
++							c,
++							qflags);
++	if (my_pkt) {
++	signatures2 = ldns_pkt_rr_list_by_name_and_type(my_pkt,
++										   key_name,
++										   LDNS_RR_TYPE_RRSIG,
++										   LDNS_SECTION_ANSWER);
++	if (signatures2) {
++		if (new_chain->signatures) {
++			printf("There were already sigs!\n");
++			ldns_rr_list_deep_free(new_chain->signatures);
++			printf("replacing the old sigs\n");
++		}
++		new_chain->signatures = signatures2;
++	}
++	ldns_pkt_free(my_pkt);
++	}
++}
++
++static ldns_dnssec_data_chain *
++ldns_dnssec_build_data_chain_nokeyname(ldns_resolver *res,
++                                       uint16_t qflags,
++                                       ldns_rr *orig_rr,
++                                       const ldns_rr_list *rrset,
++                                       ldns_dnssec_data_chain *new_chain)
++{
++	ldns_rdf *possible_parent_name;
++	ldns_pkt *my_pkt;
++	/* apparently we were not able to find a signing key, so
++	   we assume the chain ends here
++	*/
++	/* try parents for auth denial of DS */
++	if (orig_rr) {
++		possible_parent_name = ldns_rr_owner(orig_rr);
++	} else if (rrset && ldns_rr_list_rr_count(rrset) > 0) {
++		possible_parent_name = ldns_rr_owner(ldns_rr_list_rr(rrset, 0));
++	} else {
++		/* no information to go on, give up */
++		return new_chain;
++	}
++
++	my_pkt = ldns_resolver_query(res,
++	              possible_parent_name,
++	              LDNS_RR_TYPE_DS,
++	              LDNS_RR_CLASS_IN,
++	              qflags);
++	if (!my_pkt) {
++		return new_chain;
++	}
++
++	if (ldns_pkt_ancount(my_pkt) > 0) {
++		/* add error, no sigs but DS in parent */
++		/*ldns_pkt_print(stdout, my_pkt);*/
++		ldns_pkt_free(my_pkt);
++	} else {
++		/* are there signatures? */
++		new_chain->parent =  ldns_dnssec_build_data_chain(res, 
++		                          qflags, 
++		                          NULL,
++		                          my_pkt,
++		                          NULL);
++
++		new_chain->parent->packet_qtype = LDNS_RR_TYPE_DS;
++		
++	}
++	return new_chain;
++}
++
++
++ldns_dnssec_data_chain *
++ldns_dnssec_build_data_chain(ldns_resolver *res,
++					    uint16_t qflags,
++					    const ldns_rr_list *rrset,
++					    const ldns_pkt *pkt,
++					    ldns_rr *orig_rr)
++{
++	ldns_rr_list *signatures = NULL;
++	ldns_rr_list *dss = NULL;
++	
++	ldns_rr_list *my_rrset;
++
++	ldns_pkt *my_pkt;
++
++	ldns_rdf *name = NULL, *key_name = NULL;
++	ldns_rr_type type = 0;
++	ldns_rr_class c = 0;
++
++	bool other_rrset = false;
++
++	ldns_dnssec_data_chain *new_chain = ldns_dnssec_data_chain_new();
++
++	assert(pkt != NULL);
++
++	if (!ldns_dnssec_pkt_has_rrsigs(pkt)) {
++		/* hmm. no dnssec data in the packet. go up to try and deny
++		 * DS? */
++		return new_chain;
++	}
++
++	if (orig_rr) {
++		new_chain->rrset = ldns_rr_list_new();
++		ldns_rr_list_push_rr(new_chain->rrset, orig_rr);
++		new_chain->parent = ldns_dnssec_build_data_chain(res,
++											    qflags,
++											    rrset,
++											    pkt,
++											    NULL);
++		new_chain->packet_rcode = ldns_pkt_get_rcode(pkt);
++		new_chain->packet_qtype = ldns_rr_get_type(orig_rr);
++		if (ldns_pkt_ancount(pkt) == 0) {
++			new_chain->packet_nodata = true;
++		}
++		return new_chain;
++	}
++	
++	if (!rrset || ldns_rr_list_rr_count(rrset) < 1) {
++		/* hmm, no data, do we have denial? only works if pkt was given,
++		   otherwise caller has to do the check himself */
++		new_chain->packet_nodata = true;
++		if (pkt) {
++			my_rrset = ldns_pkt_rr_list_by_type(pkt,
++										 LDNS_RR_TYPE_NSEC,
++										 LDNS_SECTION_ANY_NOQUESTION
++										 );
++			if (my_rrset) {
++				if (ldns_rr_list_rr_count(my_rrset) > 0) {
++					type = LDNS_RR_TYPE_NSEC;
++					other_rrset = true;
++				} else {
++					ldns_rr_list_deep_free(my_rrset);
++					my_rrset = NULL;
++				}
++			} else {
++				/* nothing, try nsec3 */
++				my_rrset = ldns_pkt_rr_list_by_type(pkt,
++						     LDNS_RR_TYPE_NSEC3,
++							LDNS_SECTION_ANY_NOQUESTION);
++				if (my_rrset) {
++					if (ldns_rr_list_rr_count(my_rrset) > 0) {
++						type = LDNS_RR_TYPE_NSEC3;
++						other_rrset = true;
++					} else {
++						ldns_rr_list_deep_free(my_rrset);
++						my_rrset = NULL;
++					}
++				} else {
++					/* nothing, stop */
++					/* try parent zone? for denied insecure? */
++					return new_chain;
++				}
++			}
++		} else {
++			return new_chain;
++		}
++	} else {
++		my_rrset = (ldns_rr_list *) rrset;
++	}
++	
++	if (my_rrset && ldns_rr_list_rr_count(my_rrset) > 0) {
++		new_chain->rrset = ldns_rr_list_clone(my_rrset);
++		name = ldns_rr_owner(ldns_rr_list_rr(my_rrset, 0));
++		type = ldns_rr_get_type(ldns_rr_list_rr(my_rrset, 0));
++		c = ldns_rr_get_class(ldns_rr_list_rr(my_rrset, 0));
++	}
++	
++	if (other_rrset) {
++		ldns_rr_list_deep_free(my_rrset);
++	}
++	
++	/* normally there will only be 1 signature 'set'
++	   but there can be more than 1 denial (wildcards)
++	   so check for NSEC
++	*/
++	if (type == LDNS_RR_TYPE_NSEC || type == LDNS_RR_TYPE_NSEC3) {
++		/* just throw in all signatures, the tree builder must sort
++		   this out */
++		if (pkt) {
++			signatures = ldns_dnssec_pkt_get_rrsigs_for_type(pkt, type);
++		} else {
++			my_pkt = ldns_resolver_query(res, name, type, c, qflags);
++			if (my_pkt) {
++			signatures = ldns_dnssec_pkt_get_rrsigs_for_type(pkt, type);
++			ldns_pkt_free(my_pkt);
++			}
++		}
++	} else {
++		if (pkt) {
++			signatures =
++				ldns_dnssec_pkt_get_rrsigs_for_name_and_type(pkt,
++													name,
++													type);
++		}
++		if (!signatures) {
++			my_pkt = ldns_resolver_query(res, name, type, c, qflags);
++			if (my_pkt) {
++			signatures =
++				ldns_dnssec_pkt_get_rrsigs_for_name_and_type(my_pkt,
++													name,
++													type);
++			ldns_pkt_free(my_pkt);
++			}
++		}
++	}
++
++	if (signatures && ldns_rr_list_rr_count(signatures) > 0) {
++		key_name = ldns_rr_rdf(ldns_rr_list_rr(signatures, 0), 7);
++	}
++	if (!key_name) {
++		if (signatures) {
++			ldns_rr_list_deep_free(signatures);
++		}
++		return ldns_dnssec_build_data_chain_nokeyname(res,
++		                                              qflags,
++		                                              orig_rr,
++		                                              rrset,
++		                                              new_chain);
++	}
++	if (type != LDNS_RR_TYPE_DNSKEY) {
++		ldns_dnssec_build_data_chain_dnskey(res,
++		                                    qflags,
++		                                    pkt,
++		                                    signatures,
++		                                    new_chain,
++		                                    key_name,
++		                                    c
++		                                   );
++	} else {
++		ldns_dnssec_build_data_chain_other(res,
++		                                   qflags,
++		                                   new_chain,
++		                                   key_name,
++		                                   c,
++		                                   dss
++		                                  );
++	}
++	if (signatures) {
++		ldns_rr_list_deep_free(signatures);
++	}
++	return new_chain;
++}
++
++ldns_dnssec_trust_tree *
++ldns_dnssec_trust_tree_new(void)
++{
++	ldns_dnssec_trust_tree *new_tree = LDNS_XMALLOC(ldns_dnssec_trust_tree,
++										   1);
++        if(!new_tree) return NULL;
++	new_tree->rr = NULL;
++	new_tree->rrset = NULL;
++	new_tree->parent_count = 0;
++
++	return new_tree;
++}
++
++void
++ldns_dnssec_trust_tree_free(ldns_dnssec_trust_tree *tree)
++{
++	size_t i;
++	if (tree) {
++		for (i = 0; i < tree->parent_count; i++) {
++			ldns_dnssec_trust_tree_free(tree->parents[i]);
++		}
++	}
++	LDNS_FREE(tree);
++}
++
++size_t
++ldns_dnssec_trust_tree_depth(ldns_dnssec_trust_tree *tree)
++{
++	size_t result = 0;
++	size_t parent = 0;
++	size_t i;
++	
++	for (i = 0; i < tree->parent_count; i++) {
++		parent = ldns_dnssec_trust_tree_depth(tree->parents[i]);
++		if (parent > result) {
++			result = parent;
++		}
++	}
++	return 1 + result;
++}
++
++/* TODO ldns_ */
++static void
++print_tabs(FILE *out, size_t nr, uint8_t *map, size_t treedepth)
++{
++	size_t i;
++	for (i = 0; i < nr; i++) {
++		if (i == nr - 1) {
++			fprintf(out, "|---");
++		} else if (map && i < treedepth && map[i] == 1) {
++			fprintf(out, "|   ");
++		} else {
++			fprintf(out, "    ");
++		}
++	}
++}
++
++static void
++ldns_dnssec_trust_tree_print_sm_fmt(FILE *out, 
++		const ldns_output_format *fmt,
++		ldns_dnssec_trust_tree *tree,
++		size_t tabs,
++		bool extended,
++		uint8_t *sibmap,
++		size_t treedepth)
++{
++	size_t i;
++	const ldns_rr_descriptor *descriptor;
++	bool mapset = false;
++	
++	if (!sibmap) {
++		treedepth = ldns_dnssec_trust_tree_depth(tree);
++		sibmap = LDNS_XMALLOC(uint8_t, treedepth);
++                if(!sibmap)
++                        return; /* mem err */
++		memset(sibmap, 0, treedepth);
++		mapset = true;
++	}
++	
++	if (tree) {
++		if (tree->rr) {
++			print_tabs(out, tabs, sibmap, treedepth);
++			ldns_rdf_print(out, ldns_rr_owner(tree->rr));
++			descriptor = ldns_rr_descript(ldns_rr_get_type(tree->rr));
++
++			if (descriptor->_name) {
++				fprintf(out, " (%s", descriptor->_name);
++			} else {
++				fprintf(out, " (TYPE%d", 
++					   ldns_rr_get_type(tree->rr));
++			}
++			if (tabs > 0) {
++				if (ldns_rr_get_type(tree->rr) == LDNS_RR_TYPE_DNSKEY) {
++					fprintf(out, " keytag: %u",
++					        (unsigned int) ldns_calc_keytag(tree->rr));
++					fprintf(out, " alg: ");
++					ldns_rdf_print(out, ldns_rr_rdf(tree->rr, 2));
++					fprintf(out, " flags: ");
++					ldns_rdf_print(out, ldns_rr_rdf(tree->rr, 0));
++				} else if (ldns_rr_get_type(tree->rr) == LDNS_RR_TYPE_DS) {
++					fprintf(out, " keytag: ");
++					ldns_rdf_print(out, ldns_rr_rdf(tree->rr, 0));
++					fprintf(out, " digest type: ");
++					ldns_rdf_print(out, ldns_rr_rdf(tree->rr, 2));
++				}
++				if (ldns_rr_get_type(tree->rr) == LDNS_RR_TYPE_NSEC) {
++					fprintf(out, " ");
++					ldns_rdf_print(out, ldns_rr_rdf(tree->rr, 0));
++					fprintf(out, " ");
++					ldns_rdf_print(out, ldns_rr_rdf(tree->rr, 1));
++				}
++			}
++			
++			fprintf(out, ")\n");
++			for (i = 0; i < tree->parent_count; i++) {
++				if (tree->parent_count > 1 && i < tree->parent_count - 1) {
++					sibmap[tabs] = 1;
++				} else {
++					sibmap[tabs] = 0;
++				}
++				/* only print errors */
++				if (ldns_rr_get_type(tree->parents[i]->rr) == 
++				    LDNS_RR_TYPE_NSEC ||
++				    ldns_rr_get_type(tree->parents[i]->rr) ==
++				    LDNS_RR_TYPE_NSEC3) {
++					if (tree->parent_status[i] == LDNS_STATUS_OK) {
++						print_tabs(out, tabs + 1, sibmap, treedepth);
++						if (tabs == 0 &&
++						    ldns_rr_get_type(tree->rr) == LDNS_RR_TYPE_NS &&
++							ldns_rr_rd_count(tree->rr) > 0) {
++							fprintf(out, "Existence of DS is denied by:\n");
++						} else {
++							fprintf(out, "Existence is denied by:\n");
++						}
++					} else {
++						/* NS records aren't signed */
++						if (ldns_rr_get_type(tree->rr) == LDNS_RR_TYPE_NS) {
++							fprintf(out, "Existence of DS is denied by:\n");
++						} else {
++							print_tabs(out, tabs + 1, sibmap, treedepth);
++							fprintf(out,
++								   "Error in denial of existence: %s\n",
++								   ldns_get_errorstr_by_id(
++									   tree->parent_status[i]));
++						}
++					}
++				} else
++					if (tree->parent_status[i] != LDNS_STATUS_OK) {
++						print_tabs(out, tabs + 1, sibmap, treedepth);
++						fprintf(out,
++							   "%s:\n",
++							   ldns_get_errorstr_by_id(
++							       tree->parent_status[i]));
++						if (tree->parent_status[i]
++						    == LDNS_STATUS_SSL_ERR) {
++							printf("; SSL Error: ");
++							ERR_load_crypto_strings();
++							ERR_print_errors_fp(stdout);
++							printf("\n");
++						}
++						ldns_rr_print_fmt(out, fmt, 
++							tree->
++							parent_signature[i]);
++						printf("For RRset:\n");
++						ldns_rr_list_print_fmt(out, fmt,
++								tree->rrset);
++						printf("With key:\n");
++						ldns_rr_print_fmt(out, fmt,
++							tree->parents[i]->rr);
++					}
++				ldns_dnssec_trust_tree_print_sm_fmt(out, fmt,
++						tree->parents[i],
++						tabs+1,
++						extended,
++						sibmap,
++						treedepth);
++			}
++		} else {
++			print_tabs(out, tabs, sibmap, treedepth);
++			fprintf(out, "<no data>\n");
++		}
++	} else {
++		fprintf(out, "<null pointer>\n");
++	}
++	
++	if (mapset) {
++		LDNS_FREE(sibmap);
++	}
++}
++
++void
++ldns_dnssec_trust_tree_print_fmt(FILE *out, const ldns_output_format *fmt,
++		ldns_dnssec_trust_tree *tree,
++		size_t tabs,
++		bool extended)
++{
++	ldns_dnssec_trust_tree_print_sm_fmt(out, fmt, 
++			tree, tabs, extended, NULL, 0);
++}
++
++void
++ldns_dnssec_trust_tree_print(FILE *out,
++		ldns_dnssec_trust_tree *tree,
++		size_t tabs,
++		bool extended)
++{
++	ldns_dnssec_trust_tree_print_fmt(out, ldns_output_format_default, 
++			tree, tabs, extended);
++}
++
++
++ldns_status
++ldns_dnssec_trust_tree_add_parent(ldns_dnssec_trust_tree *tree,
++                                  const ldns_dnssec_trust_tree *parent,
++                                  const ldns_rr *signature,
++                                  const ldns_status parent_status)
++{
++	if (tree
++	    && parent
++	    && tree->parent_count < LDNS_DNSSEC_TRUST_TREE_MAX_PARENTS) {
++		/*
++		  printf("Add parent for: ");
++		  ldns_rr_print(stdout, tree->rr);
++		  printf("parent: ");
++		  ldns_rr_print(stdout, parent->rr);
++		*/
++		tree->parents[tree->parent_count] =
++			(ldns_dnssec_trust_tree *) parent;
++		tree->parent_status[tree->parent_count] = parent_status;
++		tree->parent_signature[tree->parent_count] = (ldns_rr *) signature;
++		tree->parent_count++;
++		return LDNS_STATUS_OK;
++	} else {
++		return LDNS_STATUS_ERR;
++	}
++}
++
++/* if rr is null, take the first from the rrset */
++ldns_dnssec_trust_tree *
++ldns_dnssec_derive_trust_tree_time(
++		ldns_dnssec_data_chain *data_chain, 
++		ldns_rr *rr, 
++		time_t check_time
++		)
++{
++	ldns_rr_list *cur_rrset;
++	ldns_rr_list *cur_sigs;
++	ldns_rr *cur_rr = NULL;
++	ldns_rr *cur_sig_rr;
++	size_t i, j;
++
++	ldns_dnssec_trust_tree *new_tree = ldns_dnssec_trust_tree_new();
++        if(!new_tree)
++                return NULL;
++	
++	if (data_chain && data_chain->rrset) {
++		cur_rrset = data_chain->rrset;
++	
++		cur_sigs = data_chain->signatures;
++
++		if (rr) {
++			cur_rr = rr;
++		}
++
++		if (!cur_rr && ldns_rr_list_rr_count(cur_rrset) > 0) {
++			cur_rr = ldns_rr_list_rr(cur_rrset, 0);
++		}
++
++		if (cur_rr) {
++			new_tree->rr = cur_rr;
++			new_tree->rrset = cur_rrset;
++			/* there are three possibilities:
++			   1 - 'normal' rrset, signed by a key
++			   2 - dnskey signed by other dnskey
++			   3 - dnskey proven by higher level DS
++			   (data denied by nsec is a special case that can
++			   occur in multiple places)
++				   
++			*/
++			if (cur_sigs) {
++				for (i = 0; i < ldns_rr_list_rr_count(cur_sigs); i++) {
++					/* find the appropriate key in the parent list */
++					cur_sig_rr = ldns_rr_list_rr(cur_sigs, i);
++
++					if (ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_NSEC) {
++						if (ldns_dname_compare(ldns_rr_owner(cur_sig_rr),
++										   ldns_rr_owner(cur_rr)))
++							{
++								/* find first that does match */
++
++								for (j = 0;
++								     j < ldns_rr_list_rr_count(cur_rrset) && 
++										ldns_dname_compare(ldns_rr_owner(cur_sig_rr),ldns_rr_owner(cur_rr)) != 0;
++								     j++) {
++									cur_rr = ldns_rr_list_rr(cur_rrset, j);
++									
++								}
++								if (ldns_dname_compare(ldns_rr_owner(cur_sig_rr), 
++												   ldns_rr_owner(cur_rr)))
++									{
++										break;
++									}
++							}
++							
++					}
++					/* option 1 */
++					if (data_chain->parent) {
++						ldns_dnssec_derive_trust_tree_normal_rrset_time(
++						    new_tree,
++						    data_chain,
++						    cur_sig_rr,
++						    check_time);
++					}
++
++					/* option 2 */
++					ldns_dnssec_derive_trust_tree_dnskey_rrset_time(
++					    new_tree,
++					    data_chain,
++					    cur_rr,
++					    cur_sig_rr,
++					    check_time);
++				}
++					
++				ldns_dnssec_derive_trust_tree_ds_rrset_time(
++						new_tree, data_chain, 
++						cur_rr, check_time);
++			} else {
++				/* no signatures? maybe it's nsec data */
++					
++				/* just add every rr from parent as new parent */
++				ldns_dnssec_derive_trust_tree_no_sig_time(
++					new_tree, data_chain, check_time);
++			}
++		}
++	}
++
++	return new_tree;
++}
++
++ldns_dnssec_trust_tree *
++ldns_dnssec_derive_trust_tree(ldns_dnssec_data_chain *data_chain, ldns_rr *rr)
++{
++	return ldns_dnssec_derive_trust_tree_time(data_chain, rr, ldns_time(NULL));
++}
++
++void
++ldns_dnssec_derive_trust_tree_normal_rrset_time(
++		ldns_dnssec_trust_tree *new_tree, 
++		ldns_dnssec_data_chain *data_chain, 
++		ldns_rr *cur_sig_rr,
++		time_t check_time)
++{
++	size_t i, j;
++	ldns_rr_list *cur_rrset = ldns_rr_list_clone(data_chain->rrset); 
++	ldns_dnssec_trust_tree *cur_parent_tree;
++	ldns_rr *cur_parent_rr;
++	uint16_t cur_keytag;
++	ldns_rr_list *tmp_rrset = NULL;
++	ldns_status cur_status;
++
++	cur_keytag = ldns_rdf2native_int16(ldns_rr_rrsig_keytag(cur_sig_rr));
++	
++	for (j = 0; j < ldns_rr_list_rr_count(data_chain->parent->rrset); j++) {
++		cur_parent_rr = ldns_rr_list_rr(data_chain->parent->rrset, j);
++		if (ldns_rr_get_type(cur_parent_rr) == LDNS_RR_TYPE_DNSKEY) {
++			if (ldns_calc_keytag(cur_parent_rr) == cur_keytag) {
++
++				/* TODO: check wildcard nsec too */
++				if (cur_rrset && ldns_rr_list_rr_count(cur_rrset) > 0) {
++					tmp_rrset = cur_rrset;
++					if (ldns_rr_get_type(ldns_rr_list_rr(cur_rrset, 0))
++					    == LDNS_RR_TYPE_NSEC ||
++					    ldns_rr_get_type(ldns_rr_list_rr(cur_rrset, 0))
++					    == LDNS_RR_TYPE_NSEC3) {
++						/* might contain different names! 
++						   sort and split */
++						ldns_rr_list_sort(cur_rrset);
++						assert(tmp_rrset == cur_rrset);
++						tmp_rrset = ldns_rr_list_pop_rrset(cur_rrset);
++						
++						/* with nsecs, this might be the wrong one */
++						while (tmp_rrset &&
++						       ldns_rr_list_rr_count(cur_rrset) > 0 &&
++						       ldns_dname_compare(
++								ldns_rr_owner(ldns_rr_list_rr(
++										        tmp_rrset, 0)),
++								ldns_rr_owner(cur_sig_rr)) != 0) {
++							ldns_rr_list_deep_free(tmp_rrset);
++							tmp_rrset =
++								ldns_rr_list_pop_rrset(cur_rrset);
++						}
++					}
++					cur_status = ldns_verify_rrsig_time(
++							tmp_rrset, 
++							cur_sig_rr, 
++							cur_parent_rr,
++							check_time);
++					if (tmp_rrset && tmp_rrset != cur_rrset
++							) {
++						ldns_rr_list_deep_free(
++								tmp_rrset);
++						tmp_rrset = NULL;
++					}
++					/* avoid dupes */
++					for (i = 0; i < new_tree->parent_count; i++) {
++						if (cur_parent_rr == new_tree->parents[i]->rr) {
++							goto done;
++						}
++					}
++
++					cur_parent_tree =
++						ldns_dnssec_derive_trust_tree_time(
++								data_chain->parent,
++						                cur_parent_rr,
++								check_time);
++					(void)ldns_dnssec_trust_tree_add_parent(new_tree,
++					           cur_parent_tree,
++					           cur_sig_rr,
++					           cur_status);
++				}
++			}
++		}
++	}
++ done:
++	ldns_rr_list_deep_free(cur_rrset);
++}
++
++void
++ldns_dnssec_derive_trust_tree_normal_rrset(ldns_dnssec_trust_tree *new_tree,
++                                           ldns_dnssec_data_chain *data_chain,
++                                           ldns_rr *cur_sig_rr)
++{
++	ldns_dnssec_derive_trust_tree_normal_rrset_time(
++			new_tree, data_chain, cur_sig_rr, ldns_time(NULL));
++}
++
++void
++ldns_dnssec_derive_trust_tree_dnskey_rrset_time(
++		ldns_dnssec_trust_tree *new_tree, 
++		ldns_dnssec_data_chain *data_chain, 
++		ldns_rr *cur_rr, 
++		ldns_rr *cur_sig_rr,
++		time_t check_time)
++{
++	size_t j;
++	ldns_rr_list *cur_rrset = data_chain->rrset;
++	ldns_dnssec_trust_tree *cur_parent_tree;
++	ldns_rr *cur_parent_rr;
++	uint16_t cur_keytag;
++	ldns_status cur_status;
++
++	cur_keytag = ldns_rdf2native_int16(ldns_rr_rrsig_keytag(cur_sig_rr));
++
++	for (j = 0; j < ldns_rr_list_rr_count(cur_rrset); j++) {
++		cur_parent_rr = ldns_rr_list_rr(cur_rrset, j);
++		if (cur_parent_rr != cur_rr &&
++		    ldns_rr_get_type(cur_parent_rr) == LDNS_RR_TYPE_DNSKEY) {
++			if (ldns_calc_keytag(cur_parent_rr) == cur_keytag
++			    ) {
++				cur_parent_tree = ldns_dnssec_trust_tree_new();
++				cur_parent_tree->rr = cur_parent_rr;
++				cur_parent_tree->rrset = cur_rrset;
++				cur_status = ldns_verify_rrsig_time(
++						cur_rrset, cur_sig_rr, 
++						cur_parent_rr, check_time);
++				(void) ldns_dnssec_trust_tree_add_parent(new_tree,
++				            cur_parent_tree, cur_sig_rr, cur_status);
++			}
++		}
++	}
++}
++
++void
++ldns_dnssec_derive_trust_tree_dnskey_rrset(ldns_dnssec_trust_tree *new_tree,
++                                           ldns_dnssec_data_chain *data_chain,
++                                           ldns_rr *cur_rr,
++                                           ldns_rr *cur_sig_rr)
++{
++	ldns_dnssec_derive_trust_tree_dnskey_rrset_time(
++			new_tree, data_chain, cur_rr, cur_sig_rr, ldns_time(NULL));
++}
++
++void
++ldns_dnssec_derive_trust_tree_ds_rrset_time(
++		ldns_dnssec_trust_tree *new_tree,
++		ldns_dnssec_data_chain *data_chain, 
++		ldns_rr *cur_rr,
++		time_t check_time)
++{
++	size_t j, h;
++	ldns_rr_list *cur_rrset = data_chain->rrset;
++	ldns_dnssec_trust_tree *cur_parent_tree;
++	ldns_rr *cur_parent_rr;
++
++	/* try the parent to see whether there are DSs there */
++	if (ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_DNSKEY &&
++	    data_chain->parent &&
++	    data_chain->parent->rrset
++	    ) {
++		for (j = 0;
++			j < ldns_rr_list_rr_count(data_chain->parent->rrset);
++			j++) {
++			cur_parent_rr = ldns_rr_list_rr(data_chain->parent->rrset, j);
++			if (ldns_rr_get_type(cur_parent_rr) == LDNS_RR_TYPE_DS) {
++				for (h = 0; h < ldns_rr_list_rr_count(cur_rrset); h++) {
++					cur_rr = ldns_rr_list_rr(cur_rrset, h);
++					if (ldns_rr_compare_ds(cur_rr, cur_parent_rr)) {
++						cur_parent_tree =
++							ldns_dnssec_derive_trust_tree_time(
++							    data_chain->parent, 
++							    cur_parent_rr,
++							    check_time);
++						(void) ldns_dnssec_trust_tree_add_parent(
++						            new_tree,
++						            cur_parent_tree,
++						            NULL,
++						            LDNS_STATUS_OK);
++					} else {
++						/*ldns_rr_print(stdout, cur_parent_rr);*/
++					}
++				}
++			}
++		}
++	}
++}
++
++void
++ldns_dnssec_derive_trust_tree_ds_rrset(ldns_dnssec_trust_tree *new_tree,
++                                       ldns_dnssec_data_chain *data_chain,
++                                       ldns_rr *cur_rr)
++{
++	ldns_dnssec_derive_trust_tree_ds_rrset_time(
++			new_tree, data_chain, cur_rr, ldns_time(NULL));
++}
++
++void
++ldns_dnssec_derive_trust_tree_no_sig_time(
++		ldns_dnssec_trust_tree *new_tree, 
++		ldns_dnssec_data_chain *data_chain,
++		time_t check_time)
++{
++	size_t i;
++	ldns_rr_list *cur_rrset;
++	ldns_rr *cur_parent_rr;
++	ldns_dnssec_trust_tree *cur_parent_tree;
++	ldns_status result;
++	
++	if (data_chain->parent && data_chain->parent->rrset) {
++		cur_rrset = data_chain->parent->rrset;
++		/* nsec? */
++		if (cur_rrset && ldns_rr_list_rr_count(cur_rrset) > 0) {
++			if (ldns_rr_get_type(ldns_rr_list_rr(cur_rrset, 0)) ==
++			    LDNS_RR_TYPE_NSEC3) {
++				result = ldns_dnssec_verify_denial_nsec3(
++					        new_tree->rr,
++						   cur_rrset,
++						   data_chain->parent->signatures,
++						   data_chain->packet_rcode,
++						   data_chain->packet_qtype,
++						   data_chain->packet_nodata);
++			} else if (ldns_rr_get_type(ldns_rr_list_rr(cur_rrset, 0)) ==
++					 LDNS_RR_TYPE_NSEC) {
++				result = ldns_dnssec_verify_denial(
++					        new_tree->rr,
++						   cur_rrset,
++						   data_chain->parent->signatures);
++			} else {
++				/* unsigned zone, unsigned parent */
++				result = LDNS_STATUS_OK;
++			}
++		} else {
++			result = LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED;
++		}
++		for (i = 0; i < ldns_rr_list_rr_count(cur_rrset); i++) {
++			cur_parent_rr = ldns_rr_list_rr(cur_rrset, i);
++			cur_parent_tree = 
++				ldns_dnssec_derive_trust_tree_time(
++						data_chain->parent, 
++						cur_parent_rr,
++						check_time);
++			(void) ldns_dnssec_trust_tree_add_parent(new_tree,
++			            cur_parent_tree, NULL, result);
++		}
++	}
++}
++
++void
++ldns_dnssec_derive_trust_tree_no_sig(ldns_dnssec_trust_tree *new_tree,
++                                     ldns_dnssec_data_chain *data_chain)
++{
++	ldns_dnssec_derive_trust_tree_no_sig_time(
++			new_tree, data_chain, ldns_time(NULL));
++}
++
++/*
++ * returns OK if there is a path from tree to key with only OK
++ * the (first) error in between otherwise
++ * or NOT_FOUND if the key wasn't present at all
++ */
++ldns_status
++ldns_dnssec_trust_tree_contains_keys(ldns_dnssec_trust_tree *tree,
++							  ldns_rr_list *trusted_keys)
++{
++	size_t i;
++	ldns_status result = LDNS_STATUS_CRYPTO_NO_DNSKEY;
++	bool equal;
++	ldns_status parent_result;
++	
++	if (tree && trusted_keys && ldns_rr_list_rr_count(trusted_keys) > 0)
++		{ if (tree->rr) {
++				for (i = 0; i < ldns_rr_list_rr_count(trusted_keys); i++) {
++					equal = ldns_rr_compare_ds(
++							  tree->rr,
++							  ldns_rr_list_rr(trusted_keys, i));
++					if (equal) {
++						result = LDNS_STATUS_OK;
++						return result;
++					}
++				}
++			}
++			for (i = 0; i < tree->parent_count; i++) {
++				parent_result =
++					ldns_dnssec_trust_tree_contains_keys(tree->parents[i],
++												  trusted_keys);
++				if (parent_result != LDNS_STATUS_CRYPTO_NO_DNSKEY) {
++					if (tree->parent_status[i] != LDNS_STATUS_OK) {
++						result = tree->parent_status[i];
++					} else {
++						if (tree->rr &&
++						    ldns_rr_get_type(tree->rr)
++						    == LDNS_RR_TYPE_NSEC &&
++						    parent_result == LDNS_STATUS_OK
++						    ) {
++							result =
++								LDNS_STATUS_DNSSEC_EXISTENCE_DENIED;
++						} else {
++							result = parent_result;
++						}
++					}
++				}
++			}
++		} else {
++		result = LDNS_STATUS_ERR;
++	}
++	
++	return result;
++}
++
++ldns_status
++ldns_verify_time(
++		ldns_rr_list *rrset,
++		ldns_rr_list *rrsig, 
++		const ldns_rr_list *keys, 
++		time_t check_time,
++		ldns_rr_list *good_keys
++		)
++{
++	uint16_t i;
++	ldns_status verify_result = LDNS_STATUS_ERR;
++
++	if (!rrset || !rrsig || !keys) {
++		return LDNS_STATUS_ERR;
++	}
++
++	if (ldns_rr_list_rr_count(rrset) < 1) {
++		return LDNS_STATUS_ERR;
++	}
++
++	if (ldns_rr_list_rr_count(rrsig) < 1) {
++		return LDNS_STATUS_CRYPTO_NO_RRSIG;
++	}
++	
++	if (ldns_rr_list_rr_count(keys) < 1) {
++		verify_result = LDNS_STATUS_CRYPTO_NO_TRUSTED_DNSKEY;
++	} else {
++		for (i = 0; i < ldns_rr_list_rr_count(rrsig); i++) {
++			ldns_status s = ldns_verify_rrsig_keylist_time(
++					rrset, ldns_rr_list_rr(rrsig, i), 
++					keys, check_time, good_keys);
++			/* try a little to get more descriptive error */
++			if(s == LDNS_STATUS_OK) {
++				verify_result = LDNS_STATUS_OK;
++			} else if(verify_result == LDNS_STATUS_ERR)
++				verify_result = s;
++			else if(s !=  LDNS_STATUS_ERR && verify_result ==
++				LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY)
++				verify_result = s;
++		}
++	}
++	return verify_result;
++}
++
++ldns_status
++ldns_verify(ldns_rr_list *rrset, ldns_rr_list *rrsig, const ldns_rr_list *keys, 
++		  ldns_rr_list *good_keys)
++{
++	return ldns_verify_time(rrset, rrsig, keys, ldns_time(NULL), good_keys);
++}
++
++ldns_status
++ldns_verify_notime(ldns_rr_list *rrset, ldns_rr_list *rrsig,
++	const ldns_rr_list *keys, ldns_rr_list *good_keys)
++{
++	uint16_t i;
++	ldns_status verify_result = LDNS_STATUS_ERR;
++
++	if (!rrset || !rrsig || !keys) {
++		return LDNS_STATUS_ERR;
++	}
++
++	if (ldns_rr_list_rr_count(rrset) < 1) {
++		return LDNS_STATUS_ERR;
++	}
++
++	if (ldns_rr_list_rr_count(rrsig) < 1) {
++		return LDNS_STATUS_CRYPTO_NO_RRSIG;
++	}
++
++	if (ldns_rr_list_rr_count(keys) < 1) {
++		verify_result = LDNS_STATUS_CRYPTO_NO_TRUSTED_DNSKEY;
++	} else {
++		for (i = 0; i < ldns_rr_list_rr_count(rrsig); i++) {
++			ldns_status s = ldns_verify_rrsig_keylist_notime(rrset,
++				ldns_rr_list_rr(rrsig, i), keys, good_keys);
++
++			/* try a little to get more descriptive error */
++			if (s == LDNS_STATUS_OK) {
++				verify_result = LDNS_STATUS_OK;
++			} else if (verify_result == LDNS_STATUS_ERR) {
++				verify_result = s;
++			} else if (s !=  LDNS_STATUS_ERR && verify_result ==
++				LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY) {
++				verify_result = s;
++			}
++		}
++	}
++	return verify_result;
++}
++
++ldns_rr_list *
++ldns_fetch_valid_domain_keys_time(const ldns_resolver *res,
++                             const ldns_rdf *domain,
++                             const ldns_rr_list *keys,
++			     time_t check_time,
++                             ldns_status *status)
++{
++	ldns_rr_list * trusted_keys = NULL;
++	ldns_rr_list * ds_keys = NULL;
++	ldns_rdf * prev_parent_domain;
++	ldns_rdf *      parent_domain;
++	ldns_rr_list * parent_keys = NULL;
++
++	if (res && domain && keys) {
++
++		if ((trusted_keys = ldns_validate_domain_dnskey_time(res,
++                                         domain, keys, check_time))) {
++			*status = LDNS_STATUS_OK;
++		} else {
++			/* No trusted keys in this domain, we'll have to find some in the parent domain */
++			*status = LDNS_STATUS_CRYPTO_NO_TRUSTED_DNSKEY;
++
++			parent_domain = ldns_dname_left_chop(domain);
++			while (parent_domain && /* Fail if we are at the root*/
++					ldns_rdf_size(parent_domain) > 0) {
++	
++				if ((parent_keys = 
++					ldns_fetch_valid_domain_keys_time(res,
++					     parent_domain,
++					     keys,
++					     check_time,
++					     status))) {
++					/* Check DS records */
++					if ((ds_keys =
++						ldns_validate_domain_ds_time(res,
++						     domain,
++						     parent_keys,
++						     check_time))) {
++						trusted_keys =
++						ldns_fetch_valid_domain_keys_time(
++								res, 
++								domain, 
++								ds_keys, 
++								check_time,
++								status);
++						ldns_rr_list_deep_free(ds_keys);
++					} else {
++						/* No valid DS at the parent -- fail */
++						*status = LDNS_STATUS_CRYPTO_NO_TRUSTED_DS ;
++					}
++					ldns_rr_list_deep_free(parent_keys);
++					break;
++				} else {
++					parent_domain = ldns_dname_left_chop((
++						prev_parent_domain 
++							= parent_domain
++						));
++					ldns_rdf_deep_free(prev_parent_domain);
++				}
++			}
++			if (parent_domain) {
++				ldns_rdf_deep_free(parent_domain);
++			}
++		}
++	}
++	return trusted_keys;
++}
++
++ldns_rr_list *
++ldns_fetch_valid_domain_keys(const ldns_resolver *res,
++                             const ldns_rdf *domain,
++                             const ldns_rr_list *keys,
++                             ldns_status *status)
++{
++	return ldns_fetch_valid_domain_keys_time(
++			res, domain, keys, ldns_time(NULL), status);
++}
++
++ldns_rr_list *
++ldns_validate_domain_dnskey_time(
++		const ldns_resolver * res,
++		const ldns_rdf * domain,
++		const ldns_rr_list * keys,
++		time_t check_time
++		)
++{
++	ldns_pkt * keypkt;
++	ldns_rr * cur_key;
++	uint16_t key_i; uint16_t key_j; uint16_t key_k;
++	uint16_t sig_i; ldns_rr * cur_sig;
++
++	ldns_rr_list * domain_keys = NULL;
++	ldns_rr_list * domain_sigs = NULL;
++	ldns_rr_list * trusted_keys = NULL;
++
++	/* Fetch keys for the domain */
++	keypkt = ldns_resolver_query(res, domain,
++		LDNS_RR_TYPE_DNSKEY, LDNS_RR_CLASS_IN, LDNS_RD);
++	if (keypkt) {
++		domain_keys = ldns_pkt_rr_list_by_type(keypkt,
++									    LDNS_RR_TYPE_DNSKEY,
++									    LDNS_SECTION_ANSWER);
++		domain_sigs = ldns_pkt_rr_list_by_type(keypkt,
++									    LDNS_RR_TYPE_RRSIG,
++									    LDNS_SECTION_ANSWER);
++
++		/* Try to validate the record using our keys */
++		for (key_i=0; key_i< ldns_rr_list_rr_count(domain_keys); key_i++) {
++      
++			cur_key = ldns_rr_list_rr(domain_keys, key_i);
++			for (key_j=0; key_j<ldns_rr_list_rr_count(keys); key_j++) {
++				if (ldns_rr_compare_ds(ldns_rr_list_rr(keys, key_j),
++								   cur_key)) {
++          
++					/* Current key is trusted -- validate */
++					trusted_keys = ldns_rr_list_new();
++          
++					for (sig_i=0;
++						sig_i<ldns_rr_list_rr_count(domain_sigs);
++						sig_i++) {
++						cur_sig = ldns_rr_list_rr(domain_sigs, sig_i);
++						/* Avoid non-matching sigs */
++						if (ldns_rdf2native_int16(
++							   ldns_rr_rrsig_keytag(cur_sig))
++						    == ldns_calc_keytag(cur_key)) {
++							if (ldns_verify_rrsig_time(
++									domain_keys,
++									cur_sig,
++									cur_key,
++									check_time)
++							    == LDNS_STATUS_OK) {
++                
++								/* Push the whole rrset 
++								   -- we can't do much more */
++								for (key_k=0;
++									key_k<ldns_rr_list_rr_count(
++											domain_keys);
++									key_k++) {
++									ldns_rr_list_push_rr(
++									    trusted_keys,
++									    ldns_rr_clone(
++										   ldns_rr_list_rr(
++											  domain_keys,
++											  key_k)));
++								}
++                
++								ldns_rr_list_deep_free(domain_keys);
++								ldns_rr_list_deep_free(domain_sigs);
++								ldns_pkt_free(keypkt);
++								return trusted_keys;
++							}
++						}
++					}
++	  
++					/* Only push our trusted key */
++					ldns_rr_list_push_rr(trusted_keys,
++									 ldns_rr_clone(cur_key));
++				}
++			}
++		}
++
++		ldns_rr_list_deep_free(domain_keys);
++		ldns_rr_list_deep_free(domain_sigs);
++		ldns_pkt_free(keypkt);
++
++	} else {
++		/* LDNS_STATUS_CRYPTO_NO_DNSKEY */
++	}
++    
++	return trusted_keys;
++}
++
++ldns_rr_list *
++ldns_validate_domain_dnskey(const ldns_resolver * res,
++					   const ldns_rdf * domain,
++					   const ldns_rr_list * keys)
++{
++	return ldns_validate_domain_dnskey_time(
++			res, domain, keys, ldns_time(NULL));
++}
++
++ldns_rr_list *
++ldns_validate_domain_ds_time(
++		const ldns_resolver *res, 
++		const ldns_rdf * domain,
++		const ldns_rr_list * keys,
++		time_t check_time)
++{
++	ldns_pkt * dspkt;
++	uint16_t key_i;
++	ldns_rr_list * rrset = NULL;
++	ldns_rr_list * sigs = NULL;
++	ldns_rr_list * trusted_keys = NULL;
++
++	/* Fetch DS for the domain */
++	dspkt = ldns_resolver_query(res, domain,
++		LDNS_RR_TYPE_DS, LDNS_RR_CLASS_IN, LDNS_RD);
++	if (dspkt) {
++		rrset = ldns_pkt_rr_list_by_type(dspkt,
++								   LDNS_RR_TYPE_DS,
++								   LDNS_SECTION_ANSWER);
++		sigs = ldns_pkt_rr_list_by_type(dspkt,
++								  LDNS_RR_TYPE_RRSIG,
++								  LDNS_SECTION_ANSWER);
++
++		/* Validate sigs */
++		if (ldns_verify_time(rrset, sigs, keys, check_time, NULL)
++			       	== LDNS_STATUS_OK) {
++			trusted_keys = ldns_rr_list_new();
++			for (key_i=0; key_i<ldns_rr_list_rr_count(rrset); key_i++) {
++				ldns_rr_list_push_rr(trusted_keys,
++								 ldns_rr_clone(ldns_rr_list_rr(rrset,
++														 key_i)
++											)
++								 );
++			}
++		}
++
++		ldns_rr_list_deep_free(rrset);
++		ldns_rr_list_deep_free(sigs);
++		ldns_pkt_free(dspkt);
++
++	} else {
++		/* LDNS_STATUS_CRYPTO_NO_DS */
++	}
++
++	return trusted_keys;
++}
++
++ldns_rr_list *
++ldns_validate_domain_ds(const ldns_resolver *res,
++				    const ldns_rdf * domain,
++				    const ldns_rr_list * keys)
++{
++	return ldns_validate_domain_ds_time(res, domain, keys, ldns_time(NULL));
++}
++
++ldns_status
++ldns_verify_trusted_time(
++		ldns_resolver *res, 
++		ldns_rr_list *rrset, 
++		ldns_rr_list * rrsigs, 
++		time_t check_time,
++		ldns_rr_list * validating_keys
++		)
++{
++	uint16_t sig_i; uint16_t key_i;
++	ldns_rr * cur_sig; ldns_rr * cur_key;
++	ldns_rr_list * trusted_keys = NULL;
++	ldns_status result = LDNS_STATUS_ERR;
++
++	if (!res || !rrset || !rrsigs) {
++		return LDNS_STATUS_ERR;
++	}
++
++	if (ldns_rr_list_rr_count(rrset) < 1) {
++		return LDNS_STATUS_ERR;
++	}
++
++	if (ldns_rr_list_rr_count(rrsigs) < 1) {
++		return LDNS_STATUS_CRYPTO_NO_RRSIG;
++	}
++  
++	/* Look at each sig */
++	for (sig_i=0; sig_i < ldns_rr_list_rr_count(rrsigs); sig_i++) {
++
++		cur_sig = ldns_rr_list_rr(rrsigs, sig_i);
++		/* Get a valid signer key and validate the sig */
++		if ((trusted_keys = ldns_fetch_valid_domain_keys_time(
++					res, 
++					ldns_rr_rrsig_signame(cur_sig), 
++					ldns_resolver_dnssec_anchors(res), 
++					check_time,
++					&result))) {
++
++			for (key_i = 0;
++				key_i < ldns_rr_list_rr_count(trusted_keys);
++				key_i++) {
++				cur_key = ldns_rr_list_rr(trusted_keys, key_i);
++
++				if ((result = ldns_verify_rrsig_time(rrset,
++								cur_sig, 
++								cur_key,
++								check_time))
++				    == LDNS_STATUS_OK) {
++					if (validating_keys) {
++						ldns_rr_list_push_rr(validating_keys,
++										 ldns_rr_clone(cur_key));
++					}
++					ldns_rr_list_deep_free(trusted_keys);
++					return LDNS_STATUS_OK;
++				} 
++			}
++		}
++	}
++
++	ldns_rr_list_deep_free(trusted_keys);
++	return result;
++}
++
++ldns_status
++ldns_verify_trusted(
++		ldns_resolver *res,
++		ldns_rr_list *rrset, 
++		ldns_rr_list * rrsigs, 
++		ldns_rr_list * validating_keys)
++{
++	return ldns_verify_trusted_time(
++			res, rrset, rrsigs, ldns_time(NULL), validating_keys);
++}
++
++
++ldns_status
++ldns_dnssec_verify_denial(ldns_rr *rr,
++                          ldns_rr_list *nsecs,
++                          ldns_rr_list *rrsigs)
++{
++	ldns_rdf *rr_name;
++	ldns_rdf *wildcard_name;
++	ldns_rdf *chopped_dname;
++	ldns_rr *cur_nsec;
++	size_t i;
++	ldns_status result;
++	/* needed for wildcard check on exact match */
++	ldns_rr *rrsig;
++	bool name_covered = false;
++	bool type_covered = false;
++	bool wildcard_covered = false;
++	bool wildcard_type_covered = false;
++
++	wildcard_name = ldns_dname_new_frm_str("*");
++	rr_name = ldns_rr_owner(rr);
++	chopped_dname = ldns_dname_left_chop(rr_name);
++	result = ldns_dname_cat(wildcard_name, chopped_dname);
++	ldns_rdf_deep_free(chopped_dname);
++	if (result != LDNS_STATUS_OK) {
++		return result;
++	}
++	
++	for  (i = 0; i < ldns_rr_list_rr_count(nsecs); i++) {
++		cur_nsec = ldns_rr_list_rr(nsecs, i);
++		if (ldns_dname_compare(rr_name, ldns_rr_owner(cur_nsec)) == 0) {
++			/* see section 5.4 of RFC4035, if the label count of the NSEC's
++			   RRSIG is equal, then it is proven that wildcard expansion 
++			   could not have been used to match the request */
++			rrsig = ldns_dnssec_get_rrsig_for_name_and_type(
++					  ldns_rr_owner(cur_nsec),
++					  ldns_rr_get_type(cur_nsec),
++					  rrsigs);
++			if (rrsig && ldns_rdf2native_int8(ldns_rr_rrsig_labels(rrsig))
++			    == ldns_dname_label_count(rr_name)) {
++				wildcard_covered = true;
++			}
++			
++			if (ldns_nsec_bitmap_covers_type(ldns_nsec_get_bitmap(cur_nsec),
++									   ldns_rr_get_type(rr))) {
++				type_covered = true;
++			}
++		}
++		if (ldns_nsec_covers_name(cur_nsec, rr_name)) {
++			name_covered = true;
++		}
++		
++		if (ldns_dname_compare(wildcard_name,
++						   ldns_rr_owner(cur_nsec)) == 0) {
++			if (ldns_nsec_bitmap_covers_type(ldns_nsec_get_bitmap(cur_nsec),
++									   ldns_rr_get_type(rr))) {
++				wildcard_type_covered = true;
++			}
++		}
++		
++		if (ldns_nsec_covers_name(cur_nsec, wildcard_name)) {
++			wildcard_covered = true;
++		}
++		
++	}
++	
++	ldns_rdf_deep_free(wildcard_name);
++	
++	if (type_covered || !name_covered) {
++		return LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED;
++	}
++	
++	if (wildcard_type_covered || !wildcard_covered) {
++		return LDNS_STATUS_DNSSEC_NSEC_WILDCARD_NOT_COVERED;
++	}
++
++	return LDNS_STATUS_OK;
++}
++
++ldns_status
++ldns_dnssec_verify_denial_nsec3_match( ldns_rr *rr
++				     , ldns_rr_list *nsecs
++				     , ATTR_UNUSED(ldns_rr_list *rrsigs)
++				     , ldns_pkt_rcode packet_rcode
++				     , ldns_rr_type packet_qtype
++				     , bool packet_nodata
++				     , ldns_rr **match
++				     )
++{
++	ldns_rdf *closest_encloser;
++	ldns_rdf *wildcard;
++	ldns_rdf *hashed_wildcard_name;
++	bool wildcard_covered = false;
++	ldns_rdf *zone_name;
++	ldns_rdf *hashed_name;
++	/* self assignment to suppress uninitialized warning */
++	ldns_rdf *next_closer = next_closer;
++	ldns_rdf *hashed_next_closer;
++	size_t i;
++	ldns_status result = LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED;
++
++	if (match) {
++		*match = NULL;
++	}
++
++	zone_name = ldns_dname_left_chop(ldns_rr_owner(ldns_rr_list_rr(nsecs,0)));
++
++	/* section 8.4 */
++	if (packet_rcode == LDNS_RCODE_NXDOMAIN) {
++		closest_encloser = ldns_dnssec_nsec3_closest_encloser(
++						   ldns_rr_owner(rr),
++						   ldns_rr_get_type(rr),
++						   nsecs);
++                if(!closest_encloser) {
++                        result = LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED;
++                        goto done;
++                }
++
++		wildcard = ldns_dname_new_frm_str("*");
++		(void) ldns_dname_cat(wildcard, closest_encloser);
++
++		for (i = 0; i < ldns_rr_list_rr_count(nsecs); i++) {
++			hashed_wildcard_name =
++				ldns_nsec3_hash_name_frm_nsec3(ldns_rr_list_rr(nsecs, 0),
++										 wildcard
++										 );
++			(void) ldns_dname_cat(hashed_wildcard_name, zone_name);
++
++			if (ldns_nsec_covers_name(ldns_rr_list_rr(nsecs, i),
++								 hashed_wildcard_name)) {
++				wildcard_covered = true;
++				if (match) {
++					*match = ldns_rr_list_rr(nsecs, i);
++				}
++			}
++			ldns_rdf_deep_free(hashed_wildcard_name);
++		}
++
++		if (! wildcard_covered) {
++			result = LDNS_STATUS_DNSSEC_NSEC_WILDCARD_NOT_COVERED;
++		} else {
++			result = LDNS_STATUS_OK;
++		}
++		ldns_rdf_deep_free(closest_encloser);
++		ldns_rdf_deep_free(wildcard);
++
++	} else if (packet_nodata && packet_qtype != LDNS_RR_TYPE_DS) {
++		/* section 8.5 */
++		hashed_name = ldns_nsec3_hash_name_frm_nsec3(
++		                   ldns_rr_list_rr(nsecs, 0),
++		                   ldns_rr_owner(rr));
++		(void) ldns_dname_cat(hashed_name, zone_name);
++		for (i = 0; i < ldns_rr_list_rr_count(nsecs); i++) {
++			if (ldns_dname_compare(hashed_name,
++			         ldns_rr_owner(ldns_rr_list_rr(nsecs, i)))
++			    == 0) {
++				if (!ldns_nsec_bitmap_covers_type(
++					    ldns_nsec3_bitmap(ldns_rr_list_rr(nsecs, i)),
++					    packet_qtype)
++				    &&
++				    !ldns_nsec_bitmap_covers_type(
++					    ldns_nsec3_bitmap(ldns_rr_list_rr(nsecs, i)),
++					    LDNS_RR_TYPE_CNAME)) {
++					result = LDNS_STATUS_OK;
++					if (match) {
++						*match = ldns_rr_list_rr(nsecs, i);
++					}
++					goto done;
++				}
++			}
++		}
++		result = LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED;
++		/* wildcard no data? section 8.7 */
++		closest_encloser = ldns_dnssec_nsec3_closest_encloser(
++				   ldns_rr_owner(rr),
++				   ldns_rr_get_type(rr),
++				   nsecs);
++		if(!closest_encloser) {
++			result = LDNS_STATUS_NSEC3_ERR;
++			goto done;
++		}
++		wildcard = ldns_dname_new_frm_str("*");
++		(void) ldns_dname_cat(wildcard, closest_encloser);
++		for (i = 0; i < ldns_rr_list_rr_count(nsecs); i++) {
++			hashed_wildcard_name =
++				ldns_nsec3_hash_name_frm_nsec3(ldns_rr_list_rr(nsecs, 0),
++					 wildcard);
++			(void) ldns_dname_cat(hashed_wildcard_name, zone_name);
++
++			if (ldns_dname_compare(hashed_wildcard_name,
++			         ldns_rr_owner(ldns_rr_list_rr(nsecs, i)))
++			    == 0) {
++				if (!ldns_nsec_bitmap_covers_type(
++					    ldns_nsec3_bitmap(ldns_rr_list_rr(nsecs, i)),
++					    packet_qtype)
++				    &&
++				    !ldns_nsec_bitmap_covers_type(
++					    ldns_nsec3_bitmap(ldns_rr_list_rr(nsecs, i)),
++					    LDNS_RR_TYPE_CNAME)) {
++					result = LDNS_STATUS_OK;
++					if (match) {
++						*match = ldns_rr_list_rr(nsecs, i);
++					}
++				}
++			}
++			ldns_rdf_deep_free(hashed_wildcard_name);
++			if (result == LDNS_STATUS_OK) {
++				break;
++			}
++		}
++		ldns_rdf_deep_free(closest_encloser);
++		ldns_rdf_deep_free(wildcard);
++	} else if (packet_nodata && packet_qtype == LDNS_RR_TYPE_DS) {
++		/* section 8.6 */
++		/* note: up to XXX this is the same as for 8.5 */
++		hashed_name = ldns_nsec3_hash_name_frm_nsec3(ldns_rr_list_rr(nsecs,
++														 0),
++											ldns_rr_owner(rr)
++											);
++		(void) ldns_dname_cat(hashed_name, zone_name);
++		for (i = 0; i < ldns_rr_list_rr_count(nsecs); i++) {
++			if (ldns_dname_compare(hashed_name,
++							   ldns_rr_owner(ldns_rr_list_rr(nsecs,
++													   i)))
++			    == 0) {
++				if (!ldns_nsec_bitmap_covers_type(
++					    ldns_nsec3_bitmap(ldns_rr_list_rr(nsecs, i)),
++					    LDNS_RR_TYPE_DS)
++				    && 
++				    !ldns_nsec_bitmap_covers_type(
++					    ldns_nsec3_bitmap(ldns_rr_list_rr(nsecs, i)),
++					    LDNS_RR_TYPE_CNAME)) {
++					result = LDNS_STATUS_OK;
++					if (match) {
++						*match = ldns_rr_list_rr(nsecs, i);
++					}
++					goto done;
++				}
++			}
++		}
++
++		/* XXX see note above */
++		result = LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED;
++
++		closest_encloser = ldns_dnssec_nsec3_closest_encloser(
++				   ldns_rr_owner(rr),
++				   ldns_rr_get_type(rr),
++				   nsecs);
++		if(!closest_encloser) {
++			result = LDNS_STATUS_NSEC3_ERR;
++			goto done;
++		}
++		/* Now check if we have a Opt-Out NSEC3 that covers the "next closer"*/
++
++		if (ldns_dname_label_count(closest_encloser) + 1
++		    >= ldns_dname_label_count(ldns_rr_owner(rr))) {
++			
++			/* Query name *is* the "next closer". */
++			hashed_next_closer = hashed_name;
++		} else {
++
++			/* "next closer" has less labels than the query name.
++			 * Create the name and hash it.
++			 */
++			next_closer = ldns_dname_clone_from(
++					ldns_rr_owner(rr),
++					ldns_dname_label_count(ldns_rr_owner(rr))
++					- (ldns_dname_label_count(closest_encloser) + 1)
++					);
++			hashed_next_closer = ldns_nsec3_hash_name_frm_nsec3(
++					ldns_rr_list_rr(nsecs, 0),
++					next_closer
++					);
++			(void) ldns_dname_cat(hashed_next_closer, zone_name);
++		}
++		/* Find the NSEC3 that covers the "next closer" */
++		for (i = 0; i < ldns_rr_list_rr_count(nsecs); i++) {
++			if (ldns_nsec_covers_name(ldns_rr_list_rr(nsecs, i),
++			                          hashed_next_closer) && 
++				ldns_nsec3_optout(ldns_rr_list_rr(nsecs, i))) {
++
++				result = LDNS_STATUS_OK;
++				if (match) {
++					*match = ldns_rr_list_rr(nsecs, i);
++				}
++				break;
++			}
++		}
++		if (ldns_dname_label_count(closest_encloser) + 1
++		    < ldns_dname_label_count(ldns_rr_owner(rr))) {
++
++			/* "next closer" has less labels than the query name.
++			 * Dispose of the temporary variables that held that name.
++			 */
++			ldns_rdf_deep_free(hashed_next_closer);
++			ldns_rdf_deep_free(next_closer);
++		}
++		ldns_rdf_deep_free(closest_encloser);
++	}
++
++ done:
++	ldns_rdf_deep_free(zone_name);
++	return result;
++}
++
++ldns_status
++ldns_dnssec_verify_denial_nsec3(ldns_rr *rr,
++						  ldns_rr_list *nsecs,
++						  ldns_rr_list *rrsigs,
++						  ldns_pkt_rcode packet_rcode,
++						  ldns_rr_type packet_qtype,
++						  bool packet_nodata)
++{
++	return ldns_dnssec_verify_denial_nsec3_match(
++				rr, nsecs, rrsigs, packet_rcode,
++				packet_qtype, packet_nodata, NULL
++	       );
++}
++
++#ifdef USE_GOST
++EVP_PKEY*
++ldns_gost2pkey_raw(unsigned char* key, size_t keylen)
++{
++	/* prefix header for X509 encoding */
++	uint8_t asn[37] = { 0x30, 0x63, 0x30, 0x1c, 0x06, 0x06, 0x2a, 0x85, 
++		0x03, 0x02, 0x02, 0x13, 0x30, 0x12, 0x06, 0x07, 0x2a, 0x85, 
++		0x03, 0x02, 0x02, 0x23, 0x01, 0x06, 0x07, 0x2a, 0x85, 0x03, 
++		0x02, 0x02, 0x1e, 0x01, 0x03, 0x43, 0x00, 0x04, 0x40};
++	unsigned char encoded[37+64];
++	const unsigned char* pp;
++	if(keylen != 64) {
++		/* key wrong size */
++		return NULL;
++	}
++
++	/* create evp_key */
++	memmove(encoded, asn, 37);
++	memmove(encoded+37, key, 64);
++	pp = (unsigned char*)&encoded[0];
++
++	return d2i_PUBKEY(NULL, &pp, (int)sizeof(encoded));
++}
++
++static ldns_status
++ldns_verify_rrsig_gost_raw(unsigned char* sig, size_t siglen, 
++	ldns_buffer* rrset, unsigned char* key, size_t keylen)
++{
++	EVP_PKEY *evp_key;
++	ldns_status result;
++
++	(void) ldns_key_EVP_load_gost_id();
++	evp_key = ldns_gost2pkey_raw(key, keylen);
++	if(!evp_key) {
++		/* could not convert key */
++		return LDNS_STATUS_CRYPTO_BOGUS;
++	}
++
++	/* verify signature */
++	result = ldns_verify_rrsig_evp_raw(sig, siglen, rrset, 
++		evp_key, EVP_get_digestbyname("md_gost94"));
++	EVP_PKEY_free(evp_key);
++
++	return result;
++}
++#endif
++
++#ifdef USE_ECDSA
++EVP_PKEY*
++ldns_ecdsa2pkey_raw(unsigned char* key, size_t keylen, uint8_t algo)
++{
++	unsigned char buf[256+2]; /* sufficient for 2*384/8+1 */
++        const unsigned char* pp = buf;
++        EVP_PKEY *evp_key;
++        EC_KEY *ec;
++	/* check length, which uncompressed must be 2 bignums */
++        if(algo == LDNS_ECDSAP256SHA256) {
++		if(keylen != 2*256/8) return NULL;
++                ec = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
++        } else if(algo == LDNS_ECDSAP384SHA384) {
++		if(keylen != 2*384/8) return NULL;
++                ec = EC_KEY_new_by_curve_name(NID_secp384r1);
++        } else    ec = NULL;
++        if(!ec) return NULL;
++	if(keylen+1 > sizeof(buf))
++		return NULL; /* sanity check */
++	/* prepend the 0x02 (from docs) (or actually 0x04 from implementation
++	 * of openssl) for uncompressed data */
++	buf[0] = POINT_CONVERSION_UNCOMPRESSED;
++	memmove(buf+1, key, keylen);
++        if(!o2i_ECPublicKey(&ec, &pp, (int)keylen+1)) {
++                EC_KEY_free(ec);
++                return NULL;
++        }
++        evp_key = EVP_PKEY_new();
++        if(!evp_key) {
++                EC_KEY_free(ec);
++                return NULL;
++        }
++        if (!EVP_PKEY_assign_EC_KEY(evp_key, ec)) {
++		EVP_PKEY_free(evp_key);
++		EC_KEY_free(ec);
++		return NULL;
++	}
++        return evp_key;
++}
++
++static ldns_status
++ldns_verify_rrsig_ecdsa_raw(unsigned char* sig, size_t siglen, 
++	ldns_buffer* rrset, unsigned char* key, size_t keylen, uint8_t algo)
++{
++        EVP_PKEY *evp_key;
++        ldns_status result;
++        const EVP_MD *d;
++
++        evp_key = ldns_ecdsa2pkey_raw(key, keylen, algo);
++        if(!evp_key) {
++		/* could not convert key */
++		return LDNS_STATUS_CRYPTO_BOGUS;
++        }
++        if(algo == LDNS_ECDSAP256SHA256)
++                d = EVP_sha256();
++        else    d = EVP_sha384(); /* LDNS_ECDSAP384SHA384 */
++	result = ldns_verify_rrsig_evp_raw(sig, siglen, rrset, evp_key, d);
++	EVP_PKEY_free(evp_key);
++	return result;
++}
++#endif
++
++ldns_status
++ldns_verify_rrsig_buffers(ldns_buffer *rawsig_buf, ldns_buffer *verify_buf, 
++					 ldns_buffer *key_buf, uint8_t algo)
++{
++	return ldns_verify_rrsig_buffers_raw(
++			 (unsigned char*)ldns_buffer_begin(rawsig_buf),
++			 ldns_buffer_position(rawsig_buf),
++			 verify_buf,
++			 (unsigned char*)ldns_buffer_begin(key_buf), 
++			 ldns_buffer_position(key_buf), algo);
++}
++
++ldns_status
++ldns_verify_rrsig_buffers_raw(unsigned char* sig, size_t siglen,
++						ldns_buffer *verify_buf, unsigned char* key, size_t keylen, 
++						uint8_t algo)
++{
++	/* check for right key */
++	switch(algo) {
++	case LDNS_DSA:
++	case LDNS_DSA_NSEC3:
++		return ldns_verify_rrsig_dsa_raw(sig,
++								   siglen,
++								   verify_buf,
++								   key,
++								   keylen);
++		break;
++	case LDNS_RSASHA1:
++	case LDNS_RSASHA1_NSEC3:
++		return ldns_verify_rrsig_rsasha1_raw(sig,
++									  siglen,
++									  verify_buf,
++									  key,
++									  keylen);
++		break;
++#ifdef USE_SHA2
++	case LDNS_RSASHA256:
++		return ldns_verify_rrsig_rsasha256_raw(sig,
++									    siglen,
++									    verify_buf,
++									    key,
++									    keylen);
++		break;
++	case LDNS_RSASHA512:
++		return ldns_verify_rrsig_rsasha512_raw(sig,
++									    siglen,
++									    verify_buf,
++									    key,
++									    keylen);
++		break;
++#endif
++#ifdef USE_GOST
++	case LDNS_ECC_GOST:
++		return ldns_verify_rrsig_gost_raw(sig, siglen, verify_buf,
++			key, keylen);
++		break;
++#endif
++#ifdef USE_ECDSA
++        case LDNS_ECDSAP256SHA256:
++        case LDNS_ECDSAP384SHA384:
++		return ldns_verify_rrsig_ecdsa_raw(sig, siglen, verify_buf,
++			key, keylen, algo);
++		break;
++#endif
++	case LDNS_RSAMD5:
++		return ldns_verify_rrsig_rsamd5_raw(sig,
++									 siglen,
++									 verify_buf,
++									 key,
++									 keylen);
++		break;
++	default:
++		/* do you know this alg?! */
++		return LDNS_STATUS_CRYPTO_UNKNOWN_ALGO;
++	}
++}
++
++
++/**
++ * Reset the ttl in the rrset with the orig_ttl from the sig 
++ * and update owner name if it was wildcard 
++ * Also canonicalizes the rrset.
++ * @param rrset: rrset to modify
++ * @param sig: signature to take TTL and wildcard values from
++ */
++static void
++ldns_rrset_use_signature_ttl(ldns_rr_list* rrset_clone, ldns_rr* rrsig)
++{
++	uint32_t orig_ttl;
++	uint16_t i;
++	uint8_t label_count;
++	ldns_rdf *wildcard_name;
++	ldns_rdf *wildcard_chopped;
++	ldns_rdf *wildcard_chopped_tmp;
++	
++	if ((rrsig == NULL) || ldns_rr_rd_count(rrsig) < 4) {
++		return;
++	}
++
++	orig_ttl = ldns_rdf2native_int32( ldns_rr_rdf(rrsig, 3));
++	label_count = ldns_rdf2native_int8(ldns_rr_rdf(rrsig, 2));
++
++	for(i = 0; i < ldns_rr_list_rr_count(rrset_clone); i++) {
++		if (label_count < 
++		    ldns_dname_label_count(
++			   ldns_rr_owner(ldns_rr_list_rr(rrset_clone, i)))) {
++			(void) ldns_str2rdf_dname(&wildcard_name, "*");
++			wildcard_chopped = ldns_rdf_clone(ldns_rr_owner(
++				ldns_rr_list_rr(rrset_clone, i)));
++			while (label_count < ldns_dname_label_count(wildcard_chopped)) {
++				wildcard_chopped_tmp = ldns_dname_left_chop(
++					wildcard_chopped);
++				ldns_rdf_deep_free(wildcard_chopped);
++				wildcard_chopped = wildcard_chopped_tmp;
++			}
++			(void) ldns_dname_cat(wildcard_name, wildcard_chopped);
++			ldns_rdf_deep_free(wildcard_chopped);
++			ldns_rdf_deep_free(ldns_rr_owner(ldns_rr_list_rr(
++				rrset_clone, i)));
++			ldns_rr_set_owner(ldns_rr_list_rr(rrset_clone, i), 
++				wildcard_name);
++		}
++		ldns_rr_set_ttl(ldns_rr_list_rr(rrset_clone, i), orig_ttl);
++		/* convert to lowercase */
++		ldns_rr2canonical(ldns_rr_list_rr(rrset_clone, i));
++	}
++}
++
++/**
++ * Make raw signature buffer out of rrsig
++ * @param rawsig_buf: raw signature buffer for result
++ * @param rrsig: signature to convert
++ * @return OK or more specific error.
++ */
++static ldns_status
++ldns_rrsig2rawsig_buffer(ldns_buffer* rawsig_buf, ldns_rr* rrsig)
++{
++	uint8_t sig_algo;
++       
++	if (rrsig == NULL) {
++		return LDNS_STATUS_CRYPTO_NO_RRSIG;
++	}
++	if (ldns_rr_rdf(rrsig, 1) == NULL) {
++		return LDNS_STATUS_MISSING_RDATA_FIELDS_RRSIG;
++	}
++	sig_algo = ldns_rdf2native_int8(ldns_rr_rdf(rrsig, 1));
++	/* check for known and implemented algo's now (otherwise 
++	 * the function could return a wrong error
++	 */
++	/* create a buffer with signature rdata */
++	/* for some algorithms we need other data than for others... */
++	/* (the DSA API wants DER encoding for instance) */
++
++	switch(sig_algo) {
++	case LDNS_RSAMD5:
++	case LDNS_RSASHA1:
++	case LDNS_RSASHA1_NSEC3:
++#ifdef USE_SHA2
++	case LDNS_RSASHA256:
++	case LDNS_RSASHA512:
++#endif
++#ifdef USE_GOST
++	case LDNS_ECC_GOST:
++#endif
++		if (ldns_rr_rdf(rrsig, 8) == NULL) {
++			return LDNS_STATUS_MISSING_RDATA_FIELDS_RRSIG;
++		}
++		if (ldns_rdf2buffer_wire(rawsig_buf, ldns_rr_rdf(rrsig, 8))
++			       	!= LDNS_STATUS_OK) {
++			return LDNS_STATUS_MEM_ERR;
++		}
++		break;
++	case LDNS_DSA:
++	case LDNS_DSA_NSEC3:
++		/* EVP takes rfc2459 format, which is a tad longer than dns format */
++		if (ldns_rr_rdf(rrsig, 8) == NULL) {
++			return LDNS_STATUS_MISSING_RDATA_FIELDS_RRSIG;
++		}
++		if (ldns_convert_dsa_rrsig_rdf2asn1(
++					rawsig_buf, ldns_rr_rdf(rrsig, 8)) 
++				!= LDNS_STATUS_OK) {
++			/*
++			  if (ldns_rdf2buffer_wire(rawsig_buf,
++			  ldns_rr_rdf(rrsig, 8)) != LDNS_STATUS_OK) {
++			*/
++			return LDNS_STATUS_MEM_ERR;
++		}
++		break;
++#ifdef USE_ECDSA
++        case LDNS_ECDSAP256SHA256:
++        case LDNS_ECDSAP384SHA384:
++                /* EVP produces an ASN prefix on the signature, which is
++                 * not used in the DNS */
++		if (ldns_rr_rdf(rrsig, 8) == NULL) {
++			return LDNS_STATUS_MISSING_RDATA_FIELDS_RRSIG;
++		}
++		if (ldns_convert_ecdsa_rrsig_rdf2asn1(
++					rawsig_buf, ldns_rr_rdf(rrsig, 8))
++				!= LDNS_STATUS_OK) {
++			return LDNS_STATUS_MEM_ERR;
++                }
++                break;
++#endif
++	case LDNS_DH:
++	case LDNS_ECC:
++	case LDNS_INDIRECT:
++		return LDNS_STATUS_CRYPTO_ALGO_NOT_IMPL;
++	default:
++		return LDNS_STATUS_CRYPTO_UNKNOWN_ALGO;
++	}
++	return LDNS_STATUS_OK;
++}
++
++/**
++ * Check RRSIG timestamps against the given 'now' time.
++ * @param rrsig: signature to check.
++ * @param now: the current time in seconds epoch.
++ * @return status code LDNS_STATUS_OK if all is fine.
++ */
++static ldns_status
++ldns_rrsig_check_timestamps(ldns_rr* rrsig, time_t now)
++{
++	int32_t inception, expiration;
++	
++	/* check the signature time stamps */
++	inception = (int32_t)ldns_rdf2native_time_t(
++		ldns_rr_rrsig_inception(rrsig));
++	expiration = (int32_t)ldns_rdf2native_time_t(
++		ldns_rr_rrsig_expiration(rrsig));
++
++	if (expiration - inception < 0) {
++		/* bad sig, expiration before inception?? Tsssg */
++		return LDNS_STATUS_CRYPTO_EXPIRATION_BEFORE_INCEPTION;
++	}
++	if (((int32_t) now) - inception < 0) {
++		/* bad sig, inception date has not yet come to pass */
++		return LDNS_STATUS_CRYPTO_SIG_NOT_INCEPTED;
++	}
++	if (expiration - ((int32_t) now) < 0) {
++		/* bad sig, expiration date has passed */
++		return LDNS_STATUS_CRYPTO_SIG_EXPIRED;
++	}
++	return LDNS_STATUS_OK;
++}
++
++/**
++ * Prepare for verification.
++ * @param rawsig_buf: raw signature buffer made ready.
++ * @param verify_buf: data for verification buffer made ready.
++ * @param rrset_clone: made ready.
++ * @param rrsig: signature to prepare for.
++ * @return LDNS_STATUS_OK is all went well. Otherwise specific error.
++ */
++static ldns_status
++ldns_prepare_for_verify(ldns_buffer* rawsig_buf, ldns_buffer* verify_buf, 
++	ldns_rr_list* rrset_clone, ldns_rr* rrsig)
++{
++	ldns_status result;
++
++	/* canonicalize the sig */
++	ldns_dname2canonical(ldns_rr_owner(rrsig));
++	
++	/* check if the typecovered is equal to the type checked */
++	if (ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rrsig)) !=
++	    ldns_rr_get_type(ldns_rr_list_rr(rrset_clone, 0)))
++		return LDNS_STATUS_CRYPTO_TYPE_COVERED_ERR;
++	
++	/* create a buffer with b64 signature rdata */
++	result = ldns_rrsig2rawsig_buffer(rawsig_buf, rrsig);
++	if(result != LDNS_STATUS_OK)
++		return result;
++
++	/* use TTL from signature. Use wildcard names for wildcards */
++	/* also canonicalizes rrset_clone */
++	ldns_rrset_use_signature_ttl(rrset_clone, rrsig);
++
++	/* sort the rrset in canonical order  */
++	ldns_rr_list_sort(rrset_clone);
++
++	/* put the signature rr (without the b64) to the verify_buf */
++	if (ldns_rrsig2buffer_wire(verify_buf, rrsig) != LDNS_STATUS_OK)
++		return LDNS_STATUS_MEM_ERR;
++
++	/* add the rrset in verify_buf */
++	if(ldns_rr_list2buffer_wire(verify_buf, rrset_clone) 
++		!= LDNS_STATUS_OK)
++		return LDNS_STATUS_MEM_ERR;
++
++	return LDNS_STATUS_OK;
++}
++
++/**
++ * Check if a key matches a signature.
++ * Checks keytag, sigalgo and signature.
++ * @param rawsig_buf: raw signature buffer for verify
++ * @param verify_buf: raw data buffer for verify
++ * @param rrsig: the rrsig
++ * @param key: key to attempt.
++ * @return LDNS_STATUS_OK if OK, else some specific error.
++ */
++static ldns_status
++ldns_verify_test_sig_key(ldns_buffer* rawsig_buf, ldns_buffer* verify_buf, 
++	ldns_rr* rrsig, ldns_rr* key)
++{
++	uint8_t sig_algo;
++       
++	if (rrsig == NULL) {
++		return LDNS_STATUS_CRYPTO_NO_RRSIG;
++	}
++	if (ldns_rr_rdf(rrsig, 1) == NULL) {
++		return LDNS_STATUS_MISSING_RDATA_FIELDS_RRSIG;
++	}
++	sig_algo = ldns_rdf2native_int8(ldns_rr_rdf(rrsig, 1));
++
++	/* before anything, check if the keytags match */
++	if (ldns_calc_keytag(key)
++	    ==
++	    ldns_rdf2native_int16(ldns_rr_rrsig_keytag(rrsig))
++	    ) {
++		ldns_buffer* key_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN);
++		ldns_status result = LDNS_STATUS_ERR;
++
++		/* put the key-data in a buffer, that's the third rdf, with
++		 * the base64 encoded key data */
++		if (ldns_rr_rdf(key, 3) == NULL) {
++			ldns_buffer_free(key_buf);
++			return LDNS_STATUS_MISSING_RDATA_FIELDS_KEY;
++		}
++		if (ldns_rdf2buffer_wire(key_buf, ldns_rr_rdf(key, 3))
++			       	!= LDNS_STATUS_OK) {
++			ldns_buffer_free(key_buf); 
++			/* returning is bad might screw up
++			   good keys later in the list
++			   what to do? */
++			return LDNS_STATUS_ERR;
++		}
++
++		if (ldns_rr_rdf(key, 2) == NULL) {
++			result = LDNS_STATUS_MISSING_RDATA_FIELDS_KEY;
++		}
++		else if (sig_algo == ldns_rdf2native_int8(
++					ldns_rr_rdf(key, 2))) {
++			result = ldns_verify_rrsig_buffers(rawsig_buf, 
++				verify_buf, key_buf, sig_algo);
++		} else {
++			/* No keys with the corresponding algorithm are found */
++			result = LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY;
++		}
++
++		ldns_buffer_free(key_buf); 
++		return result;
++	}
++	else {
++		/* No keys with the corresponding keytag are found */
++		return LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY;
++	}
++}
++
++/* 
++ * to verify:
++ * - create the wire fmt of the b64 key rdata
++ * - create the wire fmt of the sorted rrset
++ * - create the wire fmt of the b64 sig rdata
++ * - create the wire fmt of the sig without the b64 rdata
++ * - cat the sig data (without b64 rdata) to the rrset
++ * - verify the rrset+sig, with the b64 data and the b64 key data
++ */
++ldns_status
++ldns_verify_rrsig_keylist_time(
++		ldns_rr_list *rrset,
++		ldns_rr *rrsig,
++		const ldns_rr_list *keys, 
++		time_t check_time,
++		ldns_rr_list *good_keys)
++{
++	ldns_status result;
++	ldns_rr_list *valid = ldns_rr_list_new();
++	if (!valid)
++		return LDNS_STATUS_MEM_ERR;
++
++	result = ldns_verify_rrsig_keylist_notime(rrset, rrsig, keys, valid);
++	if(result != LDNS_STATUS_OK) {
++		ldns_rr_list_free(valid); 
++		return result;
++	}
++
++	/* check timestamps last; its OK except time */
++	result = ldns_rrsig_check_timestamps(rrsig, check_time);
++	if(result != LDNS_STATUS_OK) {
++		ldns_rr_list_free(valid); 
++		return result;
++	}
++
++	ldns_rr_list_cat(good_keys, valid);
++	ldns_rr_list_free(valid);
++	return LDNS_STATUS_OK;
++}
++
++/* 
++ * to verify:
++ * - create the wire fmt of the b64 key rdata
++ * - create the wire fmt of the sorted rrset
++ * - create the wire fmt of the b64 sig rdata
++ * - create the wire fmt of the sig without the b64 rdata
++ * - cat the sig data (without b64 rdata) to the rrset
++ * - verify the rrset+sig, with the b64 data and the b64 key data
++ */
++ldns_status
++ldns_verify_rrsig_keylist(ldns_rr_list *rrset,
++					 ldns_rr *rrsig,
++					 const ldns_rr_list *keys, 
++					 ldns_rr_list *good_keys)
++{
++	return ldns_verify_rrsig_keylist_time(
++			rrset, rrsig, keys, ldns_time(NULL), good_keys);
++}
++
++ldns_status
++ldns_verify_rrsig_keylist_notime(ldns_rr_list *rrset,
++					 ldns_rr *rrsig,
++					 const ldns_rr_list *keys, 
++					 ldns_rr_list *good_keys)
++{
++	ldns_buffer *rawsig_buf;
++	ldns_buffer *verify_buf;
++	uint16_t i;
++	ldns_status result, status;
++	ldns_rr_list *rrset_clone;
++	ldns_rr_list *validkeys;
++
++	if (!rrset) {
++		return LDNS_STATUS_ERR;
++	}
++
++	validkeys = ldns_rr_list_new();
++	if (!validkeys) {
++		return LDNS_STATUS_MEM_ERR;
++	}
++	
++	/* clone the rrset so that we can fiddle with it */
++	rrset_clone = ldns_rr_list_clone(rrset);
++
++	/* create the buffers which will certainly hold the raw data */
++	rawsig_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN);
++	verify_buf  = ldns_buffer_new(LDNS_MAX_PACKETLEN);
++
++	result = ldns_prepare_for_verify(rawsig_buf, verify_buf, 
++		rrset_clone, rrsig);
++	if(result != LDNS_STATUS_OK) {
++		ldns_buffer_free(verify_buf);
++		ldns_buffer_free(rawsig_buf);
++		ldns_rr_list_deep_free(rrset_clone);
++		ldns_rr_list_free(validkeys);
++		return result;
++	}
++
++	result = LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY;
++	for(i = 0; i < ldns_rr_list_rr_count(keys); i++) {
++		status = ldns_verify_test_sig_key(rawsig_buf, verify_buf, 
++			rrsig, ldns_rr_list_rr(keys, i));
++		if (status == LDNS_STATUS_OK) {
++			/* one of the keys has matched, don't break
++			 * here, instead put the 'winning' key in
++			 * the validkey list and return the list 
++			 * later */
++			if (!ldns_rr_list_push_rr(validkeys, 
++				ldns_rr_list_rr(keys,i))) {
++				/* couldn't push the key?? */
++				ldns_buffer_free(rawsig_buf);
++				ldns_buffer_free(verify_buf);
++				ldns_rr_list_deep_free(rrset_clone);
++				ldns_rr_list_free(validkeys);
++				return LDNS_STATUS_MEM_ERR;
++			}
++
++			result = status;
++		}
++
++		if (result == LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY) {
++			result = status;
++		}
++	}
++
++	/* no longer needed */
++	ldns_rr_list_deep_free(rrset_clone);
++	ldns_buffer_free(rawsig_buf);
++	ldns_buffer_free(verify_buf);
++
++	if (ldns_rr_list_rr_count(validkeys) == 0) {
++		/* no keys were added, return last error */
++		ldns_rr_list_free(validkeys); 
++		return result;
++	}
++
++	/* do not check timestamps */
++
++	ldns_rr_list_cat(good_keys, validkeys);
++	ldns_rr_list_free(validkeys);
++	return LDNS_STATUS_OK;
++}
++
++ldns_status
++ldns_verify_rrsig_time(
++		ldns_rr_list *rrset, 
++		ldns_rr *rrsig, 
++		ldns_rr *key, 
++		time_t check_time)
++{
++	ldns_buffer *rawsig_buf;
++	ldns_buffer *verify_buf;
++	ldns_status result;
++	ldns_rr_list *rrset_clone;
++
++	if (!rrset) {
++		return LDNS_STATUS_NO_DATA;
++	}
++	/* clone the rrset so that we can fiddle with it */
++	rrset_clone = ldns_rr_list_clone(rrset);
++	/* create the buffers which will certainly hold the raw data */
++	rawsig_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN);
++	verify_buf  = ldns_buffer_new(LDNS_MAX_PACKETLEN);
++
++	result = ldns_prepare_for_verify(rawsig_buf, verify_buf, 
++		rrset_clone, rrsig);
++	if(result != LDNS_STATUS_OK) {
++		ldns_rr_list_deep_free(rrset_clone);
++		ldns_buffer_free(rawsig_buf);
++		ldns_buffer_free(verify_buf);
++		return result;
++	}
++	result = ldns_verify_test_sig_key(rawsig_buf, verify_buf, 
++		rrsig, key);
++	/* no longer needed */
++	ldns_rr_list_deep_free(rrset_clone);
++	ldns_buffer_free(rawsig_buf);
++	ldns_buffer_free(verify_buf);
++
++	/* check timestamp last, apart from time its OK */
++	if(result == LDNS_STATUS_OK)
++		result = ldns_rrsig_check_timestamps(rrsig, check_time);
++
++	return result;
++}
++
++ldns_status
++ldns_verify_rrsig(ldns_rr_list *rrset, ldns_rr *rrsig, ldns_rr *key)
++{
++	return ldns_verify_rrsig_time(rrset, rrsig, key, ldns_time(NULL));
++}
++
++
++ldns_status
++ldns_verify_rrsig_evp(ldns_buffer *sig,
++				  ldns_buffer *rrset,
++				  EVP_PKEY *key,
++				  const EVP_MD *digest_type)
++{
++	return ldns_verify_rrsig_evp_raw(
++			 (unsigned char*)ldns_buffer_begin(sig),
++			 ldns_buffer_position(sig),
++			 rrset,
++			 key,
++			 digest_type);
++}
++
++ldns_status
++ldns_verify_rrsig_evp_raw(unsigned char *sig, size_t siglen, 
++					 ldns_buffer *rrset, EVP_PKEY *key, const EVP_MD *digest_type)
++{
++	EVP_MD_CTX ctx;
++	int res;
++
++	EVP_MD_CTX_init(&ctx);
++	
++	EVP_VerifyInit(&ctx, digest_type);
++	EVP_VerifyUpdate(&ctx,
++				  ldns_buffer_begin(rrset),
++				  ldns_buffer_position(rrset));
++	res = EVP_VerifyFinal(&ctx, sig, (unsigned int) siglen, key);
++	
++	EVP_MD_CTX_cleanup(&ctx);
++	
++	if (res == 1) {
++		return LDNS_STATUS_OK;
++	} else if (res == 0) {
++		return LDNS_STATUS_CRYPTO_BOGUS;
++	}
++	/* TODO how to communicate internal SSL error?
++	   let caller use ssl's get_error() */
++	return LDNS_STATUS_SSL_ERR;
++}
++
++ldns_status
++ldns_verify_rrsig_dsa(ldns_buffer *sig, ldns_buffer *rrset, ldns_buffer *key)
++{
++	return ldns_verify_rrsig_dsa_raw(
++			 (unsigned char*) ldns_buffer_begin(sig),
++			 ldns_buffer_position(sig),
++			 rrset,
++			 (unsigned char*) ldns_buffer_begin(key),
++			 ldns_buffer_position(key));
++}
++
++ldns_status
++ldns_verify_rrsig_rsasha1(ldns_buffer *sig, ldns_buffer *rrset, ldns_buffer *key)
++{
++	return ldns_verify_rrsig_rsasha1_raw(
++			 (unsigned char*)ldns_buffer_begin(sig),
++			 ldns_buffer_position(sig),
++			 rrset,
++			 (unsigned char*) ldns_buffer_begin(key),
++			 ldns_buffer_position(key));
++}
++
++ldns_status
++ldns_verify_rrsig_rsamd5(ldns_buffer *sig, ldns_buffer *rrset, ldns_buffer *key)
++{
++	return ldns_verify_rrsig_rsamd5_raw(
++			 (unsigned char*)ldns_buffer_begin(sig),
++			 ldns_buffer_position(sig),
++			 rrset,
++			 (unsigned char*) ldns_buffer_begin(key),
++			 ldns_buffer_position(key));
++}
++
++ldns_status
++ldns_verify_rrsig_dsa_raw(unsigned char* sig, size_t siglen,
++					 ldns_buffer* rrset, unsigned char* key, size_t keylen)
++{
++	EVP_PKEY *evp_key;
++	ldns_status result;
++
++	evp_key = EVP_PKEY_new();
++	if (EVP_PKEY_assign_DSA(evp_key, ldns_key_buf2dsa_raw(key, keylen))) {
++		result = ldns_verify_rrsig_evp_raw(sig,
++								siglen,
++								rrset,
++								evp_key,
++								EVP_dss1());
++	} else {
++		result = LDNS_STATUS_SSL_ERR;
++	}
++	EVP_PKEY_free(evp_key);
++	return result;
++
++}
++
++ldns_status
++ldns_verify_rrsig_rsasha1_raw(unsigned char* sig, size_t siglen,
++						ldns_buffer* rrset, unsigned char* key, size_t keylen)
++{
++	EVP_PKEY *evp_key;
++	ldns_status result;
++
++	evp_key = EVP_PKEY_new();
++	if (EVP_PKEY_assign_RSA(evp_key, ldns_key_buf2rsa_raw(key, keylen))) {
++		result = ldns_verify_rrsig_evp_raw(sig,
++								siglen,
++								rrset,
++								evp_key,
++								EVP_sha1());
++	} else {
++		result = LDNS_STATUS_SSL_ERR;
++	}
++	EVP_PKEY_free(evp_key);
++
++	return result;
++}
++
++ldns_status
++ldns_verify_rrsig_rsasha256_raw(unsigned char* sig,
++						  size_t siglen,
++						  ldns_buffer* rrset,
++						  unsigned char* key,
++						  size_t keylen)
++{
++#ifdef USE_SHA2
++	EVP_PKEY *evp_key;
++	ldns_status result;
++
++	evp_key = EVP_PKEY_new();
++	if (EVP_PKEY_assign_RSA(evp_key, ldns_key_buf2rsa_raw(key, keylen))) {
++		result = ldns_verify_rrsig_evp_raw(sig,
++								siglen,
++								rrset,
++								evp_key,
++								EVP_sha256());
++	} else {
++		result = LDNS_STATUS_SSL_ERR;
++	}
++	EVP_PKEY_free(evp_key);
++
++	return result;
++#else
++	/* touch these to prevent compiler warnings */
++	(void) sig;
++	(void) siglen;
++	(void) rrset;
++	(void) key;
++	(void) keylen;
++	return LDNS_STATUS_CRYPTO_UNKNOWN_ALGO;
++#endif
++}
++
++ldns_status
++ldns_verify_rrsig_rsasha512_raw(unsigned char* sig,
++						  size_t siglen,
++						  ldns_buffer* rrset,
++						  unsigned char* key,
++						  size_t keylen)
++{
++#ifdef USE_SHA2
++	EVP_PKEY *evp_key;
++	ldns_status result;
++
++	evp_key = EVP_PKEY_new();
++	if (EVP_PKEY_assign_RSA(evp_key, ldns_key_buf2rsa_raw(key, keylen))) {
++		result = ldns_verify_rrsig_evp_raw(sig,
++								siglen,
++								rrset,
++								evp_key,
++								EVP_sha512());
++	} else {
++		result = LDNS_STATUS_SSL_ERR;
++	}
++	EVP_PKEY_free(evp_key);
++
++	return result;
++#else
++	/* touch these to prevent compiler warnings */
++	(void) sig;
++	(void) siglen;
++	(void) rrset;
++	(void) key;
++	(void) keylen;
++	return LDNS_STATUS_CRYPTO_UNKNOWN_ALGO;
++#endif
++}
++
++
++ldns_status
++ldns_verify_rrsig_rsamd5_raw(unsigned char* sig,
++					    size_t siglen,
++					    ldns_buffer* rrset,
++					    unsigned char* key,
++					    size_t keylen)
++{
++	EVP_PKEY *evp_key;
++	ldns_status result;
++
++	evp_key = EVP_PKEY_new();
++	if (EVP_PKEY_assign_RSA(evp_key, ldns_key_buf2rsa_raw(key, keylen))) {
++		result = ldns_verify_rrsig_evp_raw(sig,
++								siglen,
++								rrset,
++								evp_key,
++								EVP_md5());
++	} else {
++		result = LDNS_STATUS_SSL_ERR;
++	}
++	EVP_PKEY_free(evp_key);
++
++	return result;
++}
++
++#endif
+diff --git a/ldns/src/dnssec_zone.c b/ldns/src/dnssec_zone.c
+new file mode 100644
+index 0000000..0fec48c
+--- /dev/null
++++ b/ldns/src/dnssec_zone.c
+@@ -0,0 +1,1192 @@
++/*
++ * special zone file structures and functions for better dnssec handling
++ */
++
++#include <ldns/config.h>
++
++#include <ldns/ldns.h>
++
++ldns_dnssec_rrs *
++ldns_dnssec_rrs_new(void)
++{
++	ldns_dnssec_rrs *new_rrs;
++	new_rrs = LDNS_MALLOC(ldns_dnssec_rrs);
++        if(!new_rrs) return NULL;
++	new_rrs->rr = NULL;
++	new_rrs->next = NULL;
++	return new_rrs;
++}
++
++INLINE void
++ldns_dnssec_rrs_free_internal(ldns_dnssec_rrs *rrs, int deep)
++{
++	ldns_dnssec_rrs *next;
++	while (rrs) {
++		next = rrs->next;
++		if (deep) {
++			ldns_rr_free(rrs->rr);
++		}
++		LDNS_FREE(rrs);
++		rrs = next;
++	}
++}
++
++void
++ldns_dnssec_rrs_free(ldns_dnssec_rrs *rrs)
++{
++	ldns_dnssec_rrs_free_internal(rrs, 0);
++}
++
++void
++ldns_dnssec_rrs_deep_free(ldns_dnssec_rrs *rrs)
++{
++	ldns_dnssec_rrs_free_internal(rrs, 1);
++}
++
++ldns_status
++ldns_dnssec_rrs_add_rr(ldns_dnssec_rrs *rrs, ldns_rr *rr)
++{
++	int cmp;
++	ldns_dnssec_rrs *new_rrs;
++	if (!rrs || !rr) {
++		return LDNS_STATUS_ERR;
++	}
++
++	/* this could be done more efficiently; name and type should already
++	   be equal */
++	cmp = ldns_rr_compare(rrs->rr, rr);
++	if (cmp < 0) {
++		if (rrs->next) {
++			return ldns_dnssec_rrs_add_rr(rrs->next, rr);
++		} else {
++			new_rrs = ldns_dnssec_rrs_new();
++			new_rrs->rr = rr;
++			rrs->next = new_rrs;
++		}
++	} else if (cmp > 0) {
++		/* put the current old rr in the new next, put the new
++		   rr in the current container */
++		new_rrs = ldns_dnssec_rrs_new();
++		new_rrs->rr = rrs->rr;
++		new_rrs->next = rrs->next;
++		rrs->rr = rr;
++		rrs->next = new_rrs;
++	}
++	/* Silently ignore equal rr's */
++	return LDNS_STATUS_OK;
++}
++
++void
++ldns_dnssec_rrs_print_fmt(FILE *out, const ldns_output_format *fmt,
++	       ldns_dnssec_rrs *rrs)
++{
++	if (!rrs) {
++		if ((fmt->flags & LDNS_COMMENT_LAYOUT))
++			fprintf(out, "; <void>");
++	} else {
++		if (rrs->rr) {
++			ldns_rr_print_fmt(out, fmt, rrs->rr);
++		}
++		if (rrs->next) {
++			ldns_dnssec_rrs_print_fmt(out, fmt, rrs->next);
++		}
++	}
++}
++
++void
++ldns_dnssec_rrs_print(FILE *out, ldns_dnssec_rrs *rrs)
++{
++	ldns_dnssec_rrs_print_fmt(out, ldns_output_format_default, rrs);
++}
++
++
++ldns_dnssec_rrsets *
++ldns_dnssec_rrsets_new(void)
++{
++	ldns_dnssec_rrsets *new_rrsets;
++	new_rrsets = LDNS_MALLOC(ldns_dnssec_rrsets);
++        if(!new_rrsets) return NULL;
++	new_rrsets->rrs = NULL;
++	new_rrsets->type = 0;
++	new_rrsets->signatures = NULL;
++	new_rrsets->next = NULL;
++	return new_rrsets;
++}
++
++INLINE void
++ldns_dnssec_rrsets_free_internal(ldns_dnssec_rrsets *rrsets, int deep)
++{
++	if (rrsets) {
++		if (rrsets->rrs) {
++			ldns_dnssec_rrs_free_internal(rrsets->rrs, deep);
++		}
++		if (rrsets->next) {
++			ldns_dnssec_rrsets_free_internal(rrsets->next, deep);
++		}
++		if (rrsets->signatures) {
++			ldns_dnssec_rrs_free_internal(rrsets->signatures, deep);
++		}
++		LDNS_FREE(rrsets);
++	}
++}
++
++void
++ldns_dnssec_rrsets_free(ldns_dnssec_rrsets *rrsets)
++{
++	ldns_dnssec_rrsets_free_internal(rrsets, 0);
++}
++
++void
++ldns_dnssec_rrsets_deep_free(ldns_dnssec_rrsets *rrsets)
++{
++	ldns_dnssec_rrsets_free_internal(rrsets, 1);
++}
++
++ldns_rr_type
++ldns_dnssec_rrsets_type(ldns_dnssec_rrsets *rrsets)
++{
++	if (rrsets) {
++		return rrsets->type;
++	} else {
++		return 0;
++	}
++}
++
++ldns_status
++ldns_dnssec_rrsets_set_type(ldns_dnssec_rrsets *rrsets,
++					   ldns_rr_type type)
++{
++	if (rrsets) {
++		rrsets->type = type;
++		return LDNS_STATUS_OK;
++	}
++	return LDNS_STATUS_ERR;
++}
++
++static ldns_dnssec_rrsets *
++ldns_dnssec_rrsets_new_frm_rr(ldns_rr *rr)
++{
++	ldns_dnssec_rrsets *new_rrsets;
++	ldns_rr_type rr_type;
++	bool rrsig;
++
++	new_rrsets = ldns_dnssec_rrsets_new();
++	rr_type = ldns_rr_get_type(rr);
++	if (rr_type == LDNS_RR_TYPE_RRSIG) {
++		rrsig = true;
++		rr_type = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
++	} else {
++		rrsig = false;
++	}
++	if (!rrsig) {
++		new_rrsets->rrs = ldns_dnssec_rrs_new();
++		new_rrsets->rrs->rr = rr;
++	} else {
++		new_rrsets->signatures = ldns_dnssec_rrs_new();
++		new_rrsets->signatures->rr = rr;
++	}
++	new_rrsets->type = rr_type;
++	return new_rrsets;
++}
++
++ldns_status
++ldns_dnssec_rrsets_add_rr(ldns_dnssec_rrsets *rrsets, ldns_rr *rr)
++{
++	ldns_dnssec_rrsets *new_rrsets;
++	ldns_rr_type rr_type;
++	bool rrsig = false;
++	ldns_status result = LDNS_STATUS_OK;
++
++	if (!rrsets || !rr) {
++		return LDNS_STATUS_ERR;
++	}
++
++	rr_type = ldns_rr_get_type(rr);
++
++	if (rr_type == LDNS_RR_TYPE_RRSIG) {
++		rrsig = true;
++		rr_type = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
++	}
++
++	if (!rrsets->rrs && rrsets->type == 0 && !rrsets->signatures) {
++		if (!rrsig) {
++			rrsets->rrs = ldns_dnssec_rrs_new();
++			rrsets->rrs->rr = rr;
++			rrsets->type = rr_type;
++		} else {
++			rrsets->signatures = ldns_dnssec_rrs_new();
++			rrsets->signatures->rr = rr;
++			rrsets->type = rr_type;
++		}
++		return LDNS_STATUS_OK;
++	}
++
++	if (rr_type > ldns_dnssec_rrsets_type(rrsets)) {
++		if (rrsets->next) {
++			result = ldns_dnssec_rrsets_add_rr(rrsets->next, rr);
++		} else {
++			new_rrsets = ldns_dnssec_rrsets_new_frm_rr(rr);
++			rrsets->next = new_rrsets;
++		}
++	} else if (rr_type < ldns_dnssec_rrsets_type(rrsets)) {
++		/* move the current one into the new next, 
++		   replace field of current with data from new rr */
++		new_rrsets = ldns_dnssec_rrsets_new();
++		new_rrsets->rrs = rrsets->rrs;
++		new_rrsets->type = rrsets->type;
++		new_rrsets->signatures = rrsets->signatures;
++		new_rrsets->next = rrsets->next;
++		if (!rrsig) {
++			rrsets->rrs = ldns_dnssec_rrs_new();
++			rrsets->rrs->rr = rr;
++			rrsets->signatures = NULL;
++		} else {
++			rrsets->rrs = NULL;
++			rrsets->signatures = ldns_dnssec_rrs_new();
++			rrsets->signatures->rr = rr;
++		}
++		rrsets->type = rr_type;
++		rrsets->next = new_rrsets;
++	} else {
++		/* equal, add to current rrsets */
++		if (rrsig) {
++			if (rrsets->signatures) {
++				result = ldns_dnssec_rrs_add_rr(rrsets->signatures, rr);
++			} else {
++				rrsets->signatures = ldns_dnssec_rrs_new();
++				rrsets->signatures->rr = rr;
++			}
++		} else {
++			if (rrsets->rrs) {
++				result = ldns_dnssec_rrs_add_rr(rrsets->rrs, rr);
++			} else {
++				rrsets->rrs = ldns_dnssec_rrs_new();
++				rrsets->rrs->rr = rr;
++			}
++		}
++	}
++
++	return result;
++}
++
++static void
++ldns_dnssec_rrsets_print_soa_fmt(FILE *out, const ldns_output_format *fmt,
++		ldns_dnssec_rrsets *rrsets,
++		bool follow,
++		bool show_soa)
++{
++	if (!rrsets) {
++		if ((fmt->flags & LDNS_COMMENT_LAYOUT))
++			fprintf(out, "; <void>\n");
++	} else {
++		if (rrsets->rrs &&
++		    (show_soa ||
++			ldns_rr_get_type(rrsets->rrs->rr) != LDNS_RR_TYPE_SOA
++		    )
++		   ) {
++			ldns_dnssec_rrs_print_fmt(out, fmt, rrsets->rrs);
++			if (rrsets->signatures) {
++				ldns_dnssec_rrs_print_fmt(out, fmt, 
++						rrsets->signatures);
++			}
++		}
++		if (follow && rrsets->next) {
++			ldns_dnssec_rrsets_print_soa_fmt(out, fmt, 
++					rrsets->next, follow, show_soa);
++		}
++	}
++}
++
++
++void
++ldns_dnssec_rrsets_print_fmt(FILE *out, const ldns_output_format *fmt,
++		ldns_dnssec_rrsets *rrsets, 
++		bool follow)
++{
++	ldns_dnssec_rrsets_print_soa_fmt(out, fmt, rrsets, follow, true);
++}
++
++void
++ldns_dnssec_rrsets_print(FILE *out, ldns_dnssec_rrsets *rrsets, bool follow)
++{
++	ldns_dnssec_rrsets_print_fmt(out, ldns_output_format_default, 
++			rrsets, follow);
++}
++
++ldns_dnssec_name *
++ldns_dnssec_name_new(void)
++{
++	ldns_dnssec_name *new_name;
++
++	new_name = LDNS_CALLOC(ldns_dnssec_name, 1);
++	if (!new_name) {
++		return NULL;
++	}
++	/*
++	 * not needed anymore because CALLOC initalizes everything to zero.
++
++	new_name->name = NULL;
++	new_name->rrsets = NULL;
++	new_name->name_alloced = false;
++	new_name->nsec = NULL;
++	new_name->nsec_signatures = NULL;
++
++	new_name->is_glue = false;
++	new_name->hashed_name = NULL;
++
++	 */
++	return new_name;
++}
++
++ldns_dnssec_name *
++ldns_dnssec_name_new_frm_rr(ldns_rr *rr)
++{
++	ldns_dnssec_name *new_name = ldns_dnssec_name_new();
++
++	new_name->name = ldns_rr_owner(rr);
++	if(ldns_dnssec_name_add_rr(new_name, rr) != LDNS_STATUS_OK) {
++		ldns_dnssec_name_free(new_name);
++		return NULL;
++	}
++
++	return new_name;
++}
++
++INLINE void
++ldns_dnssec_name_free_internal(ldns_dnssec_name *name,
++                               int deep)
++{
++	if (name) {
++		if (name->name_alloced) {
++			ldns_rdf_deep_free(name->name);
++		}
++		if (name->rrsets) {
++			ldns_dnssec_rrsets_free_internal(name->rrsets, deep);
++		}
++		if (name->nsec && deep) {
++			ldns_rr_free(name->nsec);
++		}
++		if (name->nsec_signatures) {
++			ldns_dnssec_rrs_free_internal(name->nsec_signatures, deep);
++		}
++		if (name->hashed_name) {
++			if (deep) {
++				ldns_rdf_deep_free(name->hashed_name);
++			}
++		}
++		LDNS_FREE(name);
++	}
++}
++
++void
++ldns_dnssec_name_free(ldns_dnssec_name *name)
++{
++  ldns_dnssec_name_free_internal(name, 0);
++}
++
++void
++ldns_dnssec_name_deep_free(ldns_dnssec_name *name)
++{
++  ldns_dnssec_name_free_internal(name, 1);
++}
++
++ldns_rdf *
++ldns_dnssec_name_name(ldns_dnssec_name *name)
++{
++	if (name) {
++		return name->name;
++	}
++	return NULL;
++}
++
++bool
++ldns_dnssec_name_is_glue(ldns_dnssec_name *name)
++{
++	if (name) {
++		return name->is_glue;
++	}
++	return false;
++}
++
++void
++ldns_dnssec_name_set_name(ldns_dnssec_name *rrset,
++					 ldns_rdf *dname)
++{
++	if (rrset && dname) {
++		rrset->name = dname;
++	}
++}
++
++
++void
++ldns_dnssec_name_set_nsec(ldns_dnssec_name *rrset, ldns_rr *nsec)
++{
++	if (rrset && nsec) {
++		rrset->nsec = nsec;
++	}
++}
++
++int
++ldns_dnssec_name_cmp(const void *a, const void *b)
++{
++	ldns_dnssec_name *na = (ldns_dnssec_name *) a;
++	ldns_dnssec_name *nb = (ldns_dnssec_name *) b;
++
++	if (na && nb) {
++		return ldns_dname_compare(ldns_dnssec_name_name(na),
++							 ldns_dnssec_name_name(nb));
++	} else if (na) {
++		return 1;
++	} else if (nb) {
++		return -1;
++	} else {
++		return 0;
++	}
++}
++
++ldns_status
++ldns_dnssec_name_add_rr(ldns_dnssec_name *name,
++				    ldns_rr *rr)
++{
++	ldns_status result = LDNS_STATUS_OK;
++	ldns_rr_type rr_type;
++	ldns_rr_type typecovered = 0;
++
++	/* special handling for NSEC3 and NSECX covering RRSIGS */
++
++	if (!name || !rr) {
++		return LDNS_STATUS_ERR;
++	}
++
++	rr_type = ldns_rr_get_type(rr);
++
++	if (rr_type == LDNS_RR_TYPE_RRSIG) {
++		typecovered = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
++	}
++
++	if (rr_type == LDNS_RR_TYPE_NSEC ||
++	    rr_type == LDNS_RR_TYPE_NSEC3) {
++		/* XX check if is already set (and error?) */
++		name->nsec = rr;
++	} else if (typecovered == LDNS_RR_TYPE_NSEC ||
++			 typecovered == LDNS_RR_TYPE_NSEC3) {
++		if (name->nsec_signatures) {
++			result = ldns_dnssec_rrs_add_rr(name->nsec_signatures, rr);
++		} else {
++			name->nsec_signatures = ldns_dnssec_rrs_new();
++			name->nsec_signatures->rr = rr;
++		}
++	} else {
++		/* it's a 'normal' RR, add it to the right rrset */
++		if (name->rrsets) {
++			result = ldns_dnssec_rrsets_add_rr(name->rrsets, rr);
++		} else {
++			name->rrsets = ldns_dnssec_rrsets_new();
++			result = ldns_dnssec_rrsets_add_rr(name->rrsets, rr);
++		}
++	}
++	return result;
++}
++
++ldns_dnssec_rrsets *
++ldns_dnssec_name_find_rrset(ldns_dnssec_name *name,
++					   ldns_rr_type type) {
++	ldns_dnssec_rrsets *result;
++
++	result = name->rrsets;
++	while (result) {
++		if (result->type == type) {
++			return result;
++		} else {
++			result = result->next;
++		}
++	}
++	return NULL;
++}
++
++ldns_dnssec_rrsets *
++ldns_dnssec_zone_find_rrset(ldns_dnssec_zone *zone,
++					   ldns_rdf *dname,
++					   ldns_rr_type type)
++{
++	ldns_rbnode_t *node;
++
++	if (!zone || !dname || !zone->names) {
++		return NULL;
++	}
++
++	node = ldns_rbtree_search(zone->names, dname);
++	if (node) {
++		return ldns_dnssec_name_find_rrset((ldns_dnssec_name *)node->data,
++									type);
++	} else {
++		return NULL;
++	}
++}
++
++static void
++ldns_dnssec_name_print_soa_fmt(FILE *out, const ldns_output_format *fmt,
++		ldns_dnssec_name *name, 
++		bool show_soa)
++{
++	if (name) {
++		if(name->rrsets) {
++			ldns_dnssec_rrsets_print_soa_fmt(out, fmt, 
++					name->rrsets, true, show_soa);
++		} else if ((fmt->flags & LDNS_COMMENT_LAYOUT)) {
++			fprintf(out, ";; Empty nonterminal: ");
++			ldns_rdf_print(out, name->name);
++			fprintf(out, "\n");
++		}
++		if(name->nsec) {
++			ldns_rr_print_fmt(out, fmt, name->nsec);
++		}
++		if (name->nsec_signatures) {
++			ldns_dnssec_rrs_print_fmt(out, fmt, 
++					name->nsec_signatures);
++		}
++	} else if ((fmt->flags & LDNS_COMMENT_LAYOUT)) {
++		fprintf(out, "; <void>\n");
++	}
++}
++
++
++void
++ldns_dnssec_name_print_fmt(FILE *out, const ldns_output_format *fmt,
++		ldns_dnssec_name *name)
++{
++	ldns_dnssec_name_print_soa_fmt(out, fmt, name, true);
++}
++
++void
++ldns_dnssec_name_print(FILE *out, ldns_dnssec_name *name)
++{
++	ldns_dnssec_name_print_fmt(out, ldns_output_format_default, name);
++}
++
++
++ldns_dnssec_zone *
++ldns_dnssec_zone_new(void)
++{
++	ldns_dnssec_zone *zone = LDNS_MALLOC(ldns_dnssec_zone);
++        if(!zone) return NULL;
++	zone->soa = NULL;
++	zone->names = NULL;
++	zone->hashed_names = NULL;
++	zone->_nsec3params = NULL;
++
++	return 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;
++}
++
++/* When the zone is first read into an list and then inserted into an
++ * ldns_dnssec_zone (rbtree) the nodes of the rbtree are allocated close (next)
++ * to each other. Because ldns-verify-zone (the only program that uses this
++ * function) uses the rbtree mostly for sequentual walking, this results
++ * in a speed increase (of 15% on linux) because we have less CPU-cache misses.
++ */
++#define FASTER_DNSSEC_ZONE_NEW_FRM_FP 1 /* Because of L2 cache efficiency */
++
++static ldns_status
++ldns_dnssec_zone_add_empty_nonterminals_nsec3(
++		ldns_dnssec_zone *zone, ldns_rbtree_t *nsec3s);
++
++static void
++ldns_todo_nsec3_ents_node_free(ldns_rbnode_t *node, void *arg) {
++	(void) arg;
++	ldns_rdf_deep_free((ldns_rdf *)node->key);
++	LDNS_FREE(node);
++}
++
++ldns_status
++ldns_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_rdf *my_origin = NULL;
++	ldns_rdf *my_prev = NULL;
++
++	ldns_dnssec_zone *newzone = ldns_dnssec_zone_new();
++	/* NSEC3s may occur before the names they refer to. We must remember
++	   them and add them to the name later on, after the name is read.
++	   We track not yet  matching NSEC3s*n the todo_nsec3s list */
++	ldns_rr_list* todo_nsec3s = ldns_rr_list_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.
++
++	   nsec3_ents (where ent is e.n.t.; i.e. empty non terminal) will
++	   hold the NSEC3s that still didn't have a matching name in the
++	   zone tree, even after all names were read.  They can only match
++	   after the zone is equiped with all the empty non terminals. */
++	ldns_rbtree_t todo_nsec3_ents;
++	ldns_rbnode_t *new_node;
++	ldns_rr_list* todo_nsec3_rrsigs = ldns_rr_list_new();
++
++	ldns_status status;
++
++#ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
++	ldns_zone* zone = NULL;
++#else
++	uint32_t  my_ttl = ttl;
++#endif
++
++	ldns_rbtree_init(&todo_nsec3_ents, ldns_dname_compare_v);
++
++#ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
++	status = ldns_zone_new_frm_fp_l(&zone, fp, origin,ttl, c, line_nr);
++	if (status != LDNS_STATUS_OK)
++		goto error;
++#endif
++	if (!newzone || !todo_nsec3s || !todo_nsec3_rrsigs ) {
++		status = LDNS_STATUS_MEM_ERR;
++		goto error;
++	}
++	if (origin) {
++		if (!(my_origin = ldns_rdf_clone(origin))) {
++			status = LDNS_STATUS_MEM_ERR;
++			goto error;
++		}
++		if (!(my_prev   = ldns_rdf_clone(origin))) {
++			status = LDNS_STATUS_MEM_ERR;
++			goto error;
++		}
++	}
++
++#ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
++	if (ldns_zone_soa(zone)) {
++		status = ldns_dnssec_zone_add_rr(newzone, ldns_zone_soa(zone));
++		if (status != LDNS_STATUS_OK)
++			goto error;
++	}
++	for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(zone)); i++) {
++		cur_rr = ldns_rr_list_rr(ldns_zone_rrs(zone), i);
++		status = LDNS_STATUS_OK;
++#else
++	while (!feof(fp)) {
++		status = ldns_rr_new_frm_fp_l(&cur_rr, fp, &my_ttl, &my_origin,
++				&my_prev, line_nr);
++
++#endif
++		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(todo_nsec3s,
++						       	cur_rr);
++				}
++				status = LDNS_STATUS_OK;
++
++			} else if (status != LDNS_STATUS_OK)
++				goto error;
++
++			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*/
++			status = LDNS_STATUS_OK;
++			break;
++
++		case LDNS_STATUS_SYNTAX_INCLUDE:/* $include not implemented */
++			status =  LDNS_STATUS_SYNTAX_INCLUDE_ERR_NOTIMPL;
++			break;
++
++		default:
++			goto error;
++		}
++	}
++
++	for (i = 0; status == LDNS_STATUS_OK &&
++			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);
++		if (status == LDNS_STATUS_DNSSEC_NSEC3_ORIGINAL_NOT_FOUND) {
++			if (!(new_node = LDNS_MALLOC(ldns_rbnode_t))) {
++				status = LDNS_STATUS_MEM_ERR;
++				break;
++			}
++			new_node->key  = ldns_dname_label(ldns_rr_owner(cur_rr), 0);
++			new_node->data = cur_rr;
++			if (!ldns_rbtree_insert(&todo_nsec3_ents, new_node)) {
++				LDNS_FREE(new_node);
++				status = LDNS_STATUS_MEM_ERR;
++				break;
++			}
++			status = LDNS_STATUS_OK;
++		}
++	}
++	if (todo_nsec3_ents.count > 0)
++		(void) ldns_dnssec_zone_add_empty_nonterminals_nsec3(
++				newzone, &todo_nsec3_ents);
++	for (i = 0; status == LDNS_STATUS_OK &&
++			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);
++	}
++	if (z) {
++		*z = newzone;
++		newzone = NULL;
++	} else {
++		ldns_dnssec_zone_free(newzone);
++	}
++
++error:
++#ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
++	if (zone) {
++		ldns_zone_free(zone);
++	}
++#endif
++	ldns_rr_list_free(todo_nsec3_rrsigs);
++	ldns_traverse_postorder(&todo_nsec3_ents,
++			ldns_todo_nsec3_ents_node_free, NULL);
++	ldns_rr_list_free(todo_nsec3s);
++
++	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;
++}
++
++ldns_status
++ldns_dnssec_zone_new_frm_fp(ldns_dnssec_zone** z, FILE* fp, ldns_rdf* origin,
++		uint32_t ttl, ldns_rr_class ATTR_UNUSED(c))
++{
++	return ldns_dnssec_zone_new_frm_fp_l(z, fp, origin, ttl, c, NULL);
++}
++
++static void
++ldns_dnssec_name_node_free(ldns_rbnode_t *node, void *arg) {
++	(void) arg;
++	ldns_dnssec_name_free((ldns_dnssec_name *)node->data);
++	LDNS_FREE(node);
++}
++
++static void
++ldns_dnssec_name_node_deep_free(ldns_rbnode_t *node, void *arg) {
++	(void) arg;
++	ldns_dnssec_name_deep_free((ldns_dnssec_name *)node->data);
++	LDNS_FREE(node);
++}
++
++void
++ldns_dnssec_zone_free(ldns_dnssec_zone *zone)
++{
++	if (zone) {
++		if (zone->names) {
++			/* destroy all name structures within the tree */
++			ldns_traverse_postorder(zone->names,
++						    ldns_dnssec_name_node_free,
++						    NULL);
++			LDNS_FREE(zone->names);
++		}
++		LDNS_FREE(zone);
++	}
++}
++
++void
++ldns_dnssec_zone_deep_free(ldns_dnssec_zone *zone)
++{
++	if (zone) {
++		if (zone->names) {
++			/* destroy all name structures within the tree */
++			ldns_traverse_postorder(zone->names,
++						    ldns_dnssec_name_node_deep_free,
++						    NULL);
++			LDNS_FREE(zone->names);
++		}
++		LDNS_FREE(zone);
++	}
++}
++
++/* use for dname comparison in tree */
++int
++ldns_dname_compare_v(const void *a, const void *b) {
++	return ldns_dname_compare((ldns_rdf *)a, (ldns_rdf *)b);
++}
++
++static void
++ldns_dnssec_name_make_hashed_name(ldns_dnssec_zone *zone,
++		ldns_dnssec_name* name, ldns_rr* nsec3rr);
++
++static void
++ldns_hashed_names_node_free(ldns_rbnode_t *node, void *arg) {
++	(void) arg;
++	LDNS_FREE(node);
++}
++
++static void
++ldns_dnssec_zone_hashed_names_from_nsec3(
++		ldns_dnssec_zone* zone, ldns_rr* nsec3rr)
++{
++	ldns_rbnode_t* current_node;
++	ldns_dnssec_name* current_name;
++
++	assert(zone != NULL);
++	assert(nsec3rr != NULL);
++
++	if (zone->hashed_names) {
++		ldns_traverse_postorder(zone->hashed_names,
++				ldns_hashed_names_node_free, NULL);
++		LDNS_FREE(zone->hashed_names);
++	}
++	zone->_nsec3params = nsec3rr;
++
++	/* So this is a NSEC3 zone.
++	* Calculate hashes for all names already in the zone
++	*/
++	zone->hashed_names = ldns_rbtree_create(ldns_dname_compare_v);
++	if (zone->hashed_names == NULL) {
++		return;
++	}
++	for ( current_node  = ldns_rbtree_first(zone->names)
++	    ; current_node != LDNS_RBTREE_NULL
++	    ; current_node  = ldns_rbtree_next(current_node)
++	    ) {
++		current_name = (ldns_dnssec_name *) current_node->data;
++		ldns_dnssec_name_make_hashed_name(zone, current_name, nsec3rr);
++
++	}
++}
++
++static void
++ldns_dnssec_name_make_hashed_name(ldns_dnssec_zone *zone,
++		ldns_dnssec_name* name, ldns_rr* nsec3rr)
++{
++	ldns_rbnode_t* new_node;
++
++	assert(name != NULL);
++	if (! zone->_nsec3params) {
++		if (! nsec3rr) {
++			return;
++		}
++		ldns_dnssec_zone_hashed_names_from_nsec3(zone, nsec3rr);
++
++	} else if (! nsec3rr) {
++		nsec3rr = zone->_nsec3params;
++	}
++	name->hashed_name = ldns_nsec3_hash_name_frm_nsec3(nsec3rr, name->name);
++
++	/* Also store in zone->hashed_names */
++	if ((new_node = LDNS_MALLOC(ldns_rbnode_t))) {
++
++		new_node->key  = name->hashed_name;
++		new_node->data = name;
++
++		if (ldns_rbtree_insert(zone->hashed_names, new_node) == NULL) {
++
++				LDNS_FREE(new_node);
++		}
++	}
++}
++
++
++static ldns_rbnode_t *
++ldns_dnssec_zone_find_nsec3_original(ldns_dnssec_zone *zone, ldns_rr *rr) {
++	ldns_rdf *hashed_name;
++
++	hashed_name = ldns_dname_label(ldns_rr_owner(rr), 0);
++	if (hashed_name == NULL) {
++		return NULL;
++	}
++	if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_NSEC3 && ! zone->_nsec3params){
++
++		ldns_dnssec_zone_hashed_names_from_nsec3(zone, rr);
++	}
++	if (zone->hashed_names == NULL) {
++		ldns_rdf_deep_free(hashed_name);
++		return NULL;
++	}
++	return  ldns_rbtree_search(zone->hashed_names, hashed_name);
++}
++
++ldns_status
++ldns_dnssec_zone_add_rr(ldns_dnssec_zone *zone, ldns_rr *rr)
++{
++	ldns_status result = LDNS_STATUS_OK;
++	ldns_dnssec_name *cur_name;
++	ldns_rbnode_t *cur_node;
++	ldns_rr_type type_covered = 0;
++
++	if (!zone || !rr) {
++		return LDNS_STATUS_ERR;
++	}
++
++	if (!zone->names) {
++		zone->names = ldns_rbtree_create(ldns_dname_compare_v);
++                if(!zone->names) return LDNS_STATUS_MEM_ERR;
++	}
++
++	/* we need the original of the hashed name if this is
++	   an NSEC3, or an RRSIG that covers an NSEC3 */
++	if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_RRSIG) {
++		type_covered = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
++	}
++	if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_NSEC3 ||
++	    type_covered == LDNS_RR_TYPE_NSEC3) {
++		cur_node = ldns_dnssec_zone_find_nsec3_original(zone, rr);
++		if (!cur_node) {
++			return LDNS_STATUS_DNSSEC_NSEC3_ORIGINAL_NOT_FOUND;
++		}
++	} else {
++		cur_node = ldns_rbtree_search(zone->names, ldns_rr_owner(rr));
++	}
++	if (!cur_node) {
++		/* add */
++		cur_name = ldns_dnssec_name_new_frm_rr(rr);
++                if(!cur_name) return LDNS_STATUS_MEM_ERR;
++		cur_node = LDNS_MALLOC(ldns_rbnode_t);
++                if(!cur_node) {
++                        ldns_dnssec_name_free(cur_name);
++                        return LDNS_STATUS_MEM_ERR;
++                }
++		cur_node->key = ldns_rr_owner(rr);
++		cur_node->data = cur_name;
++		(void)ldns_rbtree_insert(zone->names, cur_node);
++		ldns_dnssec_name_make_hashed_name(zone, cur_name, NULL);
++	} else {
++		cur_name = (ldns_dnssec_name *) cur_node->data;
++		result = ldns_dnssec_name_add_rr(cur_name, rr);
++	}
++	if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_SOA) {
++		zone->soa = cur_name;
++	}
++	return result;
++}
++
++void
++ldns_dnssec_zone_names_print_fmt(FILE *out, const ldns_output_format *fmt,
++		ldns_rbtree_t *tree, 
++		bool print_soa)
++{
++	ldns_rbnode_t *node;
++	ldns_dnssec_name *name;
++
++	node = ldns_rbtree_first(tree);
++	while (node != LDNS_RBTREE_NULL) {
++		name = (ldns_dnssec_name *) node->data;
++		ldns_dnssec_name_print_soa_fmt(out, fmt, name, print_soa);
++		if ((fmt->flags & LDNS_COMMENT_LAYOUT))
++			fprintf(out, ";\n");
++		node = ldns_rbtree_next(node);
++	}
++}
++
++void
++ldns_dnssec_zone_names_print(FILE *out, ldns_rbtree_t *tree, bool print_soa)
++{
++	ldns_dnssec_zone_names_print_fmt(out, ldns_output_format_default,
++		       tree, print_soa);
++}
++
++void
++ldns_dnssec_zone_print_fmt(FILE *out, const ldns_output_format *fmt,
++	       ldns_dnssec_zone *zone)
++{
++	if (zone) {
++		if (zone->soa) {
++			if ((fmt->flags & LDNS_COMMENT_LAYOUT)) {
++				fprintf(out, ";; Zone: ");
++				ldns_rdf_print(out, ldns_dnssec_name_name(
++							zone->soa));
++				fprintf(out, "\n;\n");
++			}
++			ldns_dnssec_rrsets_print_fmt(out, fmt,
++					ldns_dnssec_name_find_rrset(
++						zone->soa, 
++						LDNS_RR_TYPE_SOA), 
++					false);
++			if ((fmt->flags & LDNS_COMMENT_LAYOUT))
++				fprintf(out, ";\n");
++		}
++
++		if (zone->names) {
++			ldns_dnssec_zone_names_print_fmt(out, fmt, 
++					zone->names, false);
++		}
++	}
++}
++
++void
++ldns_dnssec_zone_print(FILE *out, ldns_dnssec_zone *zone)
++{
++	ldns_dnssec_zone_print_fmt(out, ldns_output_format_default, zone);
++}
++
++static ldns_status
++ldns_dnssec_zone_add_empty_nonterminals_nsec3(
++		ldns_dnssec_zone *zone, ldns_rbtree_t *nsec3s)
++{
++	ldns_dnssec_name *new_name;
++	ldns_rdf *cur_name;
++	ldns_rdf *next_name;
++	ldns_rbnode_t *cur_node, *next_node, *new_node;
++
++	/* for the detection */
++	uint16_t i, cur_label_count, next_label_count;
++	uint16_t soa_label_count = 0;
++	ldns_rdf *l1, *l2;
++	int lpos;
++
++	if (!zone) {
++		return LDNS_STATUS_ERR;
++	}
++	if (zone->soa && zone->soa->name) {
++		soa_label_count = ldns_dname_label_count(zone->soa->name);
++	}
++	
++	cur_node = ldns_rbtree_first(zone->names);
++	while (cur_node != LDNS_RBTREE_NULL) {
++		next_node = ldns_rbtree_next(cur_node);
++		
++		/* skip glue */
++		while (next_node != LDNS_RBTREE_NULL && 
++		       next_node->data &&
++		       ((ldns_dnssec_name *)next_node->data)->is_glue
++		) {
++			next_node = ldns_rbtree_next(next_node);
++		}
++
++		if (next_node == LDNS_RBTREE_NULL) {
++			next_node = ldns_rbtree_first(zone->names);
++		}
++		if (! cur_node->data || ! next_node->data) {
++			return LDNS_STATUS_ERR;
++		}
++		cur_name = ((ldns_dnssec_name *)cur_node->data)->name;
++		next_name = ((ldns_dnssec_name *)next_node->data)->name;
++		cur_label_count = ldns_dname_label_count(cur_name);
++		next_label_count = ldns_dname_label_count(next_name);
++
++		/* Since the names are in canonical order, we can
++		 * recognize empty non-terminals by their labels;
++		 * every label after the first one on the next owner
++		 * name is a non-terminal if it either does not exist
++		 * in the current name or is different from the same
++		 * label in the current name (counting from the end)
++		 */
++		for (i = 1; i < next_label_count - soa_label_count; i++) {
++			lpos = (int)cur_label_count - (int)next_label_count + (int)i;
++			if (lpos >= 0) {
++				l1 = ldns_dname_clone_from(cur_name, (uint8_t)lpos);
++			} else {
++				l1 = NULL;
++			}
++			l2 = ldns_dname_clone_from(next_name, i);
++
++			if (!l1 || ldns_dname_compare(l1, l2) != 0) {
++				/* We have an empty nonterminal, add it to the
++				 * tree
++				 */
++				ldns_rbnode_t *node = NULL;
++				ldns_rdf *ent_name;
++
++				if (!(ent_name = ldns_dname_clone_from(
++						next_name, i)))
++					return LDNS_STATUS_MEM_ERR;
++
++				if (nsec3s && zone->_nsec3params) {
++					ldns_rdf *ent_hashed_name;
++
++					if (!(ent_hashed_name =
++					    ldns_nsec3_hash_name_frm_nsec3(
++							zone->_nsec3params,
++							ent_name)))
++						return LDNS_STATUS_MEM_ERR;
++					node = ldns_rbtree_search(nsec3s, 
++							ent_hashed_name);
++					if (!node) {
++						ldns_rdf_deep_free(l1);
++						ldns_rdf_deep_free(l2);
++						continue;
++					}
++				}
++				new_name = ldns_dnssec_name_new();
++				if (!new_name) {
++					return LDNS_STATUS_MEM_ERR;
++				}
++				new_name->name = ent_name;
++				if (!new_name->name) {
++					ldns_dnssec_name_free(new_name);
++					return LDNS_STATUS_MEM_ERR;
++				}
++				new_name->name_alloced = true;
++				new_node = LDNS_MALLOC(ldns_rbnode_t);
++				if (!new_node) {
++					ldns_dnssec_name_free(new_name);
++					return LDNS_STATUS_MEM_ERR;
++				}
++				new_node->key = new_name->name;
++				new_node->data = new_name;
++				(void)ldns_rbtree_insert(zone->names, new_node);
++				ldns_dnssec_name_make_hashed_name(
++						zone, new_name, NULL);
++				if (node)
++					(void) ldns_dnssec_zone_add_rr(zone,
++							(ldns_rr *)node->data);
++			}
++			ldns_rdf_deep_free(l1);
++			ldns_rdf_deep_free(l2);
++		}
++		
++		/* we might have inserted a new node after
++		 * the current one so we can't just use next()
++		 */
++		if (next_node != ldns_rbtree_first(zone->names)) {
++			cur_node = next_node;
++		} else {
++			cur_node = LDNS_RBTREE_NULL;
++		}
++	}
++	return LDNS_STATUS_OK;
++}
++
++ldns_status
++ldns_dnssec_zone_add_empty_nonterminals(ldns_dnssec_zone *zone)
++{
++	return ldns_dnssec_zone_add_empty_nonterminals_nsec3(zone, NULL);
++}
++
++bool
++ldns_dnssec_zone_is_nsec3_optout(ldns_dnssec_zone* zone)
++{
++	ldns_rr* nsec3;
++	ldns_rbnode_t* node;
++
++	if (ldns_dnssec_name_find_rrset(zone->soa, LDNS_RR_TYPE_NSEC3PARAM)) {
++		node = ldns_rbtree_first(zone->names);
++		while (node != LDNS_RBTREE_NULL) {
++			nsec3 = ((ldns_dnssec_name*)node->data)->nsec;
++			if (nsec3 &&ldns_rr_get_type(nsec3) 
++					== LDNS_RR_TYPE_NSEC3 &&
++					ldns_nsec3_optout(nsec3)) {
++				return true;
++			}
++			node = ldns_rbtree_next(node);
++		}
++	}
++	return false;
++}
+diff --git a/ldns/src/duration.c b/ldns/src/duration.c
+new file mode 100644
+index 0000000..6d0a388
+--- /dev/null
++++ b/ldns/src/duration.c
+@@ -0,0 +1,354 @@
++/*
++ * $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/config.h>
++#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 (int) (d1->years - d2->years);
++    }
++    if (d1->months != d2->months) {
++        return (int) (d1->months - d2->months);
++    }
++    if (d1->weeks != d2->weeks) {
++        return (int) (d1->weeks - d2->weeks);
++    }
++    if (d1->days != d2->days) {
++        return (int) (d1->days - d2->days);
++    }
++    if (d1->hours != d2->hours) {
++        return (int) (d1->hours - d2->hours);
++    }
++    if (d1->minutes != d2->minutes) {
++        return (int) (d1->minutes - d2->minutes);
++    }
++    if (d1->seconds != d2->seconds) {
++        return (int) (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 = (time_t) 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 = (time_t) atoi(str+1);
++        str = X;
++        not_weeks = 1;
++    }
++    X = strchr(str, 'D');
++    if (X) {
++        duration->days = (time_t) atoi(str+1);
++        str = X;
++        not_weeks = 1;
++    }
++    if (T) {
++        str = T;
++        not_weeks = 1;
++    }
++    X = strchr(str, 'H');
++    if (X && T) {
++        duration->hours = (time_t) 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 = (time_t) atoi(str+1);
++        str = X;
++        not_weeks = 1;
++    }
++    X = strchr(str, 'S');
++    if (X && T) {
++        duration->seconds = (time_t) 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 = (time_t) 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", (unsigned int) 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", (unsigned int) 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", (unsigned int) 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", (unsigned int) 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", (unsigned int) 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", (unsigned int) 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", (unsigned int) 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;
++
++    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;
++}
++
++
++/**
++ * Clean up duration.
++ *
++ */
++void
++ldns_duration_cleanup(ldns_duration_type* duration)
++{
++    if (!duration) {
++        return;
++    }
++    free(duration);
++    return;
++}
+diff --git a/ldns/src/error.c b/ldns/src/error.c
+new file mode 100644
+index 0000000..82ea61a
+--- /dev/null
++++ b/ldns/src/error.c
+@@ -0,0 +1,160 @@
++/*
++ * a error2str function to make sense of all the
++ * error codes we have laying ardoun
++ *
++ * a Net::DNS like library for C
++ * LibDNS Team @ NLnet Labs
++ * (c) NLnet Labs, 2005-2006
++ * See the file LICENSE for the license
++ */
++
++#include <ldns/config.h>
++
++#include <ldns/ldns.h>
++
++ldns_lookup_table ldns_error_str[] = {
++	{ LDNS_STATUS_OK, "All OK" },
++	{ LDNS_STATUS_EMPTY_LABEL, "Empty label" },
++        { LDNS_STATUS_LABEL_OVERFLOW, "Label length overflow" },
++        { LDNS_STATUS_DOMAINNAME_OVERFLOW, "Domainname length overflow" },
++        { LDNS_STATUS_DOMAINNAME_UNDERFLOW, "Domainname length underflow (zero length)" },
++        { LDNS_STATUS_DDD_OVERFLOW, "\\DDD sequence overflow (>255)" },
++        { LDNS_STATUS_PACKET_OVERFLOW, "Packet size overflow" },
++        { LDNS_STATUS_INVALID_POINTER, "Invalid compression pointer" },
++        { LDNS_STATUS_MEM_ERR, "General memory error" },
++        { LDNS_STATUS_INTERNAL_ERR, "Internal error, this should not happen" },
++        { LDNS_STATUS_SSL_ERR, "Error in SSL library" },
++        { LDNS_STATUS_ERR, "General LDNS error" },
++        { LDNS_STATUS_INVALID_INT, "Conversion error, integer expected" },
++        { LDNS_STATUS_INVALID_IP4, "Conversion error, ip4 addr expected" },
++        { LDNS_STATUS_INVALID_IP6, "Conversion error, ip6 addr expected" },
++        { LDNS_STATUS_INVALID_STR, "Conversion error, string expected" },
++	{ LDNS_STATUS_INVALID_B32_EXT, "Conversion error, b32 ext encoding expected" },
++        { LDNS_STATUS_INVALID_B64, "Conversion error, b64 encoding expected" },
++        { LDNS_STATUS_INVALID_HEX, "Conversion error, hex encoding expected" },
++        { LDNS_STATUS_INVALID_TIME, "Conversion error, time encoding expected" },
++        { LDNS_STATUS_NETWORK_ERR, "Could not send or receive, because of network error" },
++        { LDNS_STATUS_ADDRESS_ERR, "Could not start AXFR, because of address error" },
++        { LDNS_STATUS_FILE_ERR, "Could not open the files" },
++        { LDNS_STATUS_UNKNOWN_INET, "Uknown address family" },
++        { LDNS_STATUS_NOT_IMPL, "This function is not implemented (yet), please notify the developers - or not..." },
++	{ LDNS_STATUS_NULL, "Supplied value pointer null" },
++        { LDNS_STATUS_CRYPTO_UNKNOWN_ALGO, "Unknown cryptographic algorithm" },
++        { LDNS_STATUS_CRYPTO_ALGO_NOT_IMPL, "Cryptographic algorithm not implemented" },
++        { LDNS_STATUS_CRYPTO_NO_RRSIG, "No DNSSEC signature(s)" },
++        { LDNS_STATUS_CRYPTO_NO_DNSKEY, "No DNSSEC public key(s)" },
++        { LDNS_STATUS_CRYPTO_TYPE_COVERED_ERR, "The signature does not cover this RRset" },
++        { LDNS_STATUS_CRYPTO_NO_TRUSTED_DNSKEY, "No signatures found for trusted DNSSEC public key(s)" },
++        { LDNS_STATUS_CRYPTO_NO_DS, "No DS record(s)" },
++        { LDNS_STATUS_CRYPTO_NO_TRUSTED_DS, "Could not validate DS record(s)" },
++        { LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY, "No keys with the keytag and algorithm from the RRSIG found" },
++        { LDNS_STATUS_CRYPTO_VALIDATED, "Valid DNSSEC signature" },
++        { LDNS_STATUS_CRYPTO_BOGUS, "Bogus DNSSEC signature" },
++        { LDNS_STATUS_CRYPTO_SIG_EXPIRED, "DNSSEC signature has expired" },
++        { LDNS_STATUS_CRYPTO_SIG_NOT_INCEPTED, "DNSSEC signature not incepted yet" },
++	{ LDNS_STATUS_CRYPTO_TSIG_BOGUS, "Bogus TSIG signature" },
++	{ LDNS_STATUS_CRYPTO_TSIG_ERR, "Could not create TSIG signature" },
++        { LDNS_STATUS_CRYPTO_EXPIRATION_BEFORE_INCEPTION, "DNSSEC signature has expiration date earlier than inception date" },
++	{ LDNS_STATUS_ENGINE_KEY_NOT_LOADED, "Unable to load private key from engine" },
++        { LDNS_STATUS_NSEC3_ERR, "Error in NSEC3 denial of existence proof" },
++	{ LDNS_STATUS_RES_NO_NS, "No (valid) nameservers defined in the resolver" },
++	{ LDNS_STATUS_RES_QUERY, "No correct query given to resolver" },
++	{ LDNS_STATUS_WIRE_INCOMPLETE_HEADER, "header section incomplete" },
++	{ LDNS_STATUS_WIRE_INCOMPLETE_QUESTION, "question section incomplete" },
++	{ LDNS_STATUS_WIRE_INCOMPLETE_ANSWER, "answer section incomplete" },
++	{ LDNS_STATUS_WIRE_INCOMPLETE_AUTHORITY, "authority section incomplete" },
++	{ LDNS_STATUS_WIRE_INCOMPLETE_ADDITIONAL, "additional section incomplete" },
++	{ LDNS_STATUS_NO_DATA, "No data" },
++	{ LDNS_STATUS_EXISTS_ERR, "Element already exists" },
++	{ LDNS_STATUS_CERT_BAD_ALGORITHM, "Bad algorithm type for CERT record" },
++	{ LDNS_STATUS_SYNTAX_TYPE_ERR, "Syntax error, could not parse the RR's type" },
++	{ LDNS_STATUS_SYNTAX_CLASS_ERR, "Syntax error, could not parse the RR's class" },
++	{ LDNS_STATUS_SYNTAX_TTL_ERR, "Syntax error, could not parse the RR's TTL" },
++	{ LDNS_STATUS_SYNTAX_INCLUDE_ERR_NOTIMPL, "Syntax error, $INCLUDE not implemented" },
++	{ LDNS_STATUS_SYNTAX_RDATA_ERR, "Syntax error, could not parse the RR's rdata" },
++	{ LDNS_STATUS_SYNTAX_DNAME_ERR, "Syntax error, could not parse the RR's dname(s)" },
++	{ LDNS_STATUS_SYNTAX_VERSION_ERR, "Syntax error, version mismatch" },
++	{ LDNS_STATUS_SYNTAX_ALG_ERR, "Syntax error, algorithm unknown or non parseable" },
++	{ LDNS_STATUS_SYNTAX_KEYWORD_ERR, "Syntax error, unknown keyword in input" },
++	{ LDNS_STATUS_SYNTAX_ERR, "Syntax error, could not parse the RR" },
++	{ LDNS_STATUS_SYNTAX_EMPTY, "Empty line was returned" },
++	{ LDNS_STATUS_SYNTAX_TTL, "$TTL directive was seen in the zone" },
++	{ LDNS_STATUS_SYNTAX_ORIGIN, "$ORIGIN directive was seen in the zone" },
++	{ LDNS_STATUS_SYNTAX_INCLUDE, "$INCLUDE directive was seen in the zone" },
++	{ LDNS_STATUS_SYNTAX_ITERATIONS_OVERFLOW, "Iterations count for NSEC3 record higher than maximum" },
++	{ LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR, "Syntax error, value expected" },
++	{ LDNS_STATUS_SYNTAX_INTEGER_OVERFLOW, "Syntax error, integer value too large" },
++	{ LDNS_STATUS_SYNTAX_BAD_ESCAPE, "Syntax error, bad escape sequence" },
++	{ LDNS_STATUS_SOCKET_ERROR, "Error creating socket" },
++	{ LDNS_STATUS_DNSSEC_EXISTENCE_DENIED, "Existence denied by NSEC" },
++	{ LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED, "RR not covered by the given NSEC RRs" },
++	{ LDNS_STATUS_DNSSEC_NSEC_WILDCARD_NOT_COVERED, "wildcard not covered by the given NSEC RRs" },
++	{ LDNS_STATUS_DNSSEC_NSEC3_ORIGINAL_NOT_FOUND, "original of NSEC3 hashed name could not be found" },
++	{ LDNS_STATUS_MISSING_RDATA_FIELDS_RRSIG, "The RRSIG has to few rdata fields" },
++	{ LDNS_STATUS_MISSING_RDATA_FIELDS_KEY, "The DNSKEY has to few rdata fields" },
++	{ LDNS_STATUS_CRYPTO_SIG_EXPIRED_WITHIN_MARGIN, 
++		"DNSSEC signature will expire too soon" },
++	{ LDNS_STATUS_CRYPTO_SIG_NOT_INCEPTED_WITHIN_MARGIN,
++		"DNSSEC signature not incepted long enough" },
++	{ LDNS_STATUS_DANE_UNKNOWN_CERTIFICATE_USAGE,
++		"Unknown TLSA Certificate Usage" },
++	{ LDNS_STATUS_DANE_UNKNOWN_SELECTOR, "Unknown TLSA Selector" },
++	{ LDNS_STATUS_DANE_UNKNOWN_MATCHING_TYPE,
++		"Unknown TLSA Matching Type" },
++	{ LDNS_STATUS_DANE_UNKNOWN_PROTOCOL,
++		"Unknown protocol. Only IPv4 and IPv6 are understood" },
++	{ LDNS_STATUS_DANE_UNKNOWN_TRANSPORT,
++		"Unknown transport. Should be one of {tcp, udp, sctp}" },
++	{ LDNS_STATUS_DANE_MISSING_EXTRA_CERTS,  /* Trust anchor assertion */
++		"More than one certificate should be provided" },
++	{ LDNS_STATUS_DANE_EXTRA_CERTS_NOT_USED, /* Trust anchor assertion */
++		"Non of the extra certificates is used to sign the first" },
++	{ LDNS_STATUS_DANE_OFFSET_OUT_OF_RANGE,   /* Trust anchor assertion */
++		"The offset was out of range" },
++	{ LDNS_STATUS_DANE_INSECURE,             /* Unused by library */
++		"The queried resource records were insecure" },
++	{ LDNS_STATUS_DANE_BOGUS,             /* Unused by library */
++		"The queried resource records were bogus" },
++	{ LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH,
++		"The TLSA record(s) "
++		"did not match with the server certificate (chain)" },
++	{ LDNS_STATUS_DANE_NON_CA_CERTIFICATE,
++		"The certificate was not a CA certificate" },
++	{ LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE,
++		"Could not PKIX validate" },
++	{ LDNS_STATUS_DANE_PKIX_NO_SELF_SIGNED_TRUST_ANCHOR,
++		"The validation path "
++		"did not end in a self-signed certificate" },
++        { LDNS_STATUS_INVALID_ILNP64, 
++		"Conversion error, 4 colon separated hex numbers expected" },
++        { LDNS_STATUS_INVALID_EUI48, 
++		"Conversion error, 6 two character hex numbers "
++		"separated by dashes expected (i.e. xx-xx-xx-xx-xx-xx" },
++        { LDNS_STATUS_INVALID_EUI64, 
++		"Conversion error, 8 two character hex numbers "
++		"separated by dashes expected (i.e. xx-xx-xx-xx-xx-xx-xx-xx" },
++	{ LDNS_STATUS_WIRE_RDATA_ERR, "invalid rdata in wire format" },
++        { LDNS_STATUS_INVALID_TAG, 
++		"Conversion error, a non-zero sequence of US-ASCII letters "
++		"and numbers in lower case expected" },
++        { LDNS_STATUS_TYPE_NOT_IN_BITMAP, 
++		"The RR type bitmap rdata field did not have "
++		"a bit reserved for the specific RR type" },
++        { LDNS_STATUS_INVALID_RDF_TYPE, 
++		"The rdata field was not of the expected type" },
++        { LDNS_STATUS_RDATA_OVERFLOW, "Rdata size overflow" },
++	{ 0, NULL }
++};
++
++const char *
++ldns_get_errorstr_by_id(ldns_status err)
++{
++        ldns_lookup_table *lt;
++
++        lt = ldns_lookup_by_id(ldns_error_str, err);
++
++        if (lt) {
++                return lt->name;
++        }
++        return NULL;
++}
+diff --git a/ldns/src/higher.c b/ldns/src/higher.c
+new file mode 100644
+index 0000000..8ce86a4
+--- /dev/null
++++ b/ldns/src/higher.c
+@@ -0,0 +1,344 @@
++/*
++ * higher.c
++ *
++ * Specify some higher level functions that would
++ * be usefull to would be developers
++ *
++ * a Net::DNS like library for C
++ *
++ * (c) NLnet Labs, 2004-2006
++ *
++ * See the file LICENSE for the license
++ */
++
++#include <ldns/config.h>
++
++#include <ldns/ldns.h>
++
++#ifdef HAVE_SSL
++#include <openssl/ssl.h>
++#include <openssl/sha.h>
++#endif /* HAVE_SSL */
++
++ldns_rr_list *
++ldns_get_rr_list_addr_by_name(ldns_resolver *res, ldns_rdf *name, ldns_rr_class c, 
++		uint16_t flags)
++{
++	ldns_pkt *pkt;
++	ldns_rr_list *aaaa;
++	ldns_rr_list *a;
++	ldns_rr_list *result = NULL;
++	ldns_rr_list *hostsfilenames;
++	size_t i;
++	uint8_t ip6;
++
++	a = NULL; 
++	aaaa = NULL; 
++	result = NULL;
++
++	if (!res) {
++		return NULL;
++	}
++	if (ldns_rdf_get_type(name) != LDNS_RDF_TYPE_DNAME) {
++		return NULL;
++	}
++
++	ip6 = ldns_resolver_ip6(res); /* we use INET_ANY here, save
++					 what was there */
++
++	ldns_resolver_set_ip6(res, LDNS_RESOLV_INETANY);
++	
++	hostsfilenames = ldns_get_rr_list_hosts_frm_file(NULL);
++	for (i = 0; i < ldns_rr_list_rr_count(hostsfilenames); i++) {
++		if (ldns_rdf_compare(name, 
++					ldns_rr_owner(ldns_rr_list_rr(hostsfilenames, 
++							i))) == 0) {
++			if (!result) {
++				result = ldns_rr_list_new();
++			}
++			ldns_rr_list_push_rr(result, 
++					ldns_rr_clone(ldns_rr_list_rr(hostsfilenames, i)));
++		}
++	}
++	ldns_rr_list_deep_free(hostsfilenames);
++
++	if (result) {
++		return result;
++	}
++
++	/* add the RD flags, because we want an answer */
++	pkt = ldns_resolver_query(res, name, LDNS_RR_TYPE_AAAA, c, flags | LDNS_RD);
++	if (pkt) {
++		/* extract the data we need */
++		aaaa = ldns_pkt_rr_list_by_type(pkt, LDNS_RR_TYPE_AAAA, 
++			LDNS_SECTION_ANSWER);
++		ldns_pkt_free(pkt);
++	} 
++
++	pkt = ldns_resolver_query(res, name, LDNS_RR_TYPE_A, c, flags | LDNS_RD);
++	if (pkt) {
++		/* extract the data we need */
++		a = ldns_pkt_rr_list_by_type(pkt, LDNS_RR_TYPE_A, LDNS_SECTION_ANSWER);
++		ldns_pkt_free(pkt);
++	} 
++	ldns_resolver_set_ip6(res, ip6);
++
++	if (aaaa && a) {
++		result = ldns_rr_list_cat_clone(aaaa, a);
++		ldns_rr_list_deep_free(aaaa);
++		ldns_rr_list_deep_free(a);
++		return result;
++	}
++	
++	if (aaaa) {
++		result = ldns_rr_list_clone(aaaa);
++	}
++	
++	if (a) {
++		result = ldns_rr_list_clone(a);
++	}
++
++	ldns_rr_list_deep_free(aaaa);
++	ldns_rr_list_deep_free(a);
++	return result;
++}
++
++ldns_rr_list *
++ldns_get_rr_list_name_by_addr(ldns_resolver *res, ldns_rdf *addr, ldns_rr_class c, 
++		uint16_t flags)
++{
++	ldns_pkt *pkt;
++	ldns_rr_list *names;
++	ldns_rdf *name;
++
++	names = NULL;
++
++	if (!res || !addr) {
++		return NULL;
++	}
++
++	if (ldns_rdf_get_type(addr) != LDNS_RDF_TYPE_A &&
++			ldns_rdf_get_type(addr) != LDNS_RDF_TYPE_AAAA) {
++		return NULL;
++	}
++
++	name = ldns_rdf_address_reverse(addr);
++	
++	/* add the RD flags, because we want an answer */
++	pkt = ldns_resolver_query(res, name, LDNS_RR_TYPE_PTR, c, flags | LDNS_RD);
++	ldns_rdf_deep_free(name);
++	if (pkt) {
++		/* extract the data we need */
++		names = ldns_pkt_rr_list_by_type(pkt, 
++				LDNS_RR_TYPE_PTR, LDNS_SECTION_ANSWER);
++		ldns_pkt_free(pkt);
++	}
++	return names;
++}
++
++/* read a line, put it in a buffer, parse the buffer */
++ldns_rr_list *
++ldns_get_rr_list_hosts_frm_fp(FILE *fp)
++{
++	return ldns_get_rr_list_hosts_frm_fp_l(fp, NULL);
++}
++
++ldns_rr_list *
++ldns_get_rr_list_hosts_frm_fp_l(FILE *fp, int *line_nr)
++{
++	ssize_t i, j;
++	size_t cnt;
++	char *line;
++	char *word;
++	char *addr;
++	char *rr_str;
++	ldns_buffer *linebuf;
++	ldns_rr *rr;
++	ldns_rr_list *list;
++	ldns_rdf *tmp;
++	bool ip6;
++	ldns_status parse_result;
++
++	line = LDNS_XMALLOC(char, LDNS_MAX_LINELEN + 1);
++	word = LDNS_XMALLOC(char, LDNS_MAX_LINELEN + 1);
++	addr = LDNS_XMALLOC(char, LDNS_MAX_LINELEN + 1);
++	rr_str = LDNS_XMALLOC(char, LDNS_MAX_LINELEN + 1);
++	ip6 = false;
++	list = ldns_rr_list_new();
++	rr = NULL;
++	if(!line || !word || !addr || !rr_str || !list) {
++		LDNS_FREE(line);
++		LDNS_FREE(word);
++		LDNS_FREE(addr);
++		LDNS_FREE(rr_str);
++		ldns_rr_list_free(list);
++		return NULL;
++	}
++
++	for(i = ldns_fget_token_l(fp, line, "\n", LDNS_MAX_LINELEN, line_nr);
++			i > 0; i = ldns_fget_token_l(fp, line, "\n", LDNS_MAX_LINELEN, line_nr)) {
++		/* # is comment */
++		if (line[0] == '#') {
++			continue;
++		}
++		/* put it in a buffer for further processing */
++		linebuf = LDNS_MALLOC(ldns_buffer);
++		if(!linebuf) {
++			LDNS_FREE(line);
++			LDNS_FREE(word);
++			LDNS_FREE(addr);
++			LDNS_FREE(rr_str);
++			ldns_rr_list_deep_free(list);
++			return NULL;
++		}
++
++		ldns_buffer_new_frm_data(linebuf, line, (size_t) i);
++		for(cnt = 0, j = ldns_bget_token(linebuf, word, LDNS_PARSE_NO_NL, LDNS_MAX_LINELEN);
++				j > 0;
++				j = ldns_bget_token(linebuf, word, LDNS_PARSE_NO_NL, LDNS_MAX_LINELEN), cnt++) {
++			if (cnt == 0) {
++				/* the address */
++				if ((tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_AAAA, 
++								word))) {
++					/* ip6 */
++					ldns_rdf_deep_free(tmp);
++					ip6 = true;
++				} else {
++					if ((tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_A, 
++									word))) {
++						/* ip4 */
++						ldns_rdf_deep_free(tmp);
++						ip6 = false;
++					} else {
++						/* kaput */
++						break;
++					}
++				}
++				(void)strlcpy(addr, word, LDNS_MAX_LINELEN+1);
++			} else {
++				/* la al la la */
++				if (ip6) {
++					snprintf(rr_str, LDNS_MAX_LINELEN, 
++						"%s IN AAAA %s", word, addr);
++				} else {
++					snprintf(rr_str, LDNS_MAX_LINELEN, 
++						"%s IN A %s", word, addr);
++				}
++				parse_result = ldns_rr_new_frm_str(&rr, rr_str, 0, NULL, NULL);
++				if (parse_result == LDNS_STATUS_OK && ldns_rr_owner(rr) && ldns_rr_rd_count(rr) > 0) {
++					ldns_rr_list_push_rr(list, ldns_rr_clone(rr));
++				}
++				ldns_rr_free(rr);
++			}
++		}
++		ldns_buffer_free(linebuf);
++	}
++	LDNS_FREE(line);
++	LDNS_FREE(word);
++	LDNS_FREE(addr);
++	LDNS_FREE(rr_str);
++	return list;
++}
++
++ldns_rr_list *
++ldns_get_rr_list_hosts_frm_file(char *filename)
++{
++	ldns_rr_list *names;
++	FILE *fp;
++
++	if (!filename) {
++                fp = fopen(LDNS_RESOLV_HOSTS, "r");
++        
++        } else {
++                fp = fopen(filename, "r");
++        }
++        if (!fp) {
++                return NULL;
++        }
++
++	names = ldns_get_rr_list_hosts_frm_fp(fp);
++	fclose(fp);
++	return names;
++}
++
++uint16_t
++ldns_getaddrinfo(ldns_resolver *res, ldns_rdf *node, ldns_rr_class c, 
++		ldns_rr_list **ret)
++{
++	ldns_rdf_type t;
++	uint16_t names_found;
++	ldns_resolver *r;
++	ldns_status s;
++
++	t = ldns_rdf_get_type(node);
++	names_found = 0;
++	r = res;
++
++	if (res == NULL) {
++		/* prepare a new resolver, using /etc/resolv.conf as a guide  */
++		s = ldns_resolver_new_frm_file(&r, NULL);
++		if (s != LDNS_STATUS_OK) {
++			return 0;
++		} 
++	}
++
++	if (t == LDNS_RDF_TYPE_DNAME) {
++		/* we're asked to query for a name */
++		*ret = ldns_get_rr_list_addr_by_name(r, node, c, 0);
++		names_found = ldns_rr_list_rr_count(*ret);
++	}
++
++	if (t == LDNS_RDF_TYPE_A || t == LDNS_RDF_TYPE_AAAA) {
++		/* an address */
++		*ret = ldns_get_rr_list_name_by_addr(r, node, c, 0);
++		names_found = ldns_rr_list_rr_count(*ret);
++	}
++
++	if (res == NULL) {
++		ldns_resolver_deep_free(r);
++	}
++	
++	return names_found;
++}
++
++bool
++ldns_nsec_type_check(ldns_rr *nsec, ldns_rr_type t)
++{
++	switch (ldns_rr_get_type(nsec)) {
++	case LDNS_RR_TYPE_NSEC	: if (ldns_rr_rd_count(nsec) < 2) {
++					  return false;
++				  }
++				  return ldns_nsec_bitmap_covers_type(
++						  ldns_rr_rdf(nsec, 1), t);
++
++	case LDNS_RR_TYPE_NSEC3	: if (ldns_rr_rd_count(nsec) < 6) {
++					  return false;
++				  }
++				  return ldns_nsec_bitmap_covers_type(
++						  ldns_rr_rdf(nsec, 5), t);
++
++	default			: return false;
++	}
++}
++
++void
++ldns_print_rr_rdf(FILE *fp, ldns_rr *r, int rdfnum, ...)
++{
++	int16_t rdf;
++	ldns_rdf *rd;
++	va_list va_rdf;
++	va_start(va_rdf, rdfnum);
++
++	for (rdf = (int16_t)rdfnum; rdf != -1; rdf = (int16_t)va_arg(va_rdf, int)) 
++	{
++		rd = ldns_rr_rdf(r, rdf);
++		if (!rd) {
++			continue;
++		} else {
++			ldns_rdf_print(fp, rd);
++			fprintf(fp, " "); /* not sure if we want to do this */
++		}
++	}
++	va_end(va_rdf);
++}
++
+diff --git a/ldns/src/host2str.c b/ldns/src/host2str.c
+new file mode 100644
+index 0000000..3445254
+--- /dev/null
++++ b/ldns/src/host2str.c
+@@ -0,0 +1,2635 @@
++/*
++ * host2str.c
++ *
++ * conversion routines from the host format
++ * to the presentation format (strings)
++ *
++ * a Net::DNS like library for C
++ *
++ * (c) NLnet Labs, 2004-2006
++ *
++ * See the file LICENSE for the license
++ */
++#include <ldns/config.h>
++
++#include <ldns/ldns.h>
++
++#include <limits.h>
++
++#ifdef HAVE_SYS_SOCKET_H
++#include <sys/socket.h>
++#endif
++#ifdef HAVE_ARPA_INET_H
++#include <arpa/inet.h>
++#endif
++#ifdef HAVE_NETDB_H
++#include <netdb.h>
++#endif
++#include <time.h>
++#include <sys/time.h>
++
++#ifndef INET_ADDRSTRLEN
++#define INET_ADDRSTRLEN 16
++#endif
++#ifndef INET6_ADDRSTRLEN
++#define INET6_ADDRSTRLEN 46
++#endif
++
++/* lookup tables for standard DNS stuff  */
++
++/* Taken from RFC 2535, section 7.  */
++ldns_lookup_table ldns_algorithms[] = {
++        { LDNS_RSAMD5, "RSAMD5" },
++        { LDNS_DH, "DH" },
++        { LDNS_DSA, "DSA" },
++        { LDNS_ECC, "ECC" },
++        { LDNS_RSASHA1, "RSASHA1" },
++        { LDNS_DSA_NSEC3, "DSA-NSEC3-SHA1" },
++        { LDNS_RSASHA1_NSEC3, "RSASHA1-NSEC3-SHA1" },
++#ifdef USE_SHA2
++	{ LDNS_RSASHA256, "RSASHA256"},
++	{ LDNS_RSASHA512, "RSASHA512"},
++#endif
++#ifdef USE_GOST
++	{ LDNS_ECC_GOST, "ECC-GOST"},
++#endif
++#ifdef USE_ECDSA
++        { LDNS_ECDSAP256SHA256, "ECDSAP256SHA256"},
++        { LDNS_ECDSAP384SHA384, "ECDSAP384SHA384"},
++#endif
++        { LDNS_INDIRECT, "INDIRECT" },
++        { LDNS_PRIVATEDNS, "PRIVATEDNS" },
++        { LDNS_PRIVATEOID, "PRIVATEOID" },
++        { 0, NULL }
++};
++
++/* Taken from RFC 4398  */
++ldns_lookup_table ldns_cert_algorithms[] = {
++        { LDNS_CERT_PKIX, "PKIX" },
++        { LDNS_CERT_SPKI, "SPKI" },
++        { LDNS_CERT_PGP, "PGP" },
++        { LDNS_CERT_IPKIX, "IPKIX" },
++        { LDNS_CERT_ISPKI, "ISPKI" },
++        { LDNS_CERT_IPGP, "IPGP" },
++        { LDNS_CERT_ACPKIX, "ACPKIX" },
++        { LDNS_CERT_IACPKIX, "IACPKIX" },
++        { LDNS_CERT_URI, "URI" },
++        { LDNS_CERT_OID, "OID" },
++        { 0, NULL }
++};
++
++/* classes  */
++ldns_lookup_table ldns_rr_classes[] = {
++        { LDNS_RR_CLASS_IN, "IN" },
++        { LDNS_RR_CLASS_CH, "CH" },
++        { LDNS_RR_CLASS_HS, "HS" },
++        { LDNS_RR_CLASS_NONE, "NONE" },
++        { LDNS_RR_CLASS_ANY, "ANY" },
++        { 0, NULL }
++};
++
++/* if these are used elsewhere */
++ldns_lookup_table ldns_rcodes[] = {
++        { LDNS_RCODE_NOERROR, "NOERROR" },
++        { LDNS_RCODE_FORMERR, "FORMERR" },
++        { LDNS_RCODE_SERVFAIL, "SERVFAIL" },
++        { LDNS_RCODE_NXDOMAIN, "NXDOMAIN" },
++        { LDNS_RCODE_NOTIMPL, "NOTIMPL" },
++        { LDNS_RCODE_REFUSED, "REFUSED" },
++        { LDNS_RCODE_YXDOMAIN, "YXDOMAIN" },
++        { LDNS_RCODE_YXRRSET, "YXRRSET" },
++        { LDNS_RCODE_NXRRSET, "NXRRSET" },
++        { LDNS_RCODE_NOTAUTH, "NOTAUTH" },
++        { LDNS_RCODE_NOTZONE, "NOTZONE" },
++        { 0, NULL }
++};
++
++ldns_lookup_table ldns_opcodes[] = {
++        { LDNS_PACKET_QUERY, "QUERY" },
++        { LDNS_PACKET_IQUERY, "IQUERY" },
++        { LDNS_PACKET_STATUS, "STATUS" },
++	{ LDNS_PACKET_NOTIFY, "NOTIFY" },
++	{ LDNS_PACKET_UPDATE, "UPDATE" },
++        { 0, NULL }
++};
++
++const ldns_output_format   ldns_output_format_nocomments_record = { 0, NULL };
++const ldns_output_format  *ldns_output_format_nocomments 
++			= &ldns_output_format_nocomments_record;
++const ldns_output_format   ldns_output_format_onlykeyids_record = {
++	LDNS_COMMENT_KEY, NULL
++};
++const ldns_output_format  *ldns_output_format_onlykeyids
++			= &ldns_output_format_onlykeyids_record;
++const ldns_output_format  *ldns_output_format_default
++			= &ldns_output_format_onlykeyids_record;
++
++const ldns_output_format   ldns_output_format_bubblebabble_record = { 
++	LDNS_COMMENT_KEY | LDNS_COMMENT_BUBBLEBABBLE | LDNS_COMMENT_FLAGS, NULL
++};
++const ldns_output_format  *ldns_output_format_bubblebabble 
++			= &ldns_output_format_bubblebabble_record;
++
++static bool
++ldns_output_format_covers_type(const ldns_output_format* fmt, ldns_rr_type t)
++{
++	return fmt && (fmt->flags & LDNS_FMT_RFC3597) &&
++		((ldns_output_format_storage*)fmt)->bitmap &&
++		ldns_nsec_bitmap_covers_type(
++				((ldns_output_format_storage*)fmt)->bitmap, t);
++}
++
++ldns_status
++ldns_output_format_set_type(ldns_output_format* fmt, ldns_rr_type t)
++{
++	ldns_output_format_storage* fmt_st = (ldns_output_format_storage*)fmt;
++	ldns_status s;
++	
++	assert(fmt != NULL);
++	
++	if (!(fmt_st->flags & LDNS_FMT_RFC3597)) {
++		ldns_output_format_set(fmt, LDNS_FMT_RFC3597);
++	}
++	if (! fmt_st->bitmap) {
++		s = ldns_rdf_bitmap_known_rr_types_space(&fmt_st->bitmap);
++		if (s != LDNS_STATUS_OK) {
++			return s;
++		}
++	}
++	return ldns_nsec_bitmap_set_type(fmt_st->bitmap, t);
++}
++
++ldns_status
++ldns_output_format_clear_type(ldns_output_format* fmt, ldns_rr_type t)
++{
++	ldns_output_format_storage* fmt_st = (ldns_output_format_storage*)fmt;
++	ldns_status s;
++	
++	assert(fmt != NULL);
++
++	if (!(fmt_st->flags & LDNS_FMT_RFC3597)) {
++		ldns_output_format_set(fmt, LDNS_FMT_RFC3597);
++	}
++	if (! fmt_st->bitmap) {
++		s = ldns_rdf_bitmap_known_rr_types(&fmt_st->bitmap);
++		if (s != LDNS_STATUS_OK) {
++			return s;
++		}
++	}
++	return ldns_nsec_bitmap_clear_type(fmt_st->bitmap, t);
++}
++
++ldns_status
++ldns_pkt_opcode2buffer_str(ldns_buffer *output, ldns_pkt_opcode opcode)
++{
++	ldns_lookup_table *lt = ldns_lookup_by_id(ldns_opcodes, opcode);
++	if (lt && lt->name) {
++		ldns_buffer_printf(output, "%s", lt->name);
++	} else {
++		ldns_buffer_printf(output, "OPCODE%u", opcode);
++	}
++	return ldns_buffer_status(output);
++}
++
++ldns_status
++ldns_pkt_rcode2buffer_str(ldns_buffer *output, ldns_pkt_rcode rcode)
++{
++	ldns_lookup_table *lt = ldns_lookup_by_id(ldns_rcodes, rcode);
++	if (lt && lt->name) {
++		ldns_buffer_printf(output, "%s", lt->name);
++	} else {
++		ldns_buffer_printf(output, "RCODE%u", rcode);
++	}
++	return ldns_buffer_status(output);
++}
++
++ldns_status
++ldns_algorithm2buffer_str(ldns_buffer *output,
++                          ldns_algorithm algorithm)
++{
++	ldns_lookup_table *lt = ldns_lookup_by_id(ldns_algorithms,
++	                                          algorithm);
++	if (lt && lt->name) {
++		ldns_buffer_printf(output, "%s", lt->name);
++	} else {
++		ldns_buffer_printf(output, "ALG%u", algorithm);
++	}
++	return ldns_buffer_status(output);
++}
++
++ldns_status
++ldns_cert_algorithm2buffer_str(ldns_buffer *output,
++                               ldns_cert_algorithm cert_algorithm)
++{
++	ldns_lookup_table *lt = ldns_lookup_by_id(ldns_cert_algorithms,
++	                                          cert_algorithm);
++	if (lt && lt->name) {
++		ldns_buffer_printf(output, "%s", lt->name);
++	} else {
++		ldns_buffer_printf(output, "CERT_ALG%u",
++		                   cert_algorithm);
++	}
++	return ldns_buffer_status(output);
++}
++
++char *
++ldns_pkt_opcode2str(ldns_pkt_opcode opcode)
++{
++	char *str;
++	ldns_buffer *buf;
++
++	buf = ldns_buffer_new(12);
++	if (!buf) {
++		return NULL;
++	}
++
++	str = NULL;
++	if (ldns_pkt_opcode2buffer_str(buf, opcode) == LDNS_STATUS_OK) {
++		str = ldns_buffer_export2str(buf);
++	}
++
++	ldns_buffer_free(buf);
++	return str;
++}
++
++char *
++ldns_pkt_rcode2str(ldns_pkt_rcode rcode)
++{
++	char *str;
++	ldns_buffer *buf;
++
++	buf = ldns_buffer_new(10);
++	if (!buf) {
++		return NULL;
++	}
++
++	str = NULL;
++	if (ldns_pkt_rcode2buffer_str(buf, rcode) == LDNS_STATUS_OK) {
++		str = ldns_buffer_export2str(buf);
++	}
++
++	ldns_buffer_free(buf);
++	return str;
++}
++
++char *
++ldns_pkt_algorithm2str(ldns_algorithm algorithm)
++{
++	char *str;
++	ldns_buffer *buf;
++
++	buf = ldns_buffer_new(10);
++	if (!buf) {
++		return NULL;
++	}
++
++	str = NULL;
++	if (ldns_algorithm2buffer_str(buf, algorithm)
++	    == LDNS_STATUS_OK) {
++		str = ldns_buffer_export2str(buf);
++	}
++
++	ldns_buffer_free(buf);
++	return str;
++}
++
++char *
++ldns_pkt_cert_algorithm2str(ldns_cert_algorithm cert_algorithm)
++{
++	char *str;
++	ldns_buffer *buf;
++
++	buf = ldns_buffer_new(10);
++	if (!buf) {
++		return NULL;
++	}
++
++	str = NULL;
++	if (ldns_cert_algorithm2buffer_str(buf, cert_algorithm)
++	    == LDNS_STATUS_OK) {
++		str = ldns_buffer_export2str(buf);
++	}
++
++	ldns_buffer_free(buf);
++	return str;
++}
++
++
++/* do NOT pass compressed data here :p */
++ldns_status
++ldns_rdf2buffer_str_dname(ldns_buffer *output, const ldns_rdf *dname)
++{
++	/* can we do with 1 pos var? or without at all? */
++	uint8_t src_pos = 0;
++	uint8_t len;
++	uint8_t *data;
++	uint8_t i;
++	unsigned char c;
++
++	data = (uint8_t*)ldns_rdf_data(dname);
++	len = data[src_pos];
++
++	if (ldns_rdf_size(dname) > LDNS_MAX_DOMAINLEN) {
++		/* too large, return */
++		return LDNS_STATUS_DOMAINNAME_OVERFLOW;
++	}
++
++	/* special case: root label */
++	if (1 == ldns_rdf_size(dname)) {
++		ldns_buffer_printf(output, ".");
++	} else {
++		while ((len > 0) && src_pos < ldns_rdf_size(dname)) {
++			src_pos++;
++			for(i = 0; i < len; i++) {
++				/* paranoia check for various 'strange'
++				   characters in dnames
++				*/
++				c = (unsigned char) data[src_pos];
++				if(c == '.' || c == ';' ||
++				   c == '(' || c == ')' ||
++				   c == '\\') {
++					ldns_buffer_printf(output, "\\%c",
++							data[src_pos]);
++				} else if (!(isascii(c) && isgraph(c))) {
++					ldns_buffer_printf(output, "\\%03u",
++						        data[src_pos]);
++				} else {
++					ldns_buffer_printf(output, "%c", data[src_pos]);
++				}
++				src_pos++;
++			}
++
++			if (src_pos < ldns_rdf_size(dname)) {
++				ldns_buffer_printf(output, ".");
++			}
++			len = data[src_pos];
++		}
++	}
++	return ldns_buffer_status(output);
++}
++
++ldns_status
++ldns_rdf2buffer_str_int8(ldns_buffer *output, const ldns_rdf *rdf)
++{
++	uint8_t data = ldns_rdf_data(rdf)[0];
++	ldns_buffer_printf(output, "%lu", (unsigned long) data);
++	return ldns_buffer_status(output);
++}
++
++ldns_status
++ldns_rdf2buffer_str_int16(ldns_buffer *output, const ldns_rdf *rdf)
++{
++	uint16_t data = ldns_read_uint16(ldns_rdf_data(rdf));
++	ldns_buffer_printf(output, "%lu", (unsigned long) data);
++	return ldns_buffer_status(output);
++}
++
++ldns_status
++ldns_rdf2buffer_str_int32(ldns_buffer *output, const ldns_rdf *rdf)
++{
++	uint32_t data = ldns_read_uint32(ldns_rdf_data(rdf));
++	ldns_buffer_printf(output, "%lu", (unsigned long) data);
++	return ldns_buffer_status(output);
++}
++
++ldns_status
++ldns_rdf2buffer_str_time(ldns_buffer *output, const ldns_rdf *rdf)
++{
++	/* create a YYYYMMDDHHMMSS string if possible */
++	struct tm tm;
++	char date_buf[16];
++
++	memset(&tm, 0, sizeof(tm));
++	if (ldns_serial_arithmitics_gmtime_r(ldns_rdf2native_int32(rdf), time(NULL), &tm)
++	    && strftime(date_buf, 15, "%Y%m%d%H%M%S", &tm)) {
++		ldns_buffer_printf(output, "%s", date_buf);
++	}
++	return ldns_buffer_status(output);
++}
++
++ldns_status
++ldns_rdf2buffer_str_a(ldns_buffer *output, const ldns_rdf *rdf)
++{
++	char str[INET_ADDRSTRLEN];
++
++	if (inet_ntop(AF_INET, ldns_rdf_data(rdf), str, INET_ADDRSTRLEN)) {
++		ldns_buffer_printf(output, "%s", str);
++	}
++	return ldns_buffer_status(output);
++}
++
++ldns_status
++ldns_rdf2buffer_str_aaaa(ldns_buffer *output, const ldns_rdf *rdf)
++{
++	char str[INET6_ADDRSTRLEN];
++
++	if (inet_ntop(AF_INET6, ldns_rdf_data(rdf), str, INET6_ADDRSTRLEN)) {
++		ldns_buffer_printf(output, "%s", str);
++	}
++
++	return ldns_buffer_status(output);
++}
++
++static void 
++ldns_characters2buffer_str(ldns_buffer* output,
++		size_t amount, const uint8_t* characters)
++{
++	uint8_t ch;
++	while (amount > 0) {
++		ch = *characters++;
++		if (isprint((int)ch) || ch == '\t') {
++			if (ch == '\"' || ch == '\\')
++				ldns_buffer_printf(output, "\\%c", ch);
++			else
++				ldns_buffer_printf(output, "%c", ch);
++		} else {
++			ldns_buffer_printf(output, "\\%03u",
++                                (unsigned)(uint8_t) ch);
++		}
++		amount--;
++	}
++}
++
++ldns_status
++ldns_rdf2buffer_str_str(ldns_buffer *output, const ldns_rdf *rdf)
++{
++        if(ldns_rdf_size(rdf) < 1) {
++                return LDNS_STATUS_WIRE_RDATA_ERR;
++        }
++        if((int)ldns_rdf_size(rdf) < (int)ldns_rdf_data(rdf)[0] + 1) {
++                return LDNS_STATUS_WIRE_RDATA_ERR;
++        }
++	ldns_buffer_printf(output, "\"");
++	ldns_characters2buffer_str(output, 
++			ldns_rdf_data(rdf)[0], ldns_rdf_data(rdf) + 1);
++	ldns_buffer_printf(output, "\"");
++	return ldns_buffer_status(output);
++}
++
++ldns_status
++ldns_rdf2buffer_str_b64(ldns_buffer *output, const ldns_rdf *rdf)
++{
++	size_t size = ldns_b64_ntop_calculate_size(ldns_rdf_size(rdf));
++	char *b64 = LDNS_XMALLOC(char, size);
++	if(!b64) return LDNS_STATUS_MEM_ERR;
++	if (ldns_b64_ntop(ldns_rdf_data(rdf), ldns_rdf_size(rdf), b64, size)) {
++		ldns_buffer_printf(output, "%s", b64);
++	}
++	LDNS_FREE(b64);
++	return ldns_buffer_status(output);
++}
++
++ldns_status
++ldns_rdf2buffer_str_b32_ext(ldns_buffer *output, const ldns_rdf *rdf)
++{
++	size_t size;
++	char *b32;
++	if(ldns_rdf_size(rdf) == 0)
++		return LDNS_STATUS_OK;
++        /* remove -1 for the b32-hash-len octet */
++	size = ldns_b32_ntop_calculate_size(ldns_rdf_size(rdf) - 1);
++        /* add one for the end nul for the string */
++	b32 = LDNS_XMALLOC(char, size + 1);
++	if(!b32) return LDNS_STATUS_MEM_ERR;
++	size = (size_t) ldns_b32_ntop_extended_hex(ldns_rdf_data(rdf) + 1,
++		ldns_rdf_size(rdf) - 1, b32, size+1);
++	if (size > 0) {
++		ldns_buffer_printf(output, "%s", b32);
++	}
++	LDNS_FREE(b32);
++	return ldns_buffer_status(output);
++}
++
++ldns_status
++ldns_rdf2buffer_str_hex(ldns_buffer *output, const ldns_rdf *rdf)
++{
++	size_t i;
++	for (i = 0; i < ldns_rdf_size(rdf); i++) {
++		ldns_buffer_printf(output, "%02x", ldns_rdf_data(rdf)[i]);
++	}
++
++	return ldns_buffer_status(output);
++}
++
++static ldns_status
++ldns_rdf2buffer_str_type_fmt(ldns_buffer *output,
++		const ldns_output_format* fmt, const ldns_rdf *rdf)
++{
++        uint16_t data = ldns_read_uint16(ldns_rdf_data(rdf));
++
++	if (! ldns_output_format_covers_type(fmt, data) &&
++			ldns_rr_descript(data) &&
++			ldns_rr_descript(data)->_name) {
++
++		ldns_buffer_printf(output, "%s",ldns_rr_descript(data)->_name);
++	} else {
++		ldns_buffer_printf(output, "TYPE%u", data);
++	}
++	return  ldns_buffer_status(output);
++}
++
++ldns_status
++ldns_rdf2buffer_str_type(ldns_buffer *output, const ldns_rdf *rdf)
++{
++	return ldns_rdf2buffer_str_type_fmt(output,
++			ldns_output_format_default, rdf);
++}
++
++ldns_status
++ldns_rdf2buffer_str_class(ldns_buffer *output, const ldns_rdf *rdf)
++{
++	uint16_t data = ldns_read_uint16(ldns_rdf_data(rdf));
++	ldns_lookup_table *lt;
++
++ 	lt = ldns_lookup_by_id(ldns_rr_classes, (int) data);
++	if (lt) {
++		ldns_buffer_printf(output, "\t%s", lt->name);
++	} else {
++		ldns_buffer_printf(output, "\tCLASS%d", data);
++	}
++	return ldns_buffer_status(output);
++}
++
++ldns_status
++ldns_rdf2buffer_str_cert_alg(ldns_buffer *output, const ldns_rdf *rdf)
++{
++        uint16_t data = ldns_read_uint16(ldns_rdf_data(rdf));
++	ldns_lookup_table *lt;
++ 	lt = ldns_lookup_by_id(ldns_cert_algorithms, (int) data);
++	if (lt) {
++		ldns_buffer_printf(output, "%s", lt->name);
++	} else {
++		ldns_buffer_printf(output, "%d", data);
++	}
++	return ldns_buffer_status(output);
++}
++
++ldns_status
++ldns_rdf2buffer_str_alg(ldns_buffer *output, const ldns_rdf *rdf)
++{
++	return ldns_rdf2buffer_str_int8(output, rdf);
++}
++
++static void
++loc_cm_print(ldns_buffer *output, uint8_t mantissa, uint8_t exponent)
++{
++	uint8_t i;
++	/* is it 0.<two digits> ? */
++	if(exponent < 2) {
++		if(exponent == 1)
++			mantissa *= 10;
++		ldns_buffer_printf(output, "0.%02ld", (long)mantissa);
++		return;
++	}
++	/* always <digit><string of zeros> */
++	ldns_buffer_printf(output, "%d", (int)mantissa);
++	for(i=0; i<exponent-2; i++)
++		ldns_buffer_printf(output, "0");
++}
++
++ldns_status
++ldns_rr_type2buffer_str(ldns_buffer *output, const ldns_rr_type type)
++{
++	const ldns_rr_descriptor *descriptor;
++
++	descriptor = ldns_rr_descript(type);
++
++	switch (type) {
++		case LDNS_RR_TYPE_IXFR:
++			ldns_buffer_printf(output, "IXFR");
++			break;
++		case LDNS_RR_TYPE_AXFR:
++			ldns_buffer_printf(output, "AXFR");
++			break;
++		case LDNS_RR_TYPE_MAILA:
++			ldns_buffer_printf(output, "MAILA");
++			break;
++		case LDNS_RR_TYPE_MAILB:
++			ldns_buffer_printf(output, "MAILB");
++			break;
++		case LDNS_RR_TYPE_ANY:
++			ldns_buffer_printf(output, "ANY");
++			break;
++		default:
++			if (descriptor && descriptor->_name) {
++				ldns_buffer_printf(output, "%s", descriptor->_name);
++			} else {
++				ldns_buffer_printf(output, "TYPE%u", type);
++			}
++	}
++	return ldns_buffer_status(output);
++}
++
++char *
++ldns_rr_type2str(const ldns_rr_type type)
++{
++	char *str;
++	ldns_buffer *buf;
++
++	buf = ldns_buffer_new(10);
++	if (!buf) {
++		return NULL;
++	}
++
++	str = NULL;
++	if (ldns_rr_type2buffer_str(buf, type) == LDNS_STATUS_OK) {
++		str = ldns_buffer_export2str(buf);
++	}
++
++	ldns_buffer_free(buf);
++	return str;
++}
++
++
++ldns_status
++ldns_rr_class2buffer_str(ldns_buffer *output,
++                         const ldns_rr_class klass)
++{
++	ldns_lookup_table *lt;
++
++	lt = ldns_lookup_by_id(ldns_rr_classes, klass);
++	if (lt) {
++		ldns_buffer_printf(output, "%s", lt->name);
++	} else {
++		ldns_buffer_printf(output, "CLASS%d", klass);
++	}
++	return ldns_buffer_status(output);
++}
++
++char *
++ldns_rr_class2str(const ldns_rr_class klass)
++{
++	ldns_buffer *buf;
++	char *str;
++
++	buf = ldns_buffer_new(10);
++	if (!buf) {
++		return NULL;
++	}
++
++	str = NULL;
++	if (ldns_rr_class2buffer_str(buf, klass) == LDNS_STATUS_OK) {
++		str = ldns_buffer_export2str(buf);
++	}
++	ldns_buffer_free(buf);
++	return str;
++}
++
++ldns_status
++ldns_rdf2buffer_str_loc(ldns_buffer *output, const ldns_rdf *rdf)
++{
++	/* we could do checking (ie degrees < 90 etc)? */
++	uint8_t version;
++	uint8_t size;
++	uint8_t horizontal_precision;
++	uint8_t vertical_precision;
++	uint32_t longitude;
++	uint32_t latitude;
++	uint32_t altitude;
++	char northerness;
++	char easterness;
++	uint32_t h;
++	uint32_t m;
++	double s;
++
++	uint32_t equator = (uint32_t) ldns_power(2, 31);
++
++        if(ldns_rdf_size(rdf) < 1) {
++                return LDNS_STATUS_WIRE_RDATA_ERR;
++        }
++       	version = ldns_rdf_data(rdf)[0];
++	if (version == 0) {
++		if(ldns_rdf_size(rdf) < 16) {
++			return LDNS_STATUS_WIRE_RDATA_ERR;
++		}
++		size = ldns_rdf_data(rdf)[1];
++		horizontal_precision = ldns_rdf_data(rdf)[2];
++		vertical_precision = ldns_rdf_data(rdf)[3];
++
++		latitude = ldns_read_uint32(&ldns_rdf_data(rdf)[4]);
++		longitude = ldns_read_uint32(&ldns_rdf_data(rdf)[8]);
++		altitude = ldns_read_uint32(&ldns_rdf_data(rdf)[12]);
++
++		if (latitude > equator) {
++			northerness = 'N';
++			latitude = latitude - equator;
++		} else {
++			northerness = 'S';
++			latitude = equator - latitude;
++		}
++		h = latitude / (1000 * 60 * 60);
++		latitude = latitude % (1000 * 60 * 60);
++		m = latitude / (1000 * 60);
++		latitude = latitude % (1000 * 60);
++		s = (double) latitude / 1000.0;
++		ldns_buffer_printf(output, "%02u %02u %0.3f %c ",
++			h, m, s, northerness);
++
++		if (longitude > equator) {
++			easterness = 'E';
++			longitude = longitude - equator;
++		} else {
++			easterness = 'W';
++			longitude = equator - longitude;
++		}
++		h = longitude / (1000 * 60 * 60);
++		longitude = longitude % (1000 * 60 * 60);
++		m = longitude / (1000 * 60);
++		longitude = longitude % (1000 * 60);
++		s = (double) longitude / (1000.0);
++		ldns_buffer_printf(output, "%02u %02u %0.3f %c ",
++			h, m, s, easterness);
++
++
++		s = ((double) altitude) / 100;
++		s -= 100000;
++
++		if(altitude%100 != 0)
++			ldns_buffer_printf(output, "%.2f", s);
++		else
++			ldns_buffer_printf(output, "%.0f", s);
++
++		ldns_buffer_printf(output, "m ");
++
++		loc_cm_print(output, (size & 0xf0) >> 4, size & 0x0f);
++		ldns_buffer_printf(output, "m ");
++
++		loc_cm_print(output, (horizontal_precision & 0xf0) >> 4,
++			horizontal_precision & 0x0f);
++		ldns_buffer_printf(output, "m ");
++
++		loc_cm_print(output, (vertical_precision & 0xf0) >> 4,
++			vertical_precision & 0x0f);
++		ldns_buffer_printf(output, "m");
++
++		return ldns_buffer_status(output);
++	} else {
++		return ldns_rdf2buffer_str_hex(output, rdf);
++	}
++}
++
++ldns_status
++ldns_rdf2buffer_str_unknown(ldns_buffer *output, const ldns_rdf *rdf)
++{
++	ldns_buffer_printf(output, "\\# %u ", ldns_rdf_size(rdf));
++	return ldns_rdf2buffer_str_hex(output, rdf);
++}
++
++ldns_status
++ldns_rdf2buffer_str_nsap(ldns_buffer *output, const ldns_rdf *rdf)
++{
++	ldns_buffer_printf(output, "0x");
++	return ldns_rdf2buffer_str_hex(output, rdf);
++}
++
++ldns_status
++ldns_rdf2buffer_str_atma(ldns_buffer *output, const ldns_rdf *rdf)
++{
++	return ldns_rdf2buffer_str_hex(output, rdf);
++}
++
++ldns_status
++ldns_rdf2buffer_str_wks(ldns_buffer *output, const ldns_rdf *rdf)
++{
++	/* protocol, followed by bitmap of services */
++	struct protoent *protocol;
++	char *proto_name = NULL;
++	uint8_t protocol_nr;
++	struct servent *service;
++	uint16_t current_service;
++
++        if(ldns_rdf_size(rdf) < 1) {
++                return LDNS_STATUS_WIRE_RDATA_ERR;
++        }
++	protocol_nr = ldns_rdf_data(rdf)[0];
++	protocol = getprotobynumber((int) protocol_nr);
++	if (protocol && (protocol->p_name != NULL)) {
++		proto_name = protocol->p_name;
++		ldns_buffer_printf(output, "%s ", protocol->p_name);
++	} else {
++		ldns_buffer_printf(output, "%u ", protocol_nr);
++	}
++
++#ifdef HAVE_ENDPROTOENT
++	endprotoent();
++#endif
++
++	for (current_service = 0;
++	     current_service < (ldns_rdf_size(rdf)-1)*8; current_service++) {
++		if (ldns_get_bit(&(ldns_rdf_data(rdf)[1]), current_service)) {
++			service = getservbyport((int) htons(current_service),
++			                        proto_name);
++			if (service && service->s_name) {
++				ldns_buffer_printf(output, "%s ", service->s_name);
++			} else {
++				ldns_buffer_printf(output, "%u ", current_service);
++			}
++#ifdef HAVE_ENDSERVENT
++			endservent();
++#endif
++		}
++	}
++	return ldns_buffer_status(output);
++}
++
++static ldns_status
++ldns_rdf2buffer_str_nsec_fmt(ldns_buffer *output,
++		const ldns_output_format* fmt, const ldns_rdf *rdf)
++{
++	/* Note: this code is duplicated in higher.c in
++	 * ldns_nsec_type_check() function
++	 */
++	uint8_t window_block_nr;
++	uint8_t bitmap_length;
++	uint16_t type;
++	uint16_t pos = 0;
++	uint16_t bit_pos;
++	uint8_t *data = ldns_rdf_data(rdf);
++
++	while((size_t)(pos + 2) < ldns_rdf_size(rdf)) {
++		window_block_nr = data[pos];
++		bitmap_length = data[pos + 1];
++		pos += 2;
++		if (ldns_rdf_size(rdf) < pos + bitmap_length) {
++			return LDNS_STATUS_WIRE_RDATA_ERR;
++		}
++		for (bit_pos = 0; bit_pos < (bitmap_length) * 8; bit_pos++) {
++			if (! ldns_get_bit(&data[pos], bit_pos)) {
++				continue;
++			}
++			type = 256 * (uint16_t) window_block_nr + bit_pos;
++
++			if (! ldns_output_format_covers_type(fmt, type) &&
++					ldns_rr_descript(type) &&
++					ldns_rr_descript(type)->_name){
++
++				ldns_buffer_printf(output, "%s ",
++						ldns_rr_descript(type)->_name);
++			} else {
++				ldns_buffer_printf(output, "TYPE%u ", type);
++			}
++		}
++		pos += (uint16_t) bitmap_length;
++	}
++	return ldns_buffer_status(output);
++}
++
++ldns_status
++ldns_rdf2buffer_str_nsec(ldns_buffer *output, const ldns_rdf *rdf)
++{
++	return ldns_rdf2buffer_str_nsec_fmt(output,
++			ldns_output_format_default, rdf);
++}
++
++ldns_status
++ldns_rdf2buffer_str_nsec3_salt(ldns_buffer *output, const ldns_rdf *rdf)
++{
++	uint8_t salt_length;
++	uint8_t salt_pos;
++
++	uint8_t *data = ldns_rdf_data(rdf);
++
++        if(ldns_rdf_size(rdf) < 1) {
++                return LDNS_STATUS_WIRE_RDATA_ERR;
++        }
++	salt_length = data[0];
++	/* from now there are variable length entries so remember pos */
++	if (salt_length == 0 || ((size_t)salt_length)+1 > ldns_rdf_size(rdf)) {
++		ldns_buffer_printf(output, "- ");
++	} else {
++		for (salt_pos = 0; salt_pos < salt_length; salt_pos++) {
++			ldns_buffer_printf(output, "%02x", data[1 + salt_pos]);
++		}
++		ldns_buffer_printf(output, " ");
++	}
++
++	return ldns_buffer_status(output);
++}
++
++ldns_status
++ldns_rdf2buffer_str_period(ldns_buffer *output, const ldns_rdf *rdf)
++{
++	/* period is the number of seconds */
++	if (ldns_rdf_size(rdf) != 4) {
++		return LDNS_STATUS_WIRE_RDATA_ERR;
++	}
++	ldns_buffer_printf(output, "%u", ldns_read_uint32(ldns_rdf_data(rdf)));
++	return ldns_buffer_status(output);
++}
++
++ldns_status
++ldns_rdf2buffer_str_tsigtime(ldns_buffer *output,const  ldns_rdf *rdf)
++{
++	/* tsigtime is 48 bits network order unsigned integer */
++	uint64_t tsigtime = 0;
++	uint8_t *data = ldns_rdf_data(rdf);
++	uint64_t d0, d1, d2, d3, d4, d5;
++
++	if (ldns_rdf_size(rdf) < 6) {
++		return LDNS_STATUS_WIRE_RDATA_ERR;
++	}
++	d0 = data[0]; /* cast to uint64 for shift operations */
++	d1 = data[1];
++	d2 = data[2];
++	d3 = data[3];
++	d4 = data[4];
++	d5 = data[5];
++	tsigtime = (d0<<40) | (d1<<32) | (d2<<24) | (d3<<16) | (d4<<8) | d5;
++
++	ldns_buffer_printf(output, "%llu ", (long long)tsigtime);
++
++	return ldns_buffer_status(output);
++}
++
++ldns_status
++ldns_rdf2buffer_str_apl(ldns_buffer *output, const ldns_rdf *rdf)
++{
++	uint8_t *data = ldns_rdf_data(rdf);
++	uint16_t address_family;
++	uint8_t prefix;
++	bool negation;
++	uint8_t adf_length;
++	size_t i;
++	size_t pos = 0;
++
++	while (pos < (unsigned int) ldns_rdf_size(rdf)) {
++                if(pos + 3 >= (unsigned)ldns_rdf_size(rdf))
++                        return LDNS_STATUS_WIRE_RDATA_ERR;
++		address_family = ldns_read_uint16(&data[pos]);
++		prefix = data[pos + 2];
++		negation = data[pos + 3] & LDNS_APL_NEGATION;
++		adf_length = data[pos + 3] & LDNS_APL_MASK;
++		if (address_family == LDNS_APL_IP4) {
++			/* check if prefix < 32? */
++			if (negation) {
++				ldns_buffer_printf(output, "!");
++			}
++			ldns_buffer_printf(output, "%u:", address_family);
++			/* address is variable length 0 - 4 */
++			for (i = 0; i < 4; i++) {
++				if (i > 0) {
++					ldns_buffer_printf(output, ".");
++				}
++				if (i < (unsigned short) adf_length) {
++                                        if(pos+i+4 >= ldns_rdf_size(rdf))
++					    return LDNS_STATUS_WIRE_RDATA_ERR;
++					ldns_buffer_printf(output, "%d",
++					                   data[pos + i + 4]);
++				} else {
++					ldns_buffer_printf(output, "0");
++				}
++			}
++			ldns_buffer_printf(output, "/%u ", prefix);
++		} else if (address_family == LDNS_APL_IP6) {
++			/* check if prefix < 128? */
++			if (negation) {
++				ldns_buffer_printf(output, "!");
++			}
++			ldns_buffer_printf(output, "%u:", address_family);
++			/* address is variable length 0 - 16 */
++			for (i = 0; i < 16; i++) {
++				if (i % 2 == 0 && i > 0) {
++					ldns_buffer_printf(output, ":");
++				}
++				if (i < (unsigned short) adf_length) {
++                                        if(pos+i+4 >= ldns_rdf_size(rdf))
++					    return LDNS_STATUS_WIRE_RDATA_ERR;
++					ldns_buffer_printf(output, "%02x",
++					                   data[pos + i + 4]);
++				} else {
++					ldns_buffer_printf(output, "00");
++				}
++			}
++			ldns_buffer_printf(output, "/%u ", prefix);
++
++		} else {
++			/* unknown address family */
++			ldns_buffer_printf(output,
++					"Unknown address family: %u data: ",
++					address_family);
++			for (i = 1; i < (unsigned short) (4 + adf_length); i++) {
++                                if(pos+i >= ldns_rdf_size(rdf))
++                                        return LDNS_STATUS_WIRE_RDATA_ERR;
++				ldns_buffer_printf(output, "%02x", data[i]);
++			}
++		}
++		pos += 4 + adf_length;
++	}
++	return ldns_buffer_status(output);
++}
++
++ldns_status
++ldns_rdf2buffer_str_int16_data(ldns_buffer *output, const ldns_rdf *rdf)
++{
++	size_t size;
++	char *b64;
++	if (ldns_rdf_size(rdf) < 2) {
++		return LDNS_STATUS_WIRE_RDATA_ERR;
++	}
++	/* Subtract the size (2) of the number that specifies the length */
++	size = ldns_b64_ntop_calculate_size(ldns_rdf_size(rdf) - 2);
++	ldns_buffer_printf(output, "%u ", ldns_rdf_size(rdf) - 2);
++	if (ldns_rdf_size(rdf) > 2) {
++		b64 = LDNS_XMALLOC(char, size);
++		if(!b64)
++			return LDNS_STATUS_MEM_ERR;
++
++		if (ldns_rdf_size(rdf) > 2 &&
++		ldns_b64_ntop(ldns_rdf_data(rdf) + 2,
++					ldns_rdf_size(rdf) - 2,
++					b64, size)) {
++			ldns_buffer_printf(output, "%s", b64);
++		}
++		LDNS_FREE(b64);
++	}
++	return ldns_buffer_status(output);
++}
++
++ldns_status
++ldns_rdf2buffer_str_ipseckey(ldns_buffer *output, const ldns_rdf *rdf)
++{
++	/* wire format from
++	   http://www.ietf.org/internet-drafts/draft-ietf-ipseckey-rr-12.txt
++	*/
++	uint8_t *data = ldns_rdf_data(rdf);
++	uint8_t precedence;
++	uint8_t gateway_type;
++	uint8_t algorithm;
++
++	ldns_rdf *gateway = NULL;
++	uint8_t *gateway_data;
++
++	size_t public_key_size;
++	uint8_t *public_key_data;
++	ldns_rdf *public_key;
++
++	size_t offset = 0;
++	ldns_status status;
++
++	if (ldns_rdf_size(rdf) < 3) {
++		return LDNS_STATUS_WIRE_RDATA_ERR;
++	}
++	precedence = data[0];
++	gateway_type = data[1];
++	algorithm = data[2];
++	offset = 3;
++
++	switch (gateway_type) {
++		case 0:
++			/* no gateway */
++			break;
++		case 1:
++			gateway_data = LDNS_XMALLOC(uint8_t, LDNS_IP4ADDRLEN);
++                        if(!gateway_data)
++                                return LDNS_STATUS_MEM_ERR;
++			if (ldns_rdf_size(rdf) < offset + LDNS_IP4ADDRLEN) {
++				return LDNS_STATUS_ERR;
++			}
++			memcpy(gateway_data, &data[offset], LDNS_IP4ADDRLEN);
++			gateway = ldns_rdf_new(LDNS_RDF_TYPE_A,
++					LDNS_IP4ADDRLEN , gateway_data);
++			offset += LDNS_IP4ADDRLEN;
++                        if(!gateway) {
++                                LDNS_FREE(gateway_data);
++                                return LDNS_STATUS_MEM_ERR;
++                        }
++			break;
++		case 2:
++			gateway_data = LDNS_XMALLOC(uint8_t, LDNS_IP6ADDRLEN);
++                        if(!gateway_data)
++                                return LDNS_STATUS_MEM_ERR;
++			if (ldns_rdf_size(rdf) < offset + LDNS_IP6ADDRLEN) {
++				return LDNS_STATUS_ERR;
++			}
++			memcpy(gateway_data, &data[offset], LDNS_IP6ADDRLEN);
++			offset += LDNS_IP6ADDRLEN;
++			gateway =
++				ldns_rdf_new(LDNS_RDF_TYPE_AAAA,
++						LDNS_IP6ADDRLEN, gateway_data);
++                        if(!gateway) {
++                                LDNS_FREE(gateway_data);
++                                return LDNS_STATUS_MEM_ERR;
++                        }
++			break;
++		case 3:
++			status = ldns_wire2dname(&gateway, data,
++					ldns_rdf_size(rdf), &offset);
++                        if(status != LDNS_STATUS_OK)
++                                return status;
++			break;
++		default:
++			/* error? */
++			break;
++	}
++
++	if (ldns_rdf_size(rdf) <= offset) {
++		return LDNS_STATUS_ERR;
++	}
++	public_key_size = ldns_rdf_size(rdf) - offset;
++	public_key_data = LDNS_XMALLOC(uint8_t, public_key_size);
++        if(!public_key_data) {
++                ldns_rdf_free(gateway);
++                return LDNS_STATUS_MEM_ERR;
++        }
++	memcpy(public_key_data, &data[offset], public_key_size);
++	public_key = ldns_rdf_new(LDNS_RDF_TYPE_B64,
++			public_key_size, public_key_data);
++        if(!public_key) {
++                LDNS_FREE(public_key_data);
++                ldns_rdf_free(gateway);
++                return LDNS_STATUS_MEM_ERR;
++        }
++
++	ldns_buffer_printf(output, "%u %u %u ", precedence, gateway_type, algorithm);
++	if (gateway)
++	  	(void) ldns_rdf2buffer_str(output, gateway);
++	else
++		ldns_buffer_printf(output, ".");
++	ldns_buffer_printf(output, " ");
++	(void) ldns_rdf2buffer_str(output, public_key);
++
++	ldns_rdf_free(gateway);
++	ldns_rdf_free(public_key);
++
++	return ldns_buffer_status(output);
++}
++
++ldns_status
++ldns_rdf2buffer_str_ilnp64(ldns_buffer *output, const ldns_rdf *rdf)
++{
++	if (ldns_rdf_size(rdf) != 8) {
++		return LDNS_STATUS_WIRE_RDATA_ERR;
++	}
++	ldns_buffer_printf(output,"%.4x:%.4x:%.4x:%.4x",
++				ldns_read_uint16(ldns_rdf_data(rdf)),
++				ldns_read_uint16(ldns_rdf_data(rdf)+2),
++				ldns_read_uint16(ldns_rdf_data(rdf)+4),
++				ldns_read_uint16(ldns_rdf_data(rdf)+6));
++	return ldns_buffer_status(output);
++}
++
++ldns_status
++ldns_rdf2buffer_str_eui48(ldns_buffer *output, const ldns_rdf *rdf)
++{
++	if (ldns_rdf_size(rdf) != 6) {
++		return LDNS_STATUS_WIRE_RDATA_ERR;
++	}
++	ldns_buffer_printf(output,"%.2x-%.2x-%.2x-%.2x-%.2x-%.2x",
++				ldns_rdf_data(rdf)[0], ldns_rdf_data(rdf)[1],
++				ldns_rdf_data(rdf)[2], ldns_rdf_data(rdf)[3],
++				ldns_rdf_data(rdf)[4], ldns_rdf_data(rdf)[5]);
++	return ldns_buffer_status(output);
++}
++
++ldns_status
++ldns_rdf2buffer_str_eui64(ldns_buffer *output, const ldns_rdf *rdf)
++{
++	if (ldns_rdf_size(rdf) != 8) {
++		return LDNS_STATUS_WIRE_RDATA_ERR;
++	}
++	ldns_buffer_printf(output,"%.2x-%.2x-%.2x-%.2x-%.2x-%.2x-%.2x-%.2x",
++				ldns_rdf_data(rdf)[0], ldns_rdf_data(rdf)[1],
++				ldns_rdf_data(rdf)[2], ldns_rdf_data(rdf)[3],
++				ldns_rdf_data(rdf)[4], ldns_rdf_data(rdf)[5],
++				ldns_rdf_data(rdf)[6], ldns_rdf_data(rdf)[7]);
++	return ldns_buffer_status(output);
++}
++
++ldns_status
++ldns_rdf2buffer_str_tag(ldns_buffer *output, const ldns_rdf *rdf)
++{
++	size_t nchars;
++	const uint8_t* chars;
++	char ch;
++	if (ldns_rdf_size(rdf) < 2) {
++		return LDNS_STATUS_WIRE_RDATA_ERR;
++	}
++	nchars = ldns_rdf_data(rdf)[0];
++	if (nchars >= ldns_rdf_size(rdf) || /* should be rdf_size - 1 */
++			nchars < 1) {
++		return LDNS_STATUS_WIRE_RDATA_ERR;
++	}
++	chars = ldns_rdf_data(rdf) + 1;
++	while (nchars > 0) {
++		ch = (char)*chars++;
++		if (! isalnum(ch)) {
++			return LDNS_STATUS_WIRE_RDATA_ERR;
++		}
++		ldns_buffer_printf(output, "%c", ch);
++		nchars--;
++	}
++	return ldns_buffer_status(output);
++}
++
++ldns_status
++ldns_rdf2buffer_str_long_str(ldns_buffer *output, const ldns_rdf *rdf)
++{
++
++	ldns_buffer_printf(output, "\"");
++	ldns_characters2buffer_str(output,
++			ldns_rdf_size(rdf), ldns_rdf_data(rdf));
++	ldns_buffer_printf(output, "\"");
++	return ldns_buffer_status(output);
++}
++
++ldns_status
++ldns_rdf2buffer_str_hip(ldns_buffer *output, const ldns_rdf *rdf)
++{
++	uint8_t *data = ldns_rdf_data(rdf);
++	size_t rdf_size = ldns_rdf_size(rdf);
++	uint8_t hit_size;
++	uint16_t pk_size;
++	int written;
++	
++	if (rdf_size < 6) {
++		return LDNS_STATUS_WIRE_RDATA_ERR;
++	}
++	if ((hit_size = data[0]) == 0 ||
++			(pk_size = ldns_read_uint16(data + 2)) == 0 ||
++			rdf_size < (size_t) hit_size + pk_size + 4) {
++
++		return LDNS_STATUS_WIRE_RDATA_ERR;
++	}
++
++	ldns_buffer_printf(output, "%d ", (int) data[1]);
++
++	for (data += 4; hit_size > 0; hit_size--, data++) {
++
++		ldns_buffer_printf(output, "%02x", (int) *data);
++	}
++	ldns_buffer_write_u8(output, (uint8_t) ' ');
++
++	if (ldns_buffer_reserve(output,
++				ldns_b64_ntop_calculate_size(pk_size))) {
++
++		written = ldns_b64_ntop(data, pk_size,
++				(char *) ldns_buffer_current(output),
++				ldns_buffer_remaining(output));
++
++		if (written > 0 &&
++				written < (int) ldns_buffer_remaining(output)) {
++
++			output->_position += written;
++		}
++	}
++	return ldns_buffer_status(output);
++}
++
++static ldns_status
++ldns_rdf2buffer_str_fmt(ldns_buffer *buffer,
++		const ldns_output_format* fmt, const ldns_rdf *rdf)
++{
++	ldns_status res = LDNS_STATUS_OK;
++
++	/*ldns_buffer_printf(buffer, "%u:", ldns_rdf_get_type(rdf));*/
++	if (rdf) {
++		switch(ldns_rdf_get_type(rdf)) {
++		case LDNS_RDF_TYPE_NONE:
++			break;
++		case LDNS_RDF_TYPE_DNAME:
++			res = ldns_rdf2buffer_str_dname(buffer, rdf);
++			break;
++		case LDNS_RDF_TYPE_INT8: /* Don't output mnemonics for these */
++		case LDNS_RDF_TYPE_ALG:
++		case LDNS_RDF_TYPE_CERTIFICATE_USAGE:
++		case LDNS_RDF_TYPE_SELECTOR:
++		case LDNS_RDF_TYPE_MATCHING_TYPE:
++			res = ldns_rdf2buffer_str_int8(buffer, rdf);
++			break;
++		case LDNS_RDF_TYPE_INT16:
++			res = ldns_rdf2buffer_str_int16(buffer, rdf);
++			break;
++		case LDNS_RDF_TYPE_INT32:
++			res = ldns_rdf2buffer_str_int32(buffer, rdf);
++			break;
++		case LDNS_RDF_TYPE_PERIOD:
++			res = ldns_rdf2buffer_str_period(buffer, rdf);
++			break;
++		case LDNS_RDF_TYPE_TSIGTIME:
++			res = ldns_rdf2buffer_str_tsigtime(buffer, rdf);
++			break;
++		case LDNS_RDF_TYPE_A:
++			res = ldns_rdf2buffer_str_a(buffer, rdf);
++			break;
++		case LDNS_RDF_TYPE_AAAA:
++			res = ldns_rdf2buffer_str_aaaa(buffer, rdf);
++			break;
++		case LDNS_RDF_TYPE_STR:
++			res = ldns_rdf2buffer_str_str(buffer, rdf);
++			break;
++		case LDNS_RDF_TYPE_APL:
++			res = ldns_rdf2buffer_str_apl(buffer, rdf);
++			break;
++		case LDNS_RDF_TYPE_B32_EXT:
++			res = ldns_rdf2buffer_str_b32_ext(buffer, rdf);
++			break;
++		case LDNS_RDF_TYPE_B64:
++			res = ldns_rdf2buffer_str_b64(buffer, rdf);
++			break;
++		case LDNS_RDF_TYPE_HEX:
++			res = ldns_rdf2buffer_str_hex(buffer, rdf);
++			break;
++		case LDNS_RDF_TYPE_NSEC:
++			res = ldns_rdf2buffer_str_nsec_fmt(buffer, fmt, rdf);
++			break;
++		case LDNS_RDF_TYPE_NSEC3_SALT:
++			res = ldns_rdf2buffer_str_nsec3_salt(buffer, rdf);
++			break;
++		case LDNS_RDF_TYPE_TYPE:
++			res = ldns_rdf2buffer_str_type_fmt(buffer, fmt, rdf);
++			break;
++		case LDNS_RDF_TYPE_CLASS:
++			res = ldns_rdf2buffer_str_class(buffer, rdf);
++			break;
++		case LDNS_RDF_TYPE_CERT_ALG:
++			res = ldns_rdf2buffer_str_cert_alg(buffer, rdf);
++			break;
++		case LDNS_RDF_TYPE_UNKNOWN:
++			res = ldns_rdf2buffer_str_unknown(buffer, rdf);
++			break;
++		case LDNS_RDF_TYPE_TIME:
++			res = ldns_rdf2buffer_str_time(buffer, rdf);
++			break;
++		case LDNS_RDF_TYPE_HIP:
++			res = ldns_rdf2buffer_str_hip(buffer, rdf);
++			break;
++		case LDNS_RDF_TYPE_LOC:
++			res = ldns_rdf2buffer_str_loc(buffer, rdf);
++			break;
++		case LDNS_RDF_TYPE_WKS:
++		case LDNS_RDF_TYPE_SERVICE:
++			res = ldns_rdf2buffer_str_wks(buffer, rdf);
++			break;
++		case LDNS_RDF_TYPE_NSAP:
++			res = ldns_rdf2buffer_str_nsap(buffer, rdf);
++			break;
++		case LDNS_RDF_TYPE_ATMA:
++			res = ldns_rdf2buffer_str_atma(buffer, rdf);
++			break;
++		case LDNS_RDF_TYPE_IPSECKEY:
++			res = ldns_rdf2buffer_str_ipseckey(buffer, rdf);
++			break;
++		case LDNS_RDF_TYPE_INT16_DATA:
++			res = ldns_rdf2buffer_str_int16_data(buffer, rdf);
++			break;
++		case LDNS_RDF_TYPE_NSEC3_NEXT_OWNER:
++			res = ldns_rdf2buffer_str_b32_ext(buffer, rdf);
++			break;
++		case LDNS_RDF_TYPE_ILNP64:
++			res = ldns_rdf2buffer_str_ilnp64(buffer, rdf);
++			break;
++		case LDNS_RDF_TYPE_EUI48:
++			res = ldns_rdf2buffer_str_eui48(buffer, rdf);
++			break;
++		case LDNS_RDF_TYPE_EUI64:
++			res = ldns_rdf2buffer_str_eui64(buffer, rdf);
++			break;
++		case LDNS_RDF_TYPE_TAG:
++			res = ldns_rdf2buffer_str_tag(buffer, rdf);
++			break;
++		case LDNS_RDF_TYPE_LONG_STR:
++			res = ldns_rdf2buffer_str_long_str(buffer, rdf);
++			break;
++		}
++	} else {
++		/** This will write mangled RRs */
++		ldns_buffer_printf(buffer, "(null) ");
++		res = LDNS_STATUS_ERR;
++	}
++	return res;
++}
++
++ldns_status
++ldns_rdf2buffer_str(ldns_buffer *buffer, const ldns_rdf *rdf)
++{
++	return ldns_rdf2buffer_str_fmt(buffer,ldns_output_format_default,rdf);
++}
++
++static ldns_rdf *
++ldns_b32_ext2dname(const ldns_rdf *rdf)
++{
++	size_t size;
++	char *b32;
++	ldns_rdf *out;
++	if(ldns_rdf_size(rdf) == 0)
++		return NULL;
++        /* remove -1 for the b32-hash-len octet */
++	size = ldns_b32_ntop_calculate_size(ldns_rdf_size(rdf) - 1);
++        /* add one for the end nul for the string */
++	b32 = LDNS_XMALLOC(char, size + 2);
++	if (b32) {
++		if (ldns_b32_ntop_extended_hex(ldns_rdf_data(rdf) + 1, 
++				ldns_rdf_size(rdf) - 1, b32, size+1) > 0) {
++			b32[size] = '.';
++			b32[size+1] = '\0';
++			if (ldns_str2rdf_dname(&out, b32) == LDNS_STATUS_OK) {
++				LDNS_FREE(b32);
++				return out;
++			}
++		}
++		LDNS_FREE(b32);
++	}
++	return NULL;
++}
++
++static ldns_status
++ldns_rr2buffer_str_rfc3597(ldns_buffer *output, const ldns_rr *rr)
++{
++	size_t total_rdfsize = 0;
++	size_t i, j;
++
++	ldns_buffer_printf(output, "TYPE%u\t", ldns_rr_get_type(rr));
++	for (i = 0; i < ldns_rr_rd_count(rr); i++) {
++		total_rdfsize += ldns_rdf_size(ldns_rr_rdf(rr, i));
++	}
++	if (total_rdfsize == 0) {
++		ldns_buffer_printf(output, "\\# 0\n");
++		return ldns_buffer_status(output);
++	}
++	ldns_buffer_printf(output, "\\# %d ", total_rdfsize);
++	for (i = 0; i < ldns_rr_rd_count(rr); i++) {
++		for (j = 0; j < ldns_rdf_size(ldns_rr_rdf(rr, i)); j++) {
++			ldns_buffer_printf(output, "%.2x",
++					ldns_rdf_data(ldns_rr_rdf(rr, i))[j]);
++		}
++	}
++	ldns_buffer_printf(output, "\n");
++	return ldns_buffer_status(output);
++}
++
++ldns_status
++ldns_rr2buffer_str_fmt(ldns_buffer *output, 
++		const ldns_output_format *fmt, const ldns_rr *rr)
++{
++	uint16_t i, flags;
++	ldns_status status = LDNS_STATUS_OK;
++	ldns_output_format_storage* fmt_st = (ldns_output_format_storage*)fmt;
++
++	if (fmt_st == NULL) {
++		fmt_st = (ldns_output_format_storage*)
++			  ldns_output_format_default;
++	}
++	if (!rr) {
++		if (LDNS_COMMENT_NULLS & fmt_st->flags) {
++			ldns_buffer_printf(output, "; (null)\n");
++		}
++		return ldns_buffer_status(output);
++	}
++	if (ldns_rr_owner(rr)) {
++		status = ldns_rdf2buffer_str_dname(output, ldns_rr_owner(rr));
++	}
++	if (status != LDNS_STATUS_OK) {
++		return status;
++	}
++
++	/* TTL should NOT be printed if it is a question */
++	if (!ldns_rr_is_question(rr)) {
++		ldns_buffer_printf(output, "\t%d", ldns_rr_ttl(rr));
++	}
++
++	ldns_buffer_printf(output, "\t");
++	status = ldns_rr_class2buffer_str(output, ldns_rr_get_class(rr));
++	if (status != LDNS_STATUS_OK) {
++		return status;
++	}
++	ldns_buffer_printf(output, "\t");
++
++	if (ldns_output_format_covers_type(fmt, ldns_rr_get_type(rr))) {
++		return ldns_rr2buffer_str_rfc3597(output, rr);
++	}
++	status = ldns_rr_type2buffer_str(output, ldns_rr_get_type(rr));
++	if (status != LDNS_STATUS_OK) {
++		return status;
++	}
++
++	if (ldns_rr_rd_count(rr) > 0) {
++		ldns_buffer_printf(output, "\t");
++	} else if (!ldns_rr_is_question(rr)) {
++		ldns_buffer_printf(output, "\t\\# 0");
++	}
++
++	for (i = 0; i < ldns_rr_rd_count(rr); i++) {
++		/* ldns_rdf2buffer_str handles NULL input fine! */
++		if ((fmt_st->flags & LDNS_FMT_ZEROIZE_RRSIGS) &&
++				(ldns_rr_get_type(rr) == LDNS_RR_TYPE_RRSIG) &&
++				((/* inception  */ i == 4 &&
++				  ldns_rdf_get_type(ldns_rr_rdf(rr, 4)) == 
++							LDNS_RDF_TYPE_TIME) ||
++				  (/* expiration */ i == 5 &&
++				   ldns_rdf_get_type(ldns_rr_rdf(rr, 5)) ==
++				   			LDNS_RDF_TYPE_TIME) ||
++				  (/* signature  */ i == 8 &&
++				   ldns_rdf_get_type(ldns_rr_rdf(rr, 8)) ==
++				   			LDNS_RDF_TYPE_B64))) {
++
++			ldns_buffer_printf(output, "(null)");
++			status = ldns_buffer_status(output);
++		} else if ((fmt_st->flags & LDNS_FMT_PAD_SOA_SERIAL) &&
++				(ldns_rr_get_type(rr) == LDNS_RR_TYPE_SOA) &&
++				/* serial */ i == 2 &&
++			 	ldns_rdf_get_type(ldns_rr_rdf(rr, 2)) ==
++			 				LDNS_RDF_TYPE_INT32) {
++			ldns_buffer_printf(output, "%10lu",
++				(unsigned long) ldns_read_uint32(
++					ldns_rdf_data(ldns_rr_rdf(rr, 2))));
++			status = ldns_buffer_status(output);
++		} else {
++			status = ldns_rdf2buffer_str_fmt(output,
++					fmt, ldns_rr_rdf(rr, i));
++		}
++		if(status != LDNS_STATUS_OK)
++			return status;
++		if (i < ldns_rr_rd_count(rr) - 1) {
++			ldns_buffer_printf(output, " ");
++		}
++	}
++	/* per RR special comments - handy for DNSSEC types */
++	/* check to prevent question sec. rr from
++	 * getting here */
++	if (ldns_rr_rd_count(rr) > 0) {
++		switch (ldns_rr_get_type(rr)) {
++		case LDNS_RR_TYPE_DNSKEY:
++			/* if ldns_rr_rd_count(rr) > 0
++				then ldns_rr_rdf(rr, 0) exists! */
++			if (! (fmt_st->flags & LDNS_COMMENT_KEY)) {
++				break;
++			}
++			flags = ldns_rdf2native_int16(ldns_rr_rdf(rr, 0));
++			ldns_buffer_printf(output, " ;{");
++			if (fmt_st->flags & LDNS_COMMENT_KEY_ID) {
++				ldns_buffer_printf(output, "id = %u",
++					(unsigned int) ldns_calc_keytag(rr));
++			}
++			if ((fmt_st->flags & LDNS_COMMENT_KEY_TYPE) &&
++					(flags & LDNS_KEY_ZONE_KEY)){
++
++				if (flags & LDNS_KEY_SEP_KEY) {
++					ldns_buffer_printf(output, " (ksk)");
++				} else {
++					ldns_buffer_printf(output, " (zsk)");
++				}
++				if (fmt_st->flags & LDNS_COMMENT_KEY_SIZE){
++					ldns_buffer_printf(output, ", ");
++				}
++			} else if (fmt_st->flags
++					& (LDNS_COMMENT_KEY_ID
++						|LDNS_COMMENT_KEY_SIZE)) {
++				ldns_buffer_printf( output, ", ");
++			}
++			if (fmt_st->flags & LDNS_COMMENT_KEY_SIZE) {
++				ldns_buffer_printf(output, "size = %db",
++					ldns_rr_dnskey_key_size(rr));
++			}
++			ldns_buffer_printf(output, "}");
++			break;
++		case LDNS_RR_TYPE_RRSIG:
++			if ((fmt_st->flags & LDNS_COMMENT_KEY)
++					&& (fmt_st->flags& LDNS_COMMENT_RRSIGS)
++					&& ldns_rr_rdf(rr, 6) != NULL) {
++				ldns_buffer_printf(output, " ;{id = %d}",
++						ldns_rdf2native_int16(
++							ldns_rr_rdf(rr, 6)));
++			}
++			break;
++		case LDNS_RR_TYPE_DS:
++			if ((fmt_st->flags & LDNS_COMMENT_BUBBLEBABBLE) &&
++					ldns_rr_rdf(rr, 3) != NULL) {
++
++				uint8_t *data = ldns_rdf_data(
++						ldns_rr_rdf(rr, 3));
++				size_t len = ldns_rdf_size(ldns_rr_rdf(rr, 3));
++				char *babble = ldns_bubblebabble(data, len);
++				if(babble) {
++					ldns_buffer_printf(output,
++							" ;{%s}", babble);
++				}
++				LDNS_FREE(babble);
++			}
++			break;
++		case LDNS_RR_TYPE_NSEC3:
++			if (! (fmt_st->flags & LDNS_COMMENT_FLAGS) &&
++				! (fmt_st->flags & LDNS_COMMENT_NSEC3_CHAIN)) {
++				break;
++			}
++			ldns_buffer_printf(output, " ;{");
++			if ((fmt_st->flags & LDNS_COMMENT_FLAGS)) {
++				if (ldns_nsec3_optout(rr)) {
++					ldns_buffer_printf(output,
++						" flags: optout");
++				} else {
++					ldns_buffer_printf(output," flags: -");
++				}
++				if (fmt_st->flags & LDNS_COMMENT_NSEC3_CHAIN &&
++						fmt_st->hashmap != NULL) {
++					ldns_buffer_printf(output, ", ");
++				}
++			}
++			if (fmt_st->flags & LDNS_COMMENT_NSEC3_CHAIN &&
++					fmt_st->hashmap != NULL) {
++				ldns_rbnode_t *node;
++				ldns_rdf *key = ldns_dname_label(
++						ldns_rr_owner(rr), 0);
++				if (key) {
++					node = ldns_rbtree_search(
++						fmt_st->hashmap,
++						(void *) key);
++					if (node->data) {
++						ldns_buffer_printf(output,
++							"from: ");
++						(void) ldns_rdf2buffer_str(
++							output,
++							ldns_dnssec_name_name(
++							   (ldns_dnssec_name*)
++							   node->data
++							));
++					}
++					ldns_rdf_free(key);
++				}
++				key = ldns_b32_ext2dname(
++						ldns_nsec3_next_owner(rr));
++				if (key) {
++					node = ldns_rbtree_search(
++						fmt_st->hashmap,
++						(void *) key);
++					if (node->data) {
++						ldns_buffer_printf(output,
++							" to: ");
++						(void) ldns_rdf2buffer_str(
++							output,
++							ldns_dnssec_name_name(
++							   (ldns_dnssec_name*)
++							   node->data
++							));
++					}
++					ldns_rdf_free(key);
++				}
++			}
++			ldns_buffer_printf(output, "}");
++			break;
++		default:
++			break;
++
++		}
++	}
++	/* last */
++	ldns_buffer_printf(output, "\n");
++	return ldns_buffer_status(output);
++}
++
++ldns_status
++ldns_rr2buffer_str(ldns_buffer *output, const ldns_rr *rr)
++{
++	return ldns_rr2buffer_str_fmt(output, ldns_output_format_default, rr);
++}
++
++ldns_status
++ldns_rr_list2buffer_str_fmt(ldns_buffer *output, 
++		const ldns_output_format *fmt, const ldns_rr_list *list)
++{
++	uint16_t i;
++
++	for(i = 0; i < ldns_rr_list_rr_count(list); i++) {
++		(void) ldns_rr2buffer_str_fmt(output, fmt, 
++				ldns_rr_list_rr(list, i));
++	}
++	return ldns_buffer_status(output);
++}
++
++ldns_status
++ldns_rr_list2buffer_str(ldns_buffer *output, const ldns_rr_list *list)
++{
++	return ldns_rr_list2buffer_str_fmt(
++			output, ldns_output_format_default, list);
++}
++
++ldns_status
++ldns_pktheader2buffer_str(ldns_buffer *output, const ldns_pkt *pkt)
++{
++	ldns_lookup_table *opcode = ldns_lookup_by_id(ldns_opcodes,
++			                    (int) ldns_pkt_get_opcode(pkt));
++	ldns_lookup_table *rcode = ldns_lookup_by_id(ldns_rcodes,
++			                    (int) ldns_pkt_get_rcode(pkt));
++
++	ldns_buffer_printf(output, ";; ->>HEADER<<- ");
++	if (opcode) {
++		ldns_buffer_printf(output, "opcode: %s, ", opcode->name);
++	} else {
++		ldns_buffer_printf(output, "opcode: ?? (%u), ",
++				ldns_pkt_get_opcode(pkt));
++	}
++	if (rcode) {
++		ldns_buffer_printf(output, "rcode: %s, ", rcode->name);
++	} else {
++		ldns_buffer_printf(output, "rcode: ?? (%u), ", ldns_pkt_get_rcode(pkt));
++	}
++	ldns_buffer_printf(output, "id: %d\n", ldns_pkt_id(pkt));
++	ldns_buffer_printf(output, ";; flags: ");
++
++	if (ldns_pkt_qr(pkt)) {
++		ldns_buffer_printf(output, "qr ");
++	}
++	if (ldns_pkt_aa(pkt)) {
++		ldns_buffer_printf(output, "aa ");
++	}
++	if (ldns_pkt_tc(pkt)) {
++		ldns_buffer_printf(output, "tc ");
++	}
++	if (ldns_pkt_rd(pkt)) {
++		ldns_buffer_printf(output, "rd ");
++	}
++	if (ldns_pkt_cd(pkt)) {
++		ldns_buffer_printf(output, "cd ");
++	}
++	if (ldns_pkt_ra(pkt)) {
++		ldns_buffer_printf(output, "ra ");
++	}
++	if (ldns_pkt_ad(pkt)) {
++		ldns_buffer_printf(output, "ad ");
++	}
++	ldns_buffer_printf(output, "; ");
++	ldns_buffer_printf(output, "QUERY: %u, ", ldns_pkt_qdcount(pkt));
++	ldns_buffer_printf(output, "ANSWER: %u, ", ldns_pkt_ancount(pkt));
++	ldns_buffer_printf(output, "AUTHORITY: %u, ", ldns_pkt_nscount(pkt));
++	ldns_buffer_printf(output, "ADDITIONAL: %u ", ldns_pkt_arcount(pkt));
++	return ldns_buffer_status(output);
++}
++
++ldns_status
++ldns_pkt2buffer_str_fmt(ldns_buffer *output, 
++		const ldns_output_format *fmt, const ldns_pkt *pkt)
++{
++	uint16_t i;
++	ldns_status status = LDNS_STATUS_OK;
++	char *tmp;
++	struct timeval time;
++	time_t time_tt;
++
++	if (!pkt) {
++		ldns_buffer_printf(output, "null");
++		return LDNS_STATUS_OK;
++	}
++
++	if (ldns_buffer_status_ok(output)) {
++		status = ldns_pktheader2buffer_str(output, pkt);
++		if (status != LDNS_STATUS_OK) {
++			return status;
++		}
++
++		ldns_buffer_printf(output, "\n");
++
++		ldns_buffer_printf(output, ";; QUESTION SECTION:\n;; ");
++
++
++		for (i = 0; i < ldns_pkt_qdcount(pkt); i++) {
++			status = ldns_rr2buffer_str_fmt(output, fmt,
++				       ldns_rr_list_rr(
++					       ldns_pkt_question(pkt), i));
++			if (status != LDNS_STATUS_OK) {
++				return status;
++			}
++		}
++		ldns_buffer_printf(output, "\n");
++
++		ldns_buffer_printf(output, ";; ANSWER SECTION:\n");
++		for (i = 0; i < ldns_pkt_ancount(pkt); i++) {
++			status = ldns_rr2buffer_str_fmt(output, fmt,
++				       ldns_rr_list_rr(
++					       ldns_pkt_answer(pkt), i));
++			if (status != LDNS_STATUS_OK) {
++				return status;
++			}
++
++		}
++		ldns_buffer_printf(output, "\n");
++
++		ldns_buffer_printf(output, ";; AUTHORITY SECTION:\n");
++
++		for (i = 0; i < ldns_pkt_nscount(pkt); i++) {
++			status = ldns_rr2buffer_str_fmt(output, fmt,
++				       ldns_rr_list_rr(
++					       ldns_pkt_authority(pkt), i));
++			if (status != LDNS_STATUS_OK) {
++				return status;
++			}
++		}
++		ldns_buffer_printf(output, "\n");
++
++		ldns_buffer_printf(output, ";; ADDITIONAL SECTION:\n");
++		for (i = 0; i < ldns_pkt_arcount(pkt); i++) {
++			status = ldns_rr2buffer_str_fmt(output, fmt,
++				       ldns_rr_list_rr(
++					       ldns_pkt_additional(pkt), i));
++			if (status != LDNS_STATUS_OK) {
++				return status;
++			}
++
++		}
++		ldns_buffer_printf(output, "\n");
++		/* add some futher fields */
++		ldns_buffer_printf(output, ";; Query time: %d msec\n",
++				ldns_pkt_querytime(pkt));
++		if (ldns_pkt_edns(pkt)) {
++			ldns_buffer_printf(output,
++				   ";; EDNS: version %u; flags:",
++				   ldns_pkt_edns_version(pkt));
++			if (ldns_pkt_edns_do(pkt)) {
++				ldns_buffer_printf(output, " do");
++			}
++			/* the extended rcode is the value set, shifted four bits,
++			 * and or'd with the original rcode */
++			if (ldns_pkt_edns_extended_rcode(pkt)) {
++				ldns_buffer_printf(output, " ; ext-rcode: %d",
++					(ldns_pkt_edns_extended_rcode(pkt) << 4 | ldns_pkt_get_rcode(pkt)));
++			}
++			ldns_buffer_printf(output, " ; udp: %u\n",
++					   ldns_pkt_edns_udp_size(pkt));
++
++			if (ldns_pkt_edns_data(pkt)) {
++				ldns_buffer_printf(output, ";; Data: ");
++				(void)ldns_rdf2buffer_str(output,
++							  ldns_pkt_edns_data(pkt));
++				ldns_buffer_printf(output, "\n");
++			}
++		}
++		if (ldns_pkt_tsig(pkt)) {
++			ldns_buffer_printf(output, ";; TSIG:\n;; ");
++			(void) ldns_rr2buffer_str_fmt(
++					output, fmt, ldns_pkt_tsig(pkt));
++			ldns_buffer_printf(output, "\n");
++		}
++		if (ldns_pkt_answerfrom(pkt)) {
++			tmp = ldns_rdf2str(ldns_pkt_answerfrom(pkt));
++			ldns_buffer_printf(output, ";; SERVER: %s\n", tmp);
++			LDNS_FREE(tmp);
++		}
++		time = ldns_pkt_timestamp(pkt);
++		time_tt = (time_t)time.tv_sec;
++		ldns_buffer_printf(output, ";; WHEN: %s",
++				(char*)ctime(&time_tt));
++
++		ldns_buffer_printf(output, ";; MSG SIZE  rcvd: %d\n",
++				(int)ldns_pkt_size(pkt));
++	} else {
++		return ldns_buffer_status(output);
++	}
++	return status;
++}
++
++ldns_status
++ldns_pkt2buffer_str(ldns_buffer *output, const ldns_pkt *pkt)
++{
++	return ldns_pkt2buffer_str_fmt(output, ldns_output_format_default, pkt);
++}
++
++
++#ifdef HAVE_SSL
++static ldns_status
++ldns_hmac_key2buffer_str(ldns_buffer *output, const ldns_key *k)
++{
++	ldns_status status;
++	size_t i;
++	ldns_rdf *b64_bignum;
++
++	ldns_buffer_printf(output, "Key: ");
++
++ 	i = ldns_key_hmac_size(k);
++	b64_bignum =  ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, ldns_key_hmac_key(k));
++	status = ldns_rdf2buffer_str(output, b64_bignum);
++	ldns_rdf_deep_free(b64_bignum);
++	ldns_buffer_printf(output, "\n");
++	return status;
++}
++#endif
++
++#if defined(HAVE_SSL) && defined(USE_GOST)
++static ldns_status
++ldns_gost_key2buffer_str(ldns_buffer *output, EVP_PKEY *p)
++{
++	unsigned char* pp = NULL;
++	int ret;
++	ldns_rdf *b64_bignum;
++	ldns_status status;
++
++	ldns_buffer_printf(output, "GostAsn1: ");
++
++	ret = i2d_PrivateKey(p, &pp);
++	b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, (size_t)ret, pp);
++	status = ldns_rdf2buffer_str(output, b64_bignum);
++
++	ldns_rdf_deep_free(b64_bignum);
++	OPENSSL_free(pp);
++	ldns_buffer_printf(output, "\n");
++	return status;
++}
++#endif
++
++ldns_status
++ldns_key2buffer_str(ldns_buffer *output, const ldns_key *k)
++{
++	ldns_status status = LDNS_STATUS_OK;
++	unsigned char  *bignum;
++#ifdef HAVE_SSL
++#  ifndef S_SPLINT_S
++	uint16_t i;
++#  endif
++	/* not used when ssl is not defined */
++	/*@unused@*/
++	ldns_rdf *b64_bignum = NULL;
++
++	RSA *rsa;
++	DSA *dsa;
++#endif /* HAVE_SSL */
++
++	if (!k) {
++		return LDNS_STATUS_ERR;
++	}
++
++	bignum = LDNS_XMALLOC(unsigned char, LDNS_MAX_KEYLEN);
++	if (!bignum) {
++		return LDNS_STATUS_ERR;
++	}
++
++	if (ldns_buffer_status_ok(output)) {
++#ifdef HAVE_SSL
++		switch(ldns_key_algorithm(k)) {
++			case LDNS_SIGN_RSASHA1:
++			case LDNS_SIGN_RSASHA1_NSEC3:
++			case LDNS_SIGN_RSASHA256:
++			case LDNS_SIGN_RSASHA512:
++			case LDNS_SIGN_RSAMD5:
++				/* copied by looking at dnssec-keygen output */
++				/* header */
++				rsa = ldns_key_rsa_key(k);
++
++				ldns_buffer_printf(output,"Private-key-format: v1.2\n");
++				switch(ldns_key_algorithm(k)) {
++				case LDNS_SIGN_RSAMD5:
++					ldns_buffer_printf(output,
++								    "Algorithm: %u (RSA)\n",
++								    LDNS_RSAMD5);
++					break;
++				case LDNS_SIGN_RSASHA1:
++					ldns_buffer_printf(output,
++								    "Algorithm: %u (RSASHA1)\n",
++								    LDNS_RSASHA1);
++					break;
++				case LDNS_SIGN_RSASHA1_NSEC3:
++					ldns_buffer_printf(output,
++								    "Algorithm: %u (RSASHA1_NSEC3)\n",
++								    LDNS_RSASHA1_NSEC3);
++					break;
++#ifdef USE_SHA2
++				case LDNS_SIGN_RSASHA256:
++					ldns_buffer_printf(output,
++								    "Algorithm: %u (RSASHA256)\n",
++								    LDNS_RSASHA256);
++					break;
++				case LDNS_SIGN_RSASHA512:
++					ldns_buffer_printf(output,
++								    "Algorithm: %u (RSASHA512)\n",
++								    LDNS_RSASHA512);
++					break;
++#endif
++				default:
++#ifdef STDERR_MSGS
++					fprintf(stderr, "Warning: unknown signature ");
++					fprintf(stderr,
++						   "algorithm type %u\n",
++						   ldns_key_algorithm(k));
++#endif
++					ldns_buffer_printf(output,
++								    "Algorithm: %u (Unknown)\n",
++								    ldns_key_algorithm(k));
++					break;
++				}
++
++				/* print to buf, convert to bin, convert to b64,
++				 * print to buf */
++				ldns_buffer_printf(output, "Modulus: ");
++#ifndef S_SPLINT_S
++				i = (uint16_t)BN_bn2bin(rsa->n, bignum);
++				if (i > LDNS_MAX_KEYLEN) {
++					goto error;
++				}
++				b64_bignum =  ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum);
++				if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) {
++					ldns_rdf_deep_free(b64_bignum);
++					goto error;
++				}
++				ldns_rdf_deep_free(b64_bignum);
++				ldns_buffer_printf(output, "\n");
++				ldns_buffer_printf(output, "PublicExponent: ");
++				i = (uint16_t)BN_bn2bin(rsa->e, bignum);
++				if (i > LDNS_MAX_KEYLEN) {
++					goto error;
++				}
++				b64_bignum =  ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum);
++				if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) {
++					ldns_rdf_deep_free(b64_bignum);
++					goto error;
++				}
++				ldns_rdf_deep_free(b64_bignum);
++				ldns_buffer_printf(output, "\n");
++
++				ldns_buffer_printf(output, "PrivateExponent: ");
++				if (rsa->d) {
++					i = (uint16_t)BN_bn2bin(rsa->d, bignum);
++					if (i > LDNS_MAX_KEYLEN) {
++						goto error;
++					}
++					b64_bignum =  ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum);
++					if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) {
++						ldns_rdf_deep_free(b64_bignum);
++						goto error;
++					}
++					ldns_rdf_deep_free(b64_bignum);
++					ldns_buffer_printf(output, "\n");
++				} else {
++					ldns_buffer_printf(output, "(Not available)\n");
++				}
++
++				ldns_buffer_printf(output, "Prime1: ");
++				if (rsa->p) {
++					i = (uint16_t)BN_bn2bin(rsa->p, bignum);
++					if (i > LDNS_MAX_KEYLEN) {
++						goto error;
++					}
++					b64_bignum =  ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum);
++					if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) {
++						ldns_rdf_deep_free(b64_bignum);
++						goto error;
++					}
++					ldns_rdf_deep_free(b64_bignum);
++					ldns_buffer_printf(output, "\n");
++				} else {
++					ldns_buffer_printf(output, "(Not available)\n");
++				}
++
++				ldns_buffer_printf(output, "Prime2: ");
++				if (rsa->q) {
++					i = (uint16_t)BN_bn2bin(rsa->q, bignum);
++					if (i > LDNS_MAX_KEYLEN) {
++						goto error;
++					}
++					b64_bignum =  ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum);
++					if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) {
++						ldns_rdf_deep_free(b64_bignum);
++						goto error;
++					}
++					ldns_rdf_deep_free(b64_bignum);
++					ldns_buffer_printf(output, "\n");
++				} else {
++					ldns_buffer_printf(output, "(Not available)\n");
++				}
++
++				ldns_buffer_printf(output, "Exponent1: ");
++				if (rsa->dmp1) {
++					i = (uint16_t)BN_bn2bin(rsa->dmp1, bignum);
++					if (i > LDNS_MAX_KEYLEN) {
++						goto error;
++					}
++					b64_bignum =  ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum);
++					if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) {
++						ldns_rdf_deep_free(b64_bignum);
++						goto error;
++					}
++					ldns_rdf_deep_free(b64_bignum);
++					ldns_buffer_printf(output, "\n");
++				} else {
++					ldns_buffer_printf(output, "(Not available)\n");
++				}
++
++				ldns_buffer_printf(output, "Exponent2: ");
++				if (rsa->dmq1) {
++					i = (uint16_t)BN_bn2bin(rsa->dmq1, bignum);
++					if (i > LDNS_MAX_KEYLEN) {
++						goto error;
++					}
++					b64_bignum =  ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum);
++					if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) {
++						ldns_rdf_deep_free(b64_bignum);
++						goto error;
++					}
++					ldns_rdf_deep_free(b64_bignum);
++					ldns_buffer_printf(output, "\n");
++				} else {
++					ldns_buffer_printf(output, "(Not available)\n");
++				}
++
++				ldns_buffer_printf(output, "Coefficient: ");
++				if (rsa->iqmp) {
++					i = (uint16_t)BN_bn2bin(rsa->iqmp, bignum);
++					if (i > LDNS_MAX_KEYLEN) {
++						goto error;
++					}
++					b64_bignum =  ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum);
++					if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) {
++						ldns_rdf_deep_free(b64_bignum);
++						goto error;
++					}
++					ldns_rdf_deep_free(b64_bignum);
++					ldns_buffer_printf(output, "\n");
++				} else {
++					ldns_buffer_printf(output, "(Not available)\n");
++				}
++#endif /* splint */
++
++				RSA_free(rsa);
++				break;
++			case LDNS_SIGN_DSA:
++			case LDNS_SIGN_DSA_NSEC3:
++				dsa = ldns_key_dsa_key(k);
++
++				ldns_buffer_printf(output,"Private-key-format: v1.2\n");
++				if (ldns_key_algorithm(k) == LDNS_SIGN_DSA) {
++					ldns_buffer_printf(output,"Algorithm: 3 (DSA)\n");
++				} else if (ldns_key_algorithm(k) == LDNS_SIGN_DSA_NSEC3) {
++					ldns_buffer_printf(output,"Algorithm: 6 (DSA_NSEC3)\n");
++				}
++
++				/* print to buf, convert to bin, convert to b64,
++				 * print to buf */
++				ldns_buffer_printf(output, "Prime(p): ");
++#ifndef S_SPLINT_S
++				if (dsa->p) {
++					i = (uint16_t)BN_bn2bin(dsa->p, bignum);
++					if (i > LDNS_MAX_KEYLEN) {
++						goto error;
++					}
++					b64_bignum =  ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum);
++					if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) {
++						ldns_rdf_deep_free(b64_bignum);
++						goto error;
++					}
++					ldns_rdf_deep_free(b64_bignum);
++					ldns_buffer_printf(output, "\n");
++				} else {
++					printf("(Not available)\n");
++				}
++
++				ldns_buffer_printf(output, "Subprime(q): ");
++				if (dsa->q) {
++					i = (uint16_t)BN_bn2bin(dsa->q, bignum);
++					if (i > LDNS_MAX_KEYLEN) {
++						goto error;
++					}
++					b64_bignum =  ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum);
++					if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) {
++						ldns_rdf_deep_free(b64_bignum);
++						goto error;
++					}
++					ldns_rdf_deep_free(b64_bignum);
++					ldns_buffer_printf(output, "\n");
++				} else {
++					printf("(Not available)\n");
++				}
++
++				ldns_buffer_printf(output, "Base(g): ");
++				if (dsa->g) {
++					i = (uint16_t)BN_bn2bin(dsa->g, bignum);
++					if (i > LDNS_MAX_KEYLEN) {
++						goto error;
++					}
++					b64_bignum =  ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum);
++					if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) {
++						ldns_rdf_deep_free(b64_bignum);
++						goto error;
++					}
++					ldns_rdf_deep_free(b64_bignum);
++					ldns_buffer_printf(output, "\n");
++				} else {
++					printf("(Not available)\n");
++				}
++
++				ldns_buffer_printf(output, "Private_value(x): ");
++				if (dsa->priv_key) {
++					i = (uint16_t)BN_bn2bin(dsa->priv_key, bignum);
++					if (i > LDNS_MAX_KEYLEN) {
++						goto error;
++					}
++					b64_bignum =  ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum);
++					if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) {
++						ldns_rdf_deep_free(b64_bignum);
++						goto error;
++					}
++					ldns_rdf_deep_free(b64_bignum);
++					ldns_buffer_printf(output, "\n");
++				} else {
++					printf("(Not available)\n");
++				}
++
++				ldns_buffer_printf(output, "Public_value(y): ");
++				if (dsa->pub_key) {
++					i = (uint16_t)BN_bn2bin(dsa->pub_key, bignum);
++					if (i > LDNS_MAX_KEYLEN) {
++						goto error;
++					}
++					b64_bignum =  ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum);
++					if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) {
++						ldns_rdf_deep_free(b64_bignum);
++						goto error;
++					}
++					ldns_rdf_deep_free(b64_bignum);
++					ldns_buffer_printf(output, "\n");
++				} else {
++					printf("(Not available)\n");
++				}
++#endif /* splint */
++				break;
++			case LDNS_SIGN_ECC_GOST:
++				/* no format defined, use blob */
++#if defined(HAVE_SSL) && defined(USE_GOST)
++				ldns_buffer_printf(output, "Private-key-format: v1.2\n");
++				ldns_buffer_printf(output, "Algorithm: %d (ECC-GOST)\n", LDNS_SIGN_ECC_GOST);
++				status = ldns_gost_key2buffer_str(output, 
++#ifndef S_SPLINT_S
++					k->_key.key
++#else
++					NULL
++#endif
++				);
++#else
++				goto error;
++#endif /* GOST */
++				break;
++			case LDNS_SIGN_ECDSAP256SHA256:
++			case LDNS_SIGN_ECDSAP384SHA384:
++#ifdef USE_ECDSA
++                                ldns_buffer_printf(output, "Private-key-format: v1.2\n");
++				ldns_buffer_printf(output, "Algorithm: %d (", ldns_key_algorithm(k));
++                                status=ldns_algorithm2buffer_str(output, (ldns_algorithm)ldns_key_algorithm(k));
++#ifndef S_SPLINT_S
++				ldns_buffer_printf(output, ")\n");
++                                if(k->_key.key) {
++                                        EC_KEY* ec = EVP_PKEY_get1_EC_KEY(k->_key.key);
++                                        const BIGNUM* b = EC_KEY_get0_private_key(ec);
++                                        ldns_buffer_printf(output, "PrivateKey: ");
++                                        i = (uint16_t)BN_bn2bin(b, bignum);
++                                        if (i > LDNS_MAX_KEYLEN) {
++                                                goto error;
++                                        }
++                                        b64_bignum =  ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum);
++                                        if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) {
++						ldns_rdf_deep_free(b64_bignum);
++                                                goto error;
++                                        }
++                                        ldns_rdf_deep_free(b64_bignum);
++				        ldns_buffer_printf(output, "\n");
++                                        /* down reference count in EC_KEY
++                                         * its still assigned to the PKEY */
++                                        EC_KEY_free(ec);
++                                }
++#endif /* splint */
++#else
++				goto error;
++#endif /* ECDSA */
++                                break;
++			case LDNS_SIGN_HMACMD5:
++				/* there's not much of a format defined for TSIG */
++				/* It's just a binary blob, Same for all algorithms */
++                ldns_buffer_printf(output, "Private-key-format: v1.2\n");
++                ldns_buffer_printf(output, "Algorithm: 157 (HMAC_MD5)\n");
++				status = ldns_hmac_key2buffer_str(output, k);
++				break;
++			case LDNS_SIGN_HMACSHA1:
++		        ldns_buffer_printf(output, "Private-key-format: v1.2\n");
++		        ldns_buffer_printf(output, "Algorithm: 158 (HMAC_SHA1)\n");
++				status = ldns_hmac_key2buffer_str(output, k);
++				break;
++			case LDNS_SIGN_HMACSHA256:
++		        ldns_buffer_printf(output, "Private-key-format: v1.2\n");
++		        ldns_buffer_printf(output, "Algorithm: 159 (HMAC_SHA256)\n");
++				status = ldns_hmac_key2buffer_str(output, k);
++				break;
++		}
++#endif /* HAVE_SSL */
++	} else {
++		LDNS_FREE(bignum);
++		return ldns_buffer_status(output);
++	}
++	LDNS_FREE(bignum);
++	return status;
++
++#ifdef HAVE_SSL
++	/* compiles warn the label isn't used */
++error:
++	LDNS_FREE(bignum);
++	return LDNS_STATUS_ERR;
++#endif /* HAVE_SSL */
++
++}
++
++/*
++ * Zero terminate the buffer and copy data.
++ */
++char *
++ldns_buffer2str(ldns_buffer *buffer)
++{
++	char *str;
++
++	/* check if buffer ends with \0, if not, and
++	   if there is space, add it */
++	if (*(ldns_buffer_at(buffer, ldns_buffer_position(buffer))) != 0) {
++		if (!ldns_buffer_reserve(buffer, 1)) {
++			return NULL;
++		}
++		ldns_buffer_write_u8(buffer, (uint8_t) '\0');
++		if (!ldns_buffer_set_capacity(buffer, ldns_buffer_position(buffer))) {
++			return NULL;
++		}
++	}
++
++	str = strdup((const char *)ldns_buffer_begin(buffer));
++        if(!str) {
++                return NULL;
++        }
++	return str;
++}
++
++/*
++ * Zero terminate the buffer and export data.
++ */
++char *
++ldns_buffer_export2str(ldns_buffer *buffer)
++{
++	/* Append '\0' as string terminator */
++	if (! ldns_buffer_reserve(buffer, 1)) {
++		return NULL;
++	}
++	ldns_buffer_write_u8(buffer, 0);
++
++	/* reallocate memory to the size of the string and export */
++	ldns_buffer_set_capacity(buffer, ldns_buffer_position(buffer));
++	return ldns_buffer_export(buffer);
++}
++
++char *
++ldns_rdf2str(const ldns_rdf *rdf)
++{
++	char *result = NULL;
++	ldns_buffer *tmp_buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN);
++
++	if (!tmp_buffer) {
++		return NULL;
++	}
++	if (ldns_rdf2buffer_str(tmp_buffer, rdf) == LDNS_STATUS_OK) {
++		/* export and return string, destroy rest */
++		result = ldns_buffer_export2str(tmp_buffer);
++	}
++	ldns_buffer_free(tmp_buffer);
++	return result;
++}
++
++char *
++ldns_rr2str_fmt(const ldns_output_format *fmt, const ldns_rr *rr)
++{
++	char *result = NULL;
++	ldns_buffer *tmp_buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN);
++
++	if (!tmp_buffer) {
++		return NULL;
++	}
++	if (ldns_rr2buffer_str_fmt(tmp_buffer, fmt, rr)
++		       	== LDNS_STATUS_OK) {
++		/* export and return string, destroy rest */
++		result = ldns_buffer_export2str(tmp_buffer);
++	}
++	ldns_buffer_free(tmp_buffer);
++	return result;
++}
++
++char *
++ldns_rr2str(const ldns_rr *rr)
++{
++	return ldns_rr2str_fmt(ldns_output_format_default, rr);
++}
++
++char *
++ldns_pkt2str_fmt(const ldns_output_format *fmt, const ldns_pkt *pkt)
++{
++	char *result = NULL;
++	ldns_buffer *tmp_buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN);
++
++	if (!tmp_buffer) {
++		return NULL;
++	}
++	if (ldns_pkt2buffer_str_fmt(tmp_buffer, fmt, pkt)
++		       	== LDNS_STATUS_OK) {
++		/* export and return string, destroy rest */
++		result = ldns_buffer_export2str(tmp_buffer);
++	}
++
++	ldns_buffer_free(tmp_buffer);
++	return result;
++}
++
++char *
++ldns_pkt2str(const ldns_pkt *pkt)
++{
++	return ldns_pkt2str_fmt(ldns_output_format_default, pkt);
++}
++
++char *
++ldns_key2str(const ldns_key *k)
++{
++	char *result = NULL;
++	ldns_buffer *tmp_buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN);
++
++	if (!tmp_buffer) {
++		return NULL;
++	}
++	if (ldns_key2buffer_str(tmp_buffer, k) == LDNS_STATUS_OK) {
++		/* export and return string, destroy rest */
++		result = ldns_buffer_export2str(tmp_buffer);
++	}
++	ldns_buffer_free(tmp_buffer);
++	return result;
++}
++
++char *
++ldns_rr_list2str_fmt(const ldns_output_format *fmt, const ldns_rr_list *list)
++{
++	char *result = NULL;
++	ldns_buffer *tmp_buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN);
++
++	if (!tmp_buffer) {
++		return NULL;
++	}
++	if (list) {
++		if (ldns_rr_list2buffer_str_fmt(
++				   tmp_buffer, fmt, list)
++			       	== LDNS_STATUS_OK) {
++		}
++	} else {
++		if (fmt == NULL) {
++			fmt = ldns_output_format_default;
++		}
++		if (fmt->flags & LDNS_COMMENT_NULLS) {
++			ldns_buffer_printf(tmp_buffer, "; (null)\n");
++		}
++	}
++
++	/* export and return string, destroy rest */
++	result = ldns_buffer_export2str(tmp_buffer);
++	ldns_buffer_free(tmp_buffer);
++	return result;
++}
++
++char *
++ldns_rr_list2str(const ldns_rr_list *list)
++{
++	return ldns_rr_list2str_fmt(ldns_output_format_default, list);
++}
++
++void
++ldns_rdf_print(FILE *output, const ldns_rdf *rdf)
++{
++	char *str = ldns_rdf2str(rdf);
++	if (str) {
++		fprintf(output, "%s", str);
++	} else {
++		fprintf(output, ";Unable to convert rdf to string\n");
++	}
++	LDNS_FREE(str);
++}
++
++void
++ldns_rr_print_fmt(FILE *output,
++		const ldns_output_format *fmt, const ldns_rr *rr)
++{
++	char *str = ldns_rr2str_fmt(fmt, rr);
++	if (str) {
++		fprintf(output, "%s", str);
++	} else {
++		fprintf(output, ";Unable to convert rr to string\n");
++	}
++	LDNS_FREE(str);
++}
++
++void
++ldns_rr_print(FILE *output, const ldns_rr *rr)
++{
++	ldns_rr_print_fmt(output, ldns_output_format_default, rr);
++}
++
++void
++ldns_pkt_print_fmt(FILE *output, 
++		const ldns_output_format *fmt, const ldns_pkt *pkt)
++{
++	char *str = ldns_pkt2str_fmt(fmt, pkt);
++	if (str) {
++		fprintf(output, "%s", str);
++	} else {
++		fprintf(output, ";Unable to convert packet to string\n");
++	}
++	LDNS_FREE(str);
++}
++
++void
++ldns_pkt_print(FILE *output, const ldns_pkt *pkt)
++{
++	ldns_pkt_print_fmt(output, ldns_output_format_default, pkt);
++}
++
++void
++ldns_rr_list_print_fmt(FILE *output, 
++		const ldns_output_format *fmt, const ldns_rr_list *lst)
++{
++	size_t i;
++	for (i = 0; i < ldns_rr_list_rr_count(lst); i++) {
++		ldns_rr_print_fmt(output, fmt, ldns_rr_list_rr(lst, i));
++	}
++}
++
++void
++ldns_rr_list_print(FILE *output, const ldns_rr_list *lst)
++{
++	ldns_rr_list_print_fmt(output, ldns_output_format_default, lst);
++}
++
++void
++ldns_resolver_print_fmt(FILE *output, 
++		const ldns_output_format *fmt, const ldns_resolver *r)
++{
++	uint16_t i;
++	ldns_rdf **n;
++	ldns_rdf **s;
++	size_t *rtt;
++	if (!r) {
++		return;
++	}
++	n = ldns_resolver_nameservers(r);
++	s = ldns_resolver_searchlist(r);
++	rtt = ldns_resolver_rtt(r);
++
++	fprintf(output, "port: %d\n", (int)ldns_resolver_port(r));
++	fprintf(output, "edns0 size: %d\n", (int)ldns_resolver_edns_udp_size(r));
++	fprintf(output, "use ip6: %d\n", (int)ldns_resolver_ip6(r));
++
++	fprintf(output, "recursive: %d\n", ldns_resolver_recursive(r));
++	fprintf(output, "usevc: %d\n", ldns_resolver_usevc(r));
++	fprintf(output, "igntc: %d\n", ldns_resolver_igntc(r));
++	fprintf(output, "fail: %d\n", ldns_resolver_fail(r));
++	fprintf(output, "retry: %d\n", (int)ldns_resolver_retry(r));
++	fprintf(output, "retrans: %d\n", (int)ldns_resolver_retrans(r));
++	fprintf(output, "fallback: %d\n", ldns_resolver_fallback(r));
++	fprintf(output, "random: %d\n", ldns_resolver_random(r));
++	fprintf(output, "timeout: %d\n", (int)ldns_resolver_timeout(r).tv_sec);
++	fprintf(output, "dnssec: %d\n", ldns_resolver_dnssec(r));
++	fprintf(output, "dnssec cd: %d\n", ldns_resolver_dnssec_cd(r));
++	fprintf(output, "trust anchors (%d listed):\n",
++		(int)ldns_rr_list_rr_count(ldns_resolver_dnssec_anchors(r)));
++	ldns_rr_list_print_fmt(output, fmt, ldns_resolver_dnssec_anchors(r));
++	fprintf(output, "tsig: %s %s\n",
++                ldns_resolver_tsig_keyname(r)?ldns_resolver_tsig_keyname(r):"-",
++                ldns_resolver_tsig_algorithm(r)?ldns_resolver_tsig_algorithm(r):"-");
++	fprintf(output, "debug: %d\n", ldns_resolver_debug(r));
++
++	fprintf(output, "default domain: ");
++	ldns_rdf_print(output, ldns_resolver_domain(r));
++	fprintf(output, "\n");
++	fprintf(output, "apply default domain: %d\n", ldns_resolver_defnames(r));
++
++	fprintf(output, "searchlist (%d listed):\n",  (int)ldns_resolver_searchlist_count(r));
++	for (i = 0; i < ldns_resolver_searchlist_count(r); i++) {
++		fprintf(output, "\t");
++		ldns_rdf_print(output, s[i]);
++		fprintf(output, "\n");
++	}
++	fprintf(output, "apply search list: %d\n", ldns_resolver_dnsrch(r));
++
++	fprintf(output, "nameservers (%d listed):\n", (int)ldns_resolver_nameserver_count(r));
++	for (i = 0; i < ldns_resolver_nameserver_count(r); i++) {
++		fprintf(output, "\t");
++		ldns_rdf_print(output, n[i]);
++
++		switch ((int)rtt[i]) {
++			case LDNS_RESOLV_RTT_MIN:
++			fprintf(output, " - reachable\n");
++			break;
++			case LDNS_RESOLV_RTT_INF:
++			fprintf(output, " - unreachable\n");
++			break;
++		}
++	}
++}
++
++void
++ldns_resolver_print(FILE *output, const ldns_resolver *r)
++{
++	ldns_resolver_print_fmt(output, ldns_output_format_default, r);
++}
++
++void
++ldns_zone_print_fmt(FILE *output, 
++		const ldns_output_format *fmt, const ldns_zone *z)
++{
++	if(ldns_zone_soa(z))
++		ldns_rr_print_fmt(output, fmt, ldns_zone_soa(z));
++	ldns_rr_list_print_fmt(output, fmt, ldns_zone_rrs(z));
++}
++void
++ldns_zone_print(FILE *output, const ldns_zone *z)
++{
++	ldns_zone_print_fmt(output, ldns_output_format_default, z);
++}
+diff --git a/ldns/src/host2wire.c b/ldns/src/host2wire.c
+new file mode 100644
+index 0000000..06f45ba
+--- /dev/null
++++ b/ldns/src/host2wire.c
+@@ -0,0 +1,494 @@
++/*
++ * host2wire.c
++ *
++ * conversion routines from the host to the wire format.
++ * This will usually just a re-ordering of the
++ * data (as we store it in network format)
++ *
++ * a Net::DNS like library for C
++ *
++ * (c) NLnet Labs, 2004-2006
++ *
++ * See the file LICENSE for the license
++ */
++
++#include <ldns/config.h>
++
++#include <ldns/ldns.h>
++
++ldns_status
++ldns_dname2buffer_wire(ldns_buffer *buffer, const ldns_rdf *name)
++{
++	return ldns_dname2buffer_wire_compress(buffer, name, NULL);
++}
++
++ldns_status
++ldns_dname2buffer_wire_compress(ldns_buffer *buffer, const ldns_rdf *name, ldns_rbtree_t *compression_data)
++{
++	ldns_rbnode_t *node;
++	uint8_t *data;
++	size_t size;
++	ldns_rdf *label;
++	ldns_rdf *rest;
++	ldns_status s;
++
++	/* If no tree, just add the data */
++	if(!compression_data)
++	{
++		if (ldns_buffer_reserve(buffer, ldns_rdf_size(name)))
++		{
++			ldns_buffer_write(buffer, ldns_rdf_data(name), ldns_rdf_size(name));
++		}
++		return ldns_buffer_status(buffer);
++	}
++
++	/* No labels left, write final zero */
++	if(ldns_dname_label_count(name)==0)
++	{
++		if(ldns_buffer_reserve(buffer,1))
++		{
++			ldns_buffer_write_u8(buffer, 0);
++		}
++		return ldns_buffer_status(buffer);
++	}
++
++	/* Can we find the name in the tree? */
++	if((node = ldns_rbtree_search(compression_data, ldns_rdf_data(name))) != NULL)
++	{
++		/* Found */
++		uint16_t position = (uint16_t) (intptr_t) node->data | 0xC000;
++		if (ldns_buffer_reserve(buffer, 2))
++		{
++			ldns_buffer_write_u16(buffer, position);
++		}
++		return ldns_buffer_status(buffer);
++	}
++	else
++	{
++		/* Not found. Write cache entry, take off first label, write it, */
++		/* try again with the rest of the name. */
++		ldns_rbnode_t *node = LDNS_MALLOC(ldns_rbnode_t);
++		if(!node)
++		{
++			return LDNS_STATUS_MEM_ERR;
++		}
++		if (ldns_buffer_position(buffer) < 16384) {
++			node->key = strdup((const char *)ldns_rdf_data(name));
++			node->data = (void *) (intptr_t) ldns_buffer_position(buffer);
++			if(!ldns_rbtree_insert(compression_data,node))
++			{
++				/* fprintf(stderr,"Name not found but now it's there?\n"); */
++			}
++		}
++		label = ldns_dname_label(name, 0);
++		rest = ldns_dname_left_chop(name);
++		size = ldns_rdf_size(label) - 1; /* Don't want the final zero */
++		data = ldns_rdf_data(label);
++		if(ldns_buffer_reserve(buffer, size))
++		{
++			ldns_buffer_write(buffer, data, size);
++		}
++		ldns_rdf_deep_free(label);
++		s = ldns_dname2buffer_wire_compress(buffer, rest, compression_data);
++		ldns_rdf_deep_free(rest);
++		return s;
++	}
++}
++
++ldns_status
++ldns_rdf2buffer_wire(ldns_buffer *buffer, const ldns_rdf *rdf)
++{
++	return ldns_rdf2buffer_wire_compress(buffer, rdf, NULL);
++}
++
++ldns_status
++ldns_rdf2buffer_wire_compress(ldns_buffer *buffer, const ldns_rdf *rdf, ldns_rbtree_t *compression_data)
++{
++	/* If it's a DNAME, call that function to get compression */
++	if(compression_data && ldns_rdf_get_type(rdf) == LDNS_RDF_TYPE_DNAME)
++	{
++		return ldns_dname2buffer_wire_compress(buffer,rdf,compression_data);
++	}
++
++	if (ldns_buffer_reserve(buffer, ldns_rdf_size(rdf))) {
++		ldns_buffer_write(buffer, ldns_rdf_data(rdf), ldns_rdf_size(rdf));
++	}
++	return ldns_buffer_status(buffer);
++}
++
++ldns_status
++ldns_rdf2buffer_wire_canonical(ldns_buffer *buffer, const ldns_rdf *rdf)
++{
++	size_t i;
++	uint8_t *rdf_data;
++
++	if (ldns_rdf_get_type(rdf) == LDNS_RDF_TYPE_DNAME) {
++		if (ldns_buffer_reserve(buffer, ldns_rdf_size(rdf))) {
++			rdf_data = ldns_rdf_data(rdf);
++			for (i = 0; i < ldns_rdf_size(rdf); i++) {
++				ldns_buffer_write_u8(buffer,
++				    (uint8_t) LDNS_DNAME_NORMALIZE((int)rdf_data[i]));
++			}
++		}
++	} else {
++		/* direct copy for all other types */
++		if (ldns_buffer_reserve(buffer, ldns_rdf_size(rdf))) {
++			ldns_buffer_write(buffer,
++						   ldns_rdf_data(rdf),
++						   ldns_rdf_size(rdf));
++		}
++	}
++	return ldns_buffer_status(buffer);
++}
++
++/* convert a rr list to wireformat */
++ldns_status
++ldns_rr_list2buffer_wire(ldns_buffer *buffer,const ldns_rr_list *rr_list)
++{
++	uint16_t rr_count;
++	uint16_t i;
++
++	rr_count = ldns_rr_list_rr_count(rr_list);
++	for(i = 0; i < rr_count; i++) {
++		(void)ldns_rr2buffer_wire(buffer, ldns_rr_list_rr(rr_list, i), 
++					  LDNS_SECTION_ANY);
++	}
++	return ldns_buffer_status(buffer);
++}
++
++
++ldns_status
++ldns_rr2buffer_wire_canonical(ldns_buffer *buffer,
++						const ldns_rr *rr,
++						int section)
++{
++	uint16_t i;
++	uint16_t rdl_pos = 0;
++	bool pre_rfc3597 = false;
++	switch (ldns_rr_get_type(rr)) {
++	case LDNS_RR_TYPE_NS:
++	case LDNS_RR_TYPE_MD:
++	case LDNS_RR_TYPE_MF:
++	case LDNS_RR_TYPE_CNAME:
++	case LDNS_RR_TYPE_SOA:
++	case LDNS_RR_TYPE_MB:
++	case LDNS_RR_TYPE_MG:
++	case LDNS_RR_TYPE_MR:
++	case LDNS_RR_TYPE_PTR:
++	case LDNS_RR_TYPE_HINFO:
++	case LDNS_RR_TYPE_MINFO:
++	case LDNS_RR_TYPE_MX:
++	case LDNS_RR_TYPE_RP:
++	case LDNS_RR_TYPE_AFSDB:
++	case LDNS_RR_TYPE_RT:
++	case LDNS_RR_TYPE_SIG:
++	case LDNS_RR_TYPE_PX:
++	case LDNS_RR_TYPE_NXT:
++	case LDNS_RR_TYPE_NAPTR:
++	case LDNS_RR_TYPE_KX:
++	case LDNS_RR_TYPE_SRV:
++	case LDNS_RR_TYPE_DNAME:
++	case LDNS_RR_TYPE_A6:
++	case LDNS_RR_TYPE_RRSIG:
++		pre_rfc3597 = true;
++		break;
++	default:
++		break;
++	}
++	
++	if (ldns_rr_owner(rr)) {
++		(void) ldns_rdf2buffer_wire_canonical(buffer, ldns_rr_owner(rr));
++	}
++	
++	if (ldns_buffer_reserve(buffer, 4)) {
++		(void) ldns_buffer_write_u16(buffer, ldns_rr_get_type(rr));
++		(void) ldns_buffer_write_u16(buffer, ldns_rr_get_class(rr));
++	}
++
++	if (section != LDNS_SECTION_QUESTION) {
++		if (ldns_buffer_reserve(buffer, 6)) {
++			ldns_buffer_write_u32(buffer, ldns_rr_ttl(rr));
++			/* remember pos for later */
++			rdl_pos = ldns_buffer_position(buffer);
++			ldns_buffer_write_u16(buffer, 0);
++		}	
++		for (i = 0; i < ldns_rr_rd_count(rr); i++) {
++			if (pre_rfc3597) {
++				(void) ldns_rdf2buffer_wire_canonical(
++					buffer, ldns_rr_rdf(rr, i));
++			} else {
++				(void) ldns_rdf2buffer_wire(
++					buffer, ldns_rr_rdf(rr, i));
++			}
++		}
++		if (rdl_pos != 0) {
++			ldns_buffer_write_u16_at(buffer, rdl_pos,
++			                         ldns_buffer_position(buffer)
++		        	                   - rdl_pos - 2);
++		}
++	}
++	return ldns_buffer_status(buffer);
++}
++
++ldns_status
++ldns_rr2buffer_wire(ldns_buffer *buffer, const ldns_rr *rr, int section)
++{
++	return ldns_rr2buffer_wire_compress(buffer,rr,section,NULL);
++}
++
++ldns_status
++ldns_rr2buffer_wire_compress(ldns_buffer *buffer, const ldns_rr *rr, int section, ldns_rbtree_t *compression_data)
++{
++	uint16_t i;
++	uint16_t rdl_pos = 0;
++
++	if (ldns_rr_owner(rr)) {
++		(void) ldns_dname2buffer_wire_compress(buffer, ldns_rr_owner(rr), compression_data);
++	}
++	
++	if (ldns_buffer_reserve(buffer, 4)) {
++		(void) ldns_buffer_write_u16(buffer, ldns_rr_get_type(rr));
++		(void) ldns_buffer_write_u16(buffer, ldns_rr_get_class(rr));
++	}
++
++	if (section != LDNS_SECTION_QUESTION) {
++		if (ldns_buffer_reserve(buffer, 6)) {
++			ldns_buffer_write_u32(buffer, ldns_rr_ttl(rr));
++			/* remember pos for later */
++			rdl_pos = ldns_buffer_position(buffer);
++			ldns_buffer_write_u16(buffer, 0);
++		}
++		if (LDNS_RR_COMPRESS ==
++		    ldns_rr_descript(ldns_rr_get_type(rr))->_compress) {
++
++			for (i = 0; i < ldns_rr_rd_count(rr); i++) {
++				(void) ldns_rdf2buffer_wire_compress(buffer,
++				    ldns_rr_rdf(rr, i), compression_data);
++			}
++		} else {
++			for (i = 0; i < ldns_rr_rd_count(rr); i++) {
++				(void) ldns_rdf2buffer_wire(
++				    buffer, ldns_rr_rdf(rr, i));
++			}
++		}
++		if (rdl_pos != 0) {
++			ldns_buffer_write_u16_at(buffer, rdl_pos,
++			                         ldns_buffer_position(buffer)
++		        	                   - rdl_pos - 2);
++		}
++	}
++	return ldns_buffer_status(buffer);
++}
++
++ldns_status
++ldns_rrsig2buffer_wire(ldns_buffer *buffer, const ldns_rr *rr)
++{
++	uint16_t i;
++
++	/* it must be a sig RR */
++	if (ldns_rr_get_type(rr) != LDNS_RR_TYPE_RRSIG) {
++		return LDNS_STATUS_ERR;
++	}
++	
++	/* Convert all the rdfs, except the actual signature data
++	 * rdf number 8  - the last, hence: -1 */
++	for (i = 0; i < ldns_rr_rd_count(rr) - 1; i++) {
++		(void) ldns_rdf2buffer_wire_canonical(buffer, 
++				ldns_rr_rdf(rr, i));
++	}
++
++	return ldns_buffer_status(buffer);
++}
++
++ldns_status
++ldns_rr_rdata2buffer_wire(ldns_buffer *buffer, const ldns_rr *rr)
++{
++	uint16_t i;
++
++	/* convert all the rdf's */
++	for (i = 0; i < ldns_rr_rd_count(rr); i++) {
++		(void) ldns_rdf2buffer_wire(buffer, ldns_rr_rdf(rr,i));
++	}
++	return ldns_buffer_status(buffer);
++}
++
++/*
++ * Copies the packet header data to the buffer in wire format
++ */
++static ldns_status
++ldns_hdr2buffer_wire(ldns_buffer *buffer, const ldns_pkt *packet)
++{
++	uint8_t flags;
++	uint16_t arcount;
++
++	if (ldns_buffer_reserve(buffer, 12)) {
++		ldns_buffer_write_u16(buffer, ldns_pkt_id(packet));
++		
++		flags = ldns_pkt_qr(packet) << 7
++		        | ldns_pkt_get_opcode(packet) << 3
++		        | ldns_pkt_aa(packet) << 2
++		        | ldns_pkt_tc(packet) << 1 | ldns_pkt_rd(packet);
++		ldns_buffer_write_u8(buffer, flags);
++		
++		flags = ldns_pkt_ra(packet) << 7
++		        /*| ldns_pkt_z(packet) << 6*/
++		        | ldns_pkt_ad(packet) << 5
++		        | ldns_pkt_cd(packet) << 4
++			| ldns_pkt_get_rcode(packet);
++		ldns_buffer_write_u8(buffer, flags);
++		
++		ldns_buffer_write_u16(buffer, ldns_pkt_qdcount(packet));
++		ldns_buffer_write_u16(buffer, ldns_pkt_ancount(packet));
++		ldns_buffer_write_u16(buffer, ldns_pkt_nscount(packet));
++		/* add EDNS0 and TSIG to additional if they are there */
++		arcount = ldns_pkt_arcount(packet);
++		if (ldns_pkt_tsig(packet)) {
++			arcount++;
++		}
++		if (ldns_pkt_edns(packet)) {
++			arcount++;
++		}
++		ldns_buffer_write_u16(buffer, arcount);
++	}
++	
++	return ldns_buffer_status(buffer);
++}
++
++void
++compression_node_free(ldns_rbnode_t *node, void *arg)
++{
++	(void)arg; /* Yes, dear compiler, it is used */
++	free((void *)node->key);
++	LDNS_FREE(node);
++}
++
++ldns_status
++ldns_pkt2buffer_wire(ldns_buffer *buffer, const ldns_pkt *packet)
++{
++	ldns_rr_list *rr_list;
++	uint16_t i;
++
++	/* edns tmp vars */
++	ldns_rr *edns_rr;
++	uint8_t edata[4];
++
++	ldns_rbtree_t *compression_data = ldns_rbtree_create((int (*)(const void *, const void *))strcasecmp);
++	
++	(void) ldns_hdr2buffer_wire(buffer, packet);
++
++	rr_list = ldns_pkt_question(packet);
++	if (rr_list) {
++		for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
++			(void) ldns_rr2buffer_wire_compress(buffer, 
++			             ldns_rr_list_rr(rr_list, i), LDNS_SECTION_QUESTION, compression_data);
++		}
++	}
++	rr_list = ldns_pkt_answer(packet);
++	if (rr_list) {
++		for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
++			(void) ldns_rr2buffer_wire_compress(buffer, 
++			             ldns_rr_list_rr(rr_list, i), LDNS_SECTION_ANSWER, compression_data);
++		}
++	}
++	rr_list = ldns_pkt_authority(packet);
++	if (rr_list) {
++		for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
++			(void) ldns_rr2buffer_wire_compress(buffer, 
++			             ldns_rr_list_rr(rr_list, i), LDNS_SECTION_AUTHORITY, compression_data);
++		}
++	}
++	rr_list = ldns_pkt_additional(packet);
++	if (rr_list) {
++		for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
++			(void) ldns_rr2buffer_wire_compress(buffer, 
++			             ldns_rr_list_rr(rr_list, i), LDNS_SECTION_ADDITIONAL, compression_data);
++		}
++	}
++	
++	/* add EDNS to additional if it is needed */
++	if (ldns_pkt_edns(packet)) {
++		edns_rr = ldns_rr_new();
++		if(!edns_rr) return LDNS_STATUS_MEM_ERR;
++		ldns_rr_set_owner(edns_rr,
++				ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, "."));
++		ldns_rr_set_type(edns_rr, LDNS_RR_TYPE_OPT);
++		ldns_rr_set_class(edns_rr, ldns_pkt_edns_udp_size(packet));
++		edata[0] = ldns_pkt_edns_extended_rcode(packet);
++		edata[1] = ldns_pkt_edns_version(packet);
++		ldns_write_uint16(&edata[2], ldns_pkt_edns_z(packet));
++		ldns_rr_set_ttl(edns_rr, ldns_read_uint32(edata));
++		/* don't forget to add the edns rdata (if any) */
++		if (packet->_edns_data)
++			ldns_rr_push_rdf (edns_rr, packet->_edns_data);
++		(void)ldns_rr2buffer_wire_compress(buffer, edns_rr, LDNS_SECTION_ADDITIONAL, compression_data);
++		/* take the edns rdata back out of the rr before we free rr */
++		if (packet->_edns_data)
++			(void)ldns_rr_pop_rdf (edns_rr);
++		ldns_rr_free(edns_rr);
++	}
++	
++	/* add TSIG to additional if it is there */
++	if (ldns_pkt_tsig(packet)) {
++		(void) ldns_rr2buffer_wire_compress(buffer,
++		                           ldns_pkt_tsig(packet), LDNS_SECTION_ADDITIONAL, compression_data);
++	}
++
++	ldns_traverse_postorder(compression_data,compression_node_free,NULL);
++	ldns_rbtree_free(compression_data);
++
++	return LDNS_STATUS_OK;
++}
++
++ldns_status
++ldns_rdf2wire(uint8_t **dest, const ldns_rdf *rdf, size_t *result_size)
++{
++	ldns_buffer *buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN);
++	ldns_status status;
++	*result_size = 0;
++	*dest = NULL;
++	if(!buffer) return LDNS_STATUS_MEM_ERR;
++	
++	status = ldns_rdf2buffer_wire(buffer, rdf);
++	if (status == LDNS_STATUS_OK) {
++		*result_size =  ldns_buffer_position(buffer);
++		*dest = (uint8_t *) ldns_buffer_export(buffer);
++	}
++	ldns_buffer_free(buffer);
++	return status;
++}
++
++ldns_status
++ldns_rr2wire(uint8_t **dest, const ldns_rr *rr, int section, size_t *result_size)
++{
++	ldns_buffer *buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN);
++	ldns_status status;
++	*result_size = 0;
++	*dest = NULL;
++	if(!buffer) return LDNS_STATUS_MEM_ERR;
++	
++	status = ldns_rr2buffer_wire(buffer, rr, section);
++	if (status == LDNS_STATUS_OK) {
++		*result_size =  ldns_buffer_position(buffer);
++		*dest = (uint8_t *) ldns_buffer_export(buffer);
++	}
++	ldns_buffer_free(buffer);
++	return status;
++}
++
++ldns_status
++ldns_pkt2wire(uint8_t **dest, const ldns_pkt *packet, size_t *result_size)
++{
++	ldns_buffer *buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN);
++	ldns_status status;
++	*result_size = 0;
++	*dest = NULL;
++	if(!buffer) return LDNS_STATUS_MEM_ERR;
++	
++	status = ldns_pkt2buffer_wire(buffer, packet);
++	if (status == LDNS_STATUS_OK) {
++		*result_size =  ldns_buffer_position(buffer);
++		*dest = (uint8_t *) ldns_buffer_export(buffer);
++	}
++	ldns_buffer_free(buffer);
++	return status;
++}
+diff --git a/ldns/src/keys.c b/ldns/src/keys.c
+new file mode 100644
+index 0000000..8b43821
+--- /dev/null
++++ b/ldns/src/keys.c
+@@ -0,0 +1,1726 @@
++/*
++ * keys.c handle private keys for use in DNSSEC
++ *
++ * This module should hide some of the openSSL complexities
++ * and give a general interface for private keys and hmac
++ * handling
++ *
++ * (c) NLnet Labs, 2004-2006
++ *
++ * See the file LICENSE for the license
++ */
++
++#include <ldns/config.h>
++
++#include <ldns/ldns.h>
++
++#ifdef HAVE_SSL
++#include <openssl/ssl.h>
++#include <openssl/engine.h>
++#include <openssl/rand.h>
++#endif /* HAVE_SSL */
++
++ldns_lookup_table ldns_signing_algorithms[] = {
++        { LDNS_SIGN_RSAMD5, "RSAMD5" },
++        { LDNS_SIGN_RSASHA1, "RSASHA1" },
++        { LDNS_SIGN_RSASHA1_NSEC3, "RSASHA1-NSEC3-SHA1" },
++#ifdef USE_SHA2
++        { LDNS_SIGN_RSASHA256, "RSASHA256" },
++        { LDNS_SIGN_RSASHA512, "RSASHA512" },
++#endif
++#ifdef USE_GOST
++        { LDNS_SIGN_ECC_GOST, "ECC-GOST" },
++#endif
++#ifdef USE_ECDSA
++        { LDNS_SIGN_ECDSAP256SHA256, "ECDSAP256SHA256" },
++        { LDNS_SIGN_ECDSAP384SHA384, "ECDSAP384SHA384" },
++#endif
++        { LDNS_SIGN_DSA, "DSA" },
++        { LDNS_SIGN_DSA_NSEC3, "DSA-NSEC3-SHA1" },
++        { LDNS_SIGN_HMACMD5, "hmac-md5.sig-alg.reg.int" },
++        { LDNS_SIGN_HMACSHA1, "hmac-sha1" },
++        { LDNS_SIGN_HMACSHA256, "hmac-sha256" },
++        { 0, NULL }
++};
++
++ldns_key_list *
++ldns_key_list_new(void)
++{
++	ldns_key_list *key_list = LDNS_MALLOC(ldns_key_list);
++	if (!key_list) {
++		return NULL;
++	} else {
++		key_list->_key_count = 0;
++		key_list->_keys = NULL;
++		return key_list;
++	}
++}
++
++ldns_key *
++ldns_key_new(void)
++{
++	ldns_key *newkey;
++
++	newkey = LDNS_MALLOC(ldns_key);
++	if (!newkey) {
++		return NULL;
++	} else {
++		/* some defaults - not sure wether to do this */
++		ldns_key_set_use(newkey, true);
++		ldns_key_set_flags(newkey, LDNS_KEY_ZONE_KEY);
++		ldns_key_set_origttl(newkey, 0);
++		ldns_key_set_keytag(newkey, 0);
++		ldns_key_set_inception(newkey, 0);
++		ldns_key_set_expiration(newkey, 0);
++		ldns_key_set_pubkey_owner(newkey, NULL);
++#ifdef HAVE_SSL
++		ldns_key_set_evp_key(newkey, NULL);
++#endif /* HAVE_SSL */
++		ldns_key_set_hmac_key(newkey, NULL);
++		ldns_key_set_external_key(newkey, NULL);
++		return newkey;
++	}
++}
++
++ldns_status
++ldns_key_new_frm_fp(ldns_key **k, FILE *fp)
++{
++	return ldns_key_new_frm_fp_l(k, fp, NULL);
++}
++
++#ifdef HAVE_SSL
++ldns_status
++ldns_key_new_frm_engine(ldns_key **key, ENGINE *e, char *key_id, ldns_algorithm alg)
++{
++	ldns_key *k;
++
++	k = ldns_key_new();
++        if(!k) return LDNS_STATUS_MEM_ERR;
++#ifndef S_SPLINT_S
++	k->_key.key = ENGINE_load_private_key(e, key_id, UI_OpenSSL(), NULL);
++        if(!k->_key.key) {
++                ldns_key_free(k);
++                return LDNS_STATUS_ERR;
++        }
++	ldns_key_set_algorithm(k, (ldns_signing_algorithm) alg);
++	if (!k->_key.key) {
++                ldns_key_free(k);
++		return LDNS_STATUS_ENGINE_KEY_NOT_LOADED;
++	} 
++#endif /* splint */
++	*key = k;
++	return LDNS_STATUS_OK;
++}
++#endif
++
++#ifdef USE_GOST
++/** store GOST engine reference loaded into OpenSSL library */
++ENGINE* ldns_gost_engine = NULL;
++
++int
++ldns_key_EVP_load_gost_id(void)
++{
++	static int gost_id = 0;
++	const EVP_PKEY_ASN1_METHOD* meth;
++	ENGINE* e;
++
++	if(gost_id) return gost_id;
++
++	/* see if configuration loaded gost implementation from other engine*/
++	meth = EVP_PKEY_asn1_find_str(NULL, "gost2001", -1);
++	if(meth) {
++		EVP_PKEY_asn1_get0_info(&gost_id, NULL, NULL, NULL, NULL, meth);
++		return gost_id;
++	}
++
++	/* see if engine can be loaded already */
++	e = ENGINE_by_id("gost");
++	if(!e) {
++		/* load it ourself, in case statically linked */
++		ENGINE_load_builtin_engines();
++		ENGINE_load_dynamic();
++		e = ENGINE_by_id("gost");
++	}
++	if(!e) {
++		/* no gost engine in openssl */
++		return 0;
++	}
++	if(!ENGINE_set_default(e, ENGINE_METHOD_ALL)) {
++		ENGINE_finish(e);
++		ENGINE_free(e);
++		return 0;
++	}
++
++	meth = EVP_PKEY_asn1_find_str(&e, "gost2001", -1);
++	if(!meth) {
++		/* algo not found */
++		ENGINE_finish(e);
++		ENGINE_free(e);
++		return 0;
++	}
++        /* Note: do not ENGINE_finish and ENGINE_free the acquired engine
++         * on some platforms this frees up the meth and unloads gost stuff */
++        ldns_gost_engine = e;
++	
++	EVP_PKEY_asn1_get0_info(&gost_id, NULL, NULL, NULL, NULL, meth);
++	return gost_id;
++} 
++
++void ldns_key_EVP_unload_gost(void)
++{
++        if(ldns_gost_engine) {
++                ENGINE_finish(ldns_gost_engine);
++                ENGINE_free(ldns_gost_engine);
++                ldns_gost_engine = NULL;
++        }
++}
++
++/** read GOST private key */
++static EVP_PKEY*
++ldns_key_new_frm_fp_gost_l(FILE* fp, int* line_nr)
++{
++	char token[16384];
++	const unsigned char* pp;
++	int gost_id;
++	EVP_PKEY* pkey;
++	ldns_rdf* b64rdf = NULL;
++
++	gost_id = ldns_key_EVP_load_gost_id();
++	if(!gost_id)
++		return NULL;
++
++	if (ldns_fget_keyword_data_l(fp, "GostAsn1", ": ", token, "\n", 
++		sizeof(token), line_nr) == -1)
++		return NULL;
++	while(strlen(token) < 96) {
++		/* read more b64 from the file, b64 split on multiple lines */
++		if(ldns_fget_token_l(fp, token+strlen(token), "\n",
++			sizeof(token)-strlen(token), line_nr) == -1)
++			return NULL;
++	}
++	if(ldns_str2rdf_b64(&b64rdf, token) != LDNS_STATUS_OK)
++		return NULL;
++	pp = (unsigned char*)ldns_rdf_data(b64rdf);
++	pkey = d2i_PrivateKey(gost_id, NULL, &pp, (int)ldns_rdf_size(b64rdf));
++	ldns_rdf_deep_free(b64rdf);
++	return pkey;
++}
++#endif
++
++#ifdef USE_ECDSA
++/** calculate public key from private key */
++static int
++ldns_EC_KEY_calc_public(EC_KEY* ec)
++{
++        EC_POINT* pub_key;
++        const EC_GROUP* group;
++        group = EC_KEY_get0_group(ec);
++        pub_key = EC_POINT_new(group);
++        if(!pub_key) return 0;
++        if(!EC_POINT_copy(pub_key, EC_GROUP_get0_generator(group))) {
++                EC_POINT_free(pub_key);
++                return 0;
++        }
++        if(!EC_POINT_mul(group, pub_key, EC_KEY_get0_private_key(ec),
++                NULL, NULL, NULL)) {
++                EC_POINT_free(pub_key);
++                return 0;
++        }
++        if(EC_KEY_set_public_key(ec, pub_key) == 0) {
++                EC_POINT_free(pub_key);
++                return 0;
++        }
++        EC_POINT_free(pub_key);
++        return 1;
++}
++
++/** read ECDSA private key */
++static EVP_PKEY*
++ldns_key_new_frm_fp_ecdsa_l(FILE* fp, ldns_algorithm alg, int* line_nr)
++{
++	char token[16384];
++        ldns_rdf* b64rdf = NULL;
++        unsigned char* pp;
++        BIGNUM* bn;
++        EVP_PKEY* evp_key;
++        EC_KEY* ec;
++	if (ldns_fget_keyword_data_l(fp, "PrivateKey", ": ", token, "\n", 
++		sizeof(token), line_nr) == -1)
++		return NULL;
++	if(ldns_str2rdf_b64(&b64rdf, token) != LDNS_STATUS_OK)
++		return NULL;
++        pp = (unsigned char*)ldns_rdf_data(b64rdf);
++
++        if(alg == LDNS_ECDSAP256SHA256)
++                ec = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
++        else if(alg == LDNS_ECDSAP384SHA384)
++                ec = EC_KEY_new_by_curve_name(NID_secp384r1);
++        else    ec = NULL;
++        if(!ec) {
++	        ldns_rdf_deep_free(b64rdf);
++                return NULL;
++        }
++	bn = BN_bin2bn(pp, (int)ldns_rdf_size(b64rdf), NULL);
++	ldns_rdf_deep_free(b64rdf);
++        if(!bn) {
++                EC_KEY_free(ec);
++                return NULL;
++        }
++        EC_KEY_set_private_key(ec, bn);
++        BN_free(bn);
++        if(!ldns_EC_KEY_calc_public(ec)) {
++                EC_KEY_free(ec);
++                return NULL;
++        }
++
++        evp_key = EVP_PKEY_new();
++        if(!evp_key) {
++                EC_KEY_free(ec);
++                return NULL;
++        }
++        if (!EVP_PKEY_assign_EC_KEY(evp_key, ec)) {
++		EVP_PKEY_free(evp_key);
++                EC_KEY_free(ec);
++                return NULL;
++	}
++        return evp_key;
++}
++#endif
++	
++ldns_status
++ldns_key_new_frm_fp_l(ldns_key **key, FILE *fp, int *line_nr)
++{
++	ldns_key *k;
++	char *d;
++	ldns_signing_algorithm alg;
++	ldns_rr *key_rr;
++#ifdef HAVE_SSL
++	RSA *rsa;
++	DSA *dsa;
++	unsigned char *hmac;
++	size_t hmac_size;
++#endif /* HAVE_SSL */
++
++	k = ldns_key_new();
++
++	d = LDNS_XMALLOC(char, LDNS_MAX_LINELEN);
++	if (!k || !d) {
++                ldns_key_free(k);
++                LDNS_FREE(d);
++		return LDNS_STATUS_MEM_ERR;
++	}
++
++	alg = 0;
++
++	/* the file is highly structured. Do this in sequence */
++	/* RSA:
++	 * Private-key-format: v1.x.
++ 	 * Algorithm: 1 (RSA)
++
++	 */
++	/* get the key format version number */
++	if (ldns_fget_keyword_data_l(fp, "Private-key-format", ": ", d, "\n",
++				LDNS_MAX_LINELEN, line_nr) == -1) {
++		/* no version information */
++                ldns_key_free(k);
++                LDNS_FREE(d);
++		return LDNS_STATUS_SYNTAX_ERR;
++	}
++	if (strncmp(d, "v1.", 3) != 0) {
++                ldns_key_free(k);
++                LDNS_FREE(d);
++		return LDNS_STATUS_SYNTAX_VERSION_ERR;
++	}
++
++	/* get the algorithm type, our file function strip ( ) so there are
++	 * not in the return string! */
++	if (ldns_fget_keyword_data_l(fp, "Algorithm", ": ", d, "\n",
++				LDNS_MAX_LINELEN, line_nr) == -1) {
++		/* no alg information */
++                ldns_key_free(k);
++                LDNS_FREE(d);
++		return LDNS_STATUS_SYNTAX_ALG_ERR;
++	}
++
++	if (strncmp(d, "1 RSA", 2) == 0) {
++		alg = LDNS_SIGN_RSAMD5;
++	}
++	if (strncmp(d, "2 DH", 2) == 0) {
++		alg = (ldns_signing_algorithm)LDNS_DH;
++	}
++	if (strncmp(d, "3 DSA", 2) == 0) {
++		alg = LDNS_SIGN_DSA;
++	}
++	if (strncmp(d, "4 ECC", 2) == 0) {
++		alg = (ldns_signing_algorithm)LDNS_ECC;
++	}
++	if (strncmp(d, "5 RSASHA1", 2) == 0) {
++		alg = LDNS_SIGN_RSASHA1;
++	}
++	if (strncmp(d, "6 DSA", 2) == 0) {
++		alg = LDNS_SIGN_DSA_NSEC3;
++	}
++	if (strncmp(d, "7 RSASHA1", 2) == 0) {
++		alg = LDNS_SIGN_RSASHA1_NSEC3;
++	}
++
++	if (strncmp(d, "8 RSASHA256", 2) == 0) {
++#ifdef USE_SHA2
++		alg = LDNS_SIGN_RSASHA256;
++#else
++# ifdef STDERR_MSGS
++		fprintf(stderr, "Warning: SHA256 not compiled into this ");
++		fprintf(stderr, "version of ldns\n");
++# endif
++#endif
++	}
++	if (strncmp(d, "10 RSASHA512", 3) == 0) {
++#ifdef USE_SHA2
++		alg = LDNS_SIGN_RSASHA512;
++#else
++# ifdef STDERR_MSGS
++		fprintf(stderr, "Warning: SHA512 not compiled into this ");
++		fprintf(stderr, "version of ldns\n");
++# endif
++#endif
++	}
++	if (strncmp(d, "12 ECC-GOST", 3) == 0) {
++#ifdef USE_GOST
++		alg = LDNS_SIGN_ECC_GOST;
++#else
++# ifdef STDERR_MSGS
++		fprintf(stderr, "Warning: ECC-GOST not compiled into this ");
++		fprintf(stderr, "version of ldns, use --enable-gost\n");
++# endif
++#endif
++	}
++	if (strncmp(d, "13 ECDSAP256SHA256", 3) == 0) {
++#ifdef USE_ECDSA
++                alg = LDNS_SIGN_ECDSAP256SHA256;
++#else
++# ifdef STDERR_MSGS
++		fprintf(stderr, "Warning: ECDSA not compiled into this ");
++		fprintf(stderr, "version of ldns, use --enable-ecdsa\n");
++# endif
++#endif
++        }
++	if (strncmp(d, "14 ECDSAP384SHA384", 3) == 0) {
++#ifdef USE_ECDSA
++                alg = LDNS_SIGN_ECDSAP384SHA384;
++#else
++# ifdef STDERR_MSGS
++		fprintf(stderr, "Warning: ECDSA not compiled into this ");
++		fprintf(stderr, "version of ldns, use --enable-ecdsa\n");
++# endif
++#endif
++        }
++	if (strncmp(d, "157 HMAC-MD5", 4) == 0) {
++		alg = LDNS_SIGN_HMACMD5;
++	}
++	if (strncmp(d, "158 HMAC-SHA1", 4) == 0) {
++		alg = LDNS_SIGN_HMACSHA1;
++	}
++	if (strncmp(d, "159 HMAC-SHA256", 4) == 0) {
++		alg = LDNS_SIGN_HMACSHA256;
++	}
++
++	LDNS_FREE(d);
++
++	switch(alg) {
++		case LDNS_SIGN_RSAMD5:
++		case LDNS_SIGN_RSASHA1:
++		case LDNS_SIGN_RSASHA1_NSEC3:
++#ifdef USE_SHA2
++		case LDNS_SIGN_RSASHA256:
++		case LDNS_SIGN_RSASHA512:
++#endif
++			ldns_key_set_algorithm(k, alg);
++#ifdef HAVE_SSL
++			rsa = ldns_key_new_frm_fp_rsa_l(fp, line_nr);
++			if (!rsa) {
++				ldns_key_free(k);
++				return LDNS_STATUS_ERR;
++			}
++			ldns_key_assign_rsa_key(k, rsa);
++#endif /* HAVE_SSL */
++			break;
++		case LDNS_SIGN_DSA:
++		case LDNS_SIGN_DSA_NSEC3:
++			ldns_key_set_algorithm(k, alg);
++#ifdef HAVE_SSL
++			dsa = ldns_key_new_frm_fp_dsa_l(fp, line_nr);
++			if (!dsa) {
++				ldns_key_free(k);
++				return LDNS_STATUS_ERR;
++			}
++			ldns_key_assign_dsa_key(k, dsa);
++#endif /* HAVE_SSL */
++			break;
++		case LDNS_SIGN_HMACMD5:
++		case LDNS_SIGN_HMACSHA1:
++		case LDNS_SIGN_HMACSHA256:
++			ldns_key_set_algorithm(k, alg);
++#ifdef HAVE_SSL
++			hmac = ldns_key_new_frm_fp_hmac_l(fp, line_nr, &hmac_size);
++			if (!hmac) {
++				ldns_key_free(k);
++				return LDNS_STATUS_ERR;
++			}
++			ldns_key_set_hmac_size(k, hmac_size);
++			ldns_key_set_hmac_key(k, hmac);
++#endif /* HAVE_SSL */
++			break;
++		case LDNS_SIGN_ECC_GOST:
++			ldns_key_set_algorithm(k, alg);
++#if defined(HAVE_SSL) && defined(USE_GOST)
++                        if(!ldns_key_EVP_load_gost_id()) {
++				ldns_key_free(k);
++                                return LDNS_STATUS_CRYPTO_ALGO_NOT_IMPL;
++                        }
++			ldns_key_set_evp_key(k, 
++				ldns_key_new_frm_fp_gost_l(fp, line_nr));
++#ifndef S_SPLINT_S
++			if(!k->_key.key) {
++				ldns_key_free(k);
++				return LDNS_STATUS_ERR;
++			}
++#endif /* splint */
++#endif
++			break;
++#ifdef USE_ECDSA
++               case LDNS_SIGN_ECDSAP256SHA256:
++               case LDNS_SIGN_ECDSAP384SHA384:
++                        ldns_key_set_algorithm(k, alg);
++                        ldns_key_set_evp_key(k,
++                                ldns_key_new_frm_fp_ecdsa_l(fp, (ldns_algorithm)alg, line_nr));
++#ifndef S_SPLINT_S
++			if(!k->_key.key) {
++				ldns_key_free(k);
++				return LDNS_STATUS_ERR;
++			}
++#endif /* splint */
++			break;
++#endif
++		default:
++			ldns_key_free(k);
++			return LDNS_STATUS_SYNTAX_ALG_ERR;
++	}
++	key_rr = ldns_key2rr(k);
++	ldns_key_set_keytag(k, ldns_calc_keytag(key_rr));
++	ldns_rr_free(key_rr);
++
++	if (key) {
++		*key = k;
++		return LDNS_STATUS_OK;
++	}
++	ldns_key_free(k);
++	return LDNS_STATUS_ERR;
++}
++
++#ifdef HAVE_SSL
++RSA *
++ldns_key_new_frm_fp_rsa(FILE *f)
++{
++	return ldns_key_new_frm_fp_rsa_l(f, NULL);
++}
++
++RSA *
++ldns_key_new_frm_fp_rsa_l(FILE *f, int *line_nr)
++{
++	/* we parse
++ 	 * Modulus:
++ 	 * PublicExponent:
++ 	 * PrivateExponent:
++ 	 * Prime1:
++ 	 * Prime2:
++ 	 * Exponent1:
++ 	 * Exponent2:
++ 	 * Coefficient:
++	 *
++	 * man 3 RSA:
++	 *
++	 * struct
++         *     {
++         *     BIGNUM *n;              // public modulus
++         *     BIGNUM *e;              // public exponent
++         *     BIGNUM *d;              // private exponent
++         *     BIGNUM *p;              // secret prime factor
++         *     BIGNUM *q;              // secret prime factor
++         *     BIGNUM *dmp1;           // d mod (p-1)
++         *     BIGNUM *dmq1;           // d mod (q-1)
++         *     BIGNUM *iqmp;           // q^-1 mod p
++         *     // ...
++	 *
++	 */
++	char *d;
++	RSA *rsa;
++	uint8_t *buf;
++	int i;
++
++	d = LDNS_XMALLOC(char, LDNS_MAX_LINELEN);
++	buf = LDNS_XMALLOC(uint8_t, LDNS_MAX_LINELEN);
++	rsa = RSA_new();
++	if (!d || !rsa || !buf) {
++                goto error;
++	}
++
++	/* I could use functions again, but that seems an overkill,
++	 * allthough this also looks tedious
++	 */
++
++	/* Modules, rsa->n */
++	if (ldns_fget_keyword_data_l(f, "Modulus", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) {
++		goto error;
++	}
++	i = ldns_b64_pton((const char*)d, buf, ldns_b64_ntop_calculate_size(strlen(d)));
++#ifndef S_SPLINT_S
++	rsa->n = BN_bin2bn((const char unsigned*)buf, i, NULL);
++	if (!rsa->n) {
++		goto error;
++	}
++
++	/* PublicExponent, rsa->e */
++	if (ldns_fget_keyword_data_l(f, "PublicExponent", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) {
++		goto error;
++	}
++	i = ldns_b64_pton((const char*)d, buf, ldns_b64_ntop_calculate_size(strlen(d)));
++	rsa->e = BN_bin2bn((const char unsigned*)buf, i, NULL);
++	if (!rsa->e) {
++		goto error;
++	}
++
++	/* PrivateExponent, rsa->d */
++	if (ldns_fget_keyword_data_l(f, "PrivateExponent", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) {
++		goto error;
++	}
++	i = ldns_b64_pton((const char*)d, buf, ldns_b64_ntop_calculate_size(strlen(d)));
++	rsa->d = BN_bin2bn((const char unsigned*)buf, i, NULL);
++	if (!rsa->d) {
++		goto error;
++	}
++
++	/* Prime1, rsa->p */
++	if (ldns_fget_keyword_data_l(f, "Prime1", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) {
++		goto error;
++	}
++	i = ldns_b64_pton((const char*)d, buf, ldns_b64_ntop_calculate_size(strlen(d)));
++	rsa->p = BN_bin2bn((const char unsigned*)buf, i, NULL);
++	if (!rsa->p) {
++		goto error;
++	}
++
++	/* Prime2, rsa->q */
++	if (ldns_fget_keyword_data_l(f, "Prime2", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) {
++		goto error;
++	}
++	i = ldns_b64_pton((const char*)d, buf, ldns_b64_ntop_calculate_size(strlen(d)));
++	rsa->q = BN_bin2bn((const char unsigned*)buf, i, NULL);
++	if (!rsa->q) {
++		goto error;
++	}
++
++	/* Exponent1, rsa->dmp1 */
++	if (ldns_fget_keyword_data_l(f, "Exponent1", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) {
++		goto error;
++	}
++	i = ldns_b64_pton((const char*)d, buf, ldns_b64_ntop_calculate_size(strlen(d)));
++	rsa->dmp1 = BN_bin2bn((const char unsigned*)buf, i, NULL);
++	if (!rsa->dmp1) {
++		goto error;
++	}
++
++	/* Exponent2, rsa->dmq1 */
++	if (ldns_fget_keyword_data_l(f, "Exponent2", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) {
++		goto error;
++	}
++	i = ldns_b64_pton((const char*)d, buf, ldns_b64_ntop_calculate_size(strlen(d)));
++	rsa->dmq1 = BN_bin2bn((const char unsigned*)buf, i, NULL);
++	if (!rsa->dmq1) {
++		goto error;
++	}
++
++	/* Coefficient, rsa->iqmp */
++	if (ldns_fget_keyword_data_l(f, "Coefficient", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) {
++		goto error;
++	}
++	i = ldns_b64_pton((const char*)d, buf, ldns_b64_ntop_calculate_size(strlen(d)));
++	rsa->iqmp = BN_bin2bn((const char unsigned*)buf, i, NULL);
++	if (!rsa->iqmp) {
++		goto error;
++	}
++#endif /* splint */
++
++	LDNS_FREE(buf);
++	LDNS_FREE(d);
++	return rsa;
++
++error:
++	RSA_free(rsa);
++	LDNS_FREE(d);
++	LDNS_FREE(buf);
++	return NULL;
++}
++
++DSA *
++ldns_key_new_frm_fp_dsa(FILE *f)
++{
++	return ldns_key_new_frm_fp_dsa_l(f, NULL);
++}
++
++DSA *
++ldns_key_new_frm_fp_dsa_l(FILE *f, ATTR_UNUSED(int *line_nr))
++{
++	int i;
++	char *d;
++	DSA *dsa;
++	uint8_t *buf;
++
++	d = LDNS_XMALLOC(char, LDNS_MAX_LINELEN);
++	buf = LDNS_XMALLOC(uint8_t, LDNS_MAX_LINELEN);
++	dsa = DSA_new();
++	if (!d || !dsa || !buf) {
++                goto error;
++	}
++
++	/* the line parser removes the () from the input... */
++
++	/* Prime, dsa->p */
++	if (ldns_fget_keyword_data_l(f, "Primep", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) {
++		goto error;
++	}
++	i = ldns_b64_pton((const char*)d, buf, ldns_b64_ntop_calculate_size(strlen(d)));
++#ifndef S_SPLINT_S
++	dsa->p = BN_bin2bn((const char unsigned*)buf, i, NULL);
++	if (!dsa->p) {
++		goto error;
++	}
++
++	/* Subprime, dsa->q */
++	if (ldns_fget_keyword_data_l(f, "Subprimeq", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) {
++		goto error;
++	}
++	i = ldns_b64_pton((const char*)d, buf, ldns_b64_ntop_calculate_size(strlen(d)));
++	dsa->q = BN_bin2bn((const char unsigned*)buf, i, NULL);
++	if (!dsa->q) {
++		goto error;
++	}
++
++	/* Base, dsa->g */
++	if (ldns_fget_keyword_data_l(f, "Baseg", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) {
++		goto error;
++	}
++	i = ldns_b64_pton((const char*)d, buf, ldns_b64_ntop_calculate_size(strlen(d)));
++	dsa->g = BN_bin2bn((const char unsigned*)buf, i, NULL);
++	if (!dsa->g) {
++		goto error;
++	}
++
++	/* Private key, dsa->priv_key */
++	if (ldns_fget_keyword_data_l(f, "Private_valuex", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) {
++		goto error;
++	}
++	i = ldns_b64_pton((const char*)d, buf, ldns_b64_ntop_calculate_size(strlen(d)));
++	dsa->priv_key = BN_bin2bn((const char unsigned*)buf, i, NULL);
++	if (!dsa->priv_key) {
++		goto error;
++	}
++
++	/* Public key, dsa->priv_key */
++	if (ldns_fget_keyword_data_l(f, "Public_valuey", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) {
++		goto error;
++	}
++	i = ldns_b64_pton((const char*)d, buf, ldns_b64_ntop_calculate_size(strlen(d)));
++	dsa->pub_key = BN_bin2bn((const char unsigned*)buf, i, NULL);
++	if (!dsa->pub_key) {
++		goto error;
++	}
++#endif /* splint */
++
++	LDNS_FREE(buf);
++	LDNS_FREE(d);
++
++	return dsa;
++
++error:
++	LDNS_FREE(d);
++	LDNS_FREE(buf);
++        DSA_free(dsa);
++	return NULL;
++}
++
++unsigned char *
++ldns_key_new_frm_fp_hmac(FILE *f, size_t *hmac_size)
++{
++	return ldns_key_new_frm_fp_hmac_l(f, NULL, hmac_size);
++}
++
++unsigned char *
++ldns_key_new_frm_fp_hmac_l( FILE *f
++			  , ATTR_UNUSED(int *line_nr)
++			  , size_t *hmac_size
++			  )
++{
++	size_t i, bufsz;
++	char d[LDNS_MAX_LINELEN];
++	unsigned char *buf = NULL;
++
++	if (ldns_fget_keyword_data_l(f, "Key", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) {
++		goto error;
++	}
++	bufsz = ldns_b64_ntop_calculate_size(strlen(d));
++	buf = LDNS_XMALLOC(unsigned char, bufsz);
++	i = (size_t) ldns_b64_pton((const char*)d, buf, bufsz);
++
++	*hmac_size = i;
++	return buf;
++
++	error:
++	LDNS_FREE(buf);
++	*hmac_size = 0;
++	return NULL;
++}
++#endif /* HAVE_SSL */
++
++#ifdef USE_GOST
++static EVP_PKEY*
++ldns_gen_gost_key(void)
++{
++	EVP_PKEY_CTX* ctx;
++	EVP_PKEY* p = NULL;
++	int gost_id = ldns_key_EVP_load_gost_id();
++	if(!gost_id)
++		return NULL;
++	ctx = EVP_PKEY_CTX_new_id(gost_id, NULL);
++	if(!ctx) {
++		/* the id should be available now */
++		return NULL;
++	}
++	if(EVP_PKEY_CTX_ctrl_str(ctx, "paramset", "A") <= 0) {
++		/* cannot set paramset */
++		EVP_PKEY_CTX_free(ctx);
++		return NULL;
++	}
++
++	if(EVP_PKEY_keygen_init(ctx) <= 0) {
++		EVP_PKEY_CTX_free(ctx);
++		return NULL;
++	}
++	if(EVP_PKEY_keygen(ctx, &p) <= 0) {
++		EVP_PKEY_free(p);
++		EVP_PKEY_CTX_free(ctx);
++		return NULL;
++	}
++	EVP_PKEY_CTX_free(ctx);
++	return p;
++}
++#endif
++
++ldns_key *
++ldns_key_new_frm_algorithm(ldns_signing_algorithm alg, uint16_t size)
++{
++	ldns_key *k;
++#ifdef HAVE_SSL
++	DSA *d;
++	RSA *r;
++#  ifdef USE_ECDSA
++        EC_KEY *ec = NULL;
++#  endif
++#else
++	int i;
++	uint16_t offset = 0;
++#endif
++	unsigned char *hmac;
++
++	k = ldns_key_new();
++	if (!k) {
++		return NULL;
++	}
++	switch(alg) {
++		case LDNS_SIGN_RSAMD5:
++		case LDNS_SIGN_RSASHA1:
++		case LDNS_SIGN_RSASHA1_NSEC3:
++		case LDNS_SIGN_RSASHA256:
++		case LDNS_SIGN_RSASHA512:
++#ifdef HAVE_SSL
++			r = RSA_generate_key((int)size, RSA_F4, NULL, NULL);
++                        if(!r) {
++				ldns_key_free(k);
++				return NULL;
++			}
++			if (RSA_check_key(r) != 1) {
++				ldns_key_free(k);
++				return NULL;
++			}
++			ldns_key_set_rsa_key(k, r);
++			RSA_free(r);
++#endif /* HAVE_SSL */
++			break;
++		case LDNS_SIGN_DSA:
++		case LDNS_SIGN_DSA_NSEC3:
++#ifdef HAVE_SSL
++			d = DSA_generate_parameters((int)size, NULL, 0, NULL, NULL, NULL, NULL);
++			if (!d) {
++				ldns_key_free(k);
++				return NULL;
++			}
++			if (DSA_generate_key(d) != 1) {
++				ldns_key_free(k);
++				return NULL;
++			}
++			ldns_key_set_dsa_key(k, d);
++			DSA_free(d);
++#endif /* HAVE_SSL */
++			break;
++		case LDNS_SIGN_HMACMD5:
++		case LDNS_SIGN_HMACSHA1:
++		case LDNS_SIGN_HMACSHA256:
++#ifdef HAVE_SSL
++#ifndef S_SPLINT_S
++			k->_key.key = NULL;
++#endif /* splint */
++#endif /* HAVE_SSL */
++			size = size / 8;
++			ldns_key_set_hmac_size(k, size);
++
++			hmac = LDNS_XMALLOC(unsigned char, size);
++                        if(!hmac) {
++				ldns_key_free(k);
++				return NULL;
++                        }
++#ifdef HAVE_SSL
++			if (RAND_bytes(hmac, (int) size) != 1) {
++				LDNS_FREE(hmac);
++				ldns_key_free(k);
++				return NULL;
++			}
++#else
++			while (offset + sizeof(i) < size) {
++			  i = random();
++			  memcpy(&hmac[offset], &i, sizeof(i));
++			  offset += sizeof(i);
++			}
++			if (offset < size) {
++			  i = random();
++			  memcpy(&hmac[offset], &i, size - offset);
++			}
++#endif /* HAVE_SSL */
++			ldns_key_set_hmac_key(k, hmac);
++
++			ldns_key_set_flags(k, 0);
++			break;
++		case LDNS_SIGN_ECC_GOST:
++#if defined(HAVE_SSL) && defined(USE_GOST)
++			ldns_key_set_evp_key(k, ldns_gen_gost_key());
++#ifndef S_SPLINT_S
++                        if(!k->_key.key) {
++                                ldns_key_free(k);
++                                return NULL;
++                        }
++#endif /* splint */
++#else
++			ldns_key_free(k);
++			return NULL;
++#endif /* HAVE_SSL and USE_GOST */
++                        break;
++                case LDNS_SIGN_ECDSAP256SHA256:
++                case LDNS_SIGN_ECDSAP384SHA384:
++#ifdef USE_ECDSA
++                        if(alg == LDNS_SIGN_ECDSAP256SHA256)
++                                ec = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
++                        else if(alg == LDNS_SIGN_ECDSAP384SHA384)
++                                ec = EC_KEY_new_by_curve_name(NID_secp384r1);
++                        if(!ec) {
++                                ldns_key_free(k);
++                                return NULL;
++                        }
++                        if(!EC_KEY_generate_key(ec)) {
++                                ldns_key_free(k);
++                                EC_KEY_free(ec);
++                                return NULL;
++                        }
++#ifndef S_SPLINT_S
++                        k->_key.key = EVP_PKEY_new();
++                        if(!k->_key.key) {
++                                ldns_key_free(k);
++                                EC_KEY_free(ec);
++                                return NULL;
++                        }
++                        if (!EVP_PKEY_assign_EC_KEY(k->_key.key, ec)) {
++                                ldns_key_free(k);
++                                EC_KEY_free(ec);
++                                return NULL;
++			}
++#endif /* splint */
++#else
++			ldns_key_free(k);
++			return NULL;
++#endif /* ECDSA */
++			break;
++	}
++	ldns_key_set_algorithm(k, alg);
++	return k;
++}
++
++void
++ldns_key_print(FILE *output, const ldns_key *k)
++{
++	char *str = ldns_key2str(k);
++	if (str) {
++                fprintf(output, "%s", str);
++        } else {
++                fprintf(output, "Unable to convert private key to string\n");
++        }
++        LDNS_FREE(str);
++}
++
++
++void
++ldns_key_set_algorithm(ldns_key *k, ldns_signing_algorithm l)
++{
++	k->_alg = l;
++}
++
++void
++ldns_key_set_flags(ldns_key *k, uint16_t f)
++{
++	k->_extra.dnssec.flags = f;
++}
++
++#ifdef HAVE_SSL
++#ifndef S_SPLINT_S
++void
++ldns_key_set_evp_key(ldns_key *k, EVP_PKEY *e)
++{
++	k->_key.key = e;
++}
++
++void
++ldns_key_set_rsa_key(ldns_key *k, RSA *r)
++{
++	EVP_PKEY *key = EVP_PKEY_new();
++	EVP_PKEY_set1_RSA(key, r);
++	k->_key.key = key;
++}
++
++void
++ldns_key_set_dsa_key(ldns_key *k, DSA *d)
++{
++	EVP_PKEY *key = EVP_PKEY_new();
++	EVP_PKEY_set1_DSA(key, d);
++	k->_key.key  = key;
++}
++
++void
++ldns_key_assign_rsa_key(ldns_key *k, RSA *r)
++{
++	EVP_PKEY *key = EVP_PKEY_new();
++	EVP_PKEY_assign_RSA(key, r);
++	k->_key.key = key;
++}
++
++void
++ldns_key_assign_dsa_key(ldns_key *k, DSA *d)
++{
++	EVP_PKEY *key = EVP_PKEY_new();
++	EVP_PKEY_assign_DSA(key, d);
++	k->_key.key  = key;
++}
++#endif /* splint */
++#endif /* HAVE_SSL */
++
++void
++ldns_key_set_hmac_key(ldns_key *k, unsigned char *hmac)
++{
++	k->_key.hmac.key = hmac;
++}
++
++void
++ldns_key_set_hmac_size(ldns_key *k, size_t hmac_size)
++{
++	k->_key.hmac.size = hmac_size;
++}
++
++void
++ldns_key_set_external_key(ldns_key *k, void *external_key)
++{
++	k->_key.external_key = external_key;
++}
++
++void
++ldns_key_set_origttl(ldns_key *k, uint32_t t)
++{
++	k->_extra.dnssec.orig_ttl = t;
++}
++
++void
++ldns_key_set_inception(ldns_key *k, uint32_t i)
++{
++	k->_extra.dnssec.inception = i;
++}
++
++void
++ldns_key_set_expiration(ldns_key *k, uint32_t e)
++{
++	k->_extra.dnssec.expiration = e;
++}
++
++void
++ldns_key_set_pubkey_owner(ldns_key *k, ldns_rdf *r)
++{
++	k->_pubkey_owner = r;
++}
++
++void
++ldns_key_set_keytag(ldns_key *k, uint16_t tag)
++{
++	k->_extra.dnssec.keytag = tag;
++}
++
++/* read */
++size_t
++ldns_key_list_key_count(const ldns_key_list *key_list)
++{
++	        return key_list->_key_count;
++}       
++
++ldns_key *
++ldns_key_list_key(const ldns_key_list *key, size_t nr)
++{       
++	if (nr < ldns_key_list_key_count(key)) {
++		return key->_keys[nr];
++	} else {
++		return NULL;
++	}
++}
++
++ldns_signing_algorithm
++ldns_key_algorithm(const ldns_key *k) 
++{
++	return k->_alg;
++}
++
++void
++ldns_key_set_use(ldns_key *k, bool v)
++{
++	if (k) {
++		k->_use = v;
++	}
++}
++
++bool
++ldns_key_use(const ldns_key *k)
++{
++	if (k) {
++		return k->_use;
++	}
++	return false;
++}
++
++#ifdef HAVE_SSL
++#ifndef S_SPLINT_S
++EVP_PKEY *
++ldns_key_evp_key(const ldns_key *k)
++{
++	return k->_key.key;
++}
++
++RSA *
++ldns_key_rsa_key(const ldns_key *k)
++{
++	if (k->_key.key) {
++		return EVP_PKEY_get1_RSA(k->_key.key);
++	} else {
++		return NULL;
++	}
++}
++
++DSA *
++ldns_key_dsa_key(const ldns_key *k)
++{
++	if (k->_key.key) {
++		return EVP_PKEY_get1_DSA(k->_key.key);
++	} else {
++		return NULL;
++	}
++}
++#endif /* splint */
++#endif /* HAVE_SSL */
++
++unsigned char *
++ldns_key_hmac_key(const ldns_key *k)
++{
++	if (k->_key.hmac.key) {
++		return k->_key.hmac.key;
++	} else {
++		return NULL;
++	}
++}
++
++size_t
++ldns_key_hmac_size(const ldns_key *k)
++{
++	if (k->_key.hmac.size) {
++		return k->_key.hmac.size;
++	} else {
++		return 0;
++	}
++}
++
++void *
++ldns_key_external_key(const ldns_key *k)
++{
++	return k->_key.external_key;
++}
++
++uint32_t
++ldns_key_origttl(const ldns_key *k)
++{
++	return k->_extra.dnssec.orig_ttl;
++}
++
++uint16_t
++ldns_key_flags(const ldns_key *k)
++{
++	return k->_extra.dnssec.flags;
++}
++
++uint32_t
++ldns_key_inception(const ldns_key *k)
++{
++	return k->_extra.dnssec.inception;
++}
++
++uint32_t
++ldns_key_expiration(const ldns_key *k)
++{
++	return k->_extra.dnssec.expiration;
++}
++
++uint16_t
++ldns_key_keytag(const ldns_key *k)
++{
++	return k->_extra.dnssec.keytag;
++}
++
++ldns_rdf *
++ldns_key_pubkey_owner(const ldns_key *k)
++{
++	return k->_pubkey_owner;
++}
++
++/* write */
++void
++ldns_key_list_set_use(ldns_key_list *keys, bool v)
++{
++	size_t i;
++
++	for (i = 0; i < ldns_key_list_key_count(keys); i++) {
++		ldns_key_set_use(ldns_key_list_key(keys, i), v);
++	}
++}
++
++void            
++ldns_key_list_set_key_count(ldns_key_list *key, size_t count)
++{
++	        key->_key_count = count;
++}       
++
++bool             
++ldns_key_list_push_key(ldns_key_list *key_list, ldns_key *key)
++{       
++        size_t key_count;
++        ldns_key **keys;
++
++        key_count = ldns_key_list_key_count(key_list);
++
++        /* grow the array */
++        keys = LDNS_XREALLOC(
++                key_list->_keys, ldns_key *, key_count + 1);
++        if (!keys) {
++                return false;
++        }
++
++        /* add the new member */
++        key_list->_keys = keys;
++        key_list->_keys[key_count] = key;
++
++        ldns_key_list_set_key_count(key_list, key_count + 1);
++        return true;
++}
++
++ldns_key *
++ldns_key_list_pop_key(ldns_key_list *key_list)
++{                               
++        size_t key_count;
++        ldns_key** a;
++        ldns_key *pop;
++
++	if (!key_list) {
++		return NULL;
++	}
++        
++        key_count = ldns_key_list_key_count(key_list);
++        if (key_count == 0) {
++                return NULL;
++        }       
++        
++        pop = ldns_key_list_key(key_list, key_count);
++        
++        /* shrink the array */
++        a = LDNS_XREALLOC(key_list->_keys, ldns_key *, key_count - 1);
++        if(a) {
++                key_list->_keys = a;
++        }
++
++        ldns_key_list_set_key_count(key_list, key_count - 1);
++
++        return pop;
++}       
++
++#ifdef HAVE_SSL
++#ifndef S_SPLINT_S
++/* data pointer must be large enough (LDNS_MAX_KEYLEN) */
++static bool
++ldns_key_rsa2bin(unsigned char *data, RSA *k, uint16_t *size)
++{
++	int i,j;
++	
++	if (!k) {
++		return false;
++	}
++	
++	if (BN_num_bytes(k->e) <= 256) {
++		/* normally only this path is executed (small factors are
++		 * more common 
++		 */
++		data[0] = (unsigned char) BN_num_bytes(k->e);
++		i = BN_bn2bin(k->e, data + 1);  
++		j = BN_bn2bin(k->n, data + i + 1);
++		*size = (uint16_t) i + j;
++	} else if (BN_num_bytes(k->e) <= 65536) {
++		data[0] = 0;
++		/* BN_bn2bin does bigendian, _uint16 also */
++		ldns_write_uint16(data + 1, (uint16_t) BN_num_bytes(k->e)); 
++
++		BN_bn2bin(k->e, data + 3); 
++		BN_bn2bin(k->n, data + 4 + BN_num_bytes(k->e));
++		*size = (uint16_t) BN_num_bytes(k->n) + 6;
++	} else {
++		return false;
++	}
++	return true;
++}
++
++/* data pointer must be large enough (LDNS_MAX_KEYLEN) */
++static bool
++ldns_key_dsa2bin(unsigned char *data, DSA *k, uint16_t *size)
++{
++	uint8_t T;
++
++	if (!k) {
++		return false;
++	}
++	
++	/* See RFC2536 */
++	*size = (uint16_t)BN_num_bytes(k->p);
++	T = (*size - 64) / 8;
++
++	if (T > 8) {
++#ifdef STDERR_MSGS
++		fprintf(stderr, "DSA key with T > 8 (ie. > 1024 bits)");
++		fprintf(stderr, " not implemented\n");
++#endif
++		return false;
++	}
++
++	/* size = 64 + (T * 8); */
++	memset(data, 0, 21 + *size * 3);
++	data[0] = (unsigned char)T;
++	BN_bn2bin(k->q, data + 1 ); 		/* 20 octects */
++	BN_bn2bin(k->p, data + 21 ); 		/* offset octects */
++	BN_bn2bin(k->g, data + 21 + *size * 2 - BN_num_bytes(k->g));
++	BN_bn2bin(k->pub_key,data + 21 + *size * 3 - BN_num_bytes(k->pub_key));
++	*size = 21 + *size * 3;
++	return true;
++}
++
++#ifdef USE_GOST
++static bool
++ldns_key_gost2bin(unsigned char* data, EVP_PKEY* k, uint16_t* size)
++{
++	int i;
++	unsigned char* pp = NULL;
++	if(i2d_PUBKEY(k, &pp) != 37 + 64) {
++		/* expect 37 byte(ASN header) and 64 byte(X and Y) */
++		CRYPTO_free(pp);
++		return false;
++	}
++	/* omit ASN header */
++	for(i=0; i<64; i++)
++		data[i] = pp[i+37];
++	CRYPTO_free(pp);
++	*size = 64;
++	return true;
++}
++#endif /* USE_GOST */
++#endif /* splint */
++#endif /* HAVE_SSL */
++
++ldns_rr *
++ldns_key2rr(const ldns_key *k)
++{
++	/* this function will convert a the keydata contained in
++	 * rsa/dsa pointers to a DNSKEY rr. It will fill in as
++	 * much as it can, but it does not know about key-flags
++	 * for instance
++	 */
++	ldns_rr *pubkey;
++	ldns_rdf *keybin;
++	unsigned char *bin = NULL;
++	uint16_t size = 0;
++#ifdef HAVE_SSL
++	RSA *rsa = NULL;
++	DSA *dsa = NULL;
++#endif /* HAVE_SSL */
++#ifdef USE_ECDSA
++        EC_KEY* ec;
++#endif
++	int internal_data = 0;
++
++	if (!k) {
++		return NULL;
++	}
++	pubkey = ldns_rr_new();
++
++	switch (ldns_key_algorithm(k)) {
++	case LDNS_SIGN_HMACMD5:
++	case LDNS_SIGN_HMACSHA1:
++	case LDNS_SIGN_HMACSHA256:
++		ldns_rr_set_type(pubkey, LDNS_RR_TYPE_KEY);
++        	break;
++	default:
++		ldns_rr_set_type(pubkey, LDNS_RR_TYPE_DNSKEY);
++		break;
++        }
++	/* zero-th rdf - flags */
++	ldns_rr_push_rdf(pubkey,
++			ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16,
++				ldns_key_flags(k)));
++	/* first - proto */
++	ldns_rr_push_rdf(pubkey,
++			ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8, LDNS_DNSSEC_KEYPROTO));
++
++	if (ldns_key_pubkey_owner(k)) {
++		ldns_rr_set_owner(pubkey, ldns_rdf_clone(ldns_key_pubkey_owner(k)));
++	}
++
++	/* third - da algorithm */
++	switch(ldns_key_algorithm(k)) {
++		case LDNS_SIGN_RSAMD5:
++		case LDNS_SIGN_RSASHA1:
++		case LDNS_SIGN_RSASHA1_NSEC3:
++		case LDNS_SIGN_RSASHA256:
++		case LDNS_SIGN_RSASHA512:
++			ldns_rr_push_rdf(pubkey,
++						  ldns_native2rdf_int8(LDNS_RDF_TYPE_ALG, ldns_key_algorithm(k)));
++#ifdef HAVE_SSL
++			rsa =  ldns_key_rsa_key(k);
++			if (rsa) {
++				bin = LDNS_XMALLOC(unsigned char, LDNS_MAX_KEYLEN);
++				if (!bin) {
++                                        ldns_rr_free(pubkey);
++					return NULL;
++				}
++				if (!ldns_key_rsa2bin(bin, rsa, &size)) {
++		                        LDNS_FREE(bin);
++                                        ldns_rr_free(pubkey);
++					return NULL;
++				}
++				RSA_free(rsa);
++				internal_data = 1;
++			}
++#endif
++			size++;
++			break;
++		case LDNS_SIGN_DSA:
++			ldns_rr_push_rdf(pubkey,
++					ldns_native2rdf_int8(LDNS_RDF_TYPE_ALG, LDNS_DSA));
++#ifdef HAVE_SSL
++			dsa = ldns_key_dsa_key(k);
++			if (dsa) {
++				bin = LDNS_XMALLOC(unsigned char, LDNS_MAX_KEYLEN);
++				if (!bin) {
++                                        ldns_rr_free(pubkey);
++					return NULL;
++				}
++				if (!ldns_key_dsa2bin(bin, dsa, &size)) {
++		                        LDNS_FREE(bin);
++                                        ldns_rr_free(pubkey);
++					return NULL;
++				}
++				DSA_free(dsa);
++				internal_data = 1;
++			}
++#endif /* HAVE_SSL */
++			break;
++		case LDNS_SIGN_DSA_NSEC3:
++			ldns_rr_push_rdf(pubkey,
++					ldns_native2rdf_int8(LDNS_RDF_TYPE_ALG, LDNS_DSA_NSEC3));
++#ifdef HAVE_SSL
++			dsa = ldns_key_dsa_key(k);
++			if (dsa) {
++				bin = LDNS_XMALLOC(unsigned char, LDNS_MAX_KEYLEN);
++				if (!bin) {
++                                        ldns_rr_free(pubkey);
++					return NULL;
++				}
++				if (!ldns_key_dsa2bin(bin, dsa, &size)) {
++		                        LDNS_FREE(bin);
++                                        ldns_rr_free(pubkey);
++					return NULL;
++				}
++				DSA_free(dsa);
++				internal_data = 1;
++			}
++#endif /* HAVE_SSL */
++			break;
++		case LDNS_SIGN_ECC_GOST:
++			ldns_rr_push_rdf(pubkey, ldns_native2rdf_int8(
++				LDNS_RDF_TYPE_ALG, ldns_key_algorithm(k)));
++#if defined(HAVE_SSL) && defined(USE_GOST)
++			bin = LDNS_XMALLOC(unsigned char, LDNS_MAX_KEYLEN);
++			if (!bin) {
++                                ldns_rr_free(pubkey);
++				return NULL;
++                        }
++#ifndef S_SPLINT_S
++			if (!ldns_key_gost2bin(bin, k->_key.key, &size)) {
++		                LDNS_FREE(bin);
++                                ldns_rr_free(pubkey);
++				return NULL;
++			}
++#endif /* splint */
++			internal_data = 1;
++#else
++                        ldns_rr_free(pubkey);
++			return NULL;
++#endif /* HAVE_SSL and USE_GOST */
++			break;
++                case LDNS_SIGN_ECDSAP256SHA256:
++                case LDNS_SIGN_ECDSAP384SHA384:
++#ifdef USE_ECDSA
++			ldns_rr_push_rdf(pubkey, ldns_native2rdf_int8(
++				LDNS_RDF_TYPE_ALG, ldns_key_algorithm(k)));
++                        bin = NULL;
++#ifndef S_SPLINT_S
++                        ec = EVP_PKEY_get1_EC_KEY(k->_key.key);
++#endif
++                        EC_KEY_set_conv_form(ec, POINT_CONVERSION_UNCOMPRESSED);
++                        size = (uint16_t)i2o_ECPublicKey(ec, NULL);
++                        if(!i2o_ECPublicKey(ec, &bin)) {
++                                EC_KEY_free(ec);
++                                ldns_rr_free(pubkey);
++                                return NULL;
++                        }
++			if(size > 1) {
++				/* move back one byte to shave off the 0x02
++				 * 'uncompressed' indicator that openssl made
++				 * Actually its 0x04 (from implementation).
++				 */
++				assert(bin[0] == POINT_CONVERSION_UNCOMPRESSED);
++				size -= 1;
++				memmove(bin, bin+1, size);
++			}
++                        /* down the reference count for ec, its still assigned
++                         * to the pkey */
++                        EC_KEY_free(ec);
++			internal_data = 1;
++#else
++                        ldns_rr_free(pubkey);
++			return NULL;
++#endif /* ECDSA */
++                        break;
++		case LDNS_SIGN_HMACMD5:
++		case LDNS_SIGN_HMACSHA1:
++		case LDNS_SIGN_HMACSHA256:
++			bin = LDNS_XMALLOC(unsigned char, ldns_key_hmac_size(k));
++			if (!bin) {
++                                ldns_rr_free(pubkey);
++				return NULL;
++			}
++			ldns_rr_push_rdf(pubkey,
++			                 ldns_native2rdf_int8(LDNS_RDF_TYPE_ALG,
++			                 ldns_key_algorithm(k)));
++			size = ldns_key_hmac_size(k);
++			memcpy(bin, ldns_key_hmac_key(k), size);
++			internal_data = 1;
++			break;
++	}
++	/* fourth the key bin material */
++	if (internal_data) {
++		keybin = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, size, bin);
++		LDNS_FREE(bin);
++		ldns_rr_push_rdf(pubkey, keybin);
++	}
++	return pubkey;
++}
++
++void
++ldns_key_free(ldns_key *key)
++{
++	LDNS_FREE(key);
++}
++
++void
++ldns_key_deep_free(ldns_key *key)
++{
++	unsigned char* hmac;
++	if (ldns_key_pubkey_owner(key)) {
++		ldns_rdf_deep_free(ldns_key_pubkey_owner(key));
++	}
++#ifdef HAVE_SSL
++	if (ldns_key_evp_key(key)) {
++		EVP_PKEY_free(ldns_key_evp_key(key));
++	}
++#endif /* HAVE_SSL */
++	if (ldns_key_hmac_key(key)) {
++		hmac = ldns_key_hmac_key(key);
++		LDNS_FREE(hmac);
++	}
++	LDNS_FREE(key);
++}
++
++void
++ldns_key_list_free(ldns_key_list *key_list)
++{
++	size_t i;
++	for (i = 0; i < ldns_key_list_key_count(key_list); i++) {
++		ldns_key_deep_free(ldns_key_list_key(key_list, i));
++	}
++	LDNS_FREE(key_list->_keys);
++	LDNS_FREE(key_list);
++}
++
++ldns_rr *
++ldns_read_anchor_file(const char *filename)
++{
++	FILE *fp;
++	/*char line[LDNS_MAX_PACKETLEN];*/
++	char *line = LDNS_XMALLOC(char, LDNS_MAX_PACKETLEN);
++	int c;
++	size_t i = 0;
++	ldns_rr *r;
++	ldns_status status;
++        if(!line) {
++                return NULL;
++        }
++
++	fp = fopen(filename, "r");
++	if (!fp) {
++#ifdef STDERR_MSGS
++		fprintf(stderr, "Unable to open %s: %s\n", filename, strerror(errno));
++#endif
++		LDNS_FREE(line);
++		return NULL;
++	}
++	
++	while ((c = fgetc(fp)) && i+1 < LDNS_MAX_PACKETLEN && c != EOF) {
++		line[i] = c;
++		i++;
++	}
++	line[i] = '\0';
++	
++	fclose(fp);
++	
++	if (i <= 0) {
++#ifdef STDERR_MSGS
++		fprintf(stderr, "nothing read from %s", filename);
++#endif
++		LDNS_FREE(line);
++		return NULL;
++	} else {
++		status = ldns_rr_new_frm_str(&r, line, 0, NULL, NULL);
++		if (status == LDNS_STATUS_OK && (ldns_rr_get_type(r) == LDNS_RR_TYPE_DNSKEY || ldns_rr_get_type(r) == LDNS_RR_TYPE_DS)) {
++			LDNS_FREE(line);
++			return r;
++		} else {
++#ifdef STDERR_MSGS
++			fprintf(stderr, "Error creating DNSKEY or DS rr from %s: %s\n", filename, ldns_get_errorstr_by_id(status));
++#endif
++			LDNS_FREE(line);
++			return NULL;
++		}
++	}
++}
++
++char *
++ldns_key_get_file_base_name(ldns_key *key)
++{
++	ldns_buffer *buffer;
++	char *file_base_name;
++	
++	buffer = ldns_buffer_new(255);
++	ldns_buffer_printf(buffer, "K");
++	(void)ldns_rdf2buffer_str_dname(buffer, ldns_key_pubkey_owner(key));
++	ldns_buffer_printf(buffer,
++	                   "+%03u+%05u",
++			   ldns_key_algorithm(key),
++			   ldns_key_keytag(key));
++	file_base_name = ldns_buffer_export(buffer);
++	ldns_buffer_free(buffer);
++	return file_base_name;
++}
++
++int ldns_key_algo_supported(int algo)
++{
++	ldns_lookup_table *lt = ldns_signing_algorithms;
++	while(lt->name) {
++		if(lt->id == algo)
++			return 1;
++		lt++;
++	}
++	return 0;
++}
++
++ldns_signing_algorithm ldns_get_signing_algorithm_by_name(const char* name)
++{
++        /* list of (signing algorithm id, alias_name) */
++        ldns_lookup_table aliases[] = {
++                /* from bind dnssec-keygen */
++                {LDNS_SIGN_HMACMD5, "HMAC-MD5"},
++                {LDNS_SIGN_DSA_NSEC3, "NSEC3DSA"},
++                {LDNS_SIGN_RSASHA1_NSEC3, "NSEC3RSASHA1"},
++                /* old ldns usage, now RFC names */
++                {LDNS_SIGN_DSA_NSEC3, "DSA_NSEC3" },
++                {LDNS_SIGN_RSASHA1_NSEC3, "RSASHA1_NSEC3" },
++#ifdef USE_GOST
++                {LDNS_SIGN_ECC_GOST, "GOST"},
++#endif
++                /* compat with possible output */
++                {LDNS_DH, "DH"},
++                {LDNS_ECC, "ECC"},
++                {LDNS_INDIRECT, "INDIRECT"},
++                {LDNS_PRIVATEDNS, "PRIVATEDNS"},
++                {LDNS_PRIVATEOID, "PRIVATEOID"},
++                {0, NULL}};
++        ldns_lookup_table* lt = ldns_signing_algorithms;
++	ldns_signing_algorithm a;
++	char *endptr;
++
++        while(lt->name) {
++                if(strcasecmp(lt->name, name) == 0)
++                        return lt->id;
++                lt++;
++        }
++        lt = aliases;
++        while(lt->name) {
++                if(strcasecmp(lt->name, name) == 0)
++                        return lt->id;
++                lt++;
++        }
++	a = strtol(name, &endptr, 10);
++	if (*name && !*endptr)
++		return a;
++
++        return 0;
++}
+diff --git a/ldns/src/net.c b/ldns/src/net.c
+new file mode 100644
+index 0000000..b8a5385
+--- /dev/null
++++ b/ldns/src/net.c
+@@ -0,0 +1,1002 @@
++/*
++ * net.c
++ *
++ * Network implementation
++ * All network related functions are grouped here
++ *
++ * a Net::DNS like library for C
++ *
++ * (c) NLnet Labs, 2004-2006
++ *
++ * See the file LICENSE for the license
++ */
++
++#include <ldns/config.h>
++
++#include <ldns/ldns.h>
++
++#ifdef HAVE_NETINET_IN_H
++#include <netinet/in.h>
++#endif
++#ifdef HAVE_SYS_SOCKET_H
++#include <sys/socket.h>
++#endif
++#ifdef HAVE_NETDB_H
++#include <netdb.h>
++#endif
++#ifdef HAVE_ARPA_INET_H
++#include <arpa/inet.h>
++#endif
++#include <sys/time.h>
++#include <errno.h>
++#include <fcntl.h>
++
++ldns_status
++ldns_send(ldns_pkt **result_packet, ldns_resolver *r, const ldns_pkt *query_pkt)
++{
++	ldns_buffer *qb;
++	ldns_status result;
++	ldns_rdf *tsig_mac = NULL;
++
++	qb = ldns_buffer_new(LDNS_MIN_BUFLEN);
++
++	if (query_pkt && ldns_pkt_tsig(query_pkt)) {
++		tsig_mac = ldns_rr_rdf(ldns_pkt_tsig(query_pkt), 3);
++	}
++
++	if (!query_pkt ||
++	    ldns_pkt2buffer_wire(qb, query_pkt) != LDNS_STATUS_OK) {
++		result = LDNS_STATUS_ERR;
++	} else {
++        	result = ldns_send_buffer(result_packet, r, qb, tsig_mac);
++	}
++
++	ldns_buffer_free(qb);
++
++	return result;
++}
++
++/* code from rdata.c */
++static struct sockaddr_storage *
++ldns_rdf2native_sockaddr_storage_port(
++		const ldns_rdf *rd, uint16_t port, size_t *size)
++{
++        struct sockaddr_storage *data;
++        struct sockaddr_in  *data_in;
++        struct sockaddr_in6 *data_in6;
++
++        data = LDNS_MALLOC(struct sockaddr_storage);
++        if (!data) {
++                return NULL;
++        }
++	/* zero the structure for portability */
++	memset(data, 0, sizeof(struct sockaddr_storage));
++
++        switch(ldns_rdf_get_type(rd)) {
++                case LDNS_RDF_TYPE_A:
++#ifndef S_SPLINT_S
++                        data->ss_family = AF_INET;
++#endif
++                        data_in = (struct sockaddr_in*) data;
++                        data_in->sin_port = (in_port_t)htons(port);
++                        memcpy(&(data_in->sin_addr), ldns_rdf_data(rd), ldns_rdf_size(rd));
++                        *size = sizeof(struct sockaddr_in);
++                        return data;
++                case LDNS_RDF_TYPE_AAAA:
++#ifndef S_SPLINT_S
++                        data->ss_family = AF_INET6;
++#endif
++                        data_in6 = (struct sockaddr_in6*) data;
++                        data_in6->sin6_port = (in_port_t)htons(port);
++                        memcpy(&data_in6->sin6_addr, ldns_rdf_data(rd), ldns_rdf_size(rd));
++                        *size = sizeof(struct sockaddr_in6);
++                        return data;
++                default:
++                        LDNS_FREE(data);
++                        return NULL;
++        }
++}
++
++struct sockaddr_storage *
++ldns_rdf2native_sockaddr_storage(
++		const ldns_rdf *rd, uint16_t port, size_t *size)
++{
++	return ldns_rdf2native_sockaddr_storage_port(
++			rd, (port == 0 ? (uint16_t)LDNS_PORT : port), size);
++}
++
++/** best effort to set nonblocking */
++static void
++ldns_sock_nonblock(int sockfd)
++{
++#ifdef HAVE_FCNTL
++	int flag;
++	if((flag = fcntl(sockfd, F_GETFL)) != -1) {
++		flag |= O_NONBLOCK;
++		if(fcntl(sockfd, F_SETFL, flag) == -1) {
++			/* ignore error, continue blockingly */
++		}
++	}
++#elif defined(HAVE_IOCTLSOCKET)
++	unsigned long on = 1;
++	if(ioctlsocket(sockfd, FIONBIO, &on) != 0) {
++		/* ignore error, continue blockingly */
++	}
++#endif
++}
++
++/** best effort to set blocking */
++static void
++ldns_sock_block(int sockfd)
++{
++#ifdef HAVE_FCNTL
++	int flag;
++	if((flag = fcntl(sockfd, F_GETFL)) != -1) {
++		flag &= ~O_NONBLOCK;
++		if(fcntl(sockfd, F_SETFL, flag) == -1) {
++			/* ignore error, continue */
++		}
++	}
++#elif defined(HAVE_IOCTLSOCKET)
++	unsigned long off = 0;
++	if(ioctlsocket(sockfd, FIONBIO, &off) != 0) {
++		/* ignore error, continue */
++	}
++#endif
++}
++
++/** wait for a socket to become ready */
++static int
++ldns_sock_wait(int sockfd, struct timeval timeout, int write)
++{
++	int ret;
++#ifndef S_SPLINT_S
++	fd_set fds;
++	FD_ZERO(&fds);
++	FD_SET(FD_SET_T sockfd, &fds);
++	if(write)
++		ret = select(sockfd+1, NULL, &fds, NULL, &timeout);
++	else
++		ret = select(sockfd+1, &fds, NULL, NULL, &timeout);
++#endif
++	if(ret == 0)
++		/* timeout expired */
++		return 0;
++	else if(ret == -1)
++		/* error */
++		return 0;
++	return 1;
++}
++
++
++static int
++ldns_tcp_connect_from(const struct sockaddr_storage *to, socklen_t tolen, 
++	       	const struct sockaddr_storage *from, socklen_t fromlen,
++		struct timeval timeout)
++{
++	int sockfd;
++
++#ifndef S_SPLINT_S
++	if ((sockfd = socket((int)((struct sockaddr*)to)->sa_family, SOCK_STREAM, 
++					IPPROTO_TCP)) == -1) {
++		return 0;
++	}
++#endif
++	if (from && bind(sockfd, (const struct sockaddr*)from, fromlen) == -1){
++		return 0;
++	}
++
++	/* perform nonblocking connect, to be able to wait with select() */
++	ldns_sock_nonblock(sockfd);
++	if (connect(sockfd, (struct sockaddr*)to, tolen) == -1) {
++#ifndef USE_WINSOCK
++#ifdef EINPROGRESS
++		if(errno != EINPROGRESS) {
++#else
++		if(1) {
++#endif
++			close(sockfd);
++			return 0;
++		}
++#else /* USE_WINSOCK */
++		if(WSAGetLastError() != WSAEINPROGRESS &&
++			WSAGetLastError() != WSAEWOULDBLOCK) {
++			closesocket(sockfd);
++			return 0;
++		}
++#endif
++		/* error was only telling us that it would block */
++	}
++
++	/* wait(write) until connected or error */
++	while(1) {
++		int error = 0;
++		socklen_t len = (socklen_t)sizeof(error);
++
++		if(!ldns_sock_wait(sockfd, timeout, 1)) {
++#ifndef USE_WINSOCK
++			close(sockfd);
++#else
++			closesocket(sockfd);
++#endif
++			return 0;
++		}
++
++		/* check if there is a pending error for nonblocking connect */
++		if(getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void*)&error,
++			&len) < 0) {
++#ifndef USE_WINSOCK
++			error = errno; /* on solaris errno is error */
++#else
++			error = WSAGetLastError();
++#endif
++		}
++#ifndef USE_WINSOCK
++#if defined(EINPROGRESS) && defined(EWOULDBLOCK)
++		if(error == EINPROGRESS || error == EWOULDBLOCK)
++			continue; /* try again */
++#endif
++		else if(error != 0) {
++			close(sockfd);
++			/* error in errno for our user */
++			errno = error;
++			return 0;
++		}
++#else /* USE_WINSOCK */
++		if(error == WSAEINPROGRESS)
++			continue;
++		else if(error == WSAEWOULDBLOCK)
++			continue;
++		else if(error != 0) {
++			closesocket(sockfd);
++			errno = error;
++			return 0;
++		}
++#endif /* USE_WINSOCK */
++		/* connected */
++		break;
++	}
++
++	/* set the socket blocking again */
++	ldns_sock_block(sockfd);
++
++	return sockfd;
++}
++
++int
++ldns_tcp_connect(const struct sockaddr_storage *to, socklen_t tolen, 
++		struct timeval timeout)
++{
++	return ldns_tcp_connect_from(to, tolen, NULL, 0, timeout);
++}
++
++static int
++ldns_tcp_bgsend_from(ldns_buffer *qbin,
++		const struct sockaddr_storage *to, socklen_t tolen, 
++	       	const struct sockaddr_storage *from, socklen_t fromlen,
++		struct timeval timeout)
++{
++	int sockfd;
++	
++	sockfd = ldns_tcp_connect_from(to, tolen, from, fromlen, timeout);
++	
++	if (sockfd == 0) {
++		return 0;
++	}
++	
++	if (ldns_tcp_send_query(qbin, sockfd, to, tolen) == 0) {
++#ifndef USE_WINSOCK
++		close(sockfd);
++#else
++		closesocket(sockfd);
++#endif
++		return 0;
++	}
++	
++	return sockfd;
++}
++
++int
++ldns_tcp_bgsend(ldns_buffer *qbin,
++		const struct sockaddr_storage *to, socklen_t tolen, 
++		struct timeval timeout)
++{
++	return ldns_tcp_bgsend_from(qbin, to, tolen, NULL, 0, timeout);
++}
++
++
++/* keep in mind that in DNS tcp messages the first 2 bytes signal the
++ * amount data to expect
++ */
++static ldns_status
++ldns_tcp_send_from(uint8_t **result,  ldns_buffer *qbin,
++	       	const struct sockaddr_storage *to, socklen_t tolen,
++	       	const struct sockaddr_storage *from, socklen_t fromlen,
++		struct timeval timeout, size_t *answer_size)
++{
++	int sockfd;
++	uint8_t *answer;
++	
++	sockfd = ldns_tcp_bgsend_from(qbin, to, tolen, from, fromlen, timeout);
++	
++	if (sockfd == 0) {
++		return LDNS_STATUS_ERR;
++	}
++
++	answer = ldns_tcp_read_wire_timeout(sockfd, answer_size, timeout);
++#ifndef USE_WINSOCK
++	close(sockfd);
++#else
++	closesocket(sockfd);
++#endif
++
++	if (*answer_size == 0) {
++		/* oops */
++		return LDNS_STATUS_NETWORK_ERR;
++	}
++
++	/* resize accordingly */
++	*result = LDNS_XREALLOC(answer, uint8_t, (size_t)*answer_size);
++        if(!*result) {
++                LDNS_FREE(answer);
++                return LDNS_STATUS_MEM_ERR;
++        }
++	return LDNS_STATUS_OK;
++}
++
++ldns_status
++ldns_tcp_send(uint8_t **result,  ldns_buffer *qbin,
++		const struct sockaddr_storage *to, socklen_t tolen,
++		struct timeval timeout, size_t *answer_size)
++{
++	return ldns_tcp_send_from(result, qbin,
++			to, tolen, NULL, 0, timeout, answer_size);
++}
++
++int
++ldns_udp_connect(const struct sockaddr_storage *to, struct timeval ATTR_UNUSED(timeout))
++{
++	int sockfd;
++
++#ifndef S_SPLINT_S
++	if ((sockfd = socket((int)((struct sockaddr*)to)->sa_family, SOCK_DGRAM, 
++					IPPROTO_UDP)) 
++			== -1) {
++                return 0;
++        }
++#endif
++	return sockfd;
++}
++
++static int
++ldns_udp_bgsend_from(ldns_buffer *qbin,
++		const struct sockaddr_storage *to  , socklen_t tolen, 
++		const struct sockaddr_storage *from, socklen_t fromlen, 
++		struct timeval timeout)
++{
++	int sockfd;
++
++	sockfd = ldns_udp_connect(to, timeout);
++
++	if (sockfd == 0) {
++		return 0;
++	}
++
++	if (from && bind(sockfd, (const struct sockaddr*)from, fromlen) == -1){
++		return 0;
++	}
++
++	if (ldns_udp_send_query(qbin, sockfd, to, tolen) == 0) {
++#ifndef USE_WINSOCK
++		close(sockfd);
++#else
++		closesocket(sockfd);
++#endif
++		return 0;
++	}
++	return sockfd;
++}
++
++int
++ldns_udp_bgsend(ldns_buffer *qbin,
++		const struct sockaddr_storage *to  , socklen_t tolen, 
++		struct timeval timeout)
++{
++	return ldns_udp_bgsend_from(qbin, to, tolen, NULL, 0, timeout);
++}
++
++static ldns_status
++ldns_udp_send_from(uint8_t **result, ldns_buffer *qbin,
++		const struct sockaddr_storage *to  , socklen_t tolen,
++		const struct sockaddr_storage *from, socklen_t fromlen,
++		struct timeval timeout, size_t *answer_size)
++{
++	int sockfd;
++	uint8_t *answer;
++
++	sockfd = ldns_udp_bgsend_from(qbin, to, tolen, from, fromlen, timeout);
++
++	if (sockfd == 0) {
++		return LDNS_STATUS_SOCKET_ERROR;
++	}
++
++	/* wait for an response*/
++	if(!ldns_sock_wait(sockfd, timeout, 0)) {
++#ifndef USE_WINSOCK
++		close(sockfd);
++#else
++                closesocket(sockfd);
++#endif
++		return LDNS_STATUS_NETWORK_ERR;
++	}
++
++        /* set to nonblocking, so if the checksum is bad, it becomes
++         * an EGAIN error and the ldns_udp_send function does not block,
++         * but returns a 'NETWORK_ERROR' much like a timeout. */
++        ldns_sock_nonblock(sockfd);
++
++	answer = ldns_udp_read_wire(sockfd, answer_size, NULL, NULL);
++#ifndef USE_WINSOCK
++	close(sockfd);
++#else
++        closesocket(sockfd);
++#endif
++
++	if (*answer_size == 0) {
++		/* oops */
++		return LDNS_STATUS_NETWORK_ERR;
++	}
++
++	*result = answer;
++	return LDNS_STATUS_OK;
++}
++
++ldns_status
++ldns_udp_send(uint8_t **result, ldns_buffer *qbin,
++		const struct sockaddr_storage *to  , socklen_t tolen,
++		struct timeval timeout, size_t *answer_size)
++{
++	return ldns_udp_send_from(result, qbin, to, tolen, NULL, 0,
++			timeout, answer_size);
++}
++
++ldns_status
++ldns_send_buffer(ldns_pkt **result, ldns_resolver *r, ldns_buffer *qb, ldns_rdf *tsig_mac)
++{
++	uint8_t i;
++
++	struct sockaddr_storage *src = NULL;
++	size_t src_len;
++	struct sockaddr_storage *ns;
++	size_t ns_len;
++	struct timeval tv_s;
++	struct timeval tv_e;
++
++	ldns_rdf **ns_array;
++	size_t *rtt;
++	ldns_pkt *reply;
++	bool all_servers_rtt_inf;
++	uint8_t retries;
++
++	uint8_t *reply_bytes = NULL;
++	size_t reply_size = 0;
++	ldns_status status, send_status;
++
++	assert(r != NULL);
++
++	status = LDNS_STATUS_OK;
++	rtt = ldns_resolver_rtt(r);
++	ns_array = ldns_resolver_nameservers(r);
++	reply = NULL; 
++	ns_len = 0;
++
++	all_servers_rtt_inf = true;
++
++	if (ldns_resolver_random(r)) {
++		ldns_resolver_nameservers_randomize(r);
++	}
++
++	if(ldns_resolver_source(r)) {
++		src = ldns_rdf2native_sockaddr_storage_port(
++				ldns_resolver_source(r), 0, &src_len);
++	}
++
++	/* loop through all defined nameservers */
++	for (i = 0; i < ldns_resolver_nameserver_count(r); i++) {
++		if (rtt[i] == LDNS_RESOLV_RTT_INF) {
++			/* not reachable nameserver! */
++			continue;
++		}
++
++		/* maybe verbosity setting?
++		printf("Sending to ");
++		ldns_rdf_print(stdout, ns_array[i]);
++		printf("\n");
++		*/
++		ns = ldns_rdf2native_sockaddr_storage(ns_array[i],
++				ldns_resolver_port(r), &ns_len);
++
++
++#ifndef S_SPLINT_S
++		if ((ns->ss_family == AF_INET) &&
++				(ldns_resolver_ip6(r) == LDNS_RESOLV_INET6)) {
++			/* not reachable */
++			LDNS_FREE(ns);
++			continue;
++		}
++
++		if ((ns->ss_family == AF_INET6) &&
++				 (ldns_resolver_ip6(r) == LDNS_RESOLV_INET)) {
++			/* not reachable */
++			LDNS_FREE(ns);
++			continue;
++		}
++#endif
++
++		all_servers_rtt_inf = false;
++
++		gettimeofday(&tv_s, NULL);
++
++		send_status = LDNS_STATUS_ERR;
++
++		/* reply_bytes implicitly handles our error */
++		if (ldns_resolver_usevc(r)) {
++			for (retries = ldns_resolver_retry(r); retries > 0; retries--) {
++				send_status = 
++					ldns_tcp_send_from(&reply_bytes, qb, 
++						ns, (socklen_t)ns_len,
++						src, (socklen_t)src_len,
++						ldns_resolver_timeout(r),
++						&reply_size);
++				if (send_status == LDNS_STATUS_OK) {
++					break;
++				}
++			}
++		} else {
++			for (retries = ldns_resolver_retry(r); retries > 0; retries--) {
++				/* ldns_rdf_print(stdout, ns_array[i]); */
++				send_status = 
++					ldns_udp_send_from(&reply_bytes, qb,
++						ns,  (socklen_t)ns_len,
++						src, (socklen_t)src_len,
++						ldns_resolver_timeout(r),
++						&reply_size);
++				if (send_status == LDNS_STATUS_OK) {
++					break;
++				}
++			}
++		}
++
++		if (send_status != LDNS_STATUS_OK) {
++			ldns_resolver_set_nameserver_rtt(r, i, LDNS_RESOLV_RTT_INF);
++			status = send_status;
++		}
++		
++		/* obey the fail directive */
++		if (!reply_bytes) {
++			/* the current nameserver seems to have a problem, blacklist it */
++			if (ldns_resolver_fail(r)) {
++				LDNS_FREE(ns);
++				return LDNS_STATUS_ERR;
++			} else {
++				LDNS_FREE(ns);
++				continue;
++			}
++		} 
++		
++		status = ldns_wire2pkt(&reply, reply_bytes, reply_size);
++		if (status != LDNS_STATUS_OK) {
++			LDNS_FREE(reply_bytes);
++			LDNS_FREE(ns);
++			return status;
++		}
++		
++		LDNS_FREE(ns);
++		gettimeofday(&tv_e, NULL);
++
++		if (reply) {
++			ldns_pkt_set_querytime(reply, (uint32_t)
++				((tv_e.tv_sec - tv_s.tv_sec) * 1000) +
++				(tv_e.tv_usec - tv_s.tv_usec) / 1000);
++			ldns_pkt_set_answerfrom(reply,
++					ldns_rdf_clone(ns_array[i]));
++			ldns_pkt_set_timestamp(reply, tv_s);
++			ldns_pkt_set_size(reply, reply_size);
++			break;
++		} else {
++			if (ldns_resolver_fail(r)) {
++				/* if fail is set bail out, after the first
++				 * one */
++				break;
++			}
++		}
++
++		/* wait retrans seconds... */
++		sleep((unsigned int) ldns_resolver_retrans(r));
++	}
++
++	if(src) {
++		LDNS_FREE(src);
++	}
++	if (all_servers_rtt_inf) {
++		LDNS_FREE(reply_bytes);
++		return LDNS_STATUS_RES_NO_NS;
++	}
++#ifdef HAVE_SSL
++	if (tsig_mac && reply && reply_bytes) {
++		if (!ldns_pkt_tsig_verify(reply,
++		                          reply_bytes,
++					  reply_size,
++		                          ldns_resolver_tsig_keyname(r),
++		                          ldns_resolver_tsig_keydata(r), tsig_mac)) {
++			status = LDNS_STATUS_CRYPTO_TSIG_BOGUS;
++		}
++	}
++#else
++	(void)tsig_mac;
++#endif /* HAVE_SSL */
++
++	LDNS_FREE(reply_bytes);
++	if (result) {
++		*result = reply;
++	}
++
++	return status;
++}
++
++ssize_t
++ldns_tcp_send_query(ldns_buffer *qbin, int sockfd, 
++                    const struct sockaddr_storage *to, socklen_t tolen)
++{
++	uint8_t *sendbuf;
++	ssize_t bytes;
++
++	/* add length of packet */
++	sendbuf = LDNS_XMALLOC(uint8_t, ldns_buffer_position(qbin) + 2);
++	if(!sendbuf) return 0;
++	ldns_write_uint16(sendbuf, ldns_buffer_position(qbin));
++	memcpy(sendbuf + 2, ldns_buffer_begin(qbin), ldns_buffer_position(qbin));
++
++	bytes = sendto(sockfd, (void*)sendbuf,
++			ldns_buffer_position(qbin) + 2, 0, (struct sockaddr *)to, tolen);
++
++        LDNS_FREE(sendbuf);
++
++	if (bytes == -1 || (size_t) bytes != ldns_buffer_position(qbin) + 2 ) {
++		return 0;
++	}
++	return bytes;
++}
++
++/* don't wait for an answer */
++ssize_t
++ldns_udp_send_query(ldns_buffer *qbin, int sockfd, const struct sockaddr_storage *to, 
++		socklen_t tolen)
++{
++	ssize_t bytes;
++
++	bytes = sendto(sockfd, (void*)ldns_buffer_begin(qbin),
++			ldns_buffer_position(qbin), 0, (struct sockaddr *)to, tolen);
++
++	if (bytes == -1 || (size_t)bytes != ldns_buffer_position(qbin)) {
++		return 0;
++	}
++	if ((size_t) bytes != ldns_buffer_position(qbin)) {
++		return 0;
++	}
++	return bytes;
++}
++
++uint8_t *
++ldns_udp_read_wire(int sockfd, size_t *size, struct sockaddr_storage *from,
++		socklen_t *fromlen)
++{
++	uint8_t *wire, *wireout;
++	ssize_t wire_size;
++
++	wire = LDNS_XMALLOC(uint8_t, LDNS_MAX_PACKETLEN);
++	if (!wire) {
++		*size = 0;
++		return NULL;
++	}
++
++	wire_size = recvfrom(sockfd, (void*)wire, LDNS_MAX_PACKETLEN, 0, 
++			(struct sockaddr *)from, fromlen);
++
++	/* recvfrom can also return 0 */
++	if (wire_size == -1 || wire_size == 0) {
++		*size = 0;
++		LDNS_FREE(wire);
++		return NULL;
++	}
++
++	*size = (size_t)wire_size;
++	wireout = LDNS_XREALLOC(wire, uint8_t, (size_t)wire_size);
++	if(!wireout) LDNS_FREE(wire);
++
++	return wireout;
++}
++
++uint8_t *
++ldns_tcp_read_wire_timeout(int sockfd, size_t *size, struct timeval timeout)
++{
++	uint8_t *wire;
++	uint16_t wire_size;
++	ssize_t bytes = 0, rc = 0;
++
++	wire = LDNS_XMALLOC(uint8_t, 2);
++	if (!wire) {
++		*size = 0;
++		return NULL;
++	}
++	
++	while (bytes < 2) {
++		if(!ldns_sock_wait(sockfd, timeout, 0)) {
++			*size = 0;
++			LDNS_FREE(wire);
++			return NULL;
++		}
++		rc = recv(sockfd, (void*) (wire + bytes), 
++				(size_t) (2 - bytes), 0);
++		if (rc == -1 || rc == 0) {
++			*size = 0;
++			LDNS_FREE(wire);
++			return NULL;
++		}
++                bytes += rc;
++	}
++
++	wire_size = ldns_read_uint16(wire);
++	
++	LDNS_FREE(wire);
++	wire = LDNS_XMALLOC(uint8_t, wire_size);
++	if (!wire) {
++		*size = 0;
++		return NULL;
++	}
++	bytes = 0;
++
++	while (bytes < (ssize_t) wire_size) {
++		if(!ldns_sock_wait(sockfd, timeout, 0)) {
++			*size = 0;
++			LDNS_FREE(wire);
++			return NULL;
++		}
++		rc = recv(sockfd, (void*) (wire + bytes), 
++				(size_t) (wire_size - bytes), 0);
++		if (rc == -1 || rc == 0) {
++			LDNS_FREE(wire);
++			*size = 0;
++			return NULL;
++		}
++                bytes += rc;
++	}
++	
++	*size = (size_t) bytes;
++	return wire;
++}
++
++uint8_t *
++ldns_tcp_read_wire(int sockfd, size_t *size)
++{
++	uint8_t *wire;
++	uint16_t wire_size;
++	ssize_t bytes = 0, rc = 0;
++
++	wire = LDNS_XMALLOC(uint8_t, 2);
++	if (!wire) {
++		*size = 0;
++		return NULL;
++	}
++	
++	while (bytes < 2) {
++		rc = recv(sockfd, (void*) (wire + bytes), 
++				(size_t) (2 - bytes), 0);
++		if (rc == -1 || rc == 0) {
++			*size = 0;
++			LDNS_FREE(wire);
++			return NULL;
++		}
++                bytes += rc;
++	}
++
++	wire_size = ldns_read_uint16(wire);
++	
++	LDNS_FREE(wire);
++	wire = LDNS_XMALLOC(uint8_t, wire_size);
++	if (!wire) {
++		*size = 0;
++		return NULL;
++	}
++	bytes = 0;
++
++	while (bytes < (ssize_t) wire_size) {
++		rc = recv(sockfd, (void*) (wire + bytes), 
++				(size_t) (wire_size - bytes), 0);
++		if (rc == -1 || rc == 0) {
++			LDNS_FREE(wire);
++			*size = 0;
++			return NULL;
++		}
++                bytes += rc;
++	}
++	
++	*size = (size_t) bytes;
++	return wire;
++}
++
++#ifndef S_SPLINT_S
++ldns_rdf *
++ldns_sockaddr_storage2rdf(struct sockaddr_storage *sock, uint16_t *port)
++{
++        ldns_rdf *addr;
++        struct sockaddr_in *data_in;
++        struct sockaddr_in6 *data_in6;
++
++        switch(sock->ss_family) {
++                case AF_INET:
++                        data_in = (struct sockaddr_in*)sock;
++                        if (port) {
++                                *port = ntohs((uint16_t)data_in->sin_port);
++                        }
++                        addr = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_A,
++                                        LDNS_IP4ADDRLEN, &data_in->sin_addr);
++                        break;
++                case AF_INET6:
++                        data_in6 = (struct sockaddr_in6*)sock;
++                        if (port) {
++                                *port = ntohs((uint16_t)data_in6->sin6_port);
++                        }
++                        addr = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_AAAA,
++                                        LDNS_IP6ADDRLEN, &data_in6->sin6_addr);
++                        break;
++                default:
++                        if (port) {
++                                *port = 0;
++                        }
++                        return NULL;
++        }
++        return addr;
++}
++#endif
++
++/* code from resolver.c */
++ldns_status
++ldns_axfr_start(ldns_resolver *resolver, ldns_rdf *domain, ldns_rr_class class) 
++{
++        ldns_pkt *query;
++        ldns_buffer *query_wire;
++
++        struct sockaddr_storage *src = NULL;
++        size_t src_len = 0;
++        struct sockaddr_storage *ns = NULL;
++        size_t ns_len = 0;
++        size_t ns_i;
++        ldns_status status;
++
++        if (!resolver || ldns_resolver_nameserver_count(resolver) < 1) {
++                return LDNS_STATUS_ERR;
++        }
++
++        query = ldns_pkt_query_new(ldns_rdf_clone(domain), LDNS_RR_TYPE_AXFR, class, 0);
++
++        if (!query) {
++                return LDNS_STATUS_ADDRESS_ERR;
++        }
++	if(ldns_resolver_source(resolver)) {
++		src = ldns_rdf2native_sockaddr_storage_port(
++				ldns_resolver_source(resolver), 0, &src_len);
++	}
++        /* For AXFR, we have to make the connection ourselves */
++        /* try all nameservers (which usually would mean v4 fallback if
++         * @hostname is used */
++        for (ns_i = 0;
++             ns_i < ldns_resolver_nameserver_count(resolver) &&
++             resolver->_socket == 0;
++             ns_i++) {
++		if (ns != NULL) {
++			LDNS_FREE(ns);
++		}
++	        ns = ldns_rdf2native_sockaddr_storage(
++	        	resolver->_nameservers[ns_i],
++			ldns_resolver_port(resolver), &ns_len);
++
++		resolver->_socket = ldns_tcp_connect_from(
++				ns, (socklen_t)ns_len,
++				src, (socklen_t)src_len,
++				ldns_resolver_timeout(resolver));
++	}
++
++	if (resolver->_socket == 0) {
++		ldns_pkt_free(query);
++		LDNS_FREE(ns);
++		return LDNS_STATUS_NETWORK_ERR;
++	}
++
++#ifdef HAVE_SSL
++	if (ldns_resolver_tsig_keyname(resolver) && ldns_resolver_tsig_keydata(resolver)) {
++		status = ldns_pkt_tsig_sign(query,
++		                            ldns_resolver_tsig_keyname(resolver),
++		                            ldns_resolver_tsig_keydata(resolver),
++		                            300, ldns_resolver_tsig_algorithm(resolver), NULL);
++		if (status != LDNS_STATUS_OK) {
++			/* to prevent problems on subsequent calls to 
++			 * ldns_axfr_start we have to close the socket here! */
++#ifndef USE_WINSOCK
++			close(resolver->_socket);
++#else
++			closesocket(resolver->_socket);
++#endif
++			resolver->_socket = 0;
++
++			ldns_pkt_free(query);
++			LDNS_FREE(ns);
++
++			return LDNS_STATUS_CRYPTO_TSIG_ERR;
++		}
++	}
++#endif /* HAVE_SSL */
++
++        /* Convert the query to a buffer
++         * Is this necessary?
++         */
++        query_wire = ldns_buffer_new(LDNS_MAX_PACKETLEN);
++        if(!query_wire) {
++                ldns_pkt_free(query);
++                LDNS_FREE(ns);
++#ifndef USE_WINSOCK
++		close(resolver->_socket);
++#else
++		closesocket(resolver->_socket);
++#endif
++		resolver->_socket = 0;
++
++                return LDNS_STATUS_MEM_ERR;
++        }
++        status = ldns_pkt2buffer_wire(query_wire, query);
++        if (status != LDNS_STATUS_OK) {
++                ldns_pkt_free(query);
++		ldns_buffer_free(query_wire);
++                LDNS_FREE(ns);
++
++		/* to prevent problems on subsequent calls to ldns_axfr_start
++		 * we have to close the socket here! */
++#ifndef USE_WINSOCK
++		close(resolver->_socket);
++#else
++		closesocket(resolver->_socket);
++#endif
++		resolver->_socket = 0;
++
++                return status;
++        }
++        /* Send the query */
++        if (ldns_tcp_send_query(query_wire, resolver->_socket, ns,
++				(socklen_t)ns_len) == 0) {
++                ldns_pkt_free(query);
++                ldns_buffer_free(query_wire);
++                LDNS_FREE(ns);
++
++		/* to prevent problems on subsequent calls to ldns_axfr_start
++		 * we have to close the socket here! */
++
++#ifndef USE_WINSOCK
++		close(resolver->_socket);
++#else
++		closesocket(resolver->_socket);
++#endif
++		resolver->_socket = 0;
++
++                return LDNS_STATUS_NETWORK_ERR;
++        }
++
++        ldns_pkt_free(query);
++        ldns_buffer_free(query_wire);
++        LDNS_FREE(ns);
++
++        /*
++         * The AXFR is done once the second SOA record is sent
++         */
++        resolver->_axfr_soa_count = 0;
++        return LDNS_STATUS_OK;
++}
+diff --git a/ldns/src/packet.c b/ldns/src/packet.c
+new file mode 100644
+index 0000000..62bfd07
+--- /dev/null
++++ b/ldns/src/packet.c
+@@ -0,0 +1,1159 @@
++/*
++ * packet.c
++ *
++ * dns packet implementation
++ *
++ * a Net::DNS like library for C
++ *
++ * (c) NLnet Labs, 2004-2006
++ *
++ * See the file LICENSE for the license
++ */
++
++#include <ldns/config.h>
++
++#include <ldns/ldns.h>
++
++#include <strings.h>
++#include <limits.h>
++
++#ifdef HAVE_SSL
++#include <openssl/rand.h>
++#endif
++
++/* Access functions 
++ * do this as functions to get type checking
++ */
++
++#define LDNS_EDNS_MASK_DO_BIT 0x8000
++
++/* TODO defines for 3600 */
++/* convert to and from numerical flag values */
++ldns_lookup_table ldns_edns_flags[] = {
++	{ 3600, "do"},
++	{ 0, NULL}
++};
++
++/* read */
++uint16_t
++ldns_pkt_id(const ldns_pkt *packet)
++{
++	return packet->_header->_id;
++}
++
++bool
++ldns_pkt_qr(const ldns_pkt *packet)
++{
++	return packet->_header->_qr;
++}
++
++bool
++ldns_pkt_aa(const ldns_pkt *packet)
++{
++	return packet->_header->_aa;
++}
++
++bool
++ldns_pkt_tc(const ldns_pkt *packet)
++{
++	return packet->_header->_tc;
++}
++
++bool
++ldns_pkt_rd(const ldns_pkt *packet)
++{
++	return packet->_header->_rd;
++}
++
++bool
++ldns_pkt_cd(const ldns_pkt *packet)
++{
++	return packet->_header->_cd;
++}
++
++bool
++ldns_pkt_ra(const ldns_pkt *packet)
++{
++	return packet->_header->_ra;
++}
++
++bool
++ldns_pkt_ad(const ldns_pkt *packet)
++{
++	return packet->_header->_ad;
++}
++
++ldns_pkt_opcode
++ldns_pkt_get_opcode(const ldns_pkt *packet)
++{
++	return packet->_header->_opcode;
++}
++
++ldns_pkt_rcode
++ldns_pkt_get_rcode(const ldns_pkt *packet)
++{
++	return packet->_header->_rcode;
++}
++
++uint16_t
++ldns_pkt_qdcount(const ldns_pkt *packet)
++{
++	return packet->_header->_qdcount;
++}
++
++uint16_t
++ldns_pkt_ancount(const ldns_pkt *packet)
++{
++	return packet->_header->_ancount;
++}
++
++uint16_t
++ldns_pkt_nscount(const ldns_pkt *packet)
++{
++	return packet->_header->_nscount;
++}
++
++uint16_t
++ldns_pkt_arcount(const ldns_pkt *packet)
++{
++	return packet->_header->_arcount;
++}
++
++ldns_rr_list *
++ldns_pkt_question(const ldns_pkt *packet)
++{
++	return packet->_question;
++}
++
++ldns_rr_list *
++ldns_pkt_answer(const ldns_pkt *packet)
++{
++	return packet->_answer;
++}
++
++ldns_rr_list *
++ldns_pkt_authority(const ldns_pkt *packet)
++{
++	return packet->_authority;
++}
++
++ldns_rr_list *
++ldns_pkt_additional(const ldns_pkt *packet)
++{
++	return packet->_additional;
++}
++
++/* return ALL section concatenated */
++ldns_rr_list *
++ldns_pkt_all(const ldns_pkt *packet)
++{
++	ldns_rr_list *all, *prev_all;
++
++	all = ldns_rr_list_cat_clone(
++			ldns_pkt_question(packet),
++			ldns_pkt_answer(packet));
++	prev_all = all;
++	all = ldns_rr_list_cat_clone(all,
++			ldns_pkt_authority(packet));
++	ldns_rr_list_deep_free(prev_all);
++	prev_all = all;
++	all = ldns_rr_list_cat_clone(all,
++			ldns_pkt_additional(packet));
++	ldns_rr_list_deep_free(prev_all);
++	return all;
++}
++
++ldns_rr_list *
++ldns_pkt_all_noquestion(const ldns_pkt *packet)
++{
++	ldns_rr_list *all, *all2;
++
++	all = ldns_rr_list_cat_clone(
++			ldns_pkt_answer(packet),
++			ldns_pkt_authority(packet));
++	all2 = ldns_rr_list_cat_clone(all,
++			ldns_pkt_additional(packet));
++	
++	ldns_rr_list_deep_free(all);
++	return all2;
++}
++
++size_t
++ldns_pkt_size(const ldns_pkt *packet)
++{
++	return packet->_size;
++}
++
++uint32_t 
++ldns_pkt_querytime(const ldns_pkt *packet)
++{
++	return packet->_querytime;
++}
++
++ldns_rdf *
++ldns_pkt_answerfrom(const ldns_pkt *packet)
++{
++	return packet->_answerfrom;
++}
++
++struct timeval
++ldns_pkt_timestamp(const ldns_pkt *packet)
++{
++	return packet->timestamp;
++}
++
++uint16_t
++ldns_pkt_edns_udp_size(const ldns_pkt *packet)
++{
++	return packet->_edns_udp_size;
++}
++
++uint8_t
++ldns_pkt_edns_extended_rcode(const ldns_pkt *packet)
++{
++	return packet->_edns_extended_rcode;
++}
++
++uint8_t
++ldns_pkt_edns_version(const ldns_pkt *packet)
++{
++	return packet->_edns_version;
++}
++
++uint16_t
++ldns_pkt_edns_z(const ldns_pkt *packet)
++{
++	return packet->_edns_z;
++}
++
++bool
++ldns_pkt_edns_do(const ldns_pkt *packet)
++{
++	return (packet->_edns_z & LDNS_EDNS_MASK_DO_BIT);
++}
++
++void
++ldns_pkt_set_edns_do(ldns_pkt *packet, bool value)
++{
++	if (value) {
++		packet->_edns_z = packet->_edns_z | LDNS_EDNS_MASK_DO_BIT;
++	} else {
++		packet->_edns_z = packet->_edns_z & ~LDNS_EDNS_MASK_DO_BIT;
++	}
++}
++
++ldns_rdf *
++ldns_pkt_edns_data(const ldns_pkt *packet)
++{
++	return packet->_edns_data;
++}
++
++/* return only those rr that share the ownername */
++ldns_rr_list *
++ldns_pkt_rr_list_by_name(ldns_pkt *packet,
++                         ldns_rdf *ownername,
++                         ldns_pkt_section sec)
++{
++	ldns_rr_list *rrs;
++	ldns_rr_list *ret;
++	uint16_t i;
++
++	if (!packet) {
++		return NULL;
++	}
++
++	rrs = ldns_pkt_get_section_clone(packet, sec);
++	ret = NULL;
++
++	for(i = 0; i < ldns_rr_list_rr_count(rrs); i++) {
++		if (ldns_dname_compare(ldns_rr_owner(
++						ldns_rr_list_rr(rrs, i)), 
++					ownername) == 0) {
++			/* owner names match */
++			if (ret == NULL) {
++				ret = ldns_rr_list_new();
++			}
++			ldns_rr_list_push_rr(ret,
++					     ldns_rr_clone(
++						ldns_rr_list_rr(rrs, i))
++					    );
++		}
++	}
++
++	ldns_rr_list_deep_free(rrs);
++
++	return ret;
++}
++
++/* return only those rr that share a type */
++ldns_rr_list *
++ldns_pkt_rr_list_by_type(const ldns_pkt *packet,
++                         ldns_rr_type type,
++                         ldns_pkt_section sec)
++{
++	ldns_rr_list *rrs;
++	ldns_rr_list *new;
++	uint16_t i;
++
++	if(!packet) {
++		return NULL;
++	}
++	
++	rrs = ldns_pkt_get_section_clone(packet, sec);
++	new = ldns_rr_list_new();
++	
++	for(i = 0; i < ldns_rr_list_rr_count(rrs); i++) {
++		if (type == ldns_rr_get_type(ldns_rr_list_rr(rrs, i))) {
++			/* types match */
++			ldns_rr_list_push_rr(new, 
++			                     ldns_rr_clone(
++			                     	ldns_rr_list_rr(rrs, i))
++					     );
++		}
++	}
++	ldns_rr_list_deep_free(rrs);
++
++	if (ldns_rr_list_rr_count(new) == 0) {
++		ldns_rr_list_free(new);
++		return NULL;
++	} else {
++		return new;
++	}
++}
++
++/* return only those rrs that share name and type */
++ldns_rr_list *
++ldns_pkt_rr_list_by_name_and_type(const ldns_pkt *packet,
++                                  const ldns_rdf *ownername,
++                                  ldns_rr_type type,
++                                  ldns_pkt_section sec)
++{
++	ldns_rr_list *rrs;
++	ldns_rr_list *new;
++	ldns_rr_list *ret;
++	uint16_t i;
++
++	if(!packet) {
++		return NULL;
++	}
++	
++	rrs = ldns_pkt_get_section_clone(packet, sec);
++	new = ldns_rr_list_new();
++	ret = NULL;
++
++	for(i = 0; i < ldns_rr_list_rr_count(rrs); i++) {
++		if (type == ldns_rr_get_type(ldns_rr_list_rr(rrs, i)) &&
++		    ldns_dname_compare(ldns_rr_owner(ldns_rr_list_rr(rrs, i)),
++		                     ownername
++		                    ) == 0
++		   ) {
++			/* types match */
++			ldns_rr_list_push_rr(new, ldns_rr_clone(ldns_rr_list_rr(rrs, i)));
++			ret = new;
++		}
++	}
++	ldns_rr_list_deep_free(rrs);
++	if (!ret) {
++		ldns_rr_list_free(new);
++	}
++	return ret;
++}
++
++bool
++ldns_pkt_rr(ldns_pkt *pkt, ldns_pkt_section sec, ldns_rr *rr)
++{
++	bool result = false;
++
++	switch (sec) {
++	case LDNS_SECTION_QUESTION:
++		return ldns_rr_list_contains_rr(ldns_pkt_question(pkt), rr);
++	case LDNS_SECTION_ANSWER:
++		return ldns_rr_list_contains_rr(ldns_pkt_answer(pkt), rr);
++	case LDNS_SECTION_AUTHORITY:
++		return ldns_rr_list_contains_rr(ldns_pkt_authority(pkt), rr);
++	case LDNS_SECTION_ADDITIONAL:
++		return ldns_rr_list_contains_rr(ldns_pkt_additional(pkt), rr);
++	case LDNS_SECTION_ANY:
++		result = ldns_rr_list_contains_rr(ldns_pkt_question(pkt), rr);
++	case LDNS_SECTION_ANY_NOQUESTION:
++		result = result
++		    || ldns_rr_list_contains_rr(ldns_pkt_answer(pkt), rr)
++		    || ldns_rr_list_contains_rr(ldns_pkt_authority(pkt), rr)
++		    || ldns_rr_list_contains_rr(ldns_pkt_additional(pkt), rr);
++	}
++
++	return result;
++}
++
++uint16_t
++ldns_pkt_section_count(const ldns_pkt *packet, ldns_pkt_section s)
++{
++	switch(s) {
++	case LDNS_SECTION_QUESTION:
++		return ldns_pkt_qdcount(packet);
++	case LDNS_SECTION_ANSWER:
++		return ldns_pkt_ancount(packet);
++	case LDNS_SECTION_AUTHORITY:
++		return ldns_pkt_nscount(packet);
++	case LDNS_SECTION_ADDITIONAL:
++		return ldns_pkt_arcount(packet);
++	case LDNS_SECTION_ANY:
++		return ldns_pkt_qdcount(packet) +
++			ldns_pkt_ancount(packet) +
++			ldns_pkt_nscount(packet) +
++			ldns_pkt_arcount(packet);
++	case LDNS_SECTION_ANY_NOQUESTION:
++		return ldns_pkt_ancount(packet) +
++			ldns_pkt_nscount(packet) +
++			ldns_pkt_arcount(packet);
++	default:
++		return 0;
++	}
++}
++
++bool
++ldns_pkt_empty(ldns_pkt *p)
++{
++	if (!p) {
++		return true; /* NULL is empty? */
++	}
++	if (ldns_pkt_section_count(p, LDNS_SECTION_ANY) > 0) {
++		return false;
++	} else {
++		return true;
++    }
++}
++
++
++ldns_rr_list *
++ldns_pkt_get_section_clone(const ldns_pkt *packet, ldns_pkt_section s)
++{
++	switch(s) {
++	case LDNS_SECTION_QUESTION:
++		return ldns_rr_list_clone(ldns_pkt_question(packet));
++	case LDNS_SECTION_ANSWER:
++		return ldns_rr_list_clone(ldns_pkt_answer(packet));
++	case LDNS_SECTION_AUTHORITY:
++		return ldns_rr_list_clone(ldns_pkt_authority(packet));
++	case LDNS_SECTION_ADDITIONAL:
++		return ldns_rr_list_clone(ldns_pkt_additional(packet));
++	case LDNS_SECTION_ANY:
++		/* these are already clones */
++		return ldns_pkt_all(packet);
++	case LDNS_SECTION_ANY_NOQUESTION:
++		return ldns_pkt_all_noquestion(packet);
++	default:
++		return NULL;
++	}
++}
++
++ldns_rr *ldns_pkt_tsig(const ldns_pkt *pkt) {
++	return pkt->_tsig_rr;
++}
++
++/* write */
++void
++ldns_pkt_set_id(ldns_pkt *packet, uint16_t id)
++{
++	packet->_header->_id = id;
++}
++
++void
++ldns_pkt_set_random_id(ldns_pkt *packet)
++{
++	uint16_t rid = ldns_get_random();
++	ldns_pkt_set_id(packet, rid);
++}
++
++
++void
++ldns_pkt_set_qr(ldns_pkt *packet, bool qr)
++{
++	packet->_header->_qr = qr;
++}
++
++void
++ldns_pkt_set_aa(ldns_pkt *packet, bool aa)
++{
++	packet->_header->_aa = aa;
++}
++
++void
++ldns_pkt_set_tc(ldns_pkt *packet, bool tc)
++{
++	packet->_header->_tc = tc;
++}
++
++void
++ldns_pkt_set_rd(ldns_pkt *packet, bool rd)
++{
++	packet->_header->_rd = rd;
++}
++
++void
++ldns_pkt_set_additional(ldns_pkt *p, ldns_rr_list *rr)
++{
++	p->_additional = rr;
++}
++
++void
++ldns_pkt_set_question(ldns_pkt *p, ldns_rr_list *rr)
++{
++	p->_question = rr;
++}
++
++void
++ldns_pkt_set_answer(ldns_pkt *p, ldns_rr_list *rr)
++{
++	p->_answer = rr;
++}
++
++void
++ldns_pkt_set_authority(ldns_pkt *p, ldns_rr_list *rr)
++{
++	p->_authority = rr;
++}
++
++void
++ldns_pkt_set_cd(ldns_pkt *packet, bool cd)
++{
++	packet->_header->_cd = cd;
++}
++
++void
++ldns_pkt_set_ra(ldns_pkt *packet, bool ra)
++{
++	packet->_header->_ra = ra;
++}
++
++void
++ldns_pkt_set_ad(ldns_pkt *packet, bool ad)
++{
++	packet->_header->_ad = ad;
++}
++
++void
++ldns_pkt_set_opcode(ldns_pkt *packet, ldns_pkt_opcode opcode)
++{
++	packet->_header->_opcode = opcode;
++}
++
++void
++ldns_pkt_set_rcode(ldns_pkt *packet, uint8_t rcode)
++{
++	packet->_header->_rcode = rcode;
++}
++
++void
++ldns_pkt_set_qdcount(ldns_pkt *packet, uint16_t qdcount)
++{
++	packet->_header->_qdcount = qdcount;
++}
++
++void
++ldns_pkt_set_ancount(ldns_pkt *packet, uint16_t ancount)
++{
++	packet->_header->_ancount = ancount;
++}
++
++void
++ldns_pkt_set_nscount(ldns_pkt *packet, uint16_t nscount)
++{
++	packet->_header->_nscount = nscount;
++}
++
++void
++ldns_pkt_set_arcount(ldns_pkt *packet, uint16_t arcount)
++{
++	packet->_header->_arcount = arcount;
++}
++
++void
++ldns_pkt_set_querytime(ldns_pkt *packet, uint32_t time) 
++{
++	packet->_querytime = time;
++}
++
++void
++ldns_pkt_set_answerfrom(ldns_pkt *packet, ldns_rdf *answerfrom)
++{
++	packet->_answerfrom = answerfrom;
++}
++
++void
++ldns_pkt_set_timestamp(ldns_pkt *packet, struct timeval timeval)
++{
++	packet->timestamp.tv_sec = timeval.tv_sec;
++	packet->timestamp.tv_usec = timeval.tv_usec;
++}
++
++void
++ldns_pkt_set_size(ldns_pkt *packet, size_t s)
++{
++	packet->_size = s;
++}
++
++void
++ldns_pkt_set_edns_udp_size(ldns_pkt *packet, uint16_t s)
++{
++	packet->_edns_udp_size = s;
++}
++
++void
++ldns_pkt_set_edns_extended_rcode(ldns_pkt *packet, uint8_t c)
++{
++	packet->_edns_extended_rcode = c;
++}
++
++void
++ldns_pkt_set_edns_version(ldns_pkt *packet, uint8_t v)
++{
++	packet->_edns_version = v;
++}
++
++void
++ldns_pkt_set_edns_z(ldns_pkt *packet, uint16_t z)
++{
++	packet->_edns_z = z;
++}
++
++void
++ldns_pkt_set_edns_data(ldns_pkt *packet, ldns_rdf *data)
++{
++	packet->_edns_data = data;
++}
++
++void
++ldns_pkt_set_section_count(ldns_pkt *packet, ldns_pkt_section s, uint16_t count)
++{
++	switch(s) {
++		case LDNS_SECTION_QUESTION:
++			ldns_pkt_set_qdcount(packet, count);
++			break;
++		case LDNS_SECTION_ANSWER:
++			ldns_pkt_set_ancount(packet, count);
++			break;
++		case LDNS_SECTION_AUTHORITY:
++			ldns_pkt_set_nscount(packet, count);
++			break;
++		case LDNS_SECTION_ADDITIONAL:
++			ldns_pkt_set_arcount(packet, count);
++			break;
++		case LDNS_SECTION_ANY:
++		case LDNS_SECTION_ANY_NOQUESTION:
++			break;
++	}
++}
++
++void ldns_pkt_set_tsig(ldns_pkt *pkt, ldns_rr *rr)
++{
++	pkt->_tsig_rr = rr;
++}
++
++bool
++ldns_pkt_push_rr(ldns_pkt *packet, ldns_pkt_section section, ldns_rr *rr)
++{
++	switch(section) {
++		case LDNS_SECTION_QUESTION:
++			if (!ldns_rr_list_push_rr(ldns_pkt_question(packet), rr)) {
++				return false;
++			}
++			ldns_pkt_set_qdcount(packet, ldns_pkt_qdcount(packet) + 1);
++			break;
++		case LDNS_SECTION_ANSWER:
++			if (!ldns_rr_list_push_rr(ldns_pkt_answer(packet), rr)) {
++				return false;
++			}
++			ldns_pkt_set_ancount(packet, ldns_pkt_ancount(packet) + 1);
++			break;
++		case LDNS_SECTION_AUTHORITY:
++			if (!ldns_rr_list_push_rr(ldns_pkt_authority(packet), rr)) {
++				return false;
++			}
++			ldns_pkt_set_nscount(packet, ldns_pkt_nscount(packet) + 1);
++			break;
++		case LDNS_SECTION_ADDITIONAL:
++			if (!ldns_rr_list_push_rr(ldns_pkt_additional(packet), rr)) {
++				return false;
++			}
++			ldns_pkt_set_arcount(packet, ldns_pkt_arcount(packet) + 1);
++			break;
++		case LDNS_SECTION_ANY:
++		case LDNS_SECTION_ANY_NOQUESTION:
++			/* shouldn't this error? */
++			break;
++	}
++	return true;
++}
++
++bool
++ldns_pkt_safe_push_rr(ldns_pkt *pkt, ldns_pkt_section sec, ldns_rr *rr)
++{
++
++	/* check to see if its there */
++	if (ldns_pkt_rr(pkt, sec, rr)) {
++		/* already there */
++		return false;
++	}
++	return ldns_pkt_push_rr(pkt, sec, rr);
++}
++
++bool
++ldns_pkt_push_rr_list(ldns_pkt *p, ldns_pkt_section s, ldns_rr_list *list)
++{
++	size_t i;
++	for(i = 0; i < ldns_rr_list_rr_count(list); i++) {
++		if (!ldns_pkt_push_rr(p, s, ldns_rr_list_rr(list, i))) {
++			return false;
++		}
++	}
++	return true;
++}
++
++bool
++ldns_pkt_safe_push_rr_list(ldns_pkt *p, ldns_pkt_section s, ldns_rr_list *list)
++{
++	size_t i;
++	for(i = 0; i < ldns_rr_list_rr_count(list); i++) {
++		if (!ldns_pkt_safe_push_rr(p, s, ldns_rr_list_rr(list, i))) {
++			return false;
++		}
++	}
++	return true;
++}
++
++bool
++ldns_pkt_edns(const ldns_pkt *pkt) {
++	return (ldns_pkt_edns_udp_size(pkt) > 0 ||
++		ldns_pkt_edns_extended_rcode(pkt) > 0 ||
++		ldns_pkt_edns_data(pkt) ||
++		ldns_pkt_edns_do(pkt) ||
++                pkt->_edns_present
++	       );
++}
++
++
++/* Create/destroy/convert functions
++ */
++ldns_pkt *
++ldns_pkt_new(void)
++{
++	ldns_pkt *packet;
++	packet = LDNS_MALLOC(ldns_pkt);
++	if (!packet) {
++		return NULL;
++	}
++
++	packet->_header = LDNS_MALLOC(ldns_hdr);
++	if (!packet->_header) {
++		LDNS_FREE(packet);
++		return NULL;
++	}
++
++	packet->_question = ldns_rr_list_new();
++	packet->_answer = ldns_rr_list_new();
++	packet->_authority = ldns_rr_list_new();
++	packet->_additional = ldns_rr_list_new();
++
++	/* default everything to false */
++	ldns_pkt_set_qr(packet, false);
++	ldns_pkt_set_aa(packet, false);
++	ldns_pkt_set_tc(packet, false);
++	ldns_pkt_set_rd(packet, false);
++	ldns_pkt_set_ra(packet, false);
++	ldns_pkt_set_ad(packet, false);
++	ldns_pkt_set_cd(packet, false);
++
++	ldns_pkt_set_opcode(packet, LDNS_PACKET_QUERY);
++	ldns_pkt_set_rcode(packet, 0);
++	ldns_pkt_set_id(packet, 0); 
++	ldns_pkt_set_size(packet, 0);
++	ldns_pkt_set_querytime(packet, 0);
++	memset(&packet->timestamp, 0, sizeof(packet->timestamp));
++	ldns_pkt_set_answerfrom(packet, NULL);
++	ldns_pkt_set_section_count(packet, LDNS_SECTION_QUESTION, 0);
++	ldns_pkt_set_section_count(packet, LDNS_SECTION_ANSWER, 0);
++	ldns_pkt_set_section_count(packet, LDNS_SECTION_AUTHORITY, 0);
++	ldns_pkt_set_section_count(packet, LDNS_SECTION_ADDITIONAL, 0);
++	
++	ldns_pkt_set_edns_udp_size(packet, 0);
++	ldns_pkt_set_edns_extended_rcode(packet, 0);
++	ldns_pkt_set_edns_version(packet, 0);
++	ldns_pkt_set_edns_z(packet, 0);
++	ldns_pkt_set_edns_data(packet, NULL);
++	packet->_edns_present = false;
++	
++	ldns_pkt_set_tsig(packet, NULL);
++	
++	return packet;
++}
++
++void
++ldns_pkt_free(ldns_pkt *packet)
++{
++	if (packet) {
++		LDNS_FREE(packet->_header);
++		ldns_rr_list_deep_free(packet->_question);
++		ldns_rr_list_deep_free(packet->_answer);
++		ldns_rr_list_deep_free(packet->_authority);
++		ldns_rr_list_deep_free(packet->_additional);
++		ldns_rr_free(packet->_tsig_rr);
++		ldns_rdf_deep_free(packet->_edns_data);
++		ldns_rdf_deep_free(packet->_answerfrom);
++		LDNS_FREE(packet);
++	}
++}
++
++bool
++ldns_pkt_set_flags(ldns_pkt *packet, uint16_t flags)
++{
++	if (!packet) {
++		return false;
++	}
++	if ((flags & LDNS_QR) == LDNS_QR) {
++		ldns_pkt_set_qr(packet, true);
++	}
++	if ((flags & LDNS_AA) == LDNS_AA) {
++		ldns_pkt_set_aa(packet, true);
++	}
++	if ((flags & LDNS_RD) == LDNS_RD) {
++		ldns_pkt_set_rd(packet, true);
++	}
++	if ((flags & LDNS_TC) == LDNS_TC) {
++		ldns_pkt_set_tc(packet, true);
++	}
++	if ((flags & LDNS_CD) == LDNS_CD) {
++		ldns_pkt_set_cd(packet, true);
++	}
++	if ((flags & LDNS_RA) == LDNS_RA) {
++		ldns_pkt_set_ra(packet, true);
++	}
++	if ((flags & LDNS_AD) == LDNS_AD) {
++		ldns_pkt_set_ad(packet, true);
++	}
++	return true;
++}
++
++
++static ldns_rr*
++ldns_pkt_authsoa(ldns_rdf* rr_name, ldns_rr_class rr_class)
++{
++	ldns_rr* soa_rr = ldns_rr_new();
++	ldns_rdf *owner_rdf;
++	ldns_rdf *mname_rdf;
++	ldns_rdf *rname_rdf;
++	ldns_rdf *serial_rdf;
++	ldns_rdf *refresh_rdf;
++	ldns_rdf *retry_rdf;
++	ldns_rdf *expire_rdf;
++	ldns_rdf *minimum_rdf;
++
++	if (!soa_rr) {
++		return NULL;
++	}
++	owner_rdf = ldns_rdf_clone(rr_name);
++	if (!owner_rdf) {
++		ldns_rr_free(soa_rr);
++		return NULL;
++	}
++
++	ldns_rr_set_owner(soa_rr, owner_rdf);
++	ldns_rr_set_type(soa_rr, LDNS_RR_TYPE_SOA);
++	ldns_rr_set_class(soa_rr, rr_class);
++	ldns_rr_set_question(soa_rr, false);
++
++	if (ldns_str2rdf_dname(&mname_rdf, ".") != LDNS_STATUS_OK) {
++		ldns_rr_free(soa_rr);
++		return NULL;
++	} else {
++		ldns_rr_push_rdf(soa_rr, mname_rdf);
++	}
++	if (ldns_str2rdf_dname(&rname_rdf, ".") != LDNS_STATUS_OK) {
++		ldns_rr_free(soa_rr);
++		return NULL;
++	} else {
++		ldns_rr_push_rdf(soa_rr, rname_rdf);
++	}
++	serial_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0);
++	if (!serial_rdf) {
++		ldns_rr_free(soa_rr);
++		return NULL;
++	} else {
++		ldns_rr_push_rdf(soa_rr, serial_rdf);
++	}
++	refresh_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0);
++	if (!refresh_rdf) {
++		ldns_rr_free(soa_rr);
++		return NULL;
++	} else {
++		ldns_rr_push_rdf(soa_rr, refresh_rdf);
++	}
++	retry_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0);
++	if (!retry_rdf) {
++		ldns_rr_free(soa_rr);
++		return NULL;
++	} else {
++		ldns_rr_push_rdf(soa_rr, retry_rdf);
++	}
++	expire_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0);
++	if (!expire_rdf) {
++		ldns_rr_free(soa_rr);
++		return NULL;
++	} else {
++		ldns_rr_push_rdf(soa_rr, expire_rdf);
++	}
++	minimum_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0);
++	if (!minimum_rdf) {
++		ldns_rr_free(soa_rr);
++		return NULL;
++	} else {
++		ldns_rr_push_rdf(soa_rr, minimum_rdf);
++	}
++	return soa_rr;
++}
++
++
++static ldns_status
++ldns_pkt_query_new_frm_str_internal(ldns_pkt **p, const char *name,
++	ldns_rr_type rr_type, ldns_rr_class rr_class, uint16_t flags,
++	ldns_rr* authsoa_rr)
++{
++	ldns_pkt *packet;
++	ldns_rr *question_rr;
++	ldns_rdf *name_rdf;
++
++	packet = ldns_pkt_new();
++	if (!packet) {
++		return LDNS_STATUS_MEM_ERR;
++	}
++
++	if (!ldns_pkt_set_flags(packet, flags)) {
++		return LDNS_STATUS_ERR;
++	}
++
++	question_rr = ldns_rr_new();
++	if (!question_rr) {
++		return LDNS_STATUS_MEM_ERR;
++	}
++
++	if (rr_type == 0) {
++		rr_type = LDNS_RR_TYPE_A;
++	}
++	if (rr_class == 0) {
++		rr_class = LDNS_RR_CLASS_IN;
++	}
++
++	if (ldns_str2rdf_dname(&name_rdf, name) == LDNS_STATUS_OK) {
++		ldns_rr_set_owner(question_rr, name_rdf);
++		ldns_rr_set_type(question_rr, rr_type);
++		ldns_rr_set_class(question_rr, rr_class);
++                ldns_rr_set_question(question_rr, true);
++
++		ldns_pkt_push_rr(packet, LDNS_SECTION_QUESTION, question_rr);
++	} else {
++		ldns_rr_free(question_rr);
++		ldns_pkt_free(packet);
++		return LDNS_STATUS_ERR;
++	}
++
++	if (authsoa_rr) {
++		ldns_pkt_push_rr(packet, LDNS_SECTION_AUTHORITY, authsoa_rr);
++	}
++
++	packet->_tsig_rr = NULL;
++	ldns_pkt_set_answerfrom(packet, NULL);
++	if (p) {
++		*p = packet;
++		return LDNS_STATUS_OK;
++	} else {
++		ldns_pkt_free(packet);
++		return LDNS_STATUS_NULL;
++	}
++}
++
++ldns_status
++ldns_pkt_query_new_frm_str(ldns_pkt **p, const char *name,
++	ldns_rr_type rr_type, ldns_rr_class rr_class, uint16_t flags)
++{
++	return ldns_pkt_query_new_frm_str_internal(p, name, rr_type,
++		rr_class, flags, NULL);
++}
++
++ldns_status
++ldns_pkt_ixfr_request_new_frm_str(ldns_pkt **p, const char *name,
++	ldns_rr_class rr_class, uint16_t flags, ldns_rr *soa)
++{
++	ldns_rr* authsoa_rr = soa;
++	if (!authsoa_rr) {
++		ldns_rdf *name_rdf;
++		if (ldns_str2rdf_dname(&name_rdf, name) == LDNS_STATUS_OK) {
++			authsoa_rr = ldns_pkt_authsoa(name_rdf, rr_class);
++		}
++		ldns_rdf_free(name_rdf);
++	}
++	return ldns_pkt_query_new_frm_str_internal(p, name, LDNS_RR_TYPE_IXFR,
++		rr_class, flags, authsoa_rr);
++}
++
++static ldns_pkt *
++ldns_pkt_query_new_internal(ldns_rdf *rr_name, ldns_rr_type rr_type,
++	ldns_rr_class rr_class,	uint16_t flags, ldns_rr* authsoa_rr)
++{
++	ldns_pkt *packet;
++	ldns_rr *question_rr;
++
++	packet = ldns_pkt_new();
++	if (!packet) {
++		return NULL;
++	}
++
++	if (!ldns_pkt_set_flags(packet, flags)) {
++		return NULL;
++	}
++
++	question_rr = ldns_rr_new();
++	if (!question_rr) {
++		ldns_pkt_free(packet);
++		return NULL;
++	}
++
++	if (rr_type == 0) {
++		rr_type = LDNS_RR_TYPE_A;
++	}
++	if (rr_class == 0) {
++		rr_class = LDNS_RR_CLASS_IN;
++	}
++
++	ldns_rr_set_owner(question_rr, rr_name);
++	ldns_rr_set_type(question_rr, rr_type);
++	ldns_rr_set_class(question_rr, rr_class);
++        ldns_rr_set_question(question_rr, true);
++	ldns_pkt_push_rr(packet, LDNS_SECTION_QUESTION, question_rr);
++
++	if (authsoa_rr) {
++		ldns_pkt_push_rr(packet, LDNS_SECTION_AUTHORITY, authsoa_rr);
++	}
++
++	packet->_tsig_rr = NULL;
++	return packet;
++}
++
++ldns_pkt *
++ldns_pkt_query_new(ldns_rdf *rr_name, ldns_rr_type rr_type,
++	ldns_rr_class rr_class,	uint16_t flags)
++{
++	return ldns_pkt_query_new_internal(rr_name, rr_type,
++		rr_class, flags, NULL);
++}
++
++ldns_pkt *
++ldns_pkt_ixfr_request_new(ldns_rdf *rr_name, ldns_rr_class rr_class,
++	uint16_t flags, ldns_rr* soa)
++{
++	ldns_rr* authsoa_rr = soa;
++	if (!authsoa_rr) {
++		authsoa_rr = ldns_pkt_authsoa(rr_name, rr_class);
++	}
++	return ldns_pkt_query_new_internal(rr_name, LDNS_RR_TYPE_IXFR,
++		rr_class, flags, authsoa_rr);
++}
++
++ldns_pkt_type
++ldns_pkt_reply_type(ldns_pkt *p)
++{
++	ldns_rr_list *tmp;
++
++	if (!p) {
++		return LDNS_PACKET_UNKNOWN;
++	}
++
++	if (ldns_pkt_get_rcode(p) == LDNS_RCODE_NXDOMAIN) {
++		return LDNS_PACKET_NXDOMAIN;
++	}
++
++	if (ldns_pkt_ancount(p) == 0 && ldns_pkt_arcount(p) == 0
++			&& ldns_pkt_nscount(p) == 1) {
++
++		/* check for SOA */
++		tmp = ldns_pkt_rr_list_by_type(p, LDNS_RR_TYPE_SOA, 
++					LDNS_SECTION_AUTHORITY);
++		if (tmp) {
++			ldns_rr_list_deep_free(tmp);
++			return LDNS_PACKET_NODATA;
++		} else {
++			/* I have no idea ... */
++		}
++	}
++
++	if (ldns_pkt_ancount(p) == 0 && ldns_pkt_nscount(p) > 0) {
++		tmp = ldns_pkt_rr_list_by_type(p, LDNS_RR_TYPE_NS,
++		                               LDNS_SECTION_AUTHORITY);
++		if (tmp) {
++			/* there are nameservers here */
++			ldns_rr_list_deep_free(tmp);
++			return LDNS_PACKET_REFERRAL;
++		} else {
++			/* I have no idea */
++		}
++		ldns_rr_list_deep_free(tmp);
++	}
++	
++	/* if we cannot determine the packet type, we say it's an 
++	 * answer...
++	 */
++	return LDNS_PACKET_ANSWER;
++}
++
++ldns_pkt *
++ldns_pkt_clone(const ldns_pkt *pkt)
++{
++	ldns_pkt *new_pkt;
++	
++	if (!pkt) {
++		return NULL;
++	}
++	new_pkt = ldns_pkt_new();
++
++	ldns_pkt_set_id(new_pkt, ldns_pkt_id(pkt));
++	ldns_pkt_set_qr(new_pkt, ldns_pkt_qr(pkt));
++	ldns_pkt_set_aa(new_pkt, ldns_pkt_aa(pkt));
++	ldns_pkt_set_tc(new_pkt, ldns_pkt_tc(pkt));
++	ldns_pkt_set_rd(new_pkt, ldns_pkt_rd(pkt));
++	ldns_pkt_set_cd(new_pkt, ldns_pkt_cd(pkt));
++	ldns_pkt_set_ra(new_pkt, ldns_pkt_ra(pkt));
++	ldns_pkt_set_ad(new_pkt, ldns_pkt_ad(pkt));
++	ldns_pkt_set_opcode(new_pkt, ldns_pkt_get_opcode(pkt));
++	ldns_pkt_set_rcode(new_pkt, ldns_pkt_get_rcode(pkt));
++	ldns_pkt_set_qdcount(new_pkt, ldns_pkt_qdcount(pkt));
++	ldns_pkt_set_ancount(new_pkt, ldns_pkt_ancount(pkt));
++	ldns_pkt_set_nscount(new_pkt, ldns_pkt_nscount(pkt));
++	ldns_pkt_set_arcount(new_pkt, ldns_pkt_arcount(pkt));
++	if (ldns_pkt_answerfrom(pkt))
++		ldns_pkt_set_answerfrom(new_pkt,
++			ldns_rdf_clone(ldns_pkt_answerfrom(pkt)));
++	ldns_pkt_set_timestamp(new_pkt, ldns_pkt_timestamp(pkt));
++	ldns_pkt_set_querytime(new_pkt, ldns_pkt_querytime(pkt));
++	ldns_pkt_set_size(new_pkt, ldns_pkt_size(pkt));
++	ldns_pkt_set_tsig(new_pkt, ldns_rr_clone(ldns_pkt_tsig(pkt)));
++	
++	ldns_pkt_set_edns_udp_size(new_pkt, ldns_pkt_edns_udp_size(pkt));
++	ldns_pkt_set_edns_extended_rcode(new_pkt, 
++		ldns_pkt_edns_extended_rcode(pkt));
++	ldns_pkt_set_edns_version(new_pkt, ldns_pkt_edns_version(pkt));
++	new_pkt->_edns_present = pkt->_edns_present;
++	ldns_pkt_set_edns_z(new_pkt, ldns_pkt_edns_z(pkt));
++	if(ldns_pkt_edns_data(pkt))
++		ldns_pkt_set_edns_data(new_pkt, 
++			ldns_rdf_clone(ldns_pkt_edns_data(pkt)));
++	ldns_pkt_set_edns_do(new_pkt, ldns_pkt_edns_do(pkt));
++
++	ldns_rr_list_deep_free(new_pkt->_question);
++	ldns_rr_list_deep_free(new_pkt->_answer);
++	ldns_rr_list_deep_free(new_pkt->_authority);
++	ldns_rr_list_deep_free(new_pkt->_additional);
++	new_pkt->_question = ldns_rr_list_clone(ldns_pkt_question(pkt));
++	new_pkt->_answer = ldns_rr_list_clone(ldns_pkt_answer(pkt));
++	new_pkt->_authority = ldns_rr_list_clone(ldns_pkt_authority(pkt));
++	new_pkt->_additional = ldns_rr_list_clone(ldns_pkt_additional(pkt));
++	return new_pkt;
++}
+diff --git a/ldns/src/parse.c b/ldns/src/parse.c
+new file mode 100644
+index 0000000..e68627c
+--- /dev/null
++++ b/ldns/src/parse.c
+@@ -0,0 +1,434 @@
++/*
++ * a generic (simple) parser. Use to parse rr's, private key
++ * information and /etc/resolv.conf files
++ *
++ * a Net::DNS like library for C
++ * LibDNS Team @ NLnet Labs
++ * (c) NLnet Labs, 2005-2006
++ * See the file LICENSE for the license
++ */
++#include <ldns/config.h>
++#include <ldns/ldns.h>
++
++#include <limits.h>
++#include <strings.h>
++
++ldns_lookup_table ldns_directive_types[] = {
++        { LDNS_DIR_TTL, "$TTL" },
++        { LDNS_DIR_ORIGIN, "$ORIGIN" },
++        { LDNS_DIR_INCLUDE, "$INCLUDE" },
++        { 0, NULL }
++};
++
++/* add max_limit here? */
++ssize_t
++ldns_fget_token(FILE *f, char *token, const char *delim, size_t limit)
++{
++	return ldns_fget_token_l(f, token, delim, limit, NULL);
++}
++
++ssize_t
++ldns_fget_token_l(FILE *f, char *token, const char *delim, size_t limit, int *line_nr)
++{
++	int c, prev_c;
++	int p; /* 0 -> no parenthese seen, >0 nr of ( seen */
++	int com, quoted;
++	char *t;
++	size_t i;
++	const char *d;
++	const char *del;
++
++	/* standard delimeters */
++	if (!delim) {
++		/* from isspace(3) */
++		del = LDNS_PARSE_NORMAL;
++	} else {
++		del = delim;
++	}
++
++	p = 0;
++	i = 0;
++	com = 0;
++	quoted = 0;
++	prev_c = 0;
++	t = token;
++	if (del[0] == '"') {
++		quoted = 1;
++	}
++	while ((c = getc(f)) != EOF) {
++		if (c == '\r') /* carriage return */
++			c = ' ';
++		if (c == '(' && prev_c != '\\' && !quoted) {
++			/* this only counts for non-comments */
++			if (com == 0) {
++				p++;
++			}
++			prev_c = c;
++			continue;
++		}
++
++		if (c == ')' && prev_c != '\\' && !quoted) {
++			/* this only counts for non-comments */
++			if (com == 0) {
++				p--;
++			}
++			prev_c = c;
++			continue;
++		}
++
++		if (p < 0) {
++			/* more ) then ( - close off the string */
++			*t = '\0';
++			return 0;
++		}
++
++		/* do something with comments ; */
++		if (c == ';' && quoted == 0) {
++			if (prev_c != '\\') {
++				com = 1;
++			}
++		}
++		if (c == '\"' && com == 0 && prev_c != '\\') {
++			quoted = 1 - quoted;
++		}
++
++		if (c == '\n' && com != 0) {
++			/* comments */
++			com = 0;
++			*t = ' ';
++			if (line_nr) {
++				*line_nr = *line_nr + 1;
++			}
++			if (p == 0 && i > 0) {
++				goto tokenread;
++			} else {
++				prev_c = c;
++				continue;
++			}
++		}
++
++		if (com == 1) {
++			*t = ' ';
++			prev_c = c;
++			continue;
++		}
++
++		if (c == '\n' && p != 0 && t > token) {
++			/* in parentheses */
++			if (line_nr) {
++				*line_nr = *line_nr + 1;
++			}
++			*t++ = ' ';
++			prev_c = c;
++			continue;
++		}
++
++		/* check if we hit the delim */
++		for (d = del; *d; d++) {
++			if (c == *d && i > 0 && prev_c != '\\' && p == 0) {
++				if (c == '\n' && line_nr) {
++					*line_nr = *line_nr + 1;
++				}
++				goto tokenread;
++			}
++		}
++		if (c != '\0' && c != '\n') {
++			i++;
++		}
++		if (limit > 0 && (i >= limit || (size_t)(t-token) >= limit)) {
++			*t = '\0';
++			return -1;
++		}
++		if (c != '\0' && c != '\n') {
++			*t++ = c;
++		}
++		if (c == '\\' && prev_c == '\\')
++			prev_c = 0;
++		else	prev_c = c;
++	}
++	*t = '\0';
++	if (c == EOF) {
++		return (ssize_t)i;
++	}
++
++	if (i == 0) {
++		/* nothing read */
++		return -1;
++	}
++	if (p != 0) {
++		return -1;
++	}
++	return (ssize_t)i;
++
++tokenread:
++	if(*del == '"') /* do not skip over quotes, they are significant */
++		ldns_fskipcs_l(f, del+1, line_nr);
++	else	ldns_fskipcs_l(f, del, line_nr);
++	*t = '\0';
++	if (p != 0) {
++		return -1;
++	}
++
++	return (ssize_t)i;
++}
++
++ssize_t
++ldns_fget_keyword_data(FILE *f, const char *keyword, const char *k_del, char *data,
++               const char *d_del, size_t data_limit)
++{
++       return ldns_fget_keyword_data_l(f, keyword, k_del, data, d_del,
++		       data_limit, NULL);
++}
++
++ssize_t
++ldns_fget_keyword_data_l(FILE *f, const char *keyword, const char *k_del, char *data,
++               const char *d_del, size_t data_limit, int *line_nr)
++{
++       /* we assume: keyword|sep|data */
++       char *fkeyword;
++       ssize_t i;
++
++       if(strlen(keyword) >= LDNS_MAX_KEYWORDLEN)
++               return -1;
++       fkeyword = LDNS_XMALLOC(char, LDNS_MAX_KEYWORDLEN);
++       if(!fkeyword)
++               return -1;
++
++       i = ldns_fget_token(f, fkeyword, k_del, LDNS_MAX_KEYWORDLEN);
++       if(i==0 || i==-1) {
++               LDNS_FREE(fkeyword);
++               return -1;
++       }
++
++       /* case??? i instead of strlen? */
++       if (strncmp(fkeyword, keyword, LDNS_MAX_KEYWORDLEN - 1) == 0) {
++               /* whee! */
++               /* printf("%s\n%s\n", "Matching keyword", fkeyword); */
++               i = ldns_fget_token_l(f, data, d_del, data_limit, line_nr);
++               LDNS_FREE(fkeyword);
++               return i;
++       } else {
++               /*printf("no match for %s (read: %s)\n", keyword, fkeyword);*/
++               LDNS_FREE(fkeyword);
++               return -1;
++       }
++}
++
++
++ssize_t
++ldns_bget_token(ldns_buffer *b, char *token, const char *delim, size_t limit)
++{
++	int c, lc;
++	int p; /* 0 -> no parenthese seen, >0 nr of ( seen */
++	int com, quoted;
++	char *t;
++	size_t i;
++	const char *d;
++	const char *del;
++
++	/* standard delimiters */
++	if (!delim) {
++		/* from isspace(3) */
++		del = LDNS_PARSE_NORMAL;
++	} else {
++		del = delim;
++	}
++
++	p = 0;
++	i = 0;
++	com = 0;
++	quoted = 0;
++	t = token;
++	lc = 0;
++	if (del[0] == '"') {
++		quoted = 1;
++	}
++
++	while ((c = ldns_bgetc(b)) != EOF) {
++		if (c == '\r') /* carriage return */
++			c = ' ';
++		if (c == '(' && lc != '\\' && !quoted) {
++			/* this only counts for non-comments */
++			if (com == 0) {
++				p++;
++			}
++			lc = c;
++			continue;
++		}
++
++		if (c == ')' && lc != '\\' && !quoted) {
++			/* this only counts for non-comments */
++			if (com == 0) {
++				p--;
++			}
++			lc = c;
++			continue;
++		}
++
++		if (p < 0) {
++			/* more ) then ( */
++			*t = '\0';
++			return 0;
++		}
++
++		/* do something with comments ; */
++		if (c == ';' && quoted == 0) {
++			if (lc != '\\') {
++				com = 1;
++			}
++		}
++		if (c == '"' && com == 0 && lc != '\\') {
++			quoted = 1 - quoted;
++		}
++
++		if (c == '\n' && com != 0) {
++			/* comments */
++			com = 0;
++			*t = ' ';
++			lc = c;
++			continue;
++		}
++
++		if (com == 1) {
++			*t = ' ';
++			lc = c;
++			continue;
++		}
++
++		if (c == '\n' && p != 0) {
++			/* in parentheses */
++			*t++ = ' ';
++			lc = c;
++			continue;
++		}
++
++		/* check if we hit the delim */
++		for (d = del; *d; d++) {
++                        if (c == *d && lc != '\\' && p == 0) {
++				goto tokenread;
++                        }
++		}
++
++		i++;
++		if (limit > 0 && (i >= limit || (size_t)(t-token) >= limit)) {
++			*t = '\0';
++			return -1;
++		}
++		*t++ = c;
++
++		if (c == '\\' && lc == '\\') {
++			lc = 0;
++		} else {
++			lc = c;
++		}
++	}
++	*t = '\0';
++	if (i == 0) {
++		/* nothing read */
++		return -1;
++	}
++	if (p != 0) {
++		return -1;
++	}
++	return (ssize_t)i;
++
++tokenread:
++	if(*del == '"') /* do not skip over quotes, they are significant */
++		ldns_bskipcs(b, del+1);
++	else	ldns_bskipcs(b, del);
++	*t = '\0';
++
++	if (p != 0) {
++		return -1;
++	}
++	return (ssize_t)i;
++}
++
++
++void
++ldns_bskipcs(ldns_buffer *buffer, const char *s)
++{
++        bool found;
++        char c;
++        const char *d;
++
++        while(ldns_buffer_available_at(buffer, buffer->_position, sizeof(char))) {
++                c = (char) ldns_buffer_read_u8_at(buffer, buffer->_position);
++                found = false;
++                for (d = s; *d; d++) {
++                        if (*d == c) {
++                                found = true;
++                        }
++                }
++                if (found && buffer->_limit > buffer->_position) {
++                        buffer->_position += sizeof(char);
++                } else {
++                        return;
++                }
++        }
++}
++
++void
++ldns_fskipcs(FILE *fp, const char *s)
++{
++	ldns_fskipcs_l(fp, s, NULL);
++}
++
++void
++ldns_fskipcs_l(FILE *fp, const char *s, int *line_nr)
++{
++        bool found;
++        int c;
++        const char *d;
++
++	while ((c = fgetc(fp)) != EOF) {
++		if (line_nr && c == '\n') {
++			*line_nr = *line_nr + 1;
++		}
++                found = false;
++                for (d = s; *d; d++) {
++                        if (*d == c) {
++                                found = true;
++                        }
++                }
++		if (!found) {
++			/* with getc, we've read too far */
++			ungetc(c, fp);
++			return;
++		}
++	}
++}
++
++ssize_t
++ldns_bget_keyword_data(ldns_buffer *b, const char *keyword, const char *k_del, char
++*data, const char *d_del, size_t data_limit)
++{
++       /* we assume: keyword|sep|data */
++       char *fkeyword;
++       ssize_t i;
++
++       if(strlen(keyword) >= LDNS_MAX_KEYWORDLEN)
++               return -1;
++       fkeyword = LDNS_XMALLOC(char, LDNS_MAX_KEYWORDLEN);
++       if(!fkeyword)
++               return -1; /* out of memory */
++
++       i = ldns_bget_token(b, fkeyword, k_del, data_limit);
++       if(i==0 || i==-1) {
++               LDNS_FREE(fkeyword);
++               return -1; /* nothing read */
++       }
++
++       /* case??? */
++       if (strncmp(fkeyword, keyword, strlen(keyword)) == 0) {
++               LDNS_FREE(fkeyword);
++               /* whee, the match! */
++               /* retrieve it's data */
++               i = ldns_bget_token(b, data, d_del, 0);
++               return i;
++       } else {
++               LDNS_FREE(fkeyword);
++               return -1;
++       }
++}
++
+diff --git a/ldns/src/radix.c b/ldns/src/radix.c
+new file mode 100644
+index 0000000..7aac258
+--- /dev/null
++++ b/ldns/src/radix.c
+@@ -0,0 +1,1590 @@
++/*
++ * radix.c -- generic radix tree
++ *
++ * Taken from NSD4, modified for ldns
++ *
++ * Copyright (c) 2012, NLnet Labs. All rights reserved.
++ *
++ * This software is open source.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright notice,
++ * this list of conditions and the following disclaimer in the documentation
++ * and/or other materials provided with the distribution.
++ *
++ * Neither the name of the NLNET LABS nor the names of its contributors may
++ * be used to endorse or promote products derived from this software without
++ * specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
++ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
++ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
++ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
++ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ *
++ */
++
++/**
++ * \file
++ * Implementation of a radix tree.
++ */
++
++#include <ldns/config.h>
++#include <ldns/radix.h>
++#include <ldns/util.h>
++#include <stdlib.h>
++
++/** Helper functions */
++static ldns_radix_node_t* ldns_radix_new_node(void* data, uint8_t* key,
++	radix_strlen_t len);
++static int ldns_radix_find_prefix(ldns_radix_t* tree, uint8_t* key,
++	radix_strlen_t len, ldns_radix_node_t** result, radix_strlen_t* pos);
++static int ldns_radix_array_space(ldns_radix_node_t* node, uint8_t byte);
++static int ldns_radix_array_grow(ldns_radix_node_t* node, unsigned need);
++static int ldns_radix_str_create(ldns_radix_array_t* array, uint8_t* key,
++	radix_strlen_t pos, radix_strlen_t len);
++static int ldns_radix_prefix_remainder(radix_strlen_t prefix_len,
++	uint8_t* longer_str, radix_strlen_t longer_len, uint8_t** split_str,
++	radix_strlen_t* split_len);
++static int ldns_radix_array_split(ldns_radix_array_t* array, uint8_t* key,
++	radix_strlen_t pos, radix_strlen_t len, ldns_radix_node_t* add);
++static int ldns_radix_str_is_prefix(uint8_t* str1, radix_strlen_t len1,
++	uint8_t* str2, radix_strlen_t len2);
++static radix_strlen_t ldns_radix_str_common(uint8_t* str1, radix_strlen_t len1,
++	uint8_t* str2, radix_strlen_t len2);
++static ldns_radix_node_t* ldns_radix_next_in_subtree(ldns_radix_node_t* node);
++static ldns_radix_node_t* ldns_radix_prev_from_index(ldns_radix_node_t* node,
++	uint8_t index);
++static ldns_radix_node_t* ldns_radix_last_in_subtree_incl_self(
++	ldns_radix_node_t* node);
++static ldns_radix_node_t* ldns_radix_last_in_subtree(ldns_radix_node_t* node);
++static void ldns_radix_del_fix(ldns_radix_t* tree, ldns_radix_node_t* node);
++static void ldns_radix_cleanup_onechild(ldns_radix_node_t* node);
++static void ldns_radix_cleanup_leaf(ldns_radix_node_t* node);
++static void ldns_radix_node_free(ldns_radix_node_t* node, void* arg);
++static void ldns_radix_node_array_free(ldns_radix_node_t* node);
++static void ldns_radix_node_array_free_front(ldns_radix_node_t* node);
++static void ldns_radix_node_array_free_end(ldns_radix_node_t* node);
++static void ldns_radix_array_reduce(ldns_radix_node_t* node);
++static void ldns_radix_self_or_prev(ldns_radix_node_t* node,
++	ldns_radix_node_t** result);
++
++
++/**
++ * Create a new radix node.
++ *
++ */
++static ldns_radix_node_t*
++ldns_radix_new_node(void* data, uint8_t* key, radix_strlen_t len)
++{
++	ldns_radix_node_t* node = LDNS_MALLOC(ldns_radix_node_t);
++	if (!node) {
++		return NULL;
++	}
++	node->data = data;
++	node->key = key;
++	node->klen = len;
++	node->parent = NULL;
++	node->parent_index = 0;
++	node->len = 0;
++	node->offset = 0;
++	node->capacity = 0;
++	node->array = NULL;
++	return node;
++}
++
++
++/**
++ * Create a new radix tree.
++ *
++ */
++ldns_radix_t *
++ldns_radix_create(void)
++{
++	ldns_radix_t* tree;
++
++	/** Allocate memory for it */
++	tree = (ldns_radix_t *) LDNS_MALLOC(ldns_radix_t);
++	if (!tree) {
++		return NULL;
++	}
++	/** Initialize it */
++	ldns_radix_init(tree);
++	return tree;
++}
++
++
++/**
++ * Initialize radix tree.
++ *
++ */
++void
++ldns_radix_init(ldns_radix_t* tree)
++{
++	/** Initialize it */
++	if (tree) {
++		tree->root = NULL;
++		tree->count = 0;
++	}
++	return;
++}
++
++
++/**
++ * Free radix tree.
++ *
++ */
++void
++ldns_radix_free(ldns_radix_t* tree)
++{
++	if (tree) {
++		if (tree->root) {
++			ldns_radix_traverse_postorder(tree->root,
++				ldns_radix_node_free, NULL);
++		}
++		LDNS_FREE(tree);
++	}
++	return;
++}
++
++
++/**
++ * Insert data into the tree.
++ *
++ */
++ldns_status
++ldns_radix_insert(ldns_radix_t* tree, uint8_t* key, radix_strlen_t len,
++	void* data)
++{
++	radix_strlen_t pos = 0;
++	ldns_radix_node_t* add = NULL;
++	ldns_radix_node_t* prefix = NULL;
++
++	if (!tree || !key || !data) {
++		return LDNS_STATUS_NULL;
++	}
++	add = ldns_radix_new_node(data, key, len);
++	if (!add) {
++		return LDNS_STATUS_MEM_ERR;
++	}
++	/** Search the trie until we can make no further process. */
++	if (!ldns_radix_find_prefix(tree, key, len, &prefix, &pos)) {
++		/** No prefix found */
++		assert(tree->root == NULL);
++		if (len == 0) {
++			/**
++			 * Example 1: The root:
++			 * | [0]
++			 **/
++			tree->root = add;
++		} else {
++			/** Example 2: 'dns':
++			 * | [0]
++			 * --| [d+ns] dns
++			 **/
++			prefix = ldns_radix_new_node(NULL, (uint8_t*)"", 0);
++			if (!prefix) {
++				LDNS_FREE(add);
++				return LDNS_STATUS_MEM_ERR;
++			}
++			/** Find some space in the array for the first byte */
++			if (!ldns_radix_array_space(prefix, key[0])) {
++				LDNS_FREE(add);
++				LDNS_FREE(prefix->array);
++				LDNS_FREE(prefix);
++				return LDNS_STATUS_MEM_ERR;
++			}
++			/** Set relational pointers */
++			add->parent = prefix;
++			add->parent_index = 0;
++			prefix->array[0].edge = add;
++			if (len > 1) {
++				/** Store the remainder of the prefix */
++				if (!ldns_radix_prefix_remainder(1, key,
++					len, &prefix->array[0].str,
++					&prefix->array[0].len)) {
++					LDNS_FREE(add);
++					LDNS_FREE(prefix->array);
++					LDNS_FREE(prefix);
++					return LDNS_STATUS_MEM_ERR;
++				}
++			}
++			tree->root = prefix;
++		}
++	} else if (pos == len) {
++		/** Exact match found */
++		if (prefix->data) {
++			/* Element already exists */
++			LDNS_FREE(add);
++			return LDNS_STATUS_EXISTS_ERR;
++		}
++		prefix->data = data;
++		prefix->key = key;
++		prefix->klen = len; /* redundant */
++	} else {
++		/** Prefix found */
++		uint8_t byte = key[pos];
++		assert(pos < len);
++		if (byte < prefix->offset ||
++			(byte - prefix->offset) >= prefix->len) {
++			/** Find some space in the array for the byte. */
++			/**
++			 * Example 3: 'ldns'
++			 * | [0]
++			 * --| [d+ns] dns
++			 * --| [l+dns] ldns
++			 **/
++			if (!ldns_radix_array_space(prefix, byte)) {
++				LDNS_FREE(add);
++				return LDNS_STATUS_MEM_ERR;
++			}
++			assert(byte >= prefix->offset);
++			assert((byte - prefix->offset) <= prefix->len);
++			byte -= prefix->offset;
++			if (pos+1 < len) {
++				/** Create remainder of the string. */
++				if (!ldns_radix_str_create(
++					&prefix->array[byte], key, pos+1,
++					len)) {
++					LDNS_FREE(add);
++					return LDNS_STATUS_MEM_ERR;
++				}
++			}
++			/** Add new node. */
++			add->parent = prefix;
++			add->parent_index = byte;
++			prefix->array[byte].edge = add;
++		} else if (prefix->array[byte-prefix->offset].edge == NULL) {
++			/** Use existing element. */
++			/**
++			 * Example 4: 'edns'
++			 * | [0]
++			 * --| [d+ns] dns
++			 * --| [e+dns] edns
++			 * --| [l+dns] ldns
++			 **/
++			byte -= prefix->offset;
++			if (pos+1 < len) {
++				/** Create remainder of the string. */
++				if (!ldns_radix_str_create(
++					&prefix->array[byte], key, pos+1,
++					len)) {
++					LDNS_FREE(add);
++					return LDNS_STATUS_MEM_ERR;
++				}
++			}
++			/** Add new node. */
++			add->parent = prefix;
++			add->parent_index = byte;
++			prefix->array[byte].edge = add;
++		} else {
++			/**
++			 * Use existing element, but it has a shared prefix,
++			 * we need a split.
++			 */
++			if (!ldns_radix_array_split(&prefix->array[byte-(prefix->offset)],
++				key, pos+1, len, add)) {
++				LDNS_FREE(add);
++				return LDNS_STATUS_MEM_ERR;
++			}
++		}
++	}
++
++	tree->count ++;
++	return LDNS_STATUS_OK;
++}
++
++
++/**
++ * Delete data from the tree.
++ *
++ */
++void* ldns_radix_delete(ldns_radix_t* tree, uint8_t* key, radix_strlen_t len)
++{
++    ldns_radix_node_t* del = ldns_radix_search(tree, key, len);
++    void* data = NULL;
++    if (del) {
++        tree->count--;
++        data = del->data;
++        del->data = NULL;
++        ldns_radix_del_fix(tree, del);
++        return data;
++    }
++    return NULL;
++}
++
++
++/**
++ * Search data in the tree.
++ *
++ */
++ldns_radix_node_t*
++ldns_radix_search(ldns_radix_t* tree, uint8_t* key, radix_strlen_t len)
++{
++	ldns_radix_node_t* node = NULL;
++	radix_strlen_t pos = 0;
++	uint8_t byte = 0;
++
++	if (!tree || !key) {
++		return NULL;
++	}
++	node = tree->root;
++	while (node) {
++		if (pos == len) {
++			return node->data?node:NULL;
++		}
++		byte = key[pos];
++		if (byte < node->offset) {
++			return NULL;
++		}
++		byte -= node->offset;
++		if (byte >= node->len) {
++			return NULL;
++		}
++		pos++;
++		if (node->array[byte].len > 0) {
++			/** Must match additional string. */
++			if (pos + node->array[byte].len > len) {
++				return NULL;
++			}
++			if (memcmp(&key[pos], node->array[byte].str,
++				node->array[byte].len) != 0) {
++				return NULL;
++			}
++			pos += node->array[byte].len;
++		}
++		node = node->array[byte].edge;
++	}
++	return NULL;
++}
++
++
++/**
++ * Search data in the tree, and if not found, find the closest smaller
++ * element in the tree.
++ *
++ */
++int
++ldns_radix_find_less_equal(ldns_radix_t* tree, uint8_t* key,
++	radix_strlen_t len, ldns_radix_node_t** result)
++{
++	ldns_radix_node_t* node = NULL;
++	radix_strlen_t pos = 0;
++	uint8_t byte;
++	int memcmp_res = 0;
++
++	if (!tree || !tree->root || !key) {
++		*result = NULL;
++		return 0;
++	}
++
++	node = tree->root;
++	while (pos < len) {
++		byte = key[pos];
++		if (byte < node->offset) {
++			/**
++			 * No exact match. The lesser is in this or the
++			 * previous node.
++			 */
++			ldns_radix_self_or_prev(node, result);
++			return 0;
++		}
++		byte -= node->offset;
++		if (byte >= node->len) {
++			/**
++			 * No exact match. The lesser is in this node or the
++			 * last of this array, or something before this node.
++			 */
++			*result = ldns_radix_last_in_subtree_incl_self(node);
++			if (*result == NULL) {
++				*result = ldns_radix_prev(node);
++			}
++			return 0;
++		}
++		pos++;
++		if (!node->array[byte].edge) {
++			/**
++			 * No exact match. Find the previous in the array
++			 * from this index.
++			 */
++			*result = ldns_radix_prev_from_index(node, byte);
++			if (*result == NULL) {
++				ldns_radix_self_or_prev(node, result);
++			}
++			return 0;
++		}
++		if (node->array[byte].len != 0) {
++			/** Must match additional string. */
++			if (pos + node->array[byte].len > len) {
++				/** Additional string is longer than key. */
++				if (memcmp(&key[pos], node->array[byte].str,
++					len-pos) <= 0) {
++					/** Key is before this node. */
++					*result = ldns_radix_prev(
++						node->array[byte].edge);
++				} else {
++					/** Key is after additional string. */
++					*result = ldns_radix_last_in_subtree_incl_self(node->array[byte].edge);
++					if (*result == NULL) {
++						 *result = ldns_radix_prev(node->array[byte].edge);
++					}
++				}
++				return 0;
++			}
++			memcmp_res = memcmp(&key[pos], node->array[byte].str,
++				node->array[byte].len);
++			if (memcmp_res < 0) {
++				*result = ldns_radix_prev(
++					node->array[byte].edge);
++				return 0;
++			} else if (memcmp_res > 0) {
++				*result = ldns_radix_last_in_subtree_incl_self(node->array[byte].edge);
++				if (*result == NULL) {
++					 *result = ldns_radix_prev(node->array[byte].edge);
++				}
++				return 0;
++			}
++
++			pos += node->array[byte].len;
++		}
++		node = node->array[byte].edge;
++	}
++	if (node->data) {
++		/** Exact match. */
++		*result = node;
++		return 1;
++	}
++	/** There is a node which is an exact match, but has no element. */
++	*result = ldns_radix_prev(node);
++	return 0;
++}
++
++
++/**
++ * Get the first element in the tree.
++ *
++ */
++ldns_radix_node_t*
++ldns_radix_first(ldns_radix_t* tree)
++{
++	ldns_radix_node_t* first = NULL;
++	if (!tree || !tree->root) {
++		return NULL;
++	}
++	first = tree->root;
++	if (first->data) {
++		return first;
++	}
++	return ldns_radix_next(first);
++}
++
++
++/**
++ * Get the last element in the tree.
++ *
++ */
++ldns_radix_node_t*
++ldns_radix_last(ldns_radix_t* tree)
++{
++	if (!tree || !tree->root) {
++		return NULL;
++	}
++	return ldns_radix_last_in_subtree_incl_self(tree->root);
++}
++
++
++/**
++ * Next element.
++ *
++ */
++ldns_radix_node_t*
++ldns_radix_next(ldns_radix_node_t* node)
++{
++	if (!node) {
++		return NULL;
++	}
++	if (node->len) {
++		/** Go down: most-left child is the next. */
++		ldns_radix_node_t* next = ldns_radix_next_in_subtree(node);
++		if (next) {
++			return next;
++		}
++	}
++	/** No elements in subtree, get to parent and go down next branch. */
++	while (node->parent) {
++		uint8_t index = node->parent_index;
++		node = node->parent;
++		index++;
++		for (; index < node->len; index++) {
++			if (node->array[index].edge) {
++				ldns_radix_node_t* next;
++				/** Node itself. */
++				if (node->array[index].edge->data) {
++					return node->array[index].edge;
++				}
++				/** Dive into subtree. */
++				next = ldns_radix_next_in_subtree(node);
++				if (next) {
++					return next;
++				}
++			}
++		}
++	}
++	return NULL;
++}
++
++
++/**
++ * Previous element.
++ *
++ */
++ldns_radix_node_t*
++ldns_radix_prev(ldns_radix_node_t* node)
++{
++	if (!node) {
++		return NULL;
++	}
++
++	/** Get to parent and go down previous branch. */
++	while (node->parent) {
++		uint8_t index = node->parent_index;
++		ldns_radix_node_t* prev;
++		node = node->parent;
++		assert(node->len > 0);
++		prev = ldns_radix_prev_from_index(node, index);
++		if (prev) {
++			return prev;
++		}
++		if (node->data) {
++			return node;
++		}
++	}
++	return NULL;
++}
++
++
++/**
++ * Print node.
++ *
++ */
++static void
++ldns_radix_node_print(FILE* fd, ldns_radix_node_t* node,
++	uint8_t i, uint8_t* str, radix_strlen_t len, unsigned d)
++{
++	uint8_t j;
++	if (!node) {
++		return;
++	}
++	for (j = 0; j < d; j++) {
++		fprintf(fd, "--");
++	}
++	if (str) {
++		radix_strlen_t l;
++		fprintf(fd, "| [%u+", (unsigned) i);
++		for (l=0; l < len; l++) {
++			fprintf(fd, "%c", (char) str[l]);
++		}
++		fprintf(fd, "]%u", (unsigned) len);
++	} else {
++		fprintf(fd, "| [%u]", (unsigned) i);
++	}
++
++	if (node->data) {
++		fprintf(fd, " %s", (char*) node->data);
++	}
++	fprintf(fd, "\n");
++
++	for (j = 0; j < node->len; j++) {
++		if (node->array[j].edge) {
++			ldns_radix_node_print(fd, node->array[j].edge, j,
++				node->array[j].str, node->array[j].len, d+1);
++		}
++	}
++	return;
++}
++
++
++/**
++ * Print radix tree.
++ *
++ */
++void
++ldns_radix_printf(FILE* fd, ldns_radix_t* tree)
++{
++	if (!fd || !tree) {
++		return;
++	}
++	if (!tree->root) {
++		fprintf(fd, "; empty radix tree\n");
++		return;
++	}
++	ldns_radix_node_print(fd, tree->root, 0, NULL, 0, 0);
++	return;
++}
++
++
++/**
++ * Join two radix trees.
++ *
++ */
++ldns_status
++ldns_radix_join(ldns_radix_t* tree1, ldns_radix_t* tree2)
++{
++	ldns_radix_node_t* cur_node, *next_node;
++	ldns_status status;
++	if (!tree2 || !tree2->root) {
++		return LDNS_STATUS_OK;
++	}
++	/** Add all elements from tree2 into tree1. */
++
++	cur_node = ldns_radix_first(tree2);
++	while (cur_node) {
++		status = LDNS_STATUS_NO_DATA;
++		/** Insert current node into tree1 */
++		if (cur_node->data) {
++			status = ldns_radix_insert(tree1, cur_node->key,
++				cur_node->klen, cur_node->data);
++			/** Exist errors may occur */
++			if (status != LDNS_STATUS_OK &&
++			    status != LDNS_STATUS_EXISTS_ERR) {
++				return status;
++			}
++		}
++		next_node = ldns_radix_next(cur_node);
++		if (status == LDNS_STATUS_OK) {
++			(void) ldns_radix_delete(tree2, cur_node->key,
++				cur_node->klen);
++		}
++		cur_node = next_node;
++	}
++
++	return LDNS_STATUS_OK;
++}
++
++
++/**
++ * Split a radix tree intwo.
++ *
++ */
++ldns_status
++ldns_radix_split(ldns_radix_t* tree1, size_t num, ldns_radix_t** tree2)
++{
++	size_t count = 0;
++	ldns_radix_node_t* cur_node;
++	ldns_status status = LDNS_STATUS_OK;
++	if (!tree1 || !tree1->root || num == 0) {
++		return LDNS_STATUS_OK;
++	}
++	if (!tree2) {
++		return LDNS_STATUS_NULL;
++	}
++	if (!*tree2) {
++		*tree2 = ldns_radix_create();
++		if (!*tree2) {
++			return LDNS_STATUS_MEM_ERR;
++		}
++	}
++	cur_node = ldns_radix_first(tree1);
++	while (count < num && cur_node) {
++		if (cur_node->data) {
++			/** Delete current node from tree1. */
++			uint8_t* cur_key = cur_node->key;
++			radix_strlen_t cur_len = cur_node->klen;
++			void* cur_data = ldns_radix_delete(tree1, cur_key,
++				cur_len);
++			/** Insert current node into tree2/ */
++			if (!cur_data) {
++				return LDNS_STATUS_NO_DATA;
++			}
++			status = ldns_radix_insert(*tree2, cur_key, cur_len,
++				cur_data);
++			if (status != LDNS_STATUS_OK &&
++			    status != LDNS_STATUS_EXISTS_ERR) {
++				return status;
++			}
++/*
++			if (status == LDNS_STATUS_OK) {
++				cur_node->key = NULL;
++				cur_node->klen = 0;
++			}
++*/
++			/** Update count; get first element from tree1 again. */
++			count++;
++			cur_node = ldns_radix_first(tree1);
++		} else {
++			cur_node = ldns_radix_next(cur_node);
++		}
++	}
++	return LDNS_STATUS_OK;
++}
++
++
++/**
++ * Call function for all nodes in the tree, such that leaf nodes are
++ * called before parent nodes.
++ *
++ */
++void
++ldns_radix_traverse_postorder(ldns_radix_node_t* node,
++	void (*func)(ldns_radix_node_t*, void*), void* arg)
++{
++	uint8_t i;
++	if (!node) {
++		return;
++	}
++	for (i=0; i < node->len; i++) {
++		ldns_radix_traverse_postorder(node->array[i].edge,
++			func, arg);
++	}
++	/** Call user function */
++	(*func)(node, arg);
++	return;
++}
++
++
++/** Static helper functions */
++
++/**
++ * Find a prefix of the key.
++ * @param tree:   tree.
++ * @param key:    key.
++ * @param len:    length of key.
++ * @param result: the longest prefix, the entry itself if *pos==len,
++ *                otherwise an array entry.
++ * @param pos:    position in string where next unmatched byte is.
++ *                If *pos==len, an exact match is found.
++ *                If *pos== 0, a "" match was found.
++ * @return 0 (false) if no prefix found.
++ *
++ */
++static int
++ldns_radix_find_prefix(ldns_radix_t* tree, uint8_t* key,
++	radix_strlen_t len, ldns_radix_node_t** result, radix_strlen_t* respos)
++{
++	/** Start searching at the root node */
++	ldns_radix_node_t* n = tree->root;
++	radix_strlen_t pos = 0;
++	uint8_t byte;
++	*respos = 0;
++	*result = n;
++        if (!n) {
++		/** No root, no prefix found */
++		return 0;
++	}
++	/** For each node, look if we can make further progress */
++	while (n) {
++		if (pos == len) {
++			/** Exact match */
++			return 1;
++		}
++		byte = key[pos];
++		if (byte < n->offset) {
++			/** key < node */
++			return 1;
++		}
++		byte -= n->offset;
++		if (byte >= n->len) {
++			/** key > node */
++			return 1;
++		}
++		/** So far, the trie matches */
++		pos++;
++		if (n->array[byte].len != 0) {
++			/** Must match additional string */
++			if (pos + n->array[byte].len > len) {
++				return 1; /* no match at child node */
++			}
++			if (memcmp(&key[pos], n->array[byte].str,
++				n->array[byte].len) != 0) {
++				return 1; /* no match at child node */
++			}
++			pos += n->array[byte].len;
++		}
++		/** Continue searching prefix at this child node */
++		n = n->array[byte].edge;
++		if (!n) {
++			return 1;
++		}
++		/** Update the prefix node */
++		*respos = pos;
++		*result = n;
++	}
++	/** Done */
++	return 1;
++}
++
++
++/**
++ * Make space in the node's array for another byte.
++ * @param node: node.
++ * @param byte: byte.
++ * @return 1 if successful, 0 otherwise.
++ *
++ */
++static int
++ldns_radix_array_space(ldns_radix_node_t* node, uint8_t byte)
++{
++	/** Is there an array? */
++	if (!node->array) {
++		assert(node->capacity == 0);
++		/** No array, create new array */
++		node->array = LDNS_MALLOC(ldns_radix_array_t);
++		if (!node->array) {
++			return 0;
++		}
++		memset(&node->array[0], 0, sizeof(ldns_radix_array_t));
++		node->len = 1;
++		node->capacity = 1;
++		node->offset = byte;
++		return 1;
++	}
++	/** Array exist */
++	assert(node->array != NULL);
++	assert(node->capacity > 0);
++
++	if (node->len == 0) {
++		/** Unused array */
++		node->len = 1;
++		node->offset = byte;
++	} else if (byte < node->offset) {
++		/** Byte is below the offset */
++		uint8_t index;
++		uint16_t need = node->offset - byte;
++		/** Is there enough capacity? */
++		if (node->len + need > node->capacity) {
++			/** Not enough capacity, grow array */
++			if (!ldns_radix_array_grow(node,
++				(unsigned) (node->len + need))) {
++				return 0; /* failed to grow array */
++			}
++		}
++		/** Move items to the end */
++		memmove(&node->array[need], &node->array[0],
++			node->len*sizeof(ldns_radix_array_t));
++		/** Fix parent index */
++		for (index = 0; index < node->len; index++) {
++			if (node->array[index+need].edge) {
++				node->array[index+need].edge->parent_index =
++					index + need;
++			}
++		}
++		/** Zero the first */
++		memset(&node->array[0], 0, need*sizeof(ldns_radix_array_t));
++		node->len += need;
++		node->offset = byte;
++	} else if (byte - node->offset >= node->len) {
++		/** Byte does not fit in array */
++		uint16_t need = (byte - node->offset) - node->len + 1;
++		/** Is there enough capacity? */
++		if (node->len + need > node->capacity) {
++			/** Not enough capacity, grow array */
++			if (!ldns_radix_array_grow(node,
++				(unsigned) (node->len + need))) {
++				return 0; /* failed to grow array */
++			}
++		}
++		/** Zero the added items */
++		memset(&node->array[node->len], 0,
++			need*sizeof(ldns_radix_array_t));
++		node->len += need;
++	}
++	return 1;
++}
++
++
++/**
++ * Grow the array.
++ * @param node: node.
++ * @param need: number of elements the array at least need to grow.
++ *              Can't be bigger than 256.
++ * @return: 0 if failed, 1 if was successful.
++ *
++ */
++static int
++ldns_radix_array_grow(ldns_radix_node_t* node, unsigned need)
++{
++	unsigned size = ((unsigned)node->capacity)*2;
++	ldns_radix_array_t* a = NULL;
++	if (need > size) {
++		size = need;
++	}
++	if (size > 256) {
++		size = 256;
++	}
++	a = LDNS_XMALLOC(ldns_radix_array_t, size);
++	if (!a) {
++		return 0;
++	}
++	assert(node->len <= node->capacity);
++	assert(node->capacity < size);
++	memcpy(&a[0], &node->array[0], node->len*sizeof(ldns_radix_array_t));
++	LDNS_FREE(node->array);
++	node->array = a;
++	node->capacity = size;
++	return 1;
++}
++
++
++/**
++ * Create a prefix in the array string.
++ * @param array: array.
++ * @param key:   key.
++ * @param pos:   start position in key.
++ * @param len:   length of key.
++ * @return 0 if failed, 1 if was successful.
++ *
++ */
++static int
++ldns_radix_str_create(ldns_radix_array_t* array, uint8_t* key,
++	radix_strlen_t pos, radix_strlen_t len)
++{
++	array->str = LDNS_XMALLOC(uint8_t, (len-pos));
++	if (!array->str) {
++		return 0;
++	}
++	memmove(array->str, key+pos, len-pos);
++	array->len = (len-pos);
++	return 1;
++}
++
++
++/**
++ * Allocate remainder from prefixes for a split.
++ * @param prefixlen:  length of prefix.
++ * @param longer_str: the longer string.
++ * @param longer_len: the longer string length.
++ * @param split_str:  the split string.
++ * @param split_len:  the split string length.
++ * @return 0 if failed, 1 if successful.
++ *
++ */
++static int
++ldns_radix_prefix_remainder(radix_strlen_t prefix_len,
++	uint8_t* longer_str, radix_strlen_t longer_len,
++	uint8_t** split_str, radix_strlen_t* split_len)
++{
++	*split_len = longer_len - prefix_len;
++	*split_str = LDNS_XMALLOC(uint8_t, (*split_len));
++	if (!*split_str) {
++		return 0;
++	}
++	memmove(*split_str, longer_str+prefix_len, longer_len-prefix_len);
++	return 1;
++}
++
++
++/**
++ * Create a split when two nodes have a shared prefix.
++ * @param array: array.
++ * @param key:   key.
++ * @param pos:   start position in key.
++ * @param len:   length of the key.
++ * @param add:   node to be added.
++ * @return 0 if failed, 1 if was successful.
++ *
++ */
++static int
++ldns_radix_array_split(ldns_radix_array_t* array, uint8_t* key,
++	radix_strlen_t pos, radix_strlen_t len, ldns_radix_node_t* add)
++{
++	uint8_t* str_to_add = key + pos;
++	radix_strlen_t strlen_to_add = len - pos;
++
++	if (ldns_radix_str_is_prefix(str_to_add, strlen_to_add,
++		array->str, array->len)) {
++		/** The string to add is a prefix of the existing string */
++		uint8_t* split_str = NULL, *dup_str = NULL;
++		radix_strlen_t split_len = 0;
++		/**
++		 * Example 5: 'ld'
++		 * | [0]
++		 * --| [d+ns] dns
++		 * --| [e+dns] edns
++		 * --| [l+d] ld
++		 * ----| [n+s] ldns
++		 **/
++		assert(strlen_to_add < array->len);
++		/** Store the remainder in the split string */
++		if (array->len - strlen_to_add > 1) {
++			if (!ldns_radix_prefix_remainder(strlen_to_add+1,
++				array->str, array->len, &split_str,
++				&split_len)) {
++				return 0;
++			}
++		}
++		/** Duplicate the string to add */
++		if (strlen_to_add != 0) {
++			dup_str = LDNS_XMALLOC(uint8_t, strlen_to_add);
++			if (!dup_str) {
++				LDNS_FREE(split_str);
++				return 0;
++			}
++			memcpy(dup_str, str_to_add, strlen_to_add);
++		}
++		/** Make space in array for the new node */
++		if (!ldns_radix_array_space(add,
++			array->str[strlen_to_add])) {
++			LDNS_FREE(split_str);
++			LDNS_FREE(dup_str);
++			return 0;
++		}
++		/**
++		 * The added node should go direct under the existing parent.
++		 * The existing node should go under the added node.
++		 */
++		add->parent = array->edge->parent;
++		add->parent_index = array->edge->parent_index;
++		add->array[0].edge = array->edge;
++		add->array[0].str = split_str;
++		add->array[0].len = split_len;
++		array->edge->parent = add;
++		array->edge->parent_index = 0;
++		LDNS_FREE(array->str);
++		array->edge = add;
++		array->str = dup_str;
++		array->len = strlen_to_add;
++	} else if (ldns_radix_str_is_prefix(array->str, array->len,
++		str_to_add, strlen_to_add)) {
++		/** The existing string is a prefix of the string to add */
++		/**
++		 * Example 6: 'dns-ng'
++		 * | [0]
++		 * --| [d+ns] dns
++		 * ----| [-+ng] dns-ng
++		 * --| [e+dns] edns
++		 * --| [l+d] ld
++		 * ----| [n+s] ldns
++		 **/
++		uint8_t* split_str = NULL;
++		radix_strlen_t split_len = 0;
++		assert(array->len < strlen_to_add);
++		if (strlen_to_add - array->len > 1) {
++			if (!ldns_radix_prefix_remainder(array->len+1,
++				str_to_add, strlen_to_add, &split_str,
++				&split_len)) {
++				return 0;
++			}
++		}
++		/** Make space in array for the new node */
++		if (!ldns_radix_array_space(array->edge,
++			str_to_add[array->len])) {
++			LDNS_FREE(split_str);
++			return 0;
++		}
++		/**
++		 * The added node should go direct under the existing node.
++		 */
++		add->parent = array->edge;
++		add->parent_index = str_to_add[array->len] -
++							array->edge->offset;
++		array->edge->array[add->parent_index].edge = add;
++		array->edge->array[add->parent_index].str = split_str;
++		array->edge->array[add->parent_index].len = split_len;
++	} else {
++		/** Create a new split node. */
++		/**
++		 * Example 7: 'dndns'
++		 * | [0]
++		 * --| [d+n]
++		 * ----| [d+ns] dndns
++		 * ----| [s] dns
++		 * ------| [-+ng] dns-ng
++		 * --| [e+dns] edns
++		 * --| [l+d] ld
++		 * ----| [n+s] ldns
++		 **/
++		ldns_radix_node_t* common = NULL;
++		uint8_t* common_str = NULL, *s1 = NULL, *s2 = NULL;
++		radix_strlen_t common_len = 0, l1 = 0, l2 = 0;
++		common_len = ldns_radix_str_common(array->str, array->len,
++			str_to_add, strlen_to_add);
++		assert(common_len < array->len);
++		assert(common_len < strlen_to_add);
++		/** Create the new common node. */
++		common = ldns_radix_new_node(NULL, (uint8_t*)"", 0);
++		if (!common) {
++			return 0;
++		}
++		if (array->len - common_len > 1) {
++			if (!ldns_radix_prefix_remainder(common_len+1,
++				array->str, array->len, &s1, &l1)) {
++				return 0;
++			}
++		}
++		if (strlen_to_add - common_len > 1) {
++			if (!ldns_radix_prefix_remainder(common_len+1,
++				str_to_add, strlen_to_add, &s2, &l2)) {
++				return 0;
++			}
++		}
++		/** Create the shared prefix. */
++		if (common_len > 0) {
++			common_str = LDNS_XMALLOC(uint8_t, common_len);
++			if (!common_str) {
++				LDNS_FREE(common);
++				LDNS_FREE(s1);
++				LDNS_FREE(s2);
++				return 0;
++			}
++			memcpy(common_str, str_to_add, common_len);
++		}
++		/** Make space in the common node array. */
++		if (!ldns_radix_array_space(common, array->str[common_len]) ||
++		    !ldns_radix_array_space(common, str_to_add[common_len])) {
++			LDNS_FREE(common->array);
++			LDNS_FREE(common);
++			LDNS_FREE(common_str);
++			LDNS_FREE(s1);
++			LDNS_FREE(s2);
++			return 0;
++		}
++		/**
++		 * The common node should go direct under the parent node.
++		 * The added and existing nodes go under the common node.
++		 */
++		common->parent = array->edge->parent;
++		common->parent_index = array->edge->parent_index;
++		array->edge->parent = common;
++		array->edge->parent_index = array->str[common_len] -
++								common->offset;
++		add->parent = common;
++		add->parent_index = str_to_add[common_len] - common->offset;
++		common->array[array->edge->parent_index].edge = array->edge;
++		common->array[array->edge->parent_index].str = s1;
++		common->array[array->edge->parent_index].len = l1;
++		common->array[add->parent_index].edge = add;
++		common->array[add->parent_index].str = s2;
++		common->array[add->parent_index].len = l2;
++		LDNS_FREE(array->str);
++		array->edge = common;
++		array->str = common_str;
++		array->len = common_len;
++	}
++	return 1;
++}
++
++
++/**
++ * Check if one string prefix of other string.
++ * @param str1: one string.
++ * @param len1: one string length.
++ * @param str2: other string.
++ * @param len2: other string length.
++ * @return 1 if prefix, 0 otherwise.
++ *
++ */
++static int
++ldns_radix_str_is_prefix(uint8_t* str1, radix_strlen_t len1,
++	uint8_t* str2, radix_strlen_t len2)
++{
++	if (len1 == 0) {
++		return 1; /* empty prefix is also a prefix */
++	}
++	if (len1 > len2) {
++		return 0; /* len1 is longer so str1 cannot be a prefix */
++	}
++	return (memcmp(str1, str2, len1) == 0);
++}
++
++
++/**
++ * Return the number of bytes in common for the two strings.
++ * @param str1: one string.
++ * @param len1: one string length.
++ * @param str2: other string.
++ * @param len2: other string length.
++ * @return length of substring that the two strings have in common.
++ *
++ */
++static radix_strlen_t
++ldns_radix_str_common(uint8_t* str1, radix_strlen_t len1,
++	uint8_t* str2, radix_strlen_t len2)
++{
++	radix_strlen_t i, max = (len1<len2)?len1:len2;
++	for (i=0; i<max; i++) {
++		if (str1[i] != str2[i]) {
++			return i;
++		}
++	}
++	return max;
++}
++
++
++/**
++ * Find the next element in the subtree of this node.
++ * @param node: node.
++ * @return: node with next element.
++ *
++ */
++static ldns_radix_node_t*
++ldns_radix_next_in_subtree(ldns_radix_node_t* node)
++{
++	uint16_t i;
++	ldns_radix_node_t* next;
++	/** Try every subnode. */
++	for (i = 0; i < node->len; i++) {
++		if (node->array[i].edge) {
++			/** Node itself. */
++			if (node->array[i].edge->data) {
++				return node->array[i].edge;
++			}
++			/** Dive into subtree. */
++			next = ldns_radix_next_in_subtree(node->array[i].edge);
++			if (next) {
++				return next;
++			}
++		}
++	}
++	return NULL;
++}
++
++
++/**
++ * Find the previous element in the array of this node, from index.
++ * @param node: node.
++ * @param index: index.
++ * @return previous node from index.
++ *
++ */
++static ldns_radix_node_t*
++ldns_radix_prev_from_index(ldns_radix_node_t* node, uint8_t index)
++{
++	uint8_t i = index;
++	while (i > 0) {
++		i--;
++		if (node->array[i].edge) {
++			ldns_radix_node_t* prev =
++				ldns_radix_last_in_subtree_incl_self(node);
++			if (prev) {
++				return prev;
++			}
++		}
++	}
++	return NULL;
++}
++
++
++/**
++ * Find last node in subtree, or this node (if have data).
++ * @param node: node.
++ * @return last node in subtree, or this node, or NULL.
++ *
++ */
++static ldns_radix_node_t*
++ldns_radix_last_in_subtree_incl_self(ldns_radix_node_t* node)
++{
++	ldns_radix_node_t* last = ldns_radix_last_in_subtree(node);
++	if (last) {
++		return last;
++	} else if (node->data) {
++		return node;
++	}
++	return NULL;
++}
++
++
++/**
++ * Find last node in subtree.
++ * @param node: node.
++ * @return last node in subtree.
++ *
++ */
++static ldns_radix_node_t*
++ldns_radix_last_in_subtree(ldns_radix_node_t* node)
++{
++	int i;
++	/** Look for the most right leaf node. */
++	for (i=(int)(node->len)-1; i >= 0; i--) {
++		if (node->array[i].edge) {
++			/** Keep looking for the most right leaf node. */
++			if (node->array[i].edge->len > 0) {
++				ldns_radix_node_t* last =
++					ldns_radix_last_in_subtree(
++					node->array[i].edge);
++				if (last) {
++					return last;
++				}
++			}
++			/** Could this be the most right leaf node? */
++			if (node->array[i].edge->data) {
++				return node->array[i].edge;
++			}
++		}
++	}
++	return NULL;
++}
++
++
++/**
++ * Fix tree after deleting element.
++ * @param tree: tree.
++ * @param node: node with deleted element.
++ *
++ */
++static void
++ldns_radix_del_fix(ldns_radix_t* tree, ldns_radix_node_t* node)
++{
++	while (node) {
++		if (node->data) {
++			/** Thou should not delete nodes with data attached. */
++			return;
++		} else if (node->len == 1 && node->parent) {
++			/** Node with one child is fold back into. */
++			ldns_radix_cleanup_onechild(node);
++			return;
++		} else if (node->len == 0) {
++			/** Leaf node. */
++			ldns_radix_node_t* parent = node->parent;
++			if (!parent) {
++				/** The root is a leaf node. */
++				ldns_radix_node_free(node, NULL);
++				tree->root = NULL;
++				return;
++			}
++			/** Cleanup leaf node and continue with parent. */
++			ldns_radix_cleanup_leaf(node);
++			node = parent;
++		} else {
++			/**
++			 * Node cannot be deleted, because it has edge nodes
++			 * and no parent to fix up to.
++			 */
++			return;
++		}
++	}
++	/** Not reached. */
++	return;
++}
++
++
++/**
++ * Clean up a node with one child.
++ * @param node: node with one child.
++ *
++ */
++static void
++ldns_radix_cleanup_onechild(ldns_radix_node_t* node)
++{
++	uint8_t* join_str;
++	radix_strlen_t join_len;
++	uint8_t parent_index = node->parent_index;
++	ldns_radix_node_t* child = node->array[0].edge;
++	ldns_radix_node_t* parent = node->parent;
++
++	/** Node has one child, merge the child node into the parent node. */
++	assert(parent_index < parent->len);
++	join_len = parent->array[parent_index].len + node->array[0].len + 1;
++
++	join_str = LDNS_XMALLOC(uint8_t, join_len);
++	if (!join_str) {
++		/**
++		 * Cleanup failed due to out of memory.
++		 * This tree is now inefficient, with the empty node still
++		 * existing, but it is still valid.
++		 */
++		return;
++	}
++
++	memcpy(join_str, parent->array[parent_index].str,
++		parent->array[parent_index].len);
++	join_str[parent->array[parent_index].len] = child->parent_index +
++		node->offset;
++	memmove(join_str + parent->array[parent_index].len+1,
++		node->array[0].str, node->array[0].len);
++
++	LDNS_FREE(parent->array[parent_index].str);
++	parent->array[parent_index].str = join_str;
++	parent->array[parent_index].len = join_len;
++	parent->array[parent_index].edge = child;
++	child->parent = parent;
++	child->parent_index = parent_index;
++	ldns_radix_node_free(node, NULL);
++	return;
++}
++
++
++/**
++ * Clean up a leaf node.
++ * @param node: leaf node.
++ *
++ */
++static void
++ldns_radix_cleanup_leaf(ldns_radix_node_t* node)
++{
++	uint8_t parent_index = node->parent_index;
++	ldns_radix_node_t* parent = node->parent;
++	/** Delete lead node and fix parent array. */
++	assert(parent_index < parent->len);
++	ldns_radix_node_free(node, NULL);
++	LDNS_FREE(parent->array[parent_index].str);
++	parent->array[parent_index].str = NULL;
++	parent->array[parent_index].len = 0;
++	parent->array[parent_index].edge = NULL;
++	/** Fix array in parent. */
++	if (parent->len == 1) {
++		ldns_radix_node_array_free(parent);
++	} else if (parent_index == 0) {
++		ldns_radix_node_array_free_front(parent);
++	} else {
++		ldns_radix_node_array_free_end(parent);
++	}
++	return;
++}
++
++
++/**
++ * Free a radix node.
++ * @param node: node.
++ * @param arg: user argument.
++ *
++ */
++static void
++ldns_radix_node_free(ldns_radix_node_t* node, void* arg)
++{
++	uint16_t i;
++	(void) arg;
++	if (!node) {
++		return;
++	}
++	for (i=0; i < node->len; i++) {
++		LDNS_FREE(node->array[i].str);
++	}
++	node->key = NULL;
++	node->klen = 0;
++	LDNS_FREE(node->array);
++	LDNS_FREE(node);
++	return;
++}
++
++
++/**
++ * Free select edge array.
++ * @param node: node.
++ *
++ */
++static void
++ldns_radix_node_array_free(ldns_radix_node_t* node)
++{
++	node->offset = 0;
++	node->len = 0;
++	LDNS_FREE(node->array);
++	node->array = NULL;
++	node->capacity = 0;
++	return;
++}
++
++
++/**
++ * Free front of select edge array.
++ * @param node: node.
++ *
++ */
++static void
++ldns_radix_node_array_free_front(ldns_radix_node_t* node)
++{
++	uint16_t i, n = 0;
++	/** Remove until a non NULL entry. */
++   	while (n < node->len && node->array[n].edge == NULL) {
++		n++;
++	}
++	if (n == 0) {
++		return;
++	}
++	if (n == node->len) {
++		ldns_radix_node_array_free(node);
++		return;
++	}
++	assert(n < node->len);
++	assert((int) n <= (255 - (int) node->offset));
++	memmove(&node->array[0], &node->array[n],
++		(node->len - n)*sizeof(ldns_radix_array_t));
++	node->offset += n;
++	node->len -= n;
++	for (i=0; i < node->len; i++) {
++		if (node->array[i].edge) {
++			node->array[i].edge->parent_index = i;
++		}
++	}
++	ldns_radix_array_reduce(node);
++	return;
++}
++
++
++/**
++ * Free front of select edge array.
++ * @param node: node.
++ *
++ */
++static void
++ldns_radix_node_array_free_end(ldns_radix_node_t* node)
++{
++	uint16_t n = 0;
++	/** Shorten array. */
++	while (n < node->len && node->array[node->len-1-n].edge == NULL) {
++		n++;
++	}
++	if (n == 0) {
++		return;
++	}
++	if (n == node->len) {
++		ldns_radix_node_array_free(node);
++		return;
++	}
++	assert(n < node->len);
++	node->len -= n;
++	ldns_radix_array_reduce(node);
++	return;
++}
++
++
++/**
++ * Reduce the capacity of the array if needed.
++ * @param node: node.
++ *
++ */
++static void
++ldns_radix_array_reduce(ldns_radix_node_t* node)
++{
++	if (node->len <= node->capacity/2 && node->len != node->capacity) {
++		ldns_radix_array_t* a = LDNS_XMALLOC(ldns_radix_array_t,
++								node->len);
++		if (!a) {
++			return;
++		}
++		memcpy(a, node->array, sizeof(ldns_radix_array_t)*node->len);
++		LDNS_FREE(node->array);
++		node->array = a;
++		node->capacity = node->len;
++	}
++	return;
++}
++
++
++/**
++ * Return this element if it exists, the previous otherwise.
++ * @param node: from this node.
++ * @param result: result node.
++ *
++ */
++static void
++ldns_radix_self_or_prev(ldns_radix_node_t* node, ldns_radix_node_t** result)
++{
++	if (node->data) {
++		*result = node;
++	} else {
++		*result = ldns_radix_prev(node);
++	}
++	return;
++}
+diff --git a/ldns/src/rbtree.c b/ldns/src/rbtree.c
+new file mode 100644
+index 0000000..b89dff7
+--- /dev/null
++++ b/ldns/src/rbtree.c
+@@ -0,0 +1,670 @@
++/*
++ * rbtree.c -- generic red black tree
++ *
++ * Taken from Unbound, modified for ldns
++ *
++ * Copyright (c) 2001-2008, NLnet Labs. All rights reserved.
++ * 
++ * This software is open source.
++ * 
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * 
++ * Redistributions in binary form must reproduce the above copyright notice,
++ * this list of conditions and the following disclaimer in the documentation
++ * and/or other materials provided with the distribution.
++ * 
++ * Neither the name of the NLNET LABS nor the names of its contributors may
++ * be used to endorse or promote products derived from this software without
++ * specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
++ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
++ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
++ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
++ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ *
++ */
++
++/**
++ * \file
++ * Implementation of a redblack tree.
++ */
++
++#include <ldns/config.h>
++#include <ldns/rbtree.h>
++#include <ldns/util.h>
++#include <stdlib.h>
++
++/** Node colour black */
++#define	BLACK	0
++/** Node colour red */
++#define	RED	1
++
++/** the NULL node, global alloc */
++ldns_rbnode_t	ldns_rbtree_null_node = {
++	LDNS_RBTREE_NULL,	/* Parent.  */
++	LDNS_RBTREE_NULL,	/* Left.  */
++	LDNS_RBTREE_NULL,	/* Right.  */
++	NULL,			/* Key.  */
++	NULL,               /* Data. */
++	BLACK		     /* Color.  */
++};
++
++/** rotate subtree left (to preserve redblack property) */
++static void ldns_rbtree_rotate_left(ldns_rbtree_t *rbtree, ldns_rbnode_t *node);
++/** rotate subtree right (to preserve redblack property) */
++static void ldns_rbtree_rotate_right(ldns_rbtree_t *rbtree, ldns_rbnode_t *node);
++/** Fixup node colours when insert happened */
++static void ldns_rbtree_insert_fixup(ldns_rbtree_t *rbtree, ldns_rbnode_t *node);
++/** Fixup node colours when delete happened */
++static void ldns_rbtree_delete_fixup(ldns_rbtree_t* rbtree, ldns_rbnode_t* child, ldns_rbnode_t* child_parent);
++
++/*
++ * Creates a new red black tree, intializes and returns a pointer to it.
++ *
++ * Return NULL on failure.
++ *
++ */
++ldns_rbtree_t *
++ldns_rbtree_create (int (*cmpf)(const void *, const void *))
++{
++	ldns_rbtree_t *rbtree;
++
++	/* Allocate memory for it */
++	rbtree = (ldns_rbtree_t *) LDNS_MALLOC(ldns_rbtree_t);
++	if (!rbtree) {
++		return NULL;
++	}
++
++	/* Initialize it */
++	ldns_rbtree_init(rbtree, cmpf);
++
++	return rbtree;
++}
++
++void 
++ldns_rbtree_init(ldns_rbtree_t *rbtree, int (*cmpf)(const void *, const void *))
++{
++	/* Initialize it */
++	rbtree->root = LDNS_RBTREE_NULL;
++	rbtree->count = 0;
++	rbtree->cmp = cmpf;
++}
++
++void 
++ldns_rbtree_free(ldns_rbtree_t *rbtree)
++{
++	LDNS_FREE(rbtree);
++}
++
++/*
++ * Rotates the node to the left.
++ *
++ */
++static void
++ldns_rbtree_rotate_left(ldns_rbtree_t *rbtree, ldns_rbnode_t *node)
++{
++	ldns_rbnode_t *right = node->right;
++	node->right = right->left;
++	if (right->left != LDNS_RBTREE_NULL)
++		right->left->parent = node;
++
++	right->parent = node->parent;
++
++	if (node->parent != LDNS_RBTREE_NULL) {
++		if (node == node->parent->left) {
++			node->parent->left = right;
++		} else  {
++			node->parent->right = right;
++		}
++	} else {
++		rbtree->root = right;
++	}
++	right->left = node;
++	node->parent = right;
++}
++
++/*
++ * Rotates the node to the right.
++ *
++ */
++static void
++ldns_rbtree_rotate_right(ldns_rbtree_t *rbtree, ldns_rbnode_t *node)
++{
++	ldns_rbnode_t *left = node->left;
++	node->left = left->right;
++	if (left->right != LDNS_RBTREE_NULL)
++		left->right->parent = node;
++
++	left->parent = node->parent;
++
++	if (node->parent != LDNS_RBTREE_NULL) {
++		if (node == node->parent->right) {
++			node->parent->right = left;
++		} else  {
++			node->parent->left = left;
++		}
++	} else {
++		rbtree->root = left;
++	}
++	left->right = node;
++	node->parent = left;
++}
++
++static void
++ldns_rbtree_insert_fixup(ldns_rbtree_t *rbtree, ldns_rbnode_t *node)
++{
++	ldns_rbnode_t	*uncle;
++
++	/* While not at the root and need fixing... */
++	while (node != rbtree->root && node->parent->color == RED) {
++		/* If our parent is left child of our grandparent... */
++		if (node->parent == node->parent->parent->left) {
++			uncle = node->parent->parent->right;
++
++			/* If our uncle is red... */
++			if (uncle->color == RED) {
++				/* Paint the parent and the uncle black... */
++				node->parent->color = BLACK;
++				uncle->color = BLACK;
++
++				/* And the grandparent red... */
++				node->parent->parent->color = RED;
++
++				/* And continue fixing the grandparent */
++				node = node->parent->parent;
++			} else {				/* Our uncle is black... */
++				/* Are we the right child? */
++				if (node == node->parent->right) {
++					node = node->parent;
++					ldns_rbtree_rotate_left(rbtree, node);
++				}
++				/* Now we're the left child, repaint and rotate... */
++				node->parent->color = BLACK;
++				node->parent->parent->color = RED;
++				ldns_rbtree_rotate_right(rbtree, node->parent->parent);
++			}
++		} else {
++			uncle = node->parent->parent->left;
++
++			/* If our uncle is red... */
++			if (uncle->color == RED) {
++				/* Paint the parent and the uncle black... */
++				node->parent->color = BLACK;
++				uncle->color = BLACK;
++
++				/* And the grandparent red... */
++				node->parent->parent->color = RED;
++
++				/* And continue fixing the grandparent */
++				node = node->parent->parent;
++			} else {				/* Our uncle is black... */
++				/* Are we the right child? */
++				if (node == node->parent->left) {
++					node = node->parent;
++					ldns_rbtree_rotate_right(rbtree, node);
++				}
++				/* Now we're the right child, repaint and rotate... */
++				node->parent->color = BLACK;
++				node->parent->parent->color = RED;
++				ldns_rbtree_rotate_left(rbtree, node->parent->parent);
++			}
++		}
++	}
++	rbtree->root->color = BLACK;
++}
++
++void
++ldns_rbtree_insert_vref(ldns_rbnode_t *data, void *rbtree)
++{
++	(void) ldns_rbtree_insert((ldns_rbtree_t *) rbtree,
++						 data);
++}
++
++/*
++ * Inserts a node into a red black tree.
++ *
++ * Returns NULL on failure or the pointer to the newly added node
++ * otherwise.
++ */
++ldns_rbnode_t *
++ldns_rbtree_insert (ldns_rbtree_t *rbtree, ldns_rbnode_t *data)
++{
++	/* XXX Not necessary, but keeps compiler quiet... */
++	int r = 0;
++
++	/* We start at the root of the tree */
++	ldns_rbnode_t	*node = rbtree->root;
++	ldns_rbnode_t	*parent = LDNS_RBTREE_NULL;
++
++	/* Lets find the new parent... */
++	while (node != LDNS_RBTREE_NULL) {
++		/* Compare two keys, do we have a duplicate? */
++		if ((r = rbtree->cmp(data->key, node->key)) == 0) {
++			return NULL;
++		}
++		parent = node;
++
++		if (r < 0) {
++			node = node->left;
++		} else {
++			node = node->right;
++		}
++	}
++
++	/* Initialize the new node */
++	data->parent = parent;
++	data->left = data->right = LDNS_RBTREE_NULL;
++	data->color = RED;
++	rbtree->count++;
++
++	/* Insert it into the tree... */
++	if (parent != LDNS_RBTREE_NULL) {
++		if (r < 0) {
++			parent->left = data;
++		} else {
++			parent->right = data;
++		}
++	} else {
++		rbtree->root = data;
++	}
++
++	/* Fix up the red-black properties... */
++	ldns_rbtree_insert_fixup(rbtree, data);
++
++	return data;
++}
++
++/*
++ * Searches the red black tree, returns the data if key is found or NULL otherwise.
++ *
++ */
++ldns_rbnode_t *
++ldns_rbtree_search (ldns_rbtree_t *rbtree, const void *key)
++{
++	ldns_rbnode_t *node;
++
++	if (ldns_rbtree_find_less_equal(rbtree, key, &node)) {
++		return node;
++	} else {
++		return NULL;
++	}
++}
++
++/** helpers for delete: swap node colours */
++static void swap_int8(uint8_t* x, uint8_t* y) 
++{ 
++	uint8_t t = *x; *x = *y; *y = t; 
++}
++
++/** helpers for delete: swap node pointers */
++static void swap_np(ldns_rbnode_t** x, ldns_rbnode_t** y) 
++{
++	ldns_rbnode_t* t = *x; *x = *y; *y = t; 
++}
++
++/** Update parent pointers of child trees of 'parent' */
++static void change_parent_ptr(ldns_rbtree_t* rbtree, ldns_rbnode_t* parent, ldns_rbnode_t* old, ldns_rbnode_t* new)
++{
++	if(parent == LDNS_RBTREE_NULL)
++	{
++		if(rbtree->root == old) rbtree->root = new;
++		return;
++	}
++	if(parent->left == old) parent->left = new;
++	if(parent->right == old) parent->right = new;
++}
++/** Update parent pointer of a node 'child' */
++static void change_child_ptr(ldns_rbnode_t* child, ldns_rbnode_t* old, ldns_rbnode_t* new)
++{
++	if(child == LDNS_RBTREE_NULL) return;
++	if(child->parent == old) child->parent = new;
++}
++
++ldns_rbnode_t* 
++ldns_rbtree_delete(ldns_rbtree_t *rbtree, const void *key)
++{
++	ldns_rbnode_t *to_delete;
++	ldns_rbnode_t *child;
++	if((to_delete = ldns_rbtree_search(rbtree, key)) == 0) return 0;
++	rbtree->count--;
++
++	/* make sure we have at most one non-leaf child */
++	if(to_delete->left != LDNS_RBTREE_NULL &&
++	   to_delete->right != LDNS_RBTREE_NULL)
++	{
++		/* swap with smallest from right subtree (or largest from left) */
++		ldns_rbnode_t *smright = to_delete->right;
++		while(smright->left != LDNS_RBTREE_NULL)
++			smright = smright->left;
++		/* swap the smright and to_delete elements in the tree,
++		 * but the ldns_rbnode_t is first part of user data struct
++		 * so cannot just swap the keys and data pointers. Instead
++		 * readjust the pointers left,right,parent */
++
++		/* swap colors - colors are tied to the position in the tree */
++		swap_int8(&to_delete->color, &smright->color);
++
++		/* swap child pointers in parents of smright/to_delete */
++		change_parent_ptr(rbtree, to_delete->parent, to_delete, smright);
++		if(to_delete->right != smright)
++			change_parent_ptr(rbtree, smright->parent, smright, to_delete);
++
++		/* swap parent pointers in children of smright/to_delete */
++		change_child_ptr(smright->left, smright, to_delete);
++		change_child_ptr(smright->left, smright, to_delete);
++		change_child_ptr(smright->right, smright, to_delete);
++		change_child_ptr(smright->right, smright, to_delete);
++		change_child_ptr(to_delete->left, to_delete, smright);
++		if(to_delete->right != smright)
++			change_child_ptr(to_delete->right, to_delete, smright);
++		if(to_delete->right == smright)
++		{
++			/* set up so after swap they work */
++			to_delete->right = to_delete;
++			smright->parent = smright;
++		}
++
++		/* swap pointers in to_delete/smright nodes */
++		swap_np(&to_delete->parent, &smright->parent);
++		swap_np(&to_delete->left, &smright->left);
++		swap_np(&to_delete->right, &smright->right);
++
++		/* now delete to_delete (which is at the location where the smright previously was) */
++	}
++
++	if(to_delete->left != LDNS_RBTREE_NULL) child = to_delete->left;
++	else child = to_delete->right;
++
++	/* unlink to_delete from the tree, replace to_delete with child */
++	change_parent_ptr(rbtree, to_delete->parent, to_delete, child);
++	change_child_ptr(child, to_delete, to_delete->parent);
++
++	if(to_delete->color == RED)
++	{
++		/* if node is red then the child (black) can be swapped in */
++	}
++	else if(child->color == RED)
++	{
++		/* change child to BLACK, removing a RED node is no problem */
++		if(child!=LDNS_RBTREE_NULL) child->color = BLACK;
++	}
++	else ldns_rbtree_delete_fixup(rbtree, child, to_delete->parent);
++
++	/* unlink completely */
++	to_delete->parent = LDNS_RBTREE_NULL;
++	to_delete->left = LDNS_RBTREE_NULL;
++	to_delete->right = LDNS_RBTREE_NULL;
++	to_delete->color = BLACK;
++	return to_delete;
++}
++
++static void ldns_rbtree_delete_fixup(ldns_rbtree_t* rbtree, ldns_rbnode_t* child, ldns_rbnode_t* child_parent)
++{
++	ldns_rbnode_t* sibling;
++	int go_up = 1;
++
++	/* determine sibling to the node that is one-black short */
++	if(child_parent->right == child) sibling = child_parent->left;
++	else sibling = child_parent->right;
++
++	while(go_up)
++	{
++		if(child_parent == LDNS_RBTREE_NULL)
++		{
++			/* removed parent==black from root, every path, so ok */
++			return;
++		}
++
++		if(sibling->color == RED)
++		{	/* rotate to get a black sibling */
++			child_parent->color = RED;
++			sibling->color = BLACK;
++			if(child_parent->right == child)
++				ldns_rbtree_rotate_right(rbtree, child_parent);
++			else	ldns_rbtree_rotate_left(rbtree, child_parent);
++			/* new sibling after rotation */
++			if(child_parent->right == child) sibling = child_parent->left;
++			else sibling = child_parent->right;
++		}
++
++		if(child_parent->color == BLACK 
++			&& sibling->color == BLACK
++			&& sibling->left->color == BLACK
++			&& sibling->right->color == BLACK)
++		{	/* fixup local with recolor of sibling */
++			if(sibling != LDNS_RBTREE_NULL)
++				sibling->color = RED;
++
++			child = child_parent;
++			child_parent = child_parent->parent;
++			/* prepare to go up, new sibling */
++			if(child_parent->right == child) sibling = child_parent->left;
++			else sibling = child_parent->right;
++		}
++		else go_up = 0;
++	}
++
++	if(child_parent->color == RED
++		&& sibling->color == BLACK
++		&& sibling->left->color == BLACK
++		&& sibling->right->color == BLACK) 
++	{
++		/* move red to sibling to rebalance */
++		if(sibling != LDNS_RBTREE_NULL)
++			sibling->color = RED;
++		child_parent->color = BLACK;
++		return;
++	}
++
++	/* get a new sibling, by rotating at sibling. See which child
++	   of sibling is red */
++	if(child_parent->right == child
++		&& sibling->color == BLACK
++		&& sibling->right->color == RED
++		&& sibling->left->color == BLACK)
++	{
++		sibling->color = RED;
++		sibling->right->color = BLACK;
++		ldns_rbtree_rotate_left(rbtree, sibling);
++		/* new sibling after rotation */
++		if(child_parent->right == child) sibling = child_parent->left;
++		else sibling = child_parent->right;
++	}
++	else if(child_parent->left == child
++		&& sibling->color == BLACK
++		&& sibling->left->color == RED
++		&& sibling->right->color == BLACK)
++	{
++		sibling->color = RED;
++		sibling->left->color = BLACK;
++		ldns_rbtree_rotate_right(rbtree, sibling);
++		/* new sibling after rotation */
++		if(child_parent->right == child) sibling = child_parent->left;
++		else sibling = child_parent->right;
++	}
++
++	/* now we have a black sibling with a red child. rotate and exchange colors. */
++	sibling->color = child_parent->color;
++	child_parent->color = BLACK;
++	if(child_parent->right == child)
++	{
++		sibling->left->color = BLACK;
++		ldns_rbtree_rotate_right(rbtree, child_parent);
++	}
++	else
++	{
++		sibling->right->color = BLACK;
++		ldns_rbtree_rotate_left(rbtree, child_parent);
++	}
++}
++
++int
++ldns_rbtree_find_less_equal(ldns_rbtree_t *rbtree, const void *key, ldns_rbnode_t **result)
++{
++	int r;
++	ldns_rbnode_t *node;
++
++	/* We start at root... */
++	node = rbtree->root;
++
++	*result = NULL;
++
++	/* While there are children... */
++	while (node != LDNS_RBTREE_NULL) {
++		r = rbtree->cmp(key, node->key);
++		if (r == 0) {
++			/* Exact match */
++			*result = node;
++			return 1;
++		} 
++		if (r < 0) {
++			node = node->left;
++		} else {
++			/* Temporary match */
++			*result = node;
++			node = node->right;
++		}
++	}
++	return 0;
++}
++
++/*
++ * Finds the first element in the red black tree
++ *
++ */
++ldns_rbnode_t *
++ldns_rbtree_first (ldns_rbtree_t *rbtree)
++{
++	ldns_rbnode_t *node = rbtree->root;
++
++	if (rbtree->root != LDNS_RBTREE_NULL) {
++		for (node = rbtree->root; node->left != LDNS_RBTREE_NULL; node = node->left);
++	}
++	return node;
++}
++
++ldns_rbnode_t *
++ldns_rbtree_last (ldns_rbtree_t *rbtree)
++{
++	ldns_rbnode_t *node = rbtree->root;
++
++	if (rbtree->root != LDNS_RBTREE_NULL) {
++		for (node = rbtree->root; node->right != LDNS_RBTREE_NULL; node = node->right);
++	}
++	return node;
++}
++
++/*
++ * Returns the next node...
++ *
++ */
++ldns_rbnode_t *
++ldns_rbtree_next (ldns_rbnode_t *node)
++{
++	ldns_rbnode_t *parent;
++
++	if (node->right != LDNS_RBTREE_NULL) {
++		/* One right, then keep on going left... */
++		for (node = node->right;
++			node->left != LDNS_RBTREE_NULL;
++			node = node->left);
++	} else {
++		parent = node->parent;
++		while (parent != LDNS_RBTREE_NULL && node == parent->right) {
++			node = parent;
++			parent = parent->parent;
++		}
++		node = parent;
++	}
++	return node;
++}
++
++ldns_rbnode_t *
++ldns_rbtree_previous(ldns_rbnode_t *node)
++{
++	ldns_rbnode_t *parent;
++
++	if (node->left != LDNS_RBTREE_NULL) {
++		/* One left, then keep on going right... */
++		for (node = node->left;
++			node->right != LDNS_RBTREE_NULL;
++			node = node->right);
++	} else {
++		parent = node->parent;
++		while (parent != LDNS_RBTREE_NULL && node == parent->left) {
++			node = parent;
++			parent = parent->parent;
++		}
++		node = parent;
++	}
++	return node;
++}
++
++/**
++ * split off elements number of elements from the start
++ * of the name tree and return a new tree 
++ */
++ldns_rbtree_t *
++ldns_rbtree_split(ldns_rbtree_t *tree,
++			   size_t elements)
++{
++	ldns_rbtree_t *new_tree;
++	ldns_rbnode_t *cur_node;
++	ldns_rbnode_t *move_node;
++	size_t count = 0;
++
++	new_tree = ldns_rbtree_create(tree->cmp);
++
++	cur_node = ldns_rbtree_first(tree);
++	while (count < elements && cur_node != LDNS_RBTREE_NULL) {
++		move_node = ldns_rbtree_delete(tree, cur_node->key);
++		(void)ldns_rbtree_insert(new_tree, move_node);
++		cur_node = ldns_rbtree_first(tree);
++		count++;
++	}
++
++	return new_tree;
++}
++
++/*
++ * add all node from the second tree to the first (removing them from the
++ * second), and fix up nsec(3)s if present
++ */
++void
++ldns_rbtree_join(ldns_rbtree_t *tree1, ldns_rbtree_t *tree2)
++{
++	ldns_traverse_postorder(tree2, ldns_rbtree_insert_vref, tree1);
++}
++
++/** recursive descent traverse */
++static void 
++traverse_post(void (*func)(ldns_rbnode_t*, void*), void* arg, 
++	ldns_rbnode_t* node)
++{
++	if(!node || node == LDNS_RBTREE_NULL)
++		return;
++	/* recurse */
++	traverse_post(func, arg, node->left);
++	traverse_post(func, arg, node->right);
++	/* call user func */
++	(*func)(node, arg);
++}
++
++void 
++ldns_traverse_postorder(ldns_rbtree_t* tree, 
++	void (*func)(ldns_rbnode_t*, void*), void* arg)
++{
++	traverse_post(func, arg, tree->root);
++}
+diff --git a/ldns/src/rdata.c b/ldns/src/rdata.c
+new file mode 100644
+index 0000000..6eb0096
+--- /dev/null
++++ b/ldns/src/rdata.c
+@@ -0,0 +1,757 @@
++/*
++ * rdata.c
++ *
++ * rdata implementation
++ *
++ * a Net::DNS like library for C
++ *
++ * (c) NLnet Labs, 2004-2006
++ *
++ * See the file LICENSE for the license
++ */
++
++#include <ldns/config.h>
++
++#include <ldns/ldns.h>
++
++/*
++ * Access functions 
++ * do this as functions to get type checking
++ */
++
++/* read */
++size_t
++ldns_rdf_size(const ldns_rdf *rd)
++{
++	assert(rd != NULL);
++	return rd->_size;
++}
++
++ldns_rdf_type
++ldns_rdf_get_type(const ldns_rdf *rd)
++{
++	assert(rd != NULL);
++	return rd->_type;
++}
++
++uint8_t *
++ldns_rdf_data(const ldns_rdf *rd)
++{
++	assert(rd != NULL);
++	return rd->_data;
++}
++
++/* write */
++void
++ldns_rdf_set_size(ldns_rdf *rd, size_t size)
++{
++	assert(rd != NULL);
++	rd->_size = size;
++}
++
++void
++ldns_rdf_set_type(ldns_rdf *rd, ldns_rdf_type type)
++{
++	assert(rd != NULL);
++	rd->_type = type;
++}
++
++void
++ldns_rdf_set_data(ldns_rdf *rd, void *data)
++{
++	/* only copy the pointer */
++	assert(rd != NULL);
++	rd->_data = data;
++}
++
++/* for types that allow it, return
++ * the native/host order type */
++uint8_t
++ldns_rdf2native_int8(const ldns_rdf *rd)
++{
++	uint8_t data;
++
++	/* only allow 8 bit rdfs */
++	if (ldns_rdf_size(rd) != LDNS_RDF_SIZE_BYTE) {
++		return 0;
++	}
++	
++	memcpy(&data, ldns_rdf_data(rd), sizeof(data));
++	return data;
++}
++
++uint16_t
++ldns_rdf2native_int16(const ldns_rdf *rd)
++{
++	uint16_t data;
++
++	/* only allow 16 bit rdfs */
++	if (ldns_rdf_size(rd) != LDNS_RDF_SIZE_WORD) {
++		return 0;
++	}
++	
++	memcpy(&data, ldns_rdf_data(rd), sizeof(data));
++	return ntohs(data);
++}
++
++uint32_t
++ldns_rdf2native_int32(const ldns_rdf *rd)
++{
++	uint32_t data;
++
++	/* only allow 32 bit rdfs */
++	if (ldns_rdf_size(rd) != LDNS_RDF_SIZE_DOUBLEWORD) {
++		return 0;
++	}
++	
++	memcpy(&data, ldns_rdf_data(rd), sizeof(data));
++	return ntohl(data);
++}
++
++time_t
++ldns_rdf2native_time_t(const ldns_rdf *rd)
++{
++	uint32_t data;
++
++	/* only allow 32 bit rdfs */
++	if (ldns_rdf_size(rd) != LDNS_RDF_SIZE_DOUBLEWORD ||
++			ldns_rdf_get_type(rd) != LDNS_RDF_TYPE_TIME) {
++		return 0;
++	}
++	memcpy(&data, ldns_rdf_data(rd), sizeof(data));
++	return (time_t)ntohl(data);
++}
++
++ldns_rdf *
++ldns_native2rdf_int8(ldns_rdf_type type, uint8_t value)
++{
++	return ldns_rdf_new_frm_data(type, LDNS_RDF_SIZE_BYTE, &value);
++}
++
++ldns_rdf *
++ldns_native2rdf_int16(ldns_rdf_type type, uint16_t value)
++{
++	uint16_t *rdf_data = LDNS_XMALLOC(uint16_t, 1);
++        ldns_rdf* rdf;
++	if (!rdf_data) {
++		return NULL;
++	}
++	ldns_write_uint16(rdf_data, value);
++	rdf = ldns_rdf_new(type, LDNS_RDF_SIZE_WORD, rdf_data);
++        if(!rdf)
++                LDNS_FREE(rdf_data);
++        return rdf;
++}
++
++ldns_rdf *
++ldns_native2rdf_int32(ldns_rdf_type type, uint32_t value)
++{
++	uint32_t *rdf_data = LDNS_XMALLOC(uint32_t, 1);
++        ldns_rdf* rdf;
++	if (!rdf_data) {
++		return NULL;
++	}
++	ldns_write_uint32(rdf_data, value);
++	rdf = ldns_rdf_new(type, LDNS_RDF_SIZE_DOUBLEWORD, rdf_data);
++        if(!rdf)
++                LDNS_FREE(rdf_data);
++        return rdf;
++}
++
++ldns_rdf *
++ldns_native2rdf_int16_data(size_t size, uint8_t *data)
++{
++	uint8_t *rdf_data = LDNS_XMALLOC(uint8_t, size + 2);
++        ldns_rdf* rdf;
++	if (!rdf_data) {
++		return NULL;
++	}
++	ldns_write_uint16(rdf_data, size);
++	memcpy(rdf_data + 2, data, size);
++	rdf = ldns_rdf_new(LDNS_RDF_TYPE_INT16_DATA, size + 2, rdf_data);
++        if(!rdf)
++                LDNS_FREE(rdf_data);
++        return rdf;
++}
++
++/* note: data must be allocated memory */
++ldns_rdf *
++ldns_rdf_new(ldns_rdf_type type, size_t size, void *data)
++{
++	ldns_rdf *rd;
++	rd = LDNS_MALLOC(ldns_rdf);
++	if (!rd) {
++		return NULL;
++	}
++	ldns_rdf_set_size(rd, size);
++	ldns_rdf_set_type(rd, type);
++	ldns_rdf_set_data(rd, data);
++	return rd;
++}
++
++ldns_rdf *
++ldns_rdf_new_frm_data(ldns_rdf_type type, size_t size, const void *data)
++{
++	ldns_rdf *rdf;
++
++	/* if the size is too big, fail */
++	if (size > LDNS_MAX_RDFLEN) {
++		return NULL;
++	}
++
++	/* allocate space */
++	rdf = LDNS_MALLOC(ldns_rdf);
++	if (!rdf) {
++		return NULL;
++	}
++	rdf->_data = LDNS_XMALLOC(uint8_t, size);
++	if (!rdf->_data) {
++		LDNS_FREE(rdf);
++		return NULL;
++	}
++	
++	/* set the values */
++	ldns_rdf_set_type(rdf, type);
++	ldns_rdf_set_size(rdf, size);
++	memcpy(rdf->_data, data, size);
++
++	return rdf;
++}
++
++ldns_rdf *
++ldns_rdf_clone(const ldns_rdf *rd)
++{
++	assert(rd != NULL);
++	return (ldns_rdf_new_frm_data( ldns_rdf_get_type(rd),
++		ldns_rdf_size(rd), ldns_rdf_data(rd)));
++}
++
++void
++ldns_rdf_deep_free(ldns_rdf *rd)
++{
++	if (rd) {
++		if (rd->_data) {
++			LDNS_FREE(rd->_data);
++		}
++		LDNS_FREE(rd);
++	}
++}
++
++void 
++ldns_rdf_free(ldns_rdf *rd)
++{
++	if (rd) {
++		LDNS_FREE(rd);
++	}
++}
++
++ldns_rdf *
++ldns_rdf_new_frm_str(ldns_rdf_type type, const char *str)
++{
++	ldns_rdf *rdf = NULL;
++	ldns_status status;
++
++	switch (type) {
++	case LDNS_RDF_TYPE_DNAME:
++		status = ldns_str2rdf_dname(&rdf, str);
++		break;
++	case LDNS_RDF_TYPE_INT8:
++		status = ldns_str2rdf_int8(&rdf, str);
++		break;
++	case LDNS_RDF_TYPE_INT16:
++		status = ldns_str2rdf_int16(&rdf, str);
++		break;
++	case LDNS_RDF_TYPE_INT32:
++		status = ldns_str2rdf_int32(&rdf, str);
++		break;
++	case LDNS_RDF_TYPE_A:
++		status = ldns_str2rdf_a(&rdf, str);
++		break;
++	case LDNS_RDF_TYPE_AAAA:
++		status = ldns_str2rdf_aaaa(&rdf, str);
++		break;
++	case LDNS_RDF_TYPE_STR:
++		status = ldns_str2rdf_str(&rdf, str);
++		break;
++	case LDNS_RDF_TYPE_APL:
++		status = ldns_str2rdf_apl(&rdf, str);
++		break;
++	case LDNS_RDF_TYPE_B64:
++		status = ldns_str2rdf_b64(&rdf, str);
++		break;
++	case LDNS_RDF_TYPE_B32_EXT:
++		status = ldns_str2rdf_b32_ext(&rdf, str);
++		break;
++	case LDNS_RDF_TYPE_HEX:
++		status = ldns_str2rdf_hex(&rdf, str);
++		break;
++	case LDNS_RDF_TYPE_NSEC:
++		status = ldns_str2rdf_nsec(&rdf, str);
++		break;
++	case LDNS_RDF_TYPE_TYPE:
++		status = ldns_str2rdf_type(&rdf, str);
++		break;
++	case LDNS_RDF_TYPE_CLASS:
++		status = ldns_str2rdf_class(&rdf, str);
++		break;
++	case LDNS_RDF_TYPE_CERT_ALG:
++		status = ldns_str2rdf_cert_alg(&rdf, str);
++		break;
++	case LDNS_RDF_TYPE_ALG:
++		status = ldns_str2rdf_alg(&rdf, str);
++		break;
++	case LDNS_RDF_TYPE_UNKNOWN:
++		status = ldns_str2rdf_unknown(&rdf, str);
++		break;
++	case LDNS_RDF_TYPE_TIME:
++		status = ldns_str2rdf_time(&rdf, str);
++		break;
++	case LDNS_RDF_TYPE_PERIOD:
++		status = ldns_str2rdf_period(&rdf, str);
++		break;
++	case LDNS_RDF_TYPE_HIP:
++		status = ldns_str2rdf_hip(&rdf, str);
++		break;
++	case LDNS_RDF_TYPE_SERVICE:
++		status = ldns_str2rdf_service(&rdf, str);
++		break;
++	case LDNS_RDF_TYPE_LOC:
++		status = ldns_str2rdf_loc(&rdf, str);
++		break;
++	case LDNS_RDF_TYPE_WKS:
++		status = ldns_str2rdf_wks(&rdf, str);
++		break;
++	case LDNS_RDF_TYPE_NSAP:
++		status = ldns_str2rdf_nsap(&rdf, str);
++		break;
++	case LDNS_RDF_TYPE_ATMA:
++		status = ldns_str2rdf_atma(&rdf, str);
++		break;
++	case LDNS_RDF_TYPE_IPSECKEY:
++		status = ldns_str2rdf_ipseckey(&rdf, str);
++		break;
++	case LDNS_RDF_TYPE_NSEC3_SALT:
++		status = ldns_str2rdf_nsec3_salt(&rdf, str);
++		break;
++	case LDNS_RDF_TYPE_NSEC3_NEXT_OWNER:
++		status = ldns_str2rdf_b32_ext(&rdf, str);
++		break;
++	case LDNS_RDF_TYPE_ILNP64:
++		status = ldns_str2rdf_ilnp64(&rdf, str);
++		break;
++	case LDNS_RDF_TYPE_EUI48:
++		status = ldns_str2rdf_eui48(&rdf, str);
++		break;
++	case LDNS_RDF_TYPE_EUI64:
++		status = ldns_str2rdf_eui64(&rdf, str);
++		break;
++	case LDNS_RDF_TYPE_TAG:
++		status = ldns_str2rdf_tag(&rdf, str);
++		break;
++	case LDNS_RDF_TYPE_LONG_STR:
++		status = ldns_str2rdf_long_str(&rdf, str);
++		break;
++	case LDNS_RDF_TYPE_CERTIFICATE_USAGE:
++		status = ldns_str2rdf_certificate_usage(&rdf, str);
++		break;
++	case LDNS_RDF_TYPE_SELECTOR:
++		status = ldns_str2rdf_selector(&rdf, str);
++		break;
++	case LDNS_RDF_TYPE_MATCHING_TYPE:
++		status = ldns_str2rdf_matching_type(&rdf, str);
++		break;
++	case LDNS_RDF_TYPE_NONE:
++	default:
++		/* default default ??? */
++		status = LDNS_STATUS_ERR;
++		break;
++	}
++	if (LDNS_STATUS_OK == status) {
++		ldns_rdf_set_type(rdf, type);
++		return rdf;
++	}
++	if (rdf) {
++		LDNS_FREE(rdf);
++	}
++	return NULL;
++}
++
++ldns_status
++ldns_rdf_new_frm_fp(ldns_rdf **rdf, ldns_rdf_type type, FILE *fp)
++{
++	return ldns_rdf_new_frm_fp_l(rdf, type, fp, NULL);
++}
++
++ldns_status
++ldns_rdf_new_frm_fp_l(ldns_rdf **rdf, ldns_rdf_type type, FILE *fp, int *line_nr)
++{
++	char *line;
++	ldns_rdf *r;
++	ssize_t t;
++
++	line = LDNS_XMALLOC(char, LDNS_MAX_LINELEN + 1);
++	if (!line) {
++		return LDNS_STATUS_MEM_ERR;
++	}
++
++	/* read an entire line in from the file */
++	if ((t = ldns_fget_token_l(fp, line, LDNS_PARSE_SKIP_SPACE, 0, line_nr)) == -1 || t == 0) {
++		LDNS_FREE(line);
++		return LDNS_STATUS_SYNTAX_RDATA_ERR;
++	}
++	r =  ldns_rdf_new_frm_str(type, (const char*) line);
++	LDNS_FREE(line);
++	if (rdf) {
++		*rdf = r;
++		return LDNS_STATUS_OK;
++	} else {
++		return LDNS_STATUS_NULL;
++	}
++}
++
++ldns_rdf *
++ldns_rdf_address_reverse(ldns_rdf *rd)
++{
++	uint8_t buf_4[LDNS_IP4ADDRLEN];
++	uint8_t buf_6[LDNS_IP6ADDRLEN * 2];
++	ldns_rdf *rev;
++	ldns_rdf *in_addr;
++	ldns_rdf *ret_dname;
++	uint8_t octet;
++	uint8_t nnibble;
++	uint8_t nibble;
++	uint8_t i, j;
++
++	char *char_dname;
++	int nbit;
++
++	if (ldns_rdf_get_type(rd) != LDNS_RDF_TYPE_A &&
++			ldns_rdf_get_type(rd) != LDNS_RDF_TYPE_AAAA) {
++		return NULL;
++	}
++
++	in_addr = NULL;
++	ret_dname = NULL;
++
++	switch(ldns_rdf_get_type(rd)) {
++		case LDNS_RDF_TYPE_A:
++			/* the length of the buffer is 4 */
++			buf_4[3] = ldns_rdf_data(rd)[0];
++			buf_4[2] = ldns_rdf_data(rd)[1];
++			buf_4[1] = ldns_rdf_data(rd)[2];
++			buf_4[0] = ldns_rdf_data(rd)[3];
++			in_addr = ldns_dname_new_frm_str("in-addr.arpa.");
++			if (!in_addr) {
++				return NULL;
++			}
++			/* make a new rdf and convert that back  */
++			rev = ldns_rdf_new_frm_data( LDNS_RDF_TYPE_A,
++				LDNS_IP4ADDRLEN, (void*)&buf_4);
++			if (!rev) {
++				LDNS_FREE(in_addr);
++				return NULL;
++			}
++
++			/* convert rev to a string */
++			char_dname = ldns_rdf2str(rev);
++			if (!char_dname) {
++				LDNS_FREE(in_addr);
++				ldns_rdf_deep_free(rev);
++				return NULL;
++			}
++			/* transform back to rdf with type dname */
++			ret_dname = ldns_dname_new_frm_str(char_dname);
++			if (!ret_dname) {
++				LDNS_FREE(in_addr);
++				ldns_rdf_deep_free(rev);
++				LDNS_FREE(char_dname);
++				return NULL;
++			}
++			/* not needed anymore */
++			ldns_rdf_deep_free(rev);
++			LDNS_FREE(char_dname);
++			break;
++		case LDNS_RDF_TYPE_AAAA:
++			/* some foo magic to reverse the nibbles ... */
++
++			for (nbit = 127; nbit >= 0; nbit = nbit - 4) {
++				/* calculate octett (8 bit) */
++				octet = ( ((unsigned int) nbit) & 0x78) >> 3;
++				/* calculate nibble */
++				nnibble = ( ((unsigned int) nbit) & 0x04) >> 2;
++				/* extract nibble */
++				nibble = (ldns_rdf_data(rd)[octet] & ( 0xf << (4 * (1 -
++						 nnibble)) ) ) >> ( 4 * (1 - 
++						nnibble));
++
++				buf_6[(LDNS_IP6ADDRLEN * 2 - 1) -
++					(octet * 2 + nnibble)] = 
++						(uint8_t)ldns_int_to_hexdigit((int)nibble);
++			}
++
++			char_dname = LDNS_XMALLOC(char, (LDNS_IP6ADDRLEN * 4));
++			if (!char_dname) {
++				return NULL;
++			}
++			char_dname[LDNS_IP6ADDRLEN * 4 - 1] = '\0'; /* closure */
++
++			/* walk the string and add . 's */
++			for (i = 0, j = 0; i < LDNS_IP6ADDRLEN * 2; i++, j = j + 2) {
++				char_dname[j] = (char)buf_6[i];
++				if (i != LDNS_IP6ADDRLEN * 2 - 1) {
++					char_dname[j + 1] = '.';
++				}
++			}
++			in_addr = ldns_dname_new_frm_str("ip6.arpa.");
++			if (!in_addr) {
++				LDNS_FREE(char_dname);
++				return NULL;
++			}
++
++			/* convert rev to a string */
++			ret_dname = ldns_dname_new_frm_str(char_dname);
++			LDNS_FREE(char_dname);
++			if (!ret_dname) {
++				ldns_rdf_deep_free(in_addr);
++				return NULL;
++			}
++			break;
++		default:
++			break;
++	}
++	/* add the suffix */
++	rev = ldns_dname_cat_clone(ret_dname, in_addr);
++
++	ldns_rdf_deep_free(ret_dname);
++	ldns_rdf_deep_free(in_addr);
++	return rev;
++}
++
++ldns_status
++ldns_rdf_hip_get_alg_hit_pk(ldns_rdf *rdf, uint8_t* alg,
++                            uint8_t *hit_size, uint8_t** hit,
++                            uint16_t *pk_size, uint8_t** pk)
++{
++	uint8_t *data;
++	size_t rdf_size;
++
++	if (! rdf || ! alg || ! hit || ! hit_size || ! pk || ! pk_size) {
++		return LDNS_STATUS_INVALID_POINTER;
++	} else if (ldns_rdf_get_type(rdf) != LDNS_RDF_TYPE_HIP) {
++		return LDNS_STATUS_INVALID_RDF_TYPE;
++	} else if ((rdf_size = ldns_rdf_size(rdf)) < 6) {
++		return LDNS_STATUS_WIRE_RDATA_ERR;
++	}
++	data = ldns_rdf_data(rdf);
++	*hit_size = data[0];
++	*alg      = data[1];
++	*pk_size  = ldns_read_uint16(data + 2);
++	*hit      = data + 4;
++	*pk       = data + 4 + *hit_size;
++	if (*hit_size == 0 || *pk_size == 0 ||
++			rdf_size < (size_t) *hit_size + *pk_size + 4) {
++		return LDNS_STATUS_WIRE_RDATA_ERR;
++	}
++	return LDNS_STATUS_OK;
++}
++
++ldns_status
++ldns_rdf_hip_new_frm_alg_hit_pk(ldns_rdf** rdf, uint8_t alg,
++                                uint8_t hit_size, uint8_t *hit,
++				uint16_t pk_size, uint8_t *pk)
++{
++	uint8_t *data;
++
++	if (! rdf) {
++		return LDNS_STATUS_INVALID_POINTER;
++	}
++	if (4 + hit_size + pk_size > LDNS_MAX_RDFLEN) {
++		return LDNS_STATUS_RDATA_OVERFLOW;
++	}
++	data = LDNS_XMALLOC(uint8_t, 4 + hit_size + pk_size);
++	if (data == NULL) {
++		return LDNS_STATUS_MEM_ERR;
++	}
++	data[0] = hit_size;
++	data[1] = alg;
++	ldns_write_uint16(data + 2, pk_size);
++	memcpy(data + 4, hit, hit_size);
++	memcpy(data + 4 + hit_size, pk, pk_size);
++	*rdf = ldns_rdf_new(LDNS_RDF_TYPE_HIP, 4 + hit_size + pk_size, data);
++	if (! *rdf) {
++		LDNS_FREE(data);
++		return LDNS_STATUS_MEM_ERR;
++	}
++	return LDNS_STATUS_OK;
++}
++
++ldns_status
++ldns_octet(char *word, size_t *length)
++{
++    char *s; 
++    char *p;
++    *length = 0;
++
++    for (s = p = word; *s != '\0'; s++,p++) {
++        switch (*s) {
++            case '.':
++                if (s[1] == '.') {
++		    return LDNS_STATUS_EMPTY_LABEL;
++                }
++                *p = *s;
++                (*length)++;
++                break;
++            case '\\':
++                if ('0' <= s[1] && s[1] <= '9' &&
++                    '0' <= s[2] && s[2] <= '9' &&
++                    '0' <= s[3] && s[3] <= '9') {
++                    /* \DDD seen */
++                    int val = ((s[1] - '0') * 100 +
++                           (s[2] - '0') * 10 + (s[3] - '0'));
++
++                    if (0 <= val && val <= 255) {
++                        /* this also handles \0 */
++                        s += 3;
++                        *p = val;
++                        (*length)++;
++                    } else {
++                        return LDNS_STATUS_DDD_OVERFLOW;
++                    }
++                } else {
++                    /* an espaced character, like \<space> ? 
++                    * remove the '\' keep the rest */
++                    *p = *++s;
++                    (*length)++;
++                }
++                break;
++            case '\"':
++                /* non quoted " Is either first or the last character in
++                 * the string */
++
++                *p = *++s; /* skip it */
++                (*length)++;
++		/* I'm not sure if this is needed in libdns... MG */
++                if ( *s == '\0' ) {
++                    /* ok, it was the last one */
++                    *p  = '\0'; 
++		    return LDNS_STATUS_OK;
++                }
++                break;
++            default:
++                *p = *s;
++                (*length)++;
++                break;
++        }
++    }
++    *p = '\0';
++    return LDNS_STATUS_OK;
++}
++
++int
++ldns_rdf_compare(const ldns_rdf *rd1, const ldns_rdf *rd2)
++{
++	uint16_t i1, i2, i;
++	uint8_t *d1, *d2;
++
++	/* only when both are not NULL we can say anything about them */
++	if (!rd1 && !rd2) {
++		return 0;
++	}
++	if (!rd1 || !rd2) {
++		return -1;
++	}
++	i1 = ldns_rdf_size(rd1);
++	i2 = ldns_rdf_size(rd2);
++
++	if (i1 < i2) {
++		return -1;
++	} else if (i1 > i2) {
++		return +1;
++	} else {
++		d1 = (uint8_t*)ldns_rdf_data(rd1);
++		d2 = (uint8_t*)ldns_rdf_data(rd2);
++		for(i = 0; i < i1; i++) {
++			if (d1[i] < d2[i]) {
++				return -1;
++			} else if (d1[i] > d2[i]) {
++				return +1;
++			}
++		}
++	}
++	return 0;
++}
++
++uint32_t
++ldns_str2period(const char *nptr, const char **endptr)
++{
++	int sign = 0;
++	uint32_t i = 0;
++	uint32_t seconds = 0;
++
++	for(*endptr = nptr; **endptr; (*endptr)++) {
++		switch (**endptr) {
++			case ' ':
++			case '\t':
++				break;
++			case '-':
++				if(sign == 0) {
++					sign = -1;
++				} else {
++					return seconds;
++				}
++				break;
++			case '+':
++				if(sign == 0) {
++					sign = 1;
++				} else {
++					return seconds;
++				}
++				break;
++			case 's':
++			case 'S':
++				seconds += i;
++				i = 0;
++				break;
++			case 'm':
++			case 'M':
++				seconds += i * 60;
++				i = 0;
++				break;
++			case 'h':
++			case 'H':
++				seconds += i * 60 * 60;
++				i = 0;
++				break;
++			case 'd':
++			case 'D':
++				seconds += i * 60 * 60 * 24;
++				i = 0;
++				break;
++			case 'w':
++			case 'W':
++				seconds += i * 60 * 60 * 24 * 7;
++				i = 0;
++				break;
++			case '0':
++			case '1':
++			case '2':
++			case '3':
++			case '4':
++			case '5':
++			case '6':
++			case '7':
++			case '8':
++			case '9':
++				i *= 10;
++				i += (**endptr - '0');
++				break;
++			default:
++				seconds += i;
++				/* disregard signedness */
++				return seconds;
++		}
++	}
++	seconds += i;
++	/* disregard signedness */
++	return seconds;
++}
+diff --git a/ldns/src/resolver.c b/ldns/src/resolver.c
+new file mode 100644
+index 0000000..b092404
+--- /dev/null
++++ b/ldns/src/resolver.c
+@@ -0,0 +1,1603 @@
++/*
++ * resolver.c
++ *
++ * resolver implementation
++ *
++ * a Net::DNS like library for C
++ *
++ * (c) NLnet Labs, 2004-2006
++ *
++ * See the file LICENSE for the license
++ */
++
++#include <ldns/config.h>
++
++#include <ldns/ldns.h>
++#include <strings.h>
++
++/* Access function for reading
++ * and setting the different Resolver
++ * options */
++
++/* read */
++uint16_t
++ldns_resolver_port(const ldns_resolver *r)
++{
++	return r->_port;
++}
++
++ldns_rdf *
++ldns_resolver_source(const ldns_resolver *r)
++{
++	return r->_source;
++}
++
++uint16_t
++ldns_resolver_edns_udp_size(const ldns_resolver *r)
++{
++	        return r->_edns_udp_size;
++}
++
++uint8_t
++ldns_resolver_retry(const ldns_resolver *r)
++{
++	return r->_retry;
++}
++
++uint8_t
++ldns_resolver_retrans(const ldns_resolver *r)
++{
++	return r->_retrans;
++}
++
++bool
++ldns_resolver_fallback(const ldns_resolver *r)
++{
++	return r->_fallback;
++}
++
++uint8_t
++ldns_resolver_ip6(const ldns_resolver *r)
++{
++	return r->_ip6;
++}
++
++bool
++ldns_resolver_recursive(const ldns_resolver *r)
++{
++	return r->_recursive;
++}
++
++bool
++ldns_resolver_debug(const ldns_resolver *r)
++{
++	return r->_debug;
++}
++
++bool
++ldns_resolver_dnsrch(const ldns_resolver *r)
++{
++	return r->_dnsrch;
++}
++
++bool
++ldns_resolver_fail(const ldns_resolver *r)
++{
++	return r->_fail;
++}
++
++bool
++ldns_resolver_defnames(const ldns_resolver *r)
++{
++	return r->_defnames;
++}
++
++ldns_rdf *
++ldns_resolver_domain(const ldns_resolver *r)
++{
++	return r->_domain;
++}
++
++ldns_rdf **
++ldns_resolver_searchlist(const ldns_resolver *r)
++{
++	return r->_searchlist;
++}
++
++ldns_rdf **
++ldns_resolver_nameservers(const ldns_resolver *r)
++{
++	return r->_nameservers;
++}
++
++size_t
++ldns_resolver_nameserver_count(const ldns_resolver *r)
++{
++	return r->_nameserver_count;
++}
++
++bool
++ldns_resolver_dnssec(const ldns_resolver *r)
++{
++	return r->_dnssec;
++}
++
++bool
++ldns_resolver_dnssec_cd(const ldns_resolver *r)
++{
++	return r->_dnssec_cd;
++}
++
++ldns_rr_list *
++ldns_resolver_dnssec_anchors(const ldns_resolver *r)
++{
++    return r->_dnssec_anchors;
++}
++
++bool
++ldns_resolver_trusted_key(const ldns_resolver *r, ldns_rr_list * keys, ldns_rr_list * trusted_keys)
++{
++  size_t i;
++  bool result = false;
++
++  ldns_rr_list * trust_anchors;
++  ldns_rr * cur_rr;
++
++  if (!r || !keys) { return false; }
++
++  trust_anchors = ldns_resolver_dnssec_anchors(r);
++
++  if (!trust_anchors) { return false; }
++
++  for (i = 0; i < ldns_rr_list_rr_count(keys); i++) {
++
++    cur_rr = ldns_rr_list_rr(keys, i);
++    if (ldns_rr_list_contains_rr(trust_anchors, cur_rr)) {
++      if (trusted_keys) { ldns_rr_list_push_rr(trusted_keys, cur_rr); }
++      result = true;
++    }
++  }
++
++  return result;
++}
++
++bool
++ldns_resolver_igntc(const ldns_resolver *r)
++{
++	return r->_igntc;
++}
++
++bool
++ldns_resolver_usevc(const ldns_resolver *r)
++{
++	return r->_usevc;
++}
++
++size_t *
++ldns_resolver_rtt(const ldns_resolver *r)
++{
++	return r->_rtt;
++}
++
++size_t
++ldns_resolver_nameserver_rtt(const ldns_resolver *r, size_t pos)
++{
++	size_t *rtt;
++
++	assert(r != NULL);
++
++	rtt = ldns_resolver_rtt(r);
++
++	if (pos >= ldns_resolver_nameserver_count(r)) {
++		/* error ?*/
++		return 0;
++	} else {
++		return rtt[pos];
++	}
++
++}
++
++struct timeval
++ldns_resolver_timeout(const ldns_resolver *r)
++{
++	return r->_timeout;
++}
++
++char *
++ldns_resolver_tsig_keyname(const ldns_resolver *r)
++{
++	return r->_tsig_keyname;
++}
++
++char *
++ldns_resolver_tsig_algorithm(const ldns_resolver *r)
++{
++	return r->_tsig_algorithm;
++}
++
++char *
++ldns_resolver_tsig_keydata(const ldns_resolver *r)
++{
++	return r->_tsig_keydata;
++}
++
++bool
++ldns_resolver_random(const ldns_resolver *r)
++{
++	return r->_random;
++}
++
++size_t
++ldns_resolver_searchlist_count(const ldns_resolver *r)
++{
++	return r->_searchlist_count;
++}
++
++/* write */
++void
++ldns_resolver_set_port(ldns_resolver *r, uint16_t p)
++{
++	r->_port = p;
++}
++
++void
++ldns_resolver_set_source(ldns_resolver *r, ldns_rdf *s)
++{
++	r->_source = s;
++}
++
++ldns_rdf *
++ldns_resolver_pop_nameserver(ldns_resolver *r)
++{
++	ldns_rdf **nameservers;
++	ldns_rdf *pop;
++	size_t ns_count;
++	size_t *rtt;
++
++	assert(r != NULL);
++
++	ns_count = ldns_resolver_nameserver_count(r);
++	nameservers = ldns_resolver_nameservers(r);
++	rtt = ldns_resolver_rtt(r);
++	if (ns_count == 0 || !nameservers) {
++		return NULL;
++	}
++
++	pop = nameservers[ns_count - 1];
++
++	if (ns_count == 1) {
++		LDNS_FREE(nameservers);
++		LDNS_FREE(rtt);
++
++		ldns_resolver_set_nameservers(r, NULL);
++		ldns_resolver_set_rtt(r, NULL);
++	} else {
++		nameservers = LDNS_XREALLOC(nameservers, ldns_rdf *, 
++				(ns_count - 1));
++		rtt = LDNS_XREALLOC(rtt, size_t, (ns_count - 1));
++
++	        ldns_resolver_set_nameservers(r, nameservers);
++	        ldns_resolver_set_rtt(r, rtt);
++	}
++	/* decr the count */
++	ldns_resolver_dec_nameserver_count(r);
++	return pop;
++}
++
++ldns_status
++ldns_resolver_push_nameserver(ldns_resolver *r, ldns_rdf *n)
++{
++	ldns_rdf **nameservers;
++	size_t ns_count;
++	size_t *rtt;
++
++	if (ldns_rdf_get_type(n) != LDNS_RDF_TYPE_A &&
++			ldns_rdf_get_type(n) != LDNS_RDF_TYPE_AAAA) {
++		return LDNS_STATUS_ERR;
++	}
++
++	ns_count = ldns_resolver_nameserver_count(r);
++	nameservers = ldns_resolver_nameservers(r);
++	rtt = ldns_resolver_rtt(r);
++
++	/* make room for the next one */
++	if (ns_count == 0) {
++		nameservers = LDNS_XMALLOC(ldns_rdf *, 1);
++	} else {
++		nameservers = LDNS_XREALLOC(nameservers, ldns_rdf *, (ns_count + 1));
++	}
++        if(!nameservers)
++                return LDNS_STATUS_MEM_ERR;
++
++	/* set the new value in the resolver */
++	ldns_resolver_set_nameservers(r, nameservers);
++
++	/* don't forget the rtt */
++	if (ns_count == 0) {
++		rtt = LDNS_XMALLOC(size_t, 1);
++	} else {
++		rtt = LDNS_XREALLOC(rtt, size_t, (ns_count + 1));
++	}
++        if(!rtt)
++                return LDNS_STATUS_MEM_ERR;
++
++	/* slide n in its slot. */
++	/* we clone it here, because then we can free the original
++	 * rr's where it stood */
++	nameservers[ns_count] = ldns_rdf_clone(n);
++	rtt[ns_count] = LDNS_RESOLV_RTT_MIN;
++	ldns_resolver_incr_nameserver_count(r);
++	ldns_resolver_set_rtt(r, rtt);
++	return LDNS_STATUS_OK;
++}
++
++ldns_status
++ldns_resolver_push_nameserver_rr(ldns_resolver *r, ldns_rr *rr)
++{
++	ldns_rdf *address;
++	if ((!rr) || (ldns_rr_get_type(rr) != LDNS_RR_TYPE_A &&
++			ldns_rr_get_type(rr) != LDNS_RR_TYPE_AAAA)) {
++		return LDNS_STATUS_ERR;
++	}
++	address = ldns_rr_rdf(rr, 0); /* extract the ip number */
++	if (address) {
++		return ldns_resolver_push_nameserver(r, address);
++	} else {
++		return LDNS_STATUS_ERR;
++	}
++}
++
++ldns_status
++ldns_resolver_push_nameserver_rr_list(ldns_resolver *r, ldns_rr_list *rrlist)
++{
++	ldns_rr *rr;
++	ldns_status stat;
++	size_t i;
++
++	stat = LDNS_STATUS_OK;
++	if (rrlist) {
++		for(i = 0; i < ldns_rr_list_rr_count(rrlist); i++) {
++			rr = ldns_rr_list_rr(rrlist, i);
++			if (ldns_resolver_push_nameserver_rr(r, rr) != LDNS_STATUS_OK) {
++				stat = LDNS_STATUS_ERR;
++				break;
++			}
++		}
++		return stat;
++	} else {
++		return LDNS_STATUS_ERR;
++	}
++}
++
++void
++ldns_resolver_set_edns_udp_size(ldns_resolver *r, uint16_t s)
++{
++	        r->_edns_udp_size = s;
++}
++
++void
++ldns_resolver_set_recursive(ldns_resolver *r, bool re)
++{
++	r->_recursive = re;
++}
++
++void
++ldns_resolver_set_dnssec(ldns_resolver *r, bool d)
++{
++	r->_dnssec = d;
++}
++
++void
++ldns_resolver_set_dnssec_cd(ldns_resolver *r, bool d)
++{
++	r->_dnssec_cd = d;
++}
++
++void
++ldns_resolver_set_dnssec_anchors(ldns_resolver *r, ldns_rr_list * l)
++{
++  r->_dnssec_anchors = l;
++}
++
++ldns_status
++ldns_resolver_push_dnssec_anchor(ldns_resolver *r, ldns_rr *rr)
++{
++  ldns_rr_list * trust_anchors;
++
++  if ((!rr) || (ldns_rr_get_type(rr) != LDNS_RR_TYPE_DNSKEY &&
++                ldns_rr_get_type(rr) != LDNS_RR_TYPE_DS)) {
++
++    return LDNS_STATUS_ERR;
++  }
++
++  if (!(trust_anchors = ldns_resolver_dnssec_anchors(r))) { /* Initialize */
++    trust_anchors = ldns_rr_list_new();
++    ldns_resolver_set_dnssec_anchors(r, trust_anchors);
++  }
++
++  return (ldns_rr_list_push_rr(trust_anchors, ldns_rr_clone(rr))) ? LDNS_STATUS_OK : LDNS_STATUS_ERR;
++}
++
++void
++ldns_resolver_set_igntc(ldns_resolver *r, bool i)
++{
++	r->_igntc = i;
++}
++
++void
++ldns_resolver_set_usevc(ldns_resolver *r, bool vc)
++{
++	r->_usevc = vc;
++}
++
++void
++ldns_resolver_set_debug(ldns_resolver *r, bool d)
++{
++	r->_debug = d;
++}
++
++void
++ldns_resolver_set_ip6(ldns_resolver *r, uint8_t ip6)
++{
++	r->_ip6 = ip6;
++}
++
++void
++ldns_resolver_set_fail(ldns_resolver *r, bool f)
++{
++	r->_fail =f;
++}
++
++static void
++ldns_resolver_set_searchlist_count(ldns_resolver *r, size_t c)
++{
++	r->_searchlist_count = c;
++}
++
++void
++ldns_resolver_set_nameserver_count(ldns_resolver *r, size_t c)
++{
++	r->_nameserver_count = c;
++}
++
++void
++ldns_resolver_set_dnsrch(ldns_resolver *r, bool d)
++{
++	r->_dnsrch = d;
++}
++
++void
++ldns_resolver_set_retry(ldns_resolver *r, uint8_t retry)
++{
++	r->_retry = retry;
++}
++
++void
++ldns_resolver_set_retrans(ldns_resolver *r, uint8_t retrans)
++{
++	r->_retrans = retrans;
++}
++
++void
++ldns_resolver_set_fallback(ldns_resolver *r, bool fallback)
++{
++	r->_fallback = fallback;
++}
++
++void
++ldns_resolver_set_nameservers(ldns_resolver *r, ldns_rdf **n)
++{
++	r->_nameservers = n;
++}
++
++void
++ldns_resolver_set_defnames(ldns_resolver *r, bool d)
++{
++	r->_defnames = d;
++}
++
++void
++ldns_resolver_set_rtt(ldns_resolver *r, size_t *rtt)
++{
++	r->_rtt = rtt;
++}
++
++void
++ldns_resolver_set_nameserver_rtt(ldns_resolver *r, size_t pos, size_t value)
++{
++	size_t *rtt;
++
++	assert(r != NULL);
++
++	rtt = ldns_resolver_rtt(r);
++
++	if (pos >= ldns_resolver_nameserver_count(r)) {
++		/* error ?*/
++	} else {
++		rtt[pos] = value;
++	}
++
++}
++
++void
++ldns_resolver_incr_nameserver_count(ldns_resolver *r)
++{
++	size_t c;
++
++	c = ldns_resolver_nameserver_count(r);
++	ldns_resolver_set_nameserver_count(r, ++c);
++}
++
++void
++ldns_resolver_dec_nameserver_count(ldns_resolver *r)
++{
++	size_t c;
++
++	c = ldns_resolver_nameserver_count(r);
++	if (c == 0) {
++		return;
++	} else {
++		ldns_resolver_set_nameserver_count(r, --c);
++	}
++}
++
++void
++ldns_resolver_set_domain(ldns_resolver *r, ldns_rdf *d)
++{
++	r->_domain = d;
++}
++
++void
++ldns_resolver_set_timeout(ldns_resolver *r, struct timeval timeout)
++{
++	r->_timeout.tv_sec = timeout.tv_sec;
++	r->_timeout.tv_usec = timeout.tv_usec;
++}
++
++void
++ldns_resolver_push_searchlist(ldns_resolver *r, ldns_rdf *d)
++{
++	ldns_rdf **searchlist;
++	size_t list_count;
++
++	if (ldns_rdf_get_type(d) != LDNS_RDF_TYPE_DNAME) {
++		return;
++	}
++
++	list_count = ldns_resolver_searchlist_count(r);
++	searchlist = ldns_resolver_searchlist(r);
++
++	searchlist = LDNS_XREALLOC(searchlist, ldns_rdf *, (list_count + 1));
++	if (searchlist) {
++		r->_searchlist = searchlist;
++
++		searchlist[list_count] = ldns_rdf_clone(d);
++		ldns_resolver_set_searchlist_count(r, list_count + 1);
++	} /* no way to report mem err */
++}
++
++void
++ldns_resolver_set_tsig_keyname(ldns_resolver *r, char *tsig_keyname)
++{
++	LDNS_FREE(r->_tsig_keyname);
++	r->_tsig_keyname = strdup(tsig_keyname);
++}
++
++void
++ldns_resolver_set_tsig_algorithm(ldns_resolver *r, char *tsig_algorithm)
++{
++	LDNS_FREE(r->_tsig_algorithm);
++	r->_tsig_algorithm = strdup(tsig_algorithm);
++}
++
++void
++ldns_resolver_set_tsig_keydata(ldns_resolver *r, char *tsig_keydata)
++{
++	LDNS_FREE(r->_tsig_keydata);
++	r->_tsig_keydata = strdup(tsig_keydata);
++}
++
++void
++ldns_resolver_set_random(ldns_resolver *r, bool b)
++{
++	r->_random = b;
++}
++
++/* more sophisticated functions */
++ldns_resolver *
++ldns_resolver_new(void)
++{
++	ldns_resolver *r;
++
++	r = LDNS_MALLOC(ldns_resolver);
++	if (!r) {
++		return NULL;
++	}
++
++	r->_searchlist = NULL;
++	r->_nameservers = NULL;
++	r->_rtt = NULL;
++
++	/* defaults are filled out */
++	ldns_resolver_set_searchlist_count(r, 0);
++	ldns_resolver_set_nameserver_count(r, 0);
++	ldns_resolver_set_usevc(r, 0);
++	ldns_resolver_set_port(r, LDNS_PORT);
++	ldns_resolver_set_domain(r, NULL);
++	ldns_resolver_set_defnames(r, false);
++	ldns_resolver_set_retry(r, 3);
++	ldns_resolver_set_retrans(r, 2);
++	ldns_resolver_set_fallback(r, true);
++	ldns_resolver_set_fail(r, false);
++	ldns_resolver_set_edns_udp_size(r, 0);
++	ldns_resolver_set_dnssec(r, false);
++	ldns_resolver_set_dnssec_cd(r, false);
++	ldns_resolver_set_dnssec_anchors(r, NULL);
++	ldns_resolver_set_ip6(r, LDNS_RESOLV_INETANY);
++	ldns_resolver_set_igntc(r, false);
++	ldns_resolver_set_recursive(r, false);
++	ldns_resolver_set_dnsrch(r, true);
++	ldns_resolver_set_source(r, NULL);
++	ldns_resolver_set_ixfr_serial(r, 0);
++
++	/* randomize the nameserver to be queried
++	 * when there are multiple
++	 */
++	ldns_resolver_set_random(r, true);
++
++	ldns_resolver_set_debug(r, 0);
++
++	r->_timeout.tv_sec = LDNS_DEFAULT_TIMEOUT_SEC;
++	r->_timeout.tv_usec = LDNS_DEFAULT_TIMEOUT_USEC;
++
++	/* TODO: fd=0 is actually a valid socket (stdin),
++           replace with -1 */
++	r->_socket = 0;
++	r->_axfr_soa_count = 0;
++	r->_axfr_i = 0;
++	r->_cur_axfr_pkt = NULL;
++
++	r->_tsig_keyname = NULL;
++	r->_tsig_keydata = NULL;
++	r->_tsig_algorithm = NULL;
++	return r;
++}
++
++ldns_resolver *
++ldns_resolver_clone(ldns_resolver *src)
++{
++	ldns_resolver *dst;
++	size_t i;
++
++	assert(src != NULL);
++
++	if (!(dst = LDNS_MALLOC(ldns_resolver))) return NULL;
++	(void) memcpy(dst, src, sizeof(ldns_resolver));
++
++	if (dst->_searchlist_count == 0)
++		dst->_searchlist = NULL;
++	else {
++		if (!(dst->_searchlist =
++		    LDNS_XMALLOC(ldns_rdf *, dst->_searchlist_count)))
++			goto error;
++		for (i = 0; i < dst->_searchlist_count; i++)
++			if (!(dst->_searchlist[i] =
++			    ldns_rdf_clone(src->_searchlist[i]))) {
++				dst->_searchlist_count = i;
++				goto error_searchlist;
++			}
++	}
++	if (dst->_nameserver_count == 0) {
++		dst->_nameservers = NULL;
++		dst->_rtt = NULL;
++	} else {
++		if (!(dst->_nameservers =
++		    LDNS_XMALLOC(ldns_rdf *, dst->_nameserver_count)))
++			goto error_searchlist;
++		for (i = 0; i < dst->_nameserver_count; i++)
++			if (!(dst->_nameservers[i] =
++			    ldns_rdf_clone(src->_nameservers[i]))) {
++				dst->_nameserver_count = i;
++				goto error_nameservers;
++			}
++		if (!(dst->_rtt =
++		    LDNS_XMALLOC(size_t, dst->_nameserver_count)))
++			goto error_nameservers;
++		(void) memcpy(dst->_rtt, src->_rtt,
++		    sizeof(size_t) * dst->_nameserver_count);
++	}
++	if (dst->_domain && (!(dst->_domain = ldns_rdf_clone(src->_domain))))
++		goto error_rtt;
++
++	if (dst->_tsig_keyname &&
++	    (!(dst->_tsig_keyname = strdup(src->_tsig_keyname))))
++		goto error_domain;
++
++	if (dst->_tsig_keydata &&
++	    (!(dst->_tsig_keydata = strdup(src->_tsig_keydata))))
++		goto error_tsig_keyname;
++
++	if (dst->_tsig_algorithm &&
++	    (!(dst->_tsig_algorithm = strdup(src->_tsig_algorithm))))
++		goto error_tsig_keydata;
++
++	if (dst->_cur_axfr_pkt &&
++	    (!(dst->_cur_axfr_pkt = ldns_pkt_clone(src->_cur_axfr_pkt))))
++		goto error_tsig_algorithm;
++
++	if (dst->_dnssec_anchors &&
++	    (!(dst->_dnssec_anchors=ldns_rr_list_clone(src->_dnssec_anchors))))
++		goto error_cur_axfr_pkt;
++
++	return dst;
++
++error_cur_axfr_pkt:
++	ldns_pkt_free(dst->_cur_axfr_pkt);
++error_tsig_algorithm:
++	LDNS_FREE(dst->_tsig_algorithm);
++error_tsig_keydata:
++	LDNS_FREE(dst->_tsig_keydata);
++error_tsig_keyname:
++	LDNS_FREE(dst->_tsig_keyname);
++error_domain:
++	ldns_rdf_deep_free(dst->_domain);
++error_rtt:
++	LDNS_FREE(dst->_rtt);
++error_nameservers:
++	for (i = 0; i < dst->_nameserver_count; i++)
++		ldns_rdf_deep_free(dst->_nameservers[i]);
++	LDNS_FREE(dst->_nameservers);
++error_searchlist:
++	for (i = 0; i < dst->_searchlist_count; i++)
++		ldns_rdf_deep_free(dst->_searchlist[i]);
++	LDNS_FREE(dst->_searchlist);
++error:
++	LDNS_FREE(dst);
++	return NULL;
++}
++
++
++ldns_status
++ldns_resolver_new_frm_fp(ldns_resolver **res, FILE *fp)
++{
++	return ldns_resolver_new_frm_fp_l(res, fp, NULL);
++}
++
++ldns_status
++ldns_resolver_new_frm_fp_l(ldns_resolver **res, FILE *fp, int *line_nr)
++{
++	ldns_resolver *r;
++	const char *keyword[LDNS_RESOLV_KEYWORDS];
++	char word[LDNS_MAX_LINELEN + 1];
++	int8_t expect;
++	uint8_t i;
++	ldns_rdf *tmp;
++#ifdef HAVE_SSL
++	ldns_rr *tmp_rr;
++#endif
++	ssize_t gtr, bgtr;
++	ldns_buffer *b;
++        int lnr = 0, oldline;
++	FILE* myfp = fp;
++        if(!line_nr) line_nr = &lnr;
++
++	if(!fp) {
++		myfp = fopen("/etc/resolv.conf", "r");
++		if(!myfp)
++			return LDNS_STATUS_FILE_ERR;
++	}
++
++	/* do this better
++	 * expect =
++	 * 0: keyword
++	 * 1: default domain dname
++	 * 2: NS aaaa or a record
++	 */
++
++	/* recognized keywords */
++	keyword[LDNS_RESOLV_NAMESERVER] = "nameserver";
++	keyword[LDNS_RESOLV_DEFDOMAIN] = "domain";
++	keyword[LDNS_RESOLV_SEARCH] = "search";
++	/* these two are read but not used atm TODO */
++	keyword[LDNS_RESOLV_SORTLIST] = "sortlist";
++	keyword[LDNS_RESOLV_OPTIONS] = "options";
++	keyword[LDNS_RESOLV_ANCHOR] = "anchor";
++	expect = LDNS_RESOLV_KEYWORD;
++
++	r = ldns_resolver_new();
++	if (!r) {
++		if(!fp) fclose(myfp);
++		return LDNS_STATUS_MEM_ERR;
++	}
++
++	gtr = 1;
++	word[0] = 0;
++        oldline = *line_nr;
++        expect = LDNS_RESOLV_KEYWORD;
++	while (gtr > 0) {
++		/* check comments */
++		if (word[0] == '#') {
++                        word[0]='x';
++                        if(oldline == *line_nr) {
++                                /* skip until end of line */
++                                int c;
++                                do {
++                                        c = fgetc(myfp);
++                                } while(c != EOF && c != '\n');
++                                if(c=='\n') (*line_nr)++;
++                        }
++			/* and read next to prepare for further parsing */
++                        oldline = *line_nr;
++			continue;
++		}
++                oldline = *line_nr;
++		switch(expect) {
++			case LDNS_RESOLV_KEYWORD:
++				/* keyword */
++				gtr = ldns_fget_token_l(myfp, word, LDNS_PARSE_NORMAL, 0, line_nr);
++				if (gtr != 0) {
++                                        if(word[0] == '#') continue;
++					for(i = 0; i < LDNS_RESOLV_KEYWORDS; i++) {
++						if (strcasecmp(keyword[i], word) == 0) {
++							/* chosen the keyword and
++							 * expect values carefully
++	        					 */
++							expect = i;
++							break;
++						}
++					}
++					/* no keyword recognized */
++					if (expect == LDNS_RESOLV_KEYWORD) {
++						/* skip line */
++						/*
++						ldns_resolver_deep_free(r);
++						if(!fp) fclose(myfp);
++						return LDNS_STATUS_SYNTAX_KEYWORD_ERR;
++						*/
++					}
++				}
++				break;
++			case LDNS_RESOLV_DEFDOMAIN:
++				/* default domain dname */
++				gtr = ldns_fget_token_l(myfp, word, LDNS_PARSE_NORMAL, 0, line_nr);
++				if (gtr == 0) {
++					if(!fp) fclose(myfp);
++					return LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR;
++				}
++                                if(word[0] == '#') {
++                                        expect = LDNS_RESOLV_KEYWORD;
++                                        continue;
++                                }
++				tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, word);
++				if (!tmp) {
++					ldns_resolver_deep_free(r);
++					if(!fp) fclose(myfp);
++					return LDNS_STATUS_SYNTAX_DNAME_ERR;
++				}
++
++				/* DOn't free, because we copy the pointer */
++				ldns_resolver_set_domain(r, tmp);
++				expect = LDNS_RESOLV_KEYWORD;
++				break;
++			case LDNS_RESOLV_NAMESERVER:
++				/* NS aaaa or a record */
++				gtr = ldns_fget_token_l(myfp, word, LDNS_PARSE_NORMAL, 0, line_nr);
++				if (gtr == 0) {
++					if(!fp) fclose(myfp);
++					return LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR;
++				}
++                                if(word[0] == '#') {
++                                        expect = LDNS_RESOLV_KEYWORD;
++                                        continue;
++                                }
++                                if(strchr(word, '%')) {
++                                        /* snip off interface labels,
++                                         * fe80::222:19ff:fe31:4222%eth0 */
++                                        strchr(word, '%')[0]=0;
++                                }
++				tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_AAAA, word);
++				if (!tmp) {
++					/* try ip4 */
++					tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_A, word);
++				}
++				/* could not parse it, exit */
++				if (!tmp) {
++					ldns_resolver_deep_free(r);
++					if(!fp) fclose(myfp);
++					return LDNS_STATUS_SYNTAX_ERR;
++				}
++				(void)ldns_resolver_push_nameserver(r, tmp);
++				ldns_rdf_deep_free(tmp);
++				expect = LDNS_RESOLV_KEYWORD;
++				break;
++			case LDNS_RESOLV_SEARCH:
++				/* search list domain dname */
++				gtr = ldns_fget_token_l(myfp, word, LDNS_PARSE_SKIP_SPACE, 0, line_nr);
++				b = LDNS_MALLOC(ldns_buffer);
++				if(!b) {
++					ldns_resolver_deep_free(r);
++					if(!fp) fclose(myfp);
++					return LDNS_STATUS_MEM_ERR;
++				}
++
++				ldns_buffer_new_frm_data(b, word, (size_t) gtr);
++				if(ldns_buffer_status(b) != LDNS_STATUS_OK) {
++					LDNS_FREE(b);
++					ldns_resolver_deep_free(r);
++					if(!fp) fclose(myfp);
++					return LDNS_STATUS_MEM_ERR;
++				}
++				bgtr = ldns_bget_token(b, word, LDNS_PARSE_NORMAL, (size_t) gtr + 1);
++				while (bgtr > 0) {
++					gtr -= bgtr;
++                                        if(word[0] == '#') {
++                                                expect = LDNS_RESOLV_KEYWORD;
++                                                break;
++                                        }
++					tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, word);
++					if (!tmp) {
++						ldns_resolver_deep_free(r);
++						ldns_buffer_free(b);
++						if(!fp) fclose(myfp);
++						return LDNS_STATUS_SYNTAX_DNAME_ERR;
++					}
++
++					ldns_resolver_push_searchlist(r, tmp);
++
++					ldns_rdf_deep_free(tmp);
++					bgtr = ldns_bget_token(b, word, LDNS_PARSE_NORMAL,
++					    (size_t) gtr + 1);
++				}
++				ldns_buffer_free(b);
++				if (expect != LDNS_RESOLV_KEYWORD) {
++					gtr = 1;
++					expect = LDNS_RESOLV_KEYWORD;
++				}
++				break;
++			case LDNS_RESOLV_SORTLIST:
++				gtr = ldns_fget_token_l(myfp, word, LDNS_PARSE_SKIP_SPACE, 0, line_nr);
++				/* sortlist not implemented atm */
++				expect = LDNS_RESOLV_KEYWORD;
++				break;
++			case LDNS_RESOLV_OPTIONS:
++				gtr = ldns_fget_token_l(myfp, word, LDNS_PARSE_SKIP_SPACE, 0, line_nr);
++				/* options not implemented atm */
++				expect = LDNS_RESOLV_KEYWORD;
++				break;
++			case LDNS_RESOLV_ANCHOR:
++				/* a file containing a DNSSEC trust anchor */
++				gtr = ldns_fget_token_l(myfp, word, LDNS_PARSE_NORMAL, 0, line_nr);
++				if (gtr == 0) {
++					ldns_resolver_deep_free(r);
++					if(!fp) fclose(myfp);
++					return LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR;
++				}
++                                if(word[0] == '#') {
++                                        expect = LDNS_RESOLV_KEYWORD;
++                                        continue;
++                                }
++
++#ifdef HAVE_SSL
++				tmp_rr = ldns_read_anchor_file(word);
++				(void) ldns_resolver_push_dnssec_anchor(r, tmp_rr);
++				ldns_rr_free(tmp_rr);
++#endif
++				expect = LDNS_RESOLV_KEYWORD;
++				break;
++		}
++	}
++
++	if(!fp)
++		fclose(myfp);
++
++	if (res) {
++		*res = r;
++		return LDNS_STATUS_OK;
++	} else {
++		ldns_resolver_deep_free(r);
++		return LDNS_STATUS_NULL;
++	}
++}
++
++ldns_status
++ldns_resolver_new_frm_file(ldns_resolver **res, const char *filename)
++{
++	ldns_resolver *r;
++	FILE *fp;
++	ldns_status s;
++
++	if (!filename) {
++		fp = fopen(LDNS_RESOLV_CONF, "r");
++
++	} else {
++		fp = fopen(filename, "r");
++	}
++	if (!fp) {
++		return LDNS_STATUS_FILE_ERR;
++	}
++
++	s = ldns_resolver_new_frm_fp(&r, fp);
++	fclose(fp);
++	if (s == LDNS_STATUS_OK) {
++		if (res) {
++			*res = r;
++			return LDNS_STATUS_OK;
++		} else  {
++			ldns_resolver_free(r);
++			return LDNS_STATUS_NULL;
++		}
++	}
++	return s;
++}
++
++void
++ldns_resolver_free(ldns_resolver *res)
++{
++	LDNS_FREE(res);
++}
++
++void
++ldns_resolver_deep_free(ldns_resolver *res)
++{
++	size_t i;
++
++	if (res) {
++		if (res->_searchlist) {
++			for (i = 0; i < ldns_resolver_searchlist_count(res); i++) {
++				ldns_rdf_deep_free(res->_searchlist[i]);
++			}
++			LDNS_FREE(res->_searchlist);
++		}
++		if (res->_nameservers) {
++			for (i = 0; i < res->_nameserver_count; i++) {
++				ldns_rdf_deep_free(res->_nameservers[i]);
++			}
++			LDNS_FREE(res->_nameservers);
++		}
++		if (ldns_resolver_domain(res)) {
++			ldns_rdf_deep_free(ldns_resolver_domain(res));
++		}
++		if (res->_tsig_keyname) {
++			LDNS_FREE(res->_tsig_keyname);
++		}
++		if (res->_tsig_keydata) {
++			LDNS_FREE(res->_tsig_keydata);
++		}
++		if (res->_tsig_algorithm) {
++			LDNS_FREE(res->_tsig_algorithm);
++		}
++
++		if (res->_cur_axfr_pkt) {
++			ldns_pkt_free(res->_cur_axfr_pkt);
++		}
++
++		if (res->_rtt) {
++			LDNS_FREE(res->_rtt);
++		}
++		if (res->_dnssec_anchors) {
++			ldns_rr_list_deep_free(res->_dnssec_anchors);
++		}
++		LDNS_FREE(res);
++	}
++}
++
++ldns_status
++ldns_resolver_search_status(ldns_pkt** pkt,
++		ldns_resolver *r, const  ldns_rdf *name,
++		ldns_rr_type t, ldns_rr_class c, uint16_t flags)
++{
++	ldns_rdf *new_name;
++	ldns_rdf **search_list;
++	size_t i;
++	ldns_status s = LDNS_STATUS_OK;
++	ldns_rdf root_dname = { 1, LDNS_RDF_TYPE_DNAME, (void *)"" };
++
++	if (ldns_dname_absolute(name)) {
++		/* query as-is */
++		return ldns_resolver_query_status(pkt, r, name, t, c, flags);
++	} else if (ldns_resolver_dnsrch(r)) {
++		search_list = ldns_resolver_searchlist(r);
++		for (i = 0; i <= ldns_resolver_searchlist_count(r); i++) {
++			if (i == ldns_resolver_searchlist_count(r)) {
++				new_name = ldns_dname_cat_clone(name,
++						&root_dname);
++			} else {
++				new_name = ldns_dname_cat_clone(name,
++						search_list[i]);
++			}
++
++			s = ldns_resolver_query_status(pkt, r,
++					new_name, t, c, flags);
++			ldns_rdf_free(new_name);
++			if (pkt && *pkt) {
++				if (s == LDNS_STATUS_OK && 
++						ldns_pkt_get_rcode(*pkt) ==
++						LDNS_RCODE_NOERROR) {
++
++					return LDNS_STATUS_OK;
++				}
++				ldns_pkt_free(*pkt);
++				*pkt = NULL;
++			}
++		}
++	}
++	return s;
++}
++
++ldns_pkt *
++ldns_resolver_search(const ldns_resolver *r,const  ldns_rdf *name,
++	ldns_rr_type t, ldns_rr_class c, uint16_t flags)
++{
++	ldns_pkt* pkt = NULL;
++	if (ldns_resolver_search_status(&pkt, (ldns_resolver *)r,
++				name, t, c, flags) != LDNS_STATUS_OK) {
++		ldns_pkt_free(pkt);
++	}
++	return pkt;
++}
++
++ldns_status
++ldns_resolver_query_status(ldns_pkt** pkt,
++		ldns_resolver *r, const ldns_rdf *name,
++		ldns_rr_type t, ldns_rr_class c, uint16_t flags)
++{
++	ldns_rdf *newname;
++	ldns_status status;
++
++	if (!ldns_resolver_defnames(r) || !ldns_resolver_domain(r)) {
++		return ldns_resolver_send(pkt, r, name, t, c, flags);
++	}
++
++	newname = ldns_dname_cat_clone(name, ldns_resolver_domain(r));
++	if (!newname) {
++		return LDNS_STATUS_MEM_ERR;
++	}
++	status = ldns_resolver_send(pkt, r, newname, t, c, flags);
++	ldns_rdf_free(newname);
++	return status;
++}
++
++ldns_pkt *
++ldns_resolver_query(const ldns_resolver *r, const ldns_rdf *name,
++	ldns_rr_type t, ldns_rr_class c, uint16_t flags)
++{
++	ldns_pkt* pkt = NULL;
++	if (ldns_resolver_query_status(&pkt, (ldns_resolver *)r,
++				name, t, c, flags) != LDNS_STATUS_OK) {
++		ldns_pkt_free(pkt);
++	}
++	return pkt;
++}
++
++static size_t *
++ldns_resolver_backup_rtt(ldns_resolver *r)
++{
++	size_t *new_rtt;
++	size_t *old_rtt = ldns_resolver_rtt(r);
++
++	if (old_rtt && ldns_resolver_nameserver_count(r)) {
++		new_rtt = LDNS_XMALLOC(size_t
++				, ldns_resolver_nameserver_count(r));
++		memcpy(new_rtt, old_rtt, sizeof(size_t)
++				* ldns_resolver_nameserver_count(r));
++		ldns_resolver_set_rtt(r, new_rtt);
++		return old_rtt;
++	}
++	return NULL;
++}
++
++static void
++ldns_resolver_restore_rtt(ldns_resolver *r, size_t *old_rtt)
++{
++	size_t *cur_rtt = ldns_resolver_rtt(r);
++
++	if (cur_rtt) {
++		LDNS_FREE(cur_rtt);
++	}
++	ldns_resolver_set_rtt(r, old_rtt);
++}
++
++ldns_status
++ldns_resolver_send_pkt(ldns_pkt **answer, ldns_resolver *r,
++				   ldns_pkt *query_pkt)
++{
++	ldns_pkt *answer_pkt = NULL;
++	ldns_status stat = LDNS_STATUS_OK;
++	size_t *rtt;
++
++	stat = ldns_send(&answer_pkt, (ldns_resolver *)r, query_pkt);
++	if (stat != LDNS_STATUS_OK) {
++		if(answer_pkt) {
++			ldns_pkt_free(answer_pkt);
++			answer_pkt = NULL;
++		}
++	} else {
++		/* if tc=1 fall back to EDNS and/or TCP */
++		/* check for tcp first (otherwise we don't care about tc=1) */
++		if (!ldns_resolver_usevc(r) && ldns_resolver_fallback(r)) {
++			if (ldns_pkt_tc(answer_pkt)) {
++				/* was EDNS0 set? */
++				if (ldns_pkt_edns_udp_size(query_pkt) == 0) {
++					ldns_pkt_set_edns_udp_size(query_pkt
++							, 4096);
++					ldns_pkt_free(answer_pkt);
++					answer_pkt = NULL;
++					/* Nameservers should not become 
++					 * unreachable because fragments are
++					 * dropped (network error). We might
++					 * still have success with TCP.
++					 * Therefore maintain reachability
++					 * statuses of the nameservers by
++					 * backup and restore the rtt list.
++					 */
++					rtt = ldns_resolver_backup_rtt(r);
++					stat = ldns_send(&answer_pkt, r
++							, query_pkt);
++					ldns_resolver_restore_rtt(r, rtt);
++				}
++				/* either way, if it is still truncated, use TCP */
++				if (stat != LDNS_STATUS_OK ||
++				    ldns_pkt_tc(answer_pkt)) {
++					ldns_resolver_set_usevc(r, true);
++					ldns_pkt_free(answer_pkt);
++					stat = ldns_send(&answer_pkt, r, query_pkt);
++					ldns_resolver_set_usevc(r, false);
++				}
++			}
++		}
++	}
++
++	if (answer) {
++		*answer = answer_pkt;
++	}
++
++	return stat;
++}
++
++ldns_status
++ldns_resolver_prepare_query_pkt(ldns_pkt **query_pkt, ldns_resolver *r,
++                                const ldns_rdf *name, ldns_rr_type t,
++                                ldns_rr_class c, uint16_t flags)
++{
++	struct timeval now;
++	ldns_rr* soa = NULL;
++
++	/* prepare a question pkt from the parameters
++	 * and then send this */
++	if (t == LDNS_RR_TYPE_IXFR) {
++		ldns_rdf *owner_rdf;
++		ldns_rdf *mname_rdf;
++		ldns_rdf *rname_rdf;
++		ldns_rdf *serial_rdf;
++		ldns_rdf *refresh_rdf;
++		ldns_rdf *retry_rdf;
++		ldns_rdf *expire_rdf;
++		ldns_rdf *minimum_rdf;
++		soa = ldns_rr_new();
++
++		if (!soa) {
++			return LDNS_STATUS_ERR;
++		}
++		owner_rdf = ldns_rdf_clone(name);
++		if (!owner_rdf) {
++			ldns_rr_free(soa);
++			return LDNS_STATUS_ERR;
++		}
++		ldns_rr_set_owner(soa, owner_rdf);
++		ldns_rr_set_type(soa, LDNS_RR_TYPE_SOA);
++		ldns_rr_set_class(soa, c);
++		ldns_rr_set_question(soa, false);
++		if (ldns_str2rdf_dname(&mname_rdf, ".") != LDNS_STATUS_OK) {
++			ldns_rr_free(soa);
++			return LDNS_STATUS_ERR;
++		} else	ldns_rr_push_rdf(soa, mname_rdf);
++		if (ldns_str2rdf_dname(&rname_rdf, ".") != LDNS_STATUS_OK) {
++			ldns_rr_free(soa);
++			return LDNS_STATUS_ERR;
++		} else	ldns_rr_push_rdf(soa, rname_rdf);
++		serial_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, ldns_resolver_get_ixfr_serial(r));
++		if (!serial_rdf) {
++			ldns_rr_free(soa);
++			return LDNS_STATUS_ERR;
++		} else	ldns_rr_push_rdf(soa, serial_rdf);
++		refresh_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0);
++		if (!refresh_rdf) {
++			ldns_rr_free(soa);
++			return LDNS_STATUS_ERR;
++		} else	ldns_rr_push_rdf(soa, refresh_rdf);
++		retry_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0);
++		if (!retry_rdf) {
++			ldns_rr_free(soa);
++			return LDNS_STATUS_ERR;
++		} else	ldns_rr_push_rdf(soa, retry_rdf);
++		expire_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0);
++		if (!expire_rdf) {
++			ldns_rr_free(soa);
++			return LDNS_STATUS_ERR;
++		} else	ldns_rr_push_rdf(soa, expire_rdf);
++		minimum_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0);
++		if (!minimum_rdf) {
++			ldns_rr_free(soa);
++			return LDNS_STATUS_ERR;
++		} else	ldns_rr_push_rdf(soa, minimum_rdf);
++
++		*query_pkt = ldns_pkt_ixfr_request_new(ldns_rdf_clone(name),
++			c, flags, soa);
++	} else {
++		*query_pkt = ldns_pkt_query_new(ldns_rdf_clone(name), t, c, flags);
++	}
++	if (!*query_pkt) {
++		ldns_rr_free(soa);
++		return LDNS_STATUS_ERR;
++	}
++
++	/* set DO bit if necessary */
++	if (ldns_resolver_dnssec(r)) {
++		if (ldns_resolver_edns_udp_size(r) == 0) {
++			ldns_resolver_set_edns_udp_size(r, 4096);
++		}
++		ldns_pkt_set_edns_do(*query_pkt, true);
++		if (ldns_resolver_dnssec_cd(r) || (flags & LDNS_CD)) {
++			ldns_pkt_set_cd(*query_pkt, true);
++		}
++	}
++
++	/* transfer the udp_edns_size from the resolver to the packet */
++	if (ldns_resolver_edns_udp_size(r) != 0) {
++		ldns_pkt_set_edns_udp_size(*query_pkt, ldns_resolver_edns_udp_size(r));
++	}
++
++	/* set the timestamp */
++	now.tv_sec = time(NULL);
++	now.tv_usec = 0;
++	ldns_pkt_set_timestamp(*query_pkt, now);
++
++
++	if (ldns_resolver_debug(r)) {
++		ldns_pkt_print(stdout, *query_pkt);
++	}
++
++	/* only set the id if it is not set yet */
++	if (ldns_pkt_id(*query_pkt) == 0) {
++		ldns_pkt_set_random_id(*query_pkt);
++	}
++
++	return LDNS_STATUS_OK;
++}
++
++ldns_status
++ldns_resolver_send(ldns_pkt **answer, ldns_resolver *r, const ldns_rdf *name,
++		ldns_rr_type t, ldns_rr_class c, uint16_t flags)
++{
++	ldns_pkt *query_pkt;
++	ldns_pkt *answer_pkt;
++	ldns_status status;
++
++	assert(r != NULL);
++	assert(name != NULL);
++
++	answer_pkt = NULL;
++
++	/* do all the preprocessing here, then fire of an query to
++	 * the network */
++
++	if (0 == t) {
++		t= LDNS_RR_TYPE_A;
++	}
++	if (0 == c) {
++		c= LDNS_RR_CLASS_IN;
++	}
++	if (0 == ldns_resolver_nameserver_count(r)) {
++		return LDNS_STATUS_RES_NO_NS;
++	}
++	if (ldns_rdf_get_type(name) != LDNS_RDF_TYPE_DNAME) {
++		return LDNS_STATUS_RES_QUERY;
++	}
++
++	status = ldns_resolver_prepare_query_pkt(&query_pkt, r, name,
++	                                         t, c, flags);
++	if (status != LDNS_STATUS_OK) {
++		return status;
++	}
++
++	/* if tsig values are set, tsign it */
++	/* TODO: make last 3 arguments optional too? maybe make complete
++	         rr instead of separate values in resolver (and packet)
++	  Jelte
++	  should this go in pkt_prepare?
++	*/
++	if (ldns_resolver_tsig_keyname(r) && ldns_resolver_tsig_keydata(r)) {
++#ifdef HAVE_SSL
++		status = ldns_pkt_tsig_sign(query_pkt,
++		                            ldns_resolver_tsig_keyname(r),
++		                            ldns_resolver_tsig_keydata(r),
++		                            300, ldns_resolver_tsig_algorithm(r), NULL);
++		if (status != LDNS_STATUS_OK) {
++			ldns_pkt_free(query_pkt);
++			return LDNS_STATUS_CRYPTO_TSIG_ERR;
++		}
++#else
++		ldns_pkt_free(query_pkt);
++	        return LDNS_STATUS_CRYPTO_TSIG_ERR;
++#endif /* HAVE_SSL */
++	}
++
++	status = ldns_resolver_send_pkt(&answer_pkt, r, query_pkt);
++	ldns_pkt_free(query_pkt);
++
++	/* allows answer to be NULL when not interested in return value */
++	if (answer) {
++		*answer = answer_pkt;
++	}
++	return status;
++}
++
++ldns_rr *
++ldns_axfr_next(ldns_resolver *resolver)
++{
++	ldns_rr *cur_rr;
++	uint8_t *packet_wire;
++	size_t packet_wire_size;
++	ldns_status status;
++
++	/* check if start() has been called */
++	if (!resolver || resolver->_socket == 0) {
++		return NULL;
++	}
++
++	if (resolver->_cur_axfr_pkt) {
++		if (resolver->_axfr_i == ldns_pkt_ancount(resolver->_cur_axfr_pkt)) {
++			ldns_pkt_free(resolver->_cur_axfr_pkt);
++			resolver->_cur_axfr_pkt = NULL;
++			return ldns_axfr_next(resolver);
++		}
++		cur_rr = ldns_rr_clone(ldns_rr_list_rr(
++					ldns_pkt_answer(resolver->_cur_axfr_pkt),
++					resolver->_axfr_i));
++		resolver->_axfr_i++;
++		if (ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_SOA) {
++			resolver->_axfr_soa_count++;
++			if (resolver->_axfr_soa_count >= 2) {
++#ifndef USE_WINSOCK
++				close(resolver->_socket);
++#else
++				closesocket(resolver->_socket);
++#endif
++				resolver->_socket = 0;
++				ldns_pkt_free(resolver->_cur_axfr_pkt);
++				resolver->_cur_axfr_pkt = NULL;
++			}
++		}
++		return cur_rr;
++	} else {
++               packet_wire = ldns_tcp_read_wire_timeout(resolver->_socket, &packet_wire_size, resolver->_timeout);
++		if(!packet_wire)
++			return NULL;
++
++		status = ldns_wire2pkt(&resolver->_cur_axfr_pkt, packet_wire,
++				     packet_wire_size);
++		LDNS_FREE(packet_wire);
++
++		resolver->_axfr_i = 0;
++		if (status != LDNS_STATUS_OK) {
++			/* TODO: make status return type of this function (...api change) */
++#ifdef STDERR_MSGS
++			fprintf(stderr, "Error parsing rr during AXFR: %s\n", ldns_get_errorstr_by_id(status));
++#endif
++
++			/* we must now also close the socket, otherwise subsequent uses of the
++			   same resolver structure will fail because the link is still open or
++			   in an undefined state */
++#ifndef USE_WINSOCK
++			close(resolver->_socket);
++#else
++			closesocket(resolver->_socket);
++#endif
++			resolver->_socket = 0;
++
++			return NULL;
++		} else if (ldns_pkt_get_rcode(resolver->_cur_axfr_pkt) != 0) {
++#ifdef STDERR_MSGS
++			ldns_lookup_table *rcode = ldns_lookup_by_id(
++				ldns_rcodes,(int) ldns_pkt_get_rcode(
++				resolver->_cur_axfr_pkt));
++			if (rcode) {
++				fprintf(stderr, "Error in AXFR: %s\n", 
++						rcode->name);
++			} else {
++				fprintf(stderr, "Error in AXFR: %d\n", 
++						(int) ldns_pkt_get_rcode(
++						resolver->_cur_axfr_pkt));
++			}
++#endif
++
++			/* we must now also close the socket, otherwise subsequent uses of the
++			   same resolver structure will fail because the link is still open or
++			   in an undefined state */
++#ifndef USE_WINSOCK
++			close(resolver->_socket);
++#else
++			closesocket(resolver->_socket);
++#endif
++			resolver->_socket = 0;
++
++			return NULL;
++		} else {
++			return ldns_axfr_next(resolver);
++		}
++
++	}
++
++}
++
++/* this function is needed to abort a transfer that is in progress;
++ * without it an aborted transfer will lead to the AXFR code in the
++ * library staying in an indetermined state because the socket for the
++ * AXFR is never closed
++ */
++void
++ldns_axfr_abort(ldns_resolver *resolver)
++{
++	/* Only abort if an actual AXFR is in progress */
++	if (resolver->_socket != 0)
++	{
++#ifndef USE_WINSOCK
++		close(resolver->_socket);
++#else
++		closesocket(resolver->_socket);
++#endif
++		resolver->_socket = 0;
++	}
++}
++
++bool
++ldns_axfr_complete(const ldns_resolver *res)
++{
++	/* complete when soa count is 2? */
++	return res->_axfr_soa_count == 2;
++}
++
++ldns_pkt *
++ldns_axfr_last_pkt(const ldns_resolver *res)
++{
++	return res->_cur_axfr_pkt;
++}
++
++void
++ldns_resolver_set_ixfr_serial(ldns_resolver *r, uint32_t serial)
++{
++	r->_serial = serial;
++}
++
++uint32_t
++ldns_resolver_get_ixfr_serial(const ldns_resolver *res)
++{
++	return res->_serial;
++}
++
++
++/* random isn't really that good */
++void
++ldns_resolver_nameservers_randomize(ldns_resolver *r)
++{
++	uint16_t i, j;
++	ldns_rdf **ns, *tmpns;
++	size_t *rtt, tmprtt;
++
++	/* should I check for ldns_resolver_random?? */
++	assert(r != NULL);
++
++	ns = ldns_resolver_nameservers(r);
++	rtt = ldns_resolver_rtt(r);
++	for (i = 0; i < ldns_resolver_nameserver_count(r); i++) {
++		j = ldns_get_random() % ldns_resolver_nameserver_count(r);
++		tmpns = ns[i];
++		ns[i] = ns[j];
++		ns[j] = tmpns;
++		tmprtt = rtt[i];
++		rtt[i] = rtt[j];
++		rtt[j] = tmprtt;
++	}
++	ldns_resolver_set_nameservers(r, ns);
++}
++
+diff --git a/ldns/src/rr.c b/ldns/src/rr.c
+new file mode 100644
+index 0000000..e52ea80
+--- /dev/null
++++ b/ldns/src/rr.c
+@@ -0,0 +1,2705 @@
++/* rr.c
++ *
++ * access functions for ldns_rr -
++ * a Net::DNS like library for C
++ * LibDNS Team @ NLnet Labs
++ *
++ * (c) NLnet Labs, 2004-2006
++ * See the file LICENSE for the license
++ */
++#include <ldns/config.h>
++
++#include <ldns/ldns.h>
++
++#include <strings.h>
++#include <limits.h>
++
++#include <errno.h>
++
++#define LDNS_SYNTAX_DATALEN 16
++#define LDNS_TTL_DATALEN    21
++#define LDNS_RRLIST_INIT    8
++
++ldns_rr *
++ldns_rr_new(void)
++{
++	ldns_rr *rr;
++	rr = LDNS_MALLOC(ldns_rr);
++        if (!rr) {
++                return NULL;
++	}
++
++	ldns_rr_set_owner(rr, NULL);
++	ldns_rr_set_question(rr, false);
++	ldns_rr_set_rd_count(rr, 0);
++	rr->_rdata_fields = NULL;
++	ldns_rr_set_class(rr, LDNS_RR_CLASS_IN);
++	ldns_rr_set_ttl(rr, LDNS_DEFAULT_TTL);
++        return rr;
++}
++
++ldns_rr *
++ldns_rr_new_frm_type(ldns_rr_type t)
++{
++	ldns_rr *rr;
++	const ldns_rr_descriptor *desc;
++	size_t i;
++
++	rr = LDNS_MALLOC(ldns_rr);
++        if (!rr) {
++                return NULL;
++	}
++
++	desc = ldns_rr_descript(t);
++
++	rr->_rdata_fields = LDNS_XMALLOC(ldns_rdf *, ldns_rr_descriptor_minimum(desc));
++        if(!rr->_rdata_fields) {
++                LDNS_FREE(rr);
++                return NULL;
++        }
++	for (i = 0; i < ldns_rr_descriptor_minimum(desc); i++) {
++		rr->_rdata_fields[i] = NULL;
++	}
++
++	ldns_rr_set_owner(rr, NULL);
++	ldns_rr_set_question(rr, false);
++	/* set the count to minimum */
++	ldns_rr_set_rd_count(rr, ldns_rr_descriptor_minimum(desc));
++	ldns_rr_set_class(rr, LDNS_RR_CLASS_IN);
++	ldns_rr_set_ttl(rr, LDNS_DEFAULT_TTL);
++	ldns_rr_set_type(rr, t);
++	return rr;
++}
++
++void
++ldns_rr_free(ldns_rr *rr)
++{
++	size_t i;
++	if (rr) {
++		if (ldns_rr_owner(rr)) {
++			ldns_rdf_deep_free(ldns_rr_owner(rr));
++		}
++		for (i = 0; i < ldns_rr_rd_count(rr); i++) {
++			ldns_rdf_deep_free(ldns_rr_rdf(rr, i));
++		}
++		LDNS_FREE(rr->_rdata_fields);
++		LDNS_FREE(rr);
++	}
++}
++
++/* Syntactic sugar for ldns_rr_new_frm_str_internal */
++INLINE bool
++ldns_rdf_type_maybe_quoted(ldns_rdf_type rdf_type)
++{
++	return  rdf_type == LDNS_RDF_TYPE_STR ||
++		rdf_type == LDNS_RDF_TYPE_LONG_STR;
++}
++
++/*
++ * trailing spaces are allowed
++ * leading spaces are not allowed
++ * allow ttl to be optional
++ * class is optional too
++ * if ttl is missing, and default_ttl is 0, use DEF_TTL
++ * allow ttl to be written as 1d3h
++ * So the RR should look like. e.g.
++ * miek.nl. 3600 IN MX 10 elektron.atoom.net
++ * or
++ * miek.nl. 1h IN MX 10 elektron.atoom.net
++ * or
++ * miek.nl. IN MX 10 elektron.atoom.net
++ */
++static ldns_status
++ldns_rr_new_frm_str_internal(ldns_rr **newrr, const char *str,
++                             uint32_t default_ttl, ldns_rdf *origin,
++		             ldns_rdf **prev, bool question)
++{
++	ldns_rr *new;
++	const ldns_rr_descriptor *desc;
++	ldns_rr_type rr_type;
++	ldns_buffer *rr_buf = NULL;
++	ldns_buffer *rd_buf = NULL;
++	uint32_t ttl_val;
++	char  *owner = NULL;
++	char  *ttl = NULL;
++	ldns_rr_class clas_val;
++	char  *clas = NULL;
++	char  *type = NULL;
++	char  *rdata = NULL;
++	char  *rd = NULL;
++	char  *xtok = NULL; /* For RDF types with spaces (i.e. extra tokens) */
++	size_t rd_strlen;
++	const char *delimiters;
++	ssize_t c;
++	ldns_rdf *owner_dname;
++        const char* endptr;
++        int was_unknown_rr_format = 0;
++	ldns_status status = LDNS_STATUS_OK;
++
++	/* used for types with unknown number of rdatas */
++	bool done;
++	bool quoted;
++
++	ldns_rdf *r = NULL;
++	uint16_t r_cnt;
++	uint16_t r_min;
++	uint16_t r_max;
++        size_t pre_data_pos;
++
++	uint16_t hex_data_size;
++	char *hex_data_str = NULL;
++	uint16_t cur_hex_data_size;
++	size_t hex_pos = 0;
++	uint8_t *hex_data = NULL;
++
++	new = ldns_rr_new();
++
++	owner = LDNS_XMALLOC(char, LDNS_MAX_DOMAINLEN + 1);
++	ttl = LDNS_XMALLOC(char, LDNS_TTL_DATALEN);
++	clas = LDNS_XMALLOC(char, LDNS_SYNTAX_DATALEN);
++	rdata = LDNS_XMALLOC(char, LDNS_MAX_PACKETLEN + 1);
++	rr_buf = LDNS_MALLOC(ldns_buffer);
++	rd_buf = LDNS_MALLOC(ldns_buffer);
++	rd = LDNS_XMALLOC(char, LDNS_MAX_RDFLEN);
++	xtok = LDNS_XMALLOC(char, LDNS_MAX_RDFLEN);
++	if (rr_buf) {
++		rr_buf->_data = NULL;
++	}
++	if (rd_buf) {
++		rd_buf->_data = NULL;
++	}
++	if (!new || !owner || !ttl || !clas || !rdata ||
++			!rr_buf || !rd_buf || !rd || !xtok) {
++
++		goto memerror;
++	}
++
++	ldns_buffer_new_frm_data(rr_buf, (char*)str, strlen(str));
++
++	/* split the rr in its parts -1 signals trouble */
++	if (ldns_bget_token(rr_buf, owner, "\t\n ", LDNS_MAX_DOMAINLEN) == -1){
++
++		status = LDNS_STATUS_SYNTAX_ERR;
++		goto error;
++	}
++
++	if (ldns_bget_token(rr_buf, ttl, "\t\n ", LDNS_TTL_DATALEN) == -1) {
++
++		status = LDNS_STATUS_SYNTAX_TTL_ERR;
++		goto error;
++	}
++	ttl_val = (uint32_t) ldns_str2period(ttl, &endptr);
++
++	if (strlen(ttl) > 0 && !isdigit((int) ttl[0])) {
++		/* ah, it's not there or something */
++		if (default_ttl == 0) {
++			ttl_val = LDNS_DEFAULT_TTL;
++		} else {
++			ttl_val = default_ttl;
++		}
++		/* we not ASSUMING the TTL is missing and that
++		 * the rest of the RR is still there. That is
++		 * CLASS TYPE RDATA
++		 * so ttl value we read is actually the class
++		 */
++		clas_val = ldns_get_rr_class_by_name(ttl);
++		/* class can be left out too, assume IN, current
++		 * token must be type
++		 */
++		if (clas_val == 0) {
++			clas_val = LDNS_RR_CLASS_IN;
++			type = LDNS_XMALLOC(char, strlen(ttl) + 1);
++			if (!type) {
++				goto memerror;
++			}
++			strncpy(type, ttl, strlen(ttl) + 1);
++		}
++	} else {
++		if (-1 == ldns_bget_token(
++				rr_buf, clas, "\t\n ", LDNS_SYNTAX_DATALEN)) {
++
++			status = LDNS_STATUS_SYNTAX_CLASS_ERR;
++			goto error;
++		}
++		clas_val = ldns_get_rr_class_by_name(clas);
++		/* class can be left out too, assume IN, current
++		 * token must be type
++		 */
++		if (clas_val == 0) {
++			clas_val = LDNS_RR_CLASS_IN;
++			type = LDNS_XMALLOC(char, strlen(clas) + 1);
++			if (!type) {
++				goto memerror;
++			}
++			strncpy(type, clas, strlen(clas) + 1);
++		}
++	}
++	/* the rest should still be waiting for us */
++
++	if (!type) {
++		type = LDNS_XMALLOC(char, LDNS_SYNTAX_DATALEN);
++		if (!type) {
++			goto memerror;
++		}
++		if (-1 == ldns_bget_token(
++				rr_buf, type, "\t\n ", LDNS_SYNTAX_DATALEN)) {
++
++			status = LDNS_STATUS_SYNTAX_TYPE_ERR;
++			goto error;
++		}
++	}
++
++	if (ldns_bget_token(rr_buf, rdata, "\0", LDNS_MAX_PACKETLEN) == -1) {
++		/* apparently we are done, and it's only a question RR
++		 * so do not set status and go to ldnserror here
++		 */
++	}
++	ldns_buffer_new_frm_data(rd_buf, rdata, strlen(rdata));
++
++	if (strlen(owner) <= 1 && strncmp(owner, "@", 1) == 0) {
++		if (origin) {
++			ldns_rr_set_owner(new, ldns_rdf_clone(origin));
++		} else if (prev && *prev) {
++			ldns_rr_set_owner(new, ldns_rdf_clone(*prev));
++		} else {
++			/* default to root */
++			ldns_rr_set_owner(new, ldns_dname_new_frm_str("."));
++		}
++
++		/* @ also overrides prev */
++		if (prev) {
++			ldns_rdf_deep_free(*prev);
++			*prev = ldns_rdf_clone(ldns_rr_owner(new));
++			if (!*prev) {
++				goto memerror;
++			}
++		}
++	} else {
++		if (strlen(owner) == 0) {
++			/* no ownername was given, try prev, if that fails
++			 * origin, else default to root */
++			if (prev && *prev) {
++				ldns_rr_set_owner(new, ldns_rdf_clone(*prev));
++			} else if (origin) {
++				ldns_rr_set_owner(new, ldns_rdf_clone(origin));
++			} else {
++				ldns_rr_set_owner(new,
++						ldns_dname_new_frm_str("."));
++			}
++			if(!ldns_rr_owner(new)) {
++				goto memerror;
++			}
++		} else {
++			owner_dname = ldns_dname_new_frm_str(owner);
++			if (!owner_dname) {
++				status = LDNS_STATUS_SYNTAX_ERR;
++				goto error;
++			}
++
++			ldns_rr_set_owner(new, owner_dname);
++			if (!ldns_dname_str_absolute(owner) && origin) {
++				if(ldns_dname_cat(ldns_rr_owner(new), origin)
++						!= LDNS_STATUS_OK) {
++
++					status = LDNS_STATUS_SYNTAX_ERR;
++					goto error;
++				}
++			}
++			if (prev) {
++				ldns_rdf_deep_free(*prev);
++				*prev = ldns_rdf_clone(ldns_rr_owner(new));
++				if (!*prev) {
++					goto error;
++				}
++			}
++		}
++	}
++	LDNS_FREE(owner);
++
++	ldns_rr_set_question(new, question);
++
++	ldns_rr_set_ttl(new, ttl_val);
++	LDNS_FREE(ttl);
++
++	ldns_rr_set_class(new, clas_val);
++	LDNS_FREE(clas);
++
++	rr_type = ldns_get_rr_type_by_name(type);
++	LDNS_FREE(type);
++
++	desc = ldns_rr_descript((uint16_t)rr_type);
++	ldns_rr_set_type(new, rr_type);
++	if (desc) {
++		/* only the rdata remains */
++		r_max = ldns_rr_descriptor_maximum(desc);
++		r_min = ldns_rr_descriptor_minimum(desc);
++	} else {
++		r_min = 0;
++		r_max = 1;
++	}
++
++	for (done = false, r_cnt = 0; !done && r_cnt < r_max; r_cnt++) {
++		quoted = false;
++
++		switch (ldns_rr_descriptor_field_type(desc, r_cnt)) {
++		case LDNS_RDF_TYPE_B64        :
++		case LDNS_RDF_TYPE_HEX        : /* These rdf types may con- */
++		case LDNS_RDF_TYPE_LOC        : /* tain whitespace, only if */
++		case LDNS_RDF_TYPE_WKS        : /* it is the last rd field. */
++		case LDNS_RDF_TYPE_IPSECKEY   :
++		case LDNS_RDF_TYPE_NSEC       :	if (r_cnt == r_max - 1) {
++							delimiters = "\n";
++							break;
++						}
++		default                       :	delimiters = "\n\t "; 
++		}
++
++		if (ldns_rdf_type_maybe_quoted(
++				ldns_rr_descriptor_field_type(
++				desc, r_cnt)) &&
++				ldns_buffer_remaining(rd_buf) > 0){
++
++			/* skip spaces */
++			while (*(ldns_buffer_current(rd_buf)) == ' ') {
++				ldns_buffer_skip(rd_buf, 1);
++			}
++
++			if (*(ldns_buffer_current(rd_buf)) == '\"') {
++				delimiters = "\"\0";
++				ldns_buffer_skip(rd_buf, 1);
++				quoted = true;
++			}
++		}
++
++		/* because number of fields can be variable, we can't rely on
++		 * _maximum() only
++		 */
++
++		/* skip spaces */
++		while (ldns_buffer_position(rd_buf) < ldns_buffer_limit(rd_buf)
++				&& *(ldns_buffer_current(rd_buf)) == ' '
++				&& !quoted) {
++
++			ldns_buffer_skip(rd_buf, 1);
++		}
++
++		pre_data_pos = ldns_buffer_position(rd_buf);
++		if (-1 == (c = ldns_bget_token(
++				rd_buf, rd, delimiters, LDNS_MAX_RDFLEN))) {
++
++			done = true;
++			break;
++		}
++		/* hmmz, rfc3597 specifies that any type can be represented 
++		 * with \# method, which can contain spaces...
++		 * it does specify size though...
++		 */
++		rd_strlen = strlen(rd);
++
++		/* unknown RR data */
++		if (strncmp(rd, "\\#", 2) == 0 && !quoted &&
++				(rd_strlen == 2 || rd[2]==' ')) {
++
++			was_unknown_rr_format = 1;
++			/* go back to before \#
++			 * and skip it while setting delimiters better
++			 */
++			ldns_buffer_set_position(rd_buf, pre_data_pos);
++			delimiters = "\n\t ";
++			(void)ldns_bget_token(rd_buf, rd,
++					delimiters, LDNS_MAX_RDFLEN);
++			/* read rdata octet length */
++			c = ldns_bget_token(rd_buf, rd,
++					delimiters, LDNS_MAX_RDFLEN);
++			if (c == -1) {
++				/* something goes very wrong here */
++				status = LDNS_STATUS_SYNTAX_RDATA_ERR;
++				goto error;
++			}
++			hex_data_size = (uint16_t) atoi(rd);
++			/* copy hex chars into hex str (2 chars per byte) */
++			hex_data_str = LDNS_XMALLOC(char, 2*hex_data_size + 1);
++			if (!hex_data_str) {
++				/* malloc error */
++				goto memerror;
++			}
++			cur_hex_data_size = 0;
++			while(cur_hex_data_size < 2 * hex_data_size) {
++				c = ldns_bget_token(rd_buf, rd,
++						delimiters, LDNS_MAX_RDFLEN);
++				if (c != -1) {
++					rd_strlen = strlen(rd);
++				}
++				if (c == -1 || 
++				    (size_t)cur_hex_data_size + rd_strlen >
++				    2 * (size_t)hex_data_size) {
++
++					status = LDNS_STATUS_SYNTAX_RDATA_ERR;
++					goto error;
++				}
++				strncpy(hex_data_str + cur_hex_data_size, rd,
++						rd_strlen);
++
++				cur_hex_data_size += rd_strlen;
++			}
++			hex_data_str[cur_hex_data_size] = '\0';
++
++			/* correct the rdf type */
++			/* if *we* know the type, interpret it as wireformat */
++			if (desc) {
++				hex_pos = 0;
++				hex_data =
++					LDNS_XMALLOC(uint8_t, hex_data_size+2);
++
++				if (!hex_data) {
++					goto memerror;
++				}
++				ldns_write_uint16(hex_data, hex_data_size);
++				ldns_hexstring_to_data(
++						hex_data + 2, hex_data_str);
++				status = ldns_wire2rdf(new, hex_data,
++						hex_data_size + 2, &hex_pos);
++				if (status != LDNS_STATUS_OK) {
++					goto error;
++				}
++				LDNS_FREE(hex_data);
++			} else {
++				r = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_HEX,
++						hex_data_str);
++				if (!r) {
++					goto memerror;
++				}
++				ldns_rdf_set_type(r, LDNS_RDF_TYPE_UNKNOWN);
++				if (!ldns_rr_push_rdf(new, r)) {
++					goto memerror;
++				}
++			}
++			LDNS_FREE(hex_data_str);
++
++		} else if(rd_strlen > 0 || quoted) {
++			/* Normal RR */
++			switch(ldns_rr_descriptor_field_type(desc, r_cnt)) {
++
++			case LDNS_RDF_TYPE_HEX:
++			case LDNS_RDF_TYPE_B64:
++				/* When this is the last rdata field, then the
++				 * rest should be read in (cause then these
++				 * rdf types may contain spaces).
++				 */
++				if (r_cnt == r_max - 1) {
++					c = ldns_bget_token(rd_buf, xtok,
++							"\n", LDNS_MAX_RDFLEN);
++					if (c != -1) {
++						(void) strncat(rd, xtok,
++							LDNS_MAX_RDFLEN -
++							strlen(rd) - 1);
++					}
++				}
++				r = ldns_rdf_new_frm_str(
++						ldns_rr_descriptor_field_type(
++							desc, r_cnt), rd);
++				break;
++
++			case LDNS_RDF_TYPE_HIP:
++				/*
++				 * In presentation format this RDATA type has
++				 * three tokens: An algorithm byte, then a
++				 * variable length HIT (in hexbytes) and then
++				 * a variable length Public Key (in base64).
++				 *
++				 * We have just read the algorithm, so we need
++				 * two more tokens: HIT and Public Key.
++				 */
++				do {
++					/* Read and append HIT */
++					if (ldns_bget_token(rd_buf,
++							xtok, delimiters,
++							LDNS_MAX_RDFLEN) == -1)
++						break;
++
++					(void) strncat(rd, " ",
++							LDNS_MAX_RDFLEN -
++							strlen(rd) - 1);
++					(void) strncat(rd, xtok,
++							LDNS_MAX_RDFLEN -
++							strlen(rd) - 1);
++
++					/* Read and append Public Key*/
++					if (ldns_bget_token(rd_buf,
++							xtok, delimiters,
++							LDNS_MAX_RDFLEN) == -1)
++						break;
++
++					(void) strncat(rd, " ",
++							LDNS_MAX_RDFLEN -
++							strlen(rd) - 1);
++					(void) strncat(rd, xtok,
++							LDNS_MAX_RDFLEN -
++							strlen(rd) - 1);
++				} while (false);
++
++				r = ldns_rdf_new_frm_str(
++						ldns_rr_descriptor_field_type(
++							desc, r_cnt), rd);
++				break;
++
++			case LDNS_RDF_TYPE_DNAME:
++				r = ldns_rdf_new_frm_str(
++						ldns_rr_descriptor_field_type(
++							desc, r_cnt), rd);
++
++				/* check if the origin should be used
++				 * or concatenated
++				 */
++				if (r && ldns_rdf_size(r) > 1 &&
++						ldns_rdf_data(r)[0] == 1 &&
++						ldns_rdf_data(r)[1] == '@') {
++
++					ldns_rdf_deep_free(r);
++
++					r = origin ? ldns_rdf_clone(origin)
++
++					  : ( rr_type == LDNS_RR_TYPE_SOA ?
++
++					      ldns_rdf_clone(
++						      ldns_rr_owner(new))
++
++					    : ldns_rdf_new_frm_str(
++						    LDNS_RDF_TYPE_DNAME, ".")
++					    );
++
++				} else if (r && rd_strlen >= 1 && origin &&
++						!ldns_dname_str_absolute(rd)) {
++
++					status = ldns_dname_cat(r, origin);
++					if (status != LDNS_STATUS_OK) {
++						goto error;
++					}
++				}
++				break;
++			default:
++				r = ldns_rdf_new_frm_str(
++						ldns_rr_descriptor_field_type(
++							desc, r_cnt), rd);
++				break;
++			}
++			if (!r) {
++				status = LDNS_STATUS_SYNTAX_RDATA_ERR;
++				goto error;
++			}
++			ldns_rr_push_rdf(new, r);
++		}
++		if (quoted) {
++			if (ldns_buffer_available(rd_buf, 1)) {
++				ldns_buffer_skip(rd_buf, 1);
++			} else {
++				done = true;
++			}
++		}
++
++	} /* for (done = false, r_cnt = 0; !done && r_cnt < r_max; r_cnt++) */
++	LDNS_FREE(rd);
++	LDNS_FREE(xtok);
++	ldns_buffer_free(rd_buf);
++	ldns_buffer_free(rr_buf);
++	LDNS_FREE(rdata);
++
++	if (!question && desc && !was_unknown_rr_format &&
++			ldns_rr_rd_count(new) < r_min) {
++
++		ldns_rr_free(new);
++		return LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR;
++	}
++
++	if (newrr) {
++		*newrr = new;
++	} else {
++		/* Maybe the caller just wanted to see if it would parse? */
++		ldns_rr_free(new);
++	}
++	return LDNS_STATUS_OK;
++
++memerror:
++	status = LDNS_STATUS_MEM_ERR;
++error:
++	if (rd_buf && rd_buf->_data) {
++		ldns_buffer_free(rd_buf);
++	} else {
++		LDNS_FREE(rd_buf);
++	}
++	if (rr_buf && rr_buf->_data) {
++		ldns_buffer_free(rr_buf);
++	} else {
++		LDNS_FREE(rr_buf);
++	}
++	LDNS_FREE(type);
++	LDNS_FREE(owner);
++	LDNS_FREE(ttl);
++	LDNS_FREE(clas);
++	LDNS_FREE(hex_data);
++	LDNS_FREE(hex_data_str);
++	LDNS_FREE(xtok);
++	LDNS_FREE(rd);
++	LDNS_FREE(rdata);
++	ldns_rr_free(new);
++	return status;
++}
++
++ldns_status
++ldns_rr_new_frm_str(ldns_rr **newrr, const char *str,
++                    uint32_t default_ttl, ldns_rdf *origin,
++		    ldns_rdf **prev)
++{
++	return ldns_rr_new_frm_str_internal(newrr,
++	                                    str,
++	                                    default_ttl,
++	                                    origin,
++	                                    prev,
++	                                    false);
++}
++
++ldns_status
++ldns_rr_new_question_frm_str(ldns_rr **newrr, const char *str,
++                             ldns_rdf *origin, ldns_rdf **prev)
++{
++	return ldns_rr_new_frm_str_internal(newrr,
++	                                    str,
++	                                    0,
++	                                    origin,
++	                                    prev,
++	                                    true);
++}
++
++/* Strip whitespace from the start and the end of <line>.  */
++static char *
++ldns_strip_ws(char *line)
++{
++	char *s = line, *e;
++
++	for (s = line; *s && isspace(*s); s++)
++		;
++
++	for (e = strchr(s, 0); e > s+2 && isspace(e[-1]) && e[-2] != '\\'; e--)
++		;
++	*e = 0;
++
++	return s;
++}
++
++ldns_status
++ldns_rr_new_frm_fp(ldns_rr **newrr, FILE *fp, uint32_t *ttl, ldns_rdf **origin, ldns_rdf **prev)
++{
++	return ldns_rr_new_frm_fp_l(newrr, fp, ttl, origin, prev, NULL);
++}
++
++ldns_status
++ldns_rr_new_frm_fp_l(ldns_rr **newrr, FILE *fp, uint32_t *default_ttl, ldns_rdf **origin, ldns_rdf **prev, int *line_nr)
++{
++	char *line;
++	const char *endptr;  /* unused */
++	ldns_rr *rr;
++	uint32_t ttl;
++	ldns_rdf *tmp;
++	ldns_status s;
++	ssize_t size;
++
++	if (default_ttl) {
++		ttl = *default_ttl;
++	} else {
++		ttl = 0;
++	}
++
++	line = LDNS_XMALLOC(char, LDNS_MAX_LINELEN + 1);
++	if (!line) {
++		return LDNS_STATUS_MEM_ERR;
++	}
++
++	/* read an entire line in from the file */
++	if ((size = ldns_fget_token_l(fp, line, LDNS_PARSE_SKIP_SPACE, LDNS_MAX_LINELEN, line_nr)) == -1) {
++		LDNS_FREE(line);
++		/* if last line was empty, we are now at feof, which is not
++		 * always a parse error (happens when for instance last line
++		 * was a comment)
++		 */
++		return LDNS_STATUS_SYNTAX_ERR;
++	}
++
++	/* we can have the situation, where we've read ok, but still got
++	 * no bytes to play with, in this case size is 0
++	 */
++	if (size == 0) {
++		LDNS_FREE(line);
++		return LDNS_STATUS_SYNTAX_EMPTY;
++	}
++
++	if (strncmp(line, "$ORIGIN", 7) == 0 && isspace(line[7])) {
++		if (*origin) {
++			ldns_rdf_deep_free(*origin);
++			*origin = NULL;
++		}
++		tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME,
++				ldns_strip_ws(line + 8));
++		if (!tmp) {
++			/* could not parse what next to $ORIGIN */
++			LDNS_FREE(line);
++			return LDNS_STATUS_SYNTAX_DNAME_ERR;
++		}
++		*origin = tmp;
++		s = LDNS_STATUS_SYNTAX_ORIGIN;
++	} else if (strncmp(line, "$TTL", 4) == 0 && isspace(line[4])) {
++		if (default_ttl) {
++			*default_ttl = ldns_str2period(
++					ldns_strip_ws(line + 5), &endptr);
++		}
++		s = LDNS_STATUS_SYNTAX_TTL;
++	} else if (strncmp(line, "$INCLUDE", 8) == 0) {
++		s = LDNS_STATUS_SYNTAX_INCLUDE;
++	} else if (!*ldns_strip_ws(line)) {
++		LDNS_FREE(line);
++		return LDNS_STATUS_SYNTAX_EMPTY;
++	} else {
++		if (origin && *origin) {
++			s = ldns_rr_new_frm_str(&rr, (const char*) line, ttl, *origin, prev);
++		} else {
++			s = ldns_rr_new_frm_str(&rr, (const char*) line, ttl, NULL, prev);
++		}
++	}
++	LDNS_FREE(line);
++	if (s == LDNS_STATUS_OK) {
++		if (newrr) {
++			*newrr = rr;
++		} else {
++			/* Just testing if it would parse? */
++			ldns_rr_free(rr);
++		}
++	}
++	return s;
++}
++
++void
++ldns_rr_set_owner(ldns_rr *rr, ldns_rdf *owner)
++{
++	rr->_owner = owner;
++}
++
++void
++ldns_rr_set_question(ldns_rr *rr, bool question)
++{
++   rr->_rr_question = question;
++}
++
++void
++ldns_rr_set_ttl(ldns_rr *rr, uint32_t ttl)
++{
++	rr->_ttl = ttl;
++}
++
++void
++ldns_rr_set_rd_count(ldns_rr *rr, size_t count)
++{
++	rr->_rd_count = count;
++}
++
++void
++ldns_rr_set_type(ldns_rr *rr, ldns_rr_type rr_type)
++{
++	rr->_rr_type = rr_type;
++}
++
++void
++ldns_rr_set_class(ldns_rr *rr, ldns_rr_class rr_class)
++{
++	rr->_rr_class = rr_class;
++}
++
++ldns_rdf *
++ldns_rr_set_rdf(ldns_rr *rr, const ldns_rdf *f, size_t position)
++{
++	size_t rd_count;
++	ldns_rdf *pop;
++
++	rd_count = ldns_rr_rd_count(rr);
++	if (position < rd_count) {
++		/* dicard the old one */
++		pop = rr->_rdata_fields[position];
++		rr->_rdata_fields[position] = (ldns_rdf*)f;
++		return pop;
++	} else {
++		return NULL;
++	}
++}
++
++bool
++ldns_rr_push_rdf(ldns_rr *rr, const ldns_rdf *f)
++{
++	size_t rd_count;
++	ldns_rdf **rdata_fields;
++
++	rd_count = ldns_rr_rd_count(rr);
++
++	/* grow the array */
++	rdata_fields = LDNS_XREALLOC(
++		rr->_rdata_fields, ldns_rdf *, rd_count + 1);
++	if (!rdata_fields) {
++		return false;
++	}
++
++	/* add the new member */
++	rr->_rdata_fields = rdata_fields;
++	rr->_rdata_fields[rd_count] = (ldns_rdf*)f;
++
++	ldns_rr_set_rd_count(rr, rd_count + 1);
++	return true;
++}
++
++ldns_rdf *
++ldns_rr_pop_rdf(ldns_rr *rr)
++{
++	size_t rd_count;
++	ldns_rdf *pop;
++	ldns_rdf** newrd;
++
++	rd_count = ldns_rr_rd_count(rr);
++
++	if (rd_count == 0) {
++		return NULL;
++	}
++
++	pop = rr->_rdata_fields[rd_count - 1];
++
++	/* try to shrink the array */
++	if(rd_count > 1) {
++		newrd = LDNS_XREALLOC(
++			rr->_rdata_fields, ldns_rdf *, rd_count - 1);
++		if(newrd)
++			rr->_rdata_fields = newrd;
++	} else {
++		LDNS_FREE(rr->_rdata_fields);
++	}
++
++	ldns_rr_set_rd_count(rr, rd_count - 1);
++	return pop;
++}
++
++ldns_rdf *
++ldns_rr_rdf(const ldns_rr *rr, size_t nr)
++{
++	if (rr && nr < ldns_rr_rd_count(rr)) {
++		return rr->_rdata_fields[nr];
++	} else {
++		return NULL;
++	}
++}
++
++ldns_rdf *
++ldns_rr_owner(const ldns_rr *rr)
++{
++	return rr->_owner;
++}
++
++bool
++ldns_rr_is_question(const ldns_rr *rr)
++{
++   return rr->_rr_question;
++}
++
++uint32_t
++ldns_rr_ttl(const ldns_rr *rr)
++{
++	return rr->_ttl;
++}
++
++size_t
++ldns_rr_rd_count(const ldns_rr *rr)
++{
++	return rr->_rd_count;
++}
++
++ldns_rr_type
++ldns_rr_get_type(const ldns_rr *rr)
++{
++        return rr->_rr_type;
++}
++
++ldns_rr_class
++ldns_rr_get_class(const ldns_rr *rr)
++{
++        return rr->_rr_class;
++}
++
++/* rr_lists */
++
++size_t
++ldns_rr_list_rr_count(const ldns_rr_list *rr_list)
++{
++	if (rr_list) {
++		return rr_list->_rr_count;
++	} else {
++		return 0;
++	}
++}
++
++ldns_rr *
++ldns_rr_list_set_rr(ldns_rr_list *rr_list, const ldns_rr *r, size_t count)
++{
++	ldns_rr *old;
++
++	if (count > ldns_rr_list_rr_count(rr_list)) {
++		return NULL;
++	}
++
++	old = ldns_rr_list_rr(rr_list, count);
++
++	/* overwrite old's pointer */
++	rr_list->_rrs[count] = (ldns_rr*)r;
++	return old;
++}
++
++void
++ldns_rr_list_set_rr_count(ldns_rr_list *rr_list, size_t count)
++{
++	assert(count <= rr_list->_rr_capacity);
++	rr_list->_rr_count = count;
++}
++
++ldns_rr *
++ldns_rr_list_rr(const ldns_rr_list *rr_list, size_t nr)
++{
++	if (nr < ldns_rr_list_rr_count(rr_list)) {
++		return rr_list->_rrs[nr];
++	} else {
++		return NULL;
++	}
++}
++
++ldns_rr_list *
++ldns_rr_list_new(void)
++{
++	ldns_rr_list *rr_list = LDNS_MALLOC(ldns_rr_list);
++        if(!rr_list) return NULL;
++	rr_list->_rr_count = 0;
++	rr_list->_rr_capacity = 0;
++	rr_list->_rrs = NULL;
++	return rr_list;
++}
++
++void
++ldns_rr_list_free(ldns_rr_list *rr_list)
++{
++	if (rr_list) {
++		LDNS_FREE(rr_list->_rrs);
++		LDNS_FREE(rr_list);
++	}
++}
++
++void
++ldns_rr_list_deep_free(ldns_rr_list *rr_list)
++{
++	size_t i;
++
++	if (rr_list) {
++		for (i=0; i < ldns_rr_list_rr_count(rr_list); i++) {
++			ldns_rr_free(ldns_rr_list_rr(rr_list, i));
++		}
++		LDNS_FREE(rr_list->_rrs);
++		LDNS_FREE(rr_list);
++	}
++}
++
++
++/* add right to left. So we modify *left! */
++bool
++ldns_rr_list_cat(ldns_rr_list *left, ldns_rr_list *right)
++{
++	size_t r_rr_count;
++	size_t i;
++
++	if (!left) {
++		return false;
++	}
++
++	if (right) {
++		r_rr_count = ldns_rr_list_rr_count(right);
++	} else {
++		r_rr_count = 0;
++	}
++
++	/* push right to left */
++	for(i = 0; i < r_rr_count; i++) {
++		ldns_rr_list_push_rr(left, ldns_rr_list_rr(right, i));
++	}
++	return true;
++}
++
++ldns_rr_list *
++ldns_rr_list_cat_clone(ldns_rr_list *left, ldns_rr_list *right)
++{
++	size_t l_rr_count;
++	size_t r_rr_count;
++	size_t i;
++	ldns_rr_list *cat;
++
++	if (left) {
++		l_rr_count = ldns_rr_list_rr_count(left);
++	} else {
++		return ldns_rr_list_clone(right);
++	}
++
++	if (right) {
++		r_rr_count = ldns_rr_list_rr_count(right);
++	} else {
++		r_rr_count = 0;
++	}
++
++	cat = ldns_rr_list_new();
++
++	if (!cat) {
++		return NULL;
++	}
++
++	/* left */
++	for(i = 0; i < l_rr_count; i++) {
++		ldns_rr_list_push_rr(cat,
++				ldns_rr_clone(ldns_rr_list_rr(left, i)));
++	}
++	/* right */
++	for(i = 0; i < r_rr_count; i++) {
++		ldns_rr_list_push_rr(cat,
++				ldns_rr_clone(ldns_rr_list_rr(right, i)));
++	}
++	return cat;
++}
++
++ldns_rr_list *
++ldns_rr_list_subtype_by_rdf(ldns_rr_list *l, ldns_rdf *r, size_t pos)
++{
++	size_t i;
++	ldns_rr_list *subtyped;
++	ldns_rdf *list_rdf;
++
++	subtyped = ldns_rr_list_new();
++
++	for(i = 0; i < ldns_rr_list_rr_count(l); i++) {
++		list_rdf = ldns_rr_rdf(
++			ldns_rr_list_rr(l, i),
++			pos);
++		if (!list_rdf) {
++			/* pos is too large or any other error */
++			ldns_rr_list_deep_free(subtyped);
++			return NULL;
++		}
++
++		if (ldns_rdf_compare(list_rdf, r) == 0) {
++			/* a match */
++			ldns_rr_list_push_rr(subtyped,
++					ldns_rr_clone(ldns_rr_list_rr(l, i)));
++		}
++	}
++
++	if (ldns_rr_list_rr_count(subtyped) > 0) {
++		return subtyped;
++	} else {
++		ldns_rr_list_free(subtyped);
++		return NULL;
++	}
++}
++
++bool
++ldns_rr_list_push_rr(ldns_rr_list *rr_list, const ldns_rr *rr)
++{
++	size_t rr_count;
++	size_t cap;
++
++	rr_count = ldns_rr_list_rr_count(rr_list);
++	cap = rr_list->_rr_capacity;
++
++	/* grow the array */
++	if(rr_count+1 > cap) {
++		ldns_rr **rrs;
++
++		if(cap == 0)
++			cap = LDNS_RRLIST_INIT;  /* initial list size */
++		else	cap *= 2;
++		rrs = LDNS_XREALLOC(rr_list->_rrs, ldns_rr *, cap);
++		if (!rrs) {
++			return false;
++		}
++		rr_list->_rrs = rrs;
++		rr_list->_rr_capacity = cap;
++	}
++
++	/* add the new member */
++	rr_list->_rrs[rr_count] = (ldns_rr*)rr;
++
++	ldns_rr_list_set_rr_count(rr_list, rr_count + 1);
++	return true;
++}
++
++bool
++ldns_rr_list_push_rr_list(ldns_rr_list *rr_list, const ldns_rr_list *push_list)
++{
++	size_t i;
++
++	for(i = 0; i < ldns_rr_list_rr_count(push_list); i++) {
++		if (!ldns_rr_list_push_rr(rr_list,
++				ldns_rr_list_rr(push_list, i))) {
++			return false;
++		}
++	}
++	return true;
++}
++
++ldns_rr *
++ldns_rr_list_pop_rr(ldns_rr_list *rr_list)
++{
++	size_t rr_count;
++	size_t cap;
++	ldns_rr *pop;
++
++	rr_count = ldns_rr_list_rr_count(rr_list);
++
++	if (rr_count == 0) {
++		return NULL;
++	}
++
++	cap = rr_list->_rr_capacity;
++	pop = ldns_rr_list_rr(rr_list, rr_count - 1);
++
++	/* shrink the array */
++	if(cap > LDNS_RRLIST_INIT && rr_count-1 <= cap/2) {
++                ldns_rr** a;
++		cap /= 2;
++                a = LDNS_XREALLOC(rr_list->_rrs, ldns_rr *, cap);
++                if(a) {
++		        rr_list->_rrs = a;
++		        rr_list->_rr_capacity = cap;
++                }
++	}
++
++	ldns_rr_list_set_rr_count(rr_list, rr_count - 1);
++
++	return pop;
++}
++
++ldns_rr_list *
++ldns_rr_list_pop_rr_list(ldns_rr_list *rr_list, size_t howmany)
++{
++	/* pop a number of rr's and put them in a rr_list */
++	ldns_rr_list *popped;
++	ldns_rr *p;
++	size_t i = howmany;
++
++	popped = ldns_rr_list_new();
++
++	if (!popped) {
++		return NULL;
++	}
++
++
++	while(i > 0 &&
++			(p = ldns_rr_list_pop_rr(rr_list)) != NULL) {
++		ldns_rr_list_push_rr(popped, p);
++		i--;
++	}
++
++	if (i == howmany) { /* so i <= 0 */
++		ldns_rr_list_free(popped);
++		return NULL;
++	} else {
++		return popped;
++	}
++}
++
++
++bool
++ldns_rr_list_contains_rr(const ldns_rr_list *rr_list, ldns_rr *rr)
++{
++	size_t i;
++
++	if (!rr_list || !rr || ldns_rr_list_rr_count(rr_list) == 0) {
++		return false;
++	}
++
++	for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
++		if (rr == ldns_rr_list_rr(rr_list, i)) {
++			return true;
++		} else if (ldns_rr_compare(rr, ldns_rr_list_rr(rr_list, i)) == 0) {
++			return true;
++		}
++	}
++	return false;
++}
++
++bool
++ldns_is_rrset(ldns_rr_list *rr_list)
++{
++	ldns_rr_type t;
++	ldns_rr_class c;
++	ldns_rdf *o;
++	ldns_rr *tmp;
++	size_t i;
++
++	if (!rr_list || ldns_rr_list_rr_count(rr_list) == 0) {
++		return false;
++	}
++
++	tmp = ldns_rr_list_rr(rr_list, 0);
++
++	t = ldns_rr_get_type(tmp);
++	c = ldns_rr_get_class(tmp);
++	o = ldns_rr_owner(tmp);
++
++	/* compare these with the rest of the rr_list, start with 1 */
++	for (i = 1; i < ldns_rr_list_rr_count(rr_list); i++) {
++		tmp = ldns_rr_list_rr(rr_list, i);
++		if (t != ldns_rr_get_type(tmp)) {
++			return false;
++		}
++		if (c != ldns_rr_get_class(tmp)) {
++			return false;
++		}
++		if (ldns_rdf_compare(o, ldns_rr_owner(tmp)) != 0) {
++			return false;
++		}
++	}
++	return true;
++}
++
++bool
++ldns_rr_set_push_rr(ldns_rr_list *rr_list, ldns_rr *rr)
++{
++	size_t rr_count;
++	size_t i;
++	ldns_rr *last;
++
++	assert(rr != NULL);
++
++	rr_count = ldns_rr_list_rr_count(rr_list);
++
++	if (rr_count == 0) {
++		/* nothing there, so checking it is
++		 * not needed */
++		return ldns_rr_list_push_rr(rr_list, rr);
++	} else {
++		/* check with the final rr in the rr_list */
++		last = ldns_rr_list_rr(rr_list, rr_count - 1);
++
++		if (ldns_rr_get_class(last) != ldns_rr_get_class(rr)) {
++			return false;
++		}
++		if (ldns_rr_get_type(last) != ldns_rr_get_type(rr)) {
++			return false;
++		}
++		/* only check if not equal to RRSIG */
++		if (ldns_rr_get_type(rr) != LDNS_RR_TYPE_RRSIG) {
++			if (ldns_rr_ttl(last) != ldns_rr_ttl(rr)) {
++				return false;
++			}
++		}
++		if (ldns_rdf_compare(ldns_rr_owner(last),
++					ldns_rr_owner(rr)) != 0) {
++			return false;
++		}
++		/* ok, still alive - check if the rr already
++		 * exists - if so, dont' add it */
++		for(i = 0; i < rr_count; i++) {
++			if(ldns_rr_compare(
++					ldns_rr_list_rr(rr_list, i), rr) == 0) {
++				return false;
++			}
++		}
++		/* it's safe, push it */
++		return ldns_rr_list_push_rr(rr_list, rr);
++	}
++}
++
++ldns_rr *
++ldns_rr_set_pop_rr(ldns_rr_list *rr_list)
++{
++	return ldns_rr_list_pop_rr(rr_list);
++}
++
++ldns_rr_list *
++ldns_rr_list_pop_rrset(ldns_rr_list *rr_list)
++{
++	ldns_rr_list *rrset;
++	ldns_rr *last_rr = NULL;
++	ldns_rr *next_rr;
++
++	if (!rr_list) {
++		return NULL;
++	}
++
++	rrset = ldns_rr_list_new();
++	if (!last_rr) {
++		last_rr = ldns_rr_list_pop_rr(rr_list);
++		if (!last_rr) {
++			ldns_rr_list_free(rrset);
++			return NULL;
++		} else {
++			ldns_rr_list_push_rr(rrset, last_rr);
++		}
++	}
++
++	if (ldns_rr_list_rr_count(rr_list) > 0) {
++		next_rr = ldns_rr_list_rr(rr_list, ldns_rr_list_rr_count(rr_list) - 1);
++	} else {
++		next_rr = NULL;
++	}
++
++	while (next_rr) {
++		if (
++			ldns_rdf_compare(ldns_rr_owner(next_rr),
++					 ldns_rr_owner(last_rr)) == 0
++			&&
++			ldns_rr_get_type(next_rr) == ldns_rr_get_type(last_rr)
++			&&
++			ldns_rr_get_class(next_rr) == ldns_rr_get_class(last_rr)
++		   ) {
++			ldns_rr_list_push_rr(rrset, ldns_rr_list_pop_rr(rr_list));
++			if (ldns_rr_list_rr_count(rr_list) > 0) {
++				last_rr = next_rr;
++				next_rr = ldns_rr_list_rr(rr_list, ldns_rr_list_rr_count(rr_list) - 1);
++			} else {
++				next_rr = NULL;
++			}
++		} else {
++			next_rr = NULL;
++		}
++	}
++
++	return rrset;
++}
++
++ldns_rr *
++ldns_rr_clone(const ldns_rr *rr)
++{
++	size_t i;
++	ldns_rr *new_rr;
++
++	if (!rr) {
++		return NULL;
++	}
++
++	new_rr = ldns_rr_new();
++	if (!new_rr) {
++		return NULL;
++	}
++	if (ldns_rr_owner(rr)) {
++		ldns_rr_set_owner(new_rr, ldns_rdf_clone(ldns_rr_owner(rr)));
++  	}
++	ldns_rr_set_ttl(new_rr, ldns_rr_ttl(rr));
++	ldns_rr_set_type(new_rr, ldns_rr_get_type(rr));
++	ldns_rr_set_class(new_rr, ldns_rr_get_class(rr));
++	ldns_rr_set_question(new_rr, ldns_rr_is_question(rr));
++
++	for (i = 0; i < ldns_rr_rd_count(rr); i++) {
++        	if (ldns_rr_rdf(rr,i)) {
++        		ldns_rr_push_rdf(new_rr, ldns_rdf_clone(ldns_rr_rdf(rr, i)));
++                }
++	}
++
++	return new_rr;
++}
++
++ldns_rr_list *
++ldns_rr_list_clone(const ldns_rr_list *rrlist)
++{
++	size_t i;
++	ldns_rr_list *new_list;
++	ldns_rr *r;
++
++	if (!rrlist) {
++		return NULL;
++	}
++
++	new_list = ldns_rr_list_new();
++	if (!new_list) {
++		return NULL;
++	}
++	for (i = 0; i < ldns_rr_list_rr_count(rrlist); i++) {
++		r = ldns_rr_clone(
++			ldns_rr_list_rr(rrlist, i)
++		    );
++		if (!r) {
++			/* huh, failure in cloning */
++			ldns_rr_list_deep_free(new_list);
++			return NULL;
++		}
++		ldns_rr_list_push_rr(new_list, r);
++	}
++	return new_list;
++}
++
++
++static int
++qsort_schwartz_rr_compare(const void *a, const void *b)
++{
++	int result = 0;
++	ldns_rr *rr1, *rr2;
++	ldns_buffer *rr1_buf, *rr2_buf;
++	struct ldns_schwartzian_compare_struct *sa = *(struct ldns_schwartzian_compare_struct **) a;
++	struct ldns_schwartzian_compare_struct *sb = *(struct ldns_schwartzian_compare_struct **) b;
++	/* if we are doing 2wire, we need to do lowercasing on the dname (and maybe on the rdata)
++	 * this must be done for comparison only, so we need to have a temp var for both buffers,
++	 * which is only used when the transformed object value isn't there yet
++	 */
++	ldns_rr *canonical_a, *canonical_b;
++
++	rr1 = (ldns_rr *) sa->original_object;
++	rr2 = (ldns_rr *) sb->original_object;
++
++	result = ldns_rr_compare_no_rdata(rr1, rr2);
++
++	if (result == 0) {
++		if (!sa->transformed_object) {
++			canonical_a = ldns_rr_clone(sa->original_object);
++			ldns_rr2canonical(canonical_a);
++			sa->transformed_object = ldns_buffer_new(ldns_rr_uncompressed_size(canonical_a));
++			if (ldns_rr2buffer_wire(sa->transformed_object, canonical_a, LDNS_SECTION_ANY) != LDNS_STATUS_OK) {
++		                ldns_buffer_free((ldns_buffer *)sa->transformed_object);
++                                sa->transformed_object = NULL;
++				ldns_rr_free(canonical_a);
++				return 0;
++			}
++			ldns_rr_free(canonical_a);
++		}
++		if (!sb->transformed_object) {
++			canonical_b = ldns_rr_clone(sb->original_object);
++			ldns_rr2canonical(canonical_b);
++			sb->transformed_object = ldns_buffer_new(ldns_rr_uncompressed_size(canonical_b));
++			if (ldns_rr2buffer_wire(sb->transformed_object, canonical_b, LDNS_SECTION_ANY) != LDNS_STATUS_OK) {
++		                ldns_buffer_free((ldns_buffer *)sa->transformed_object);
++		                ldns_buffer_free((ldns_buffer *)sb->transformed_object);
++                                sa->transformed_object = NULL;
++                                sb->transformed_object = NULL;
++				ldns_rr_free(canonical_b);
++				return 0;
++			}
++			ldns_rr_free(canonical_b);
++		}
++		rr1_buf = (ldns_buffer *) sa->transformed_object;
++		rr2_buf = (ldns_buffer *) sb->transformed_object;
++
++		result = ldns_rr_compare_wire(rr1_buf, rr2_buf);
++	}
++
++	return result;
++}
++
++void
++ldns_rr_list_sort(ldns_rr_list *unsorted)
++{
++	struct ldns_schwartzian_compare_struct **sortables;
++	size_t item_count;
++	size_t i;
++
++	if (unsorted) {
++		item_count = ldns_rr_list_rr_count(unsorted);
++
++		sortables = LDNS_XMALLOC(struct ldns_schwartzian_compare_struct *,
++					 item_count);
++                if(!sortables) return; /* no way to return error */
++		for (i = 0; i < item_count; i++) {
++			sortables[i] = LDNS_XMALLOC(struct ldns_schwartzian_compare_struct, 1);
++                        if(!sortables[i]) {
++                                /* free the allocated parts */
++                                while(i>0) {
++                                        i--;
++                                        LDNS_FREE(sortables[i]);
++                                }
++                                /* no way to return error */
++				LDNS_FREE(sortables);
++                                return;
++                        }
++			sortables[i]->original_object = ldns_rr_list_rr(unsorted, i);
++			sortables[i]->transformed_object = NULL;
++		}
++		qsort(sortables,
++		      item_count,
++		      sizeof(struct ldns_schwartzian_compare_struct *),
++		      qsort_schwartz_rr_compare);
++		for (i = 0; i < item_count; i++) {
++			unsorted->_rrs[i] = sortables[i]->original_object;
++			if (sortables[i]->transformed_object) {
++				ldns_buffer_free(sortables[i]->transformed_object);
++			}
++			LDNS_FREE(sortables[i]);
++		}
++		LDNS_FREE(sortables);
++	}
++}
++
++int
++ldns_rr_compare_no_rdata(const ldns_rr *rr1, const ldns_rr *rr2)
++{
++	size_t rr1_len;
++	size_t rr2_len;
++        size_t offset;
++
++	assert(rr1 != NULL);
++	assert(rr2 != NULL);
++
++	rr1_len = ldns_rr_uncompressed_size(rr1);
++	rr2_len = ldns_rr_uncompressed_size(rr2);
++
++	if (ldns_dname_compare(ldns_rr_owner(rr1), ldns_rr_owner(rr2)) < 0) {
++		return -1;
++	} else if (ldns_dname_compare(ldns_rr_owner(rr1), ldns_rr_owner(rr2)) > 0) {
++		return 1;
++	}
++
++        /* should return -1 if rr1 comes before rr2, so need to do rr1 - rr2, not rr2 - rr1 */
++        if (ldns_rr_get_class(rr1) != ldns_rr_get_class(rr2)) {
++            return ldns_rr_get_class(rr1) - ldns_rr_get_class(rr2);
++        }
++
++        /* should return -1 if rr1 comes before rr2, so need to do rr1 - rr2, not rr2 - rr1 */
++        if (ldns_rr_get_type(rr1) != ldns_rr_get_type(rr2)) {
++            return ldns_rr_get_type(rr1) - ldns_rr_get_type(rr2);
++        }
++
++        /* offset is the owername length + ttl + type + class + rdlen == start of wire format rdata */
++        offset = ldns_rdf_size(ldns_rr_owner(rr1)) + 4 + 2 + 2 + 2;
++        /* if either record doesn't have any RDATA... */
++        if (offset > rr1_len || offset > rr2_len) {
++            if (rr1_len == rr2_len) {
++              return 0;
++            }
++            return ((int) rr2_len - (int) rr1_len);
++        }
++
++	return 0;
++}
++
++int ldns_rr_compare_wire(ldns_buffer *rr1_buf, ldns_buffer *rr2_buf)
++{
++        size_t rr1_len, rr2_len, min_len, i, offset;
++
++        rr1_len = ldns_buffer_capacity(rr1_buf);
++        rr2_len = ldns_buffer_capacity(rr2_buf);
++
++        /* jump past dname (checked in earlier part)
++         * and especially past TTL */
++        offset = 0;
++        while (offset < rr1_len && *ldns_buffer_at(rr1_buf, offset) != 0) {
++          offset += *ldns_buffer_at(rr1_buf, offset) + 1;
++        }
++        /* jump to rdata section (PAST the rdata length field, otherwise
++           rrs with different lengths might be sorted erroneously */
++        offset += 11;
++	   min_len = (rr1_len < rr2_len) ? rr1_len : rr2_len;
++        /* Compare RRs RDATA byte for byte. */
++        for(i = offset; i < min_len; i++) {
++                if (*ldns_buffer_at(rr1_buf,i) < *ldns_buffer_at(rr2_buf,i)) {
++                        return -1;
++                } else if (*ldns_buffer_at(rr1_buf,i) > *ldns_buffer_at(rr2_buf,i)) {
++                        return +1;
++                }
++        }
++
++        /* If both RDATAs are the same up to min_len, then the shorter one sorts first. */
++        if (rr1_len < rr2_len) {
++                return -1;
++        } else if (rr1_len > rr2_len) {
++                return +1;
++	}
++        /* The RDATAs are equal. */
++        return 0;
++
++}
++
++int
++ldns_rr_compare(const ldns_rr *rr1, const ldns_rr *rr2)
++{
++	int result;
++	size_t rr1_len, rr2_len;
++
++	ldns_buffer *rr1_buf;
++	ldns_buffer *rr2_buf;
++
++	result = ldns_rr_compare_no_rdata(rr1, rr2);
++	if (result == 0) {
++		rr1_len = ldns_rr_uncompressed_size(rr1);
++		rr2_len = ldns_rr_uncompressed_size(rr2);
++
++		rr1_buf = ldns_buffer_new(rr1_len);
++		rr2_buf = ldns_buffer_new(rr2_len);
++
++		if (ldns_rr2buffer_wire_canonical(rr1_buf,
++								    rr1,
++								    LDNS_SECTION_ANY)
++		    != LDNS_STATUS_OK) {
++			ldns_buffer_free(rr1_buf);
++			ldns_buffer_free(rr2_buf);
++			return 0;
++		}
++		if (ldns_rr2buffer_wire_canonical(rr2_buf,
++								    rr2,
++								    LDNS_SECTION_ANY)
++		    != LDNS_STATUS_OK) {
++			ldns_buffer_free(rr1_buf);
++			ldns_buffer_free(rr2_buf);
++			return 0;
++		}
++
++		result = ldns_rr_compare_wire(rr1_buf, rr2_buf);
++
++		ldns_buffer_free(rr1_buf);
++		ldns_buffer_free(rr2_buf);
++	}
++
++	return result;
++}
++
++/* convert dnskey to a ds with the given algorithm,
++ * then compare the result with the given ds */
++static int
++ldns_rr_compare_ds_dnskey(ldns_rr *ds,
++                          ldns_rr *dnskey)
++{
++	ldns_rr *ds_gen;
++	bool result = false;
++	ldns_hash algo;
++
++	if (!dnskey || !ds ||
++	    ldns_rr_get_type(ds) != LDNS_RR_TYPE_DS ||
++	    ldns_rr_get_type(dnskey) != LDNS_RR_TYPE_DNSKEY) {
++		return false;
++	}
++
++	if (ldns_rr_rdf(ds, 2) == NULL) {
++		return false;
++	}
++	algo = ldns_rdf2native_int8(ldns_rr_rdf(ds, 2));
++
++	ds_gen = ldns_key_rr2ds(dnskey, algo);
++	if (ds_gen) {
++		result = ldns_rr_compare(ds, ds_gen) == 0;
++		ldns_rr_free(ds_gen);
++	}
++	return result;
++}
++
++bool
++ldns_rr_compare_ds(const ldns_rr *orr1, const ldns_rr *orr2)
++{
++	bool result;
++	ldns_rr *rr1 = ldns_rr_clone(orr1);
++	ldns_rr *rr2 = ldns_rr_clone(orr2);
++
++	/* set ttls to zero */
++	ldns_rr_set_ttl(rr1, 0);
++	ldns_rr_set_ttl(rr2, 0);
++
++	if (ldns_rr_get_type(rr1) == LDNS_RR_TYPE_DS &&
++	    ldns_rr_get_type(rr2) == LDNS_RR_TYPE_DNSKEY) {
++		result = ldns_rr_compare_ds_dnskey(rr1, rr2);
++	} else if (ldns_rr_get_type(rr1) == LDNS_RR_TYPE_DNSKEY &&
++	    ldns_rr_get_type(rr2) == LDNS_RR_TYPE_DS) {
++		result = ldns_rr_compare_ds_dnskey(rr2, rr1);
++	} else {
++		result = (ldns_rr_compare(rr1, rr2) == 0);
++	}
++
++	ldns_rr_free(rr1);
++	ldns_rr_free(rr2);
++
++	return result;
++}
++
++int
++ldns_rr_list_compare(const ldns_rr_list *rrl1, const ldns_rr_list *rrl2)
++{
++	size_t i = 0;
++	int rr_cmp;
++
++	assert(rrl1 != NULL);
++	assert(rrl2 != NULL);
++
++	for (i = 0; i < ldns_rr_list_rr_count(rrl1) && i < ldns_rr_list_rr_count(rrl2); i++) {
++		rr_cmp = ldns_rr_compare(ldns_rr_list_rr(rrl1, i), ldns_rr_list_rr(rrl2, i));
++		if (rr_cmp != 0) {
++			return rr_cmp;
++		}
++	}
++
++	if (i == ldns_rr_list_rr_count(rrl1) &&
++	    i != ldns_rr_list_rr_count(rrl2)) {
++		return 1;
++	} else if (i == ldns_rr_list_rr_count(rrl2) &&
++	           i != ldns_rr_list_rr_count(rrl1)) {
++		return -1;
++	} else {
++		return 0;
++	}
++}
++
++size_t
++ldns_rr_uncompressed_size(const ldns_rr *r)
++{
++	size_t rrsize;
++	size_t i;
++
++	rrsize = 0;
++	/* add all the rdf sizes */
++	for(i = 0; i < ldns_rr_rd_count(r); i++) {
++		rrsize += ldns_rdf_size(ldns_rr_rdf(r, i));
++	}
++	/* ownername */
++	rrsize += ldns_rdf_size(ldns_rr_owner(r));
++	rrsize += LDNS_RR_OVERHEAD;
++	return rrsize;
++}
++
++void
++ldns_rr2canonical(ldns_rr *rr)
++{
++	uint16_t i;
++
++	if (!rr) {
++	  return;
++        }
++
++        ldns_dname2canonical(ldns_rr_owner(rr));
++
++	/*
++	 * lowercase the rdata dnames if the rr type is one
++	 * of the list in chapter 7 of RFC3597
++	 * Also added RRSIG, because a "Signer's Name" should be canonicalized
++	 * too. See dnssec-bis-updates-16. We can add it to this list because
++	 * the "Signer's Name"  is the only dname type rdata field in a RRSIG.
++	 */
++	switch(ldns_rr_get_type(rr)) {
++        	case LDNS_RR_TYPE_NS:
++        	case LDNS_RR_TYPE_MD:
++        	case LDNS_RR_TYPE_MF:
++        	case LDNS_RR_TYPE_CNAME:
++        	case LDNS_RR_TYPE_SOA:
++        	case LDNS_RR_TYPE_MB:
++        	case LDNS_RR_TYPE_MG:
++        	case LDNS_RR_TYPE_MR:
++        	case LDNS_RR_TYPE_PTR:
++        	case LDNS_RR_TYPE_MINFO:
++        	case LDNS_RR_TYPE_MX:
++        	case LDNS_RR_TYPE_RP:
++        	case LDNS_RR_TYPE_AFSDB:
++        	case LDNS_RR_TYPE_RT:
++        	case LDNS_RR_TYPE_SIG:
++        	case LDNS_RR_TYPE_PX:
++        	case LDNS_RR_TYPE_NXT:
++        	case LDNS_RR_TYPE_NAPTR:
++        	case LDNS_RR_TYPE_KX:
++        	case LDNS_RR_TYPE_SRV:
++        	case LDNS_RR_TYPE_DNAME:
++        	case LDNS_RR_TYPE_A6:
++        	case LDNS_RR_TYPE_RRSIG:
++			for (i = 0; i < ldns_rr_rd_count(rr); i++) {
++				ldns_dname2canonical(ldns_rr_rdf(rr, i));
++			}
++			return;
++		default:
++			/* do nothing */
++			return;
++	}
++}
++
++void
++ldns_rr_list2canonical(ldns_rr_list *rr_list)
++{
++	size_t i;
++	for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
++		ldns_rr2canonical(ldns_rr_list_rr(rr_list, i));
++	}
++}
++
++uint8_t
++ldns_rr_label_count(ldns_rr *rr)
++{
++	if (!rr) {
++		return 0;
++	}
++	return ldns_dname_label_count(
++			ldns_rr_owner(rr));
++}
++
++/** \cond */
++static const ldns_rdf_type type_0_wireformat[] = { LDNS_RDF_TYPE_UNKNOWN };
++static const ldns_rdf_type type_a_wireformat[] = { LDNS_RDF_TYPE_A };
++static const ldns_rdf_type type_ns_wireformat[] = { LDNS_RDF_TYPE_DNAME };
++static const ldns_rdf_type type_md_wireformat[] = { LDNS_RDF_TYPE_DNAME };
++static const ldns_rdf_type type_mf_wireformat[] = { LDNS_RDF_TYPE_DNAME };
++static const ldns_rdf_type type_cname_wireformat[] = { LDNS_RDF_TYPE_DNAME };
++static const ldns_rdf_type type_soa_wireformat[] = {
++	LDNS_RDF_TYPE_DNAME, LDNS_RDF_TYPE_DNAME, LDNS_RDF_TYPE_INT32, 
++	LDNS_RDF_TYPE_PERIOD, LDNS_RDF_TYPE_PERIOD, LDNS_RDF_TYPE_PERIOD,
++	LDNS_RDF_TYPE_PERIOD
++};
++static const ldns_rdf_type type_mb_wireformat[] = { LDNS_RDF_TYPE_DNAME };
++static const ldns_rdf_type type_mg_wireformat[] = { LDNS_RDF_TYPE_DNAME };
++static const ldns_rdf_type type_mr_wireformat[] = { LDNS_RDF_TYPE_DNAME };
++static const ldns_rdf_type type_wks_wireformat[] = {
++	LDNS_RDF_TYPE_A, LDNS_RDF_TYPE_WKS
++};
++static const ldns_rdf_type type_ptr_wireformat[] = { LDNS_RDF_TYPE_DNAME };
++static const ldns_rdf_type type_hinfo_wireformat[] = {
++	LDNS_RDF_TYPE_STR, LDNS_RDF_TYPE_STR
++};
++static const ldns_rdf_type type_minfo_wireformat[] = {
++	LDNS_RDF_TYPE_DNAME, LDNS_RDF_TYPE_DNAME
++};
++static const ldns_rdf_type type_mx_wireformat[] = {
++	LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_DNAME
++};
++static const ldns_rdf_type type_rp_wireformat[] = {
++	LDNS_RDF_TYPE_DNAME, LDNS_RDF_TYPE_DNAME
++};
++static const ldns_rdf_type type_afsdb_wireformat[] = {
++	LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_DNAME
++};
++static const ldns_rdf_type type_x25_wireformat[] = { LDNS_RDF_TYPE_STR };
++static const ldns_rdf_type type_isdn_wireformat[] = {
++	LDNS_RDF_TYPE_STR, LDNS_RDF_TYPE_STR
++};
++static const ldns_rdf_type type_rt_wireformat[] = {
++	LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_DNAME
++};
++static const ldns_rdf_type type_nsap_wireformat[] = {
++	LDNS_RDF_TYPE_NSAP
++};
++static const ldns_rdf_type type_nsap_ptr_wireformat[] = {
++	LDNS_RDF_TYPE_STR
++};
++static const ldns_rdf_type type_sig_wireformat[] = {
++	LDNS_RDF_TYPE_TYPE, LDNS_RDF_TYPE_ALG, LDNS_RDF_TYPE_INT8, LDNS_RDF_TYPE_INT32,
++	LDNS_RDF_TYPE_TIME, LDNS_RDF_TYPE_TIME, LDNS_RDF_TYPE_INT16,
++	LDNS_RDF_TYPE_DNAME, LDNS_RDF_TYPE_B64
++};
++static const ldns_rdf_type type_key_wireformat[] = {
++	LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_INT8, LDNS_RDF_TYPE_INT8, LDNS_RDF_TYPE_B64
++};
++static const ldns_rdf_type type_px_wireformat[] = {
++	LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_DNAME, LDNS_RDF_TYPE_DNAME
++};
++static const ldns_rdf_type type_gpos_wireformat[] = {
++	LDNS_RDF_TYPE_STR, LDNS_RDF_TYPE_STR, LDNS_RDF_TYPE_STR
++};
++static const ldns_rdf_type type_aaaa_wireformat[] = { LDNS_RDF_TYPE_AAAA };
++static const ldns_rdf_type type_loc_wireformat[] = { LDNS_RDF_TYPE_LOC };
++static const ldns_rdf_type type_nxt_wireformat[] = {
++	LDNS_RDF_TYPE_DNAME, LDNS_RDF_TYPE_UNKNOWN
++};
++static const ldns_rdf_type type_eid_wireformat[] = {
++	LDNS_RDF_TYPE_HEX
++};
++static const ldns_rdf_type type_nimloc_wireformat[] = {
++	LDNS_RDF_TYPE_HEX
++};
++static const ldns_rdf_type type_srv_wireformat[] = {
++	LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_DNAME
++};
++static const ldns_rdf_type type_atma_wireformat[] = {
++	LDNS_RDF_TYPE_ATMA
++};
++static const ldns_rdf_type type_naptr_wireformat[] = {
++	LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_STR, LDNS_RDF_TYPE_STR, LDNS_RDF_TYPE_STR, LDNS_RDF_TYPE_DNAME
++};
++static const ldns_rdf_type type_kx_wireformat[] = {
++	LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_DNAME
++};
++static const ldns_rdf_type type_cert_wireformat[] = {
++	 LDNS_RDF_TYPE_CERT_ALG, LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_ALG, LDNS_RDF_TYPE_B64
++};
++static const ldns_rdf_type type_a6_wireformat[] = { LDNS_RDF_TYPE_UNKNOWN };
++static const ldns_rdf_type type_dname_wireformat[] = { LDNS_RDF_TYPE_DNAME };
++static const ldns_rdf_type type_sink_wireformat[] = { LDNS_RDF_TYPE_INT8,
++	LDNS_RDF_TYPE_INT8, LDNS_RDF_TYPE_INT8, LDNS_RDF_TYPE_B64
++};
++static const ldns_rdf_type type_apl_wireformat[] = {
++	LDNS_RDF_TYPE_APL
++};
++static const ldns_rdf_type type_ds_wireformat[] = {
++	LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_ALG, LDNS_RDF_TYPE_INT8, LDNS_RDF_TYPE_HEX
++};
++static const ldns_rdf_type type_sshfp_wireformat[] = {
++	LDNS_RDF_TYPE_INT8, LDNS_RDF_TYPE_INT8, LDNS_RDF_TYPE_HEX
++};
++static const ldns_rdf_type type_ipseckey_wireformat[] = {
++	LDNS_RDF_TYPE_IPSECKEY
++};
++static const ldns_rdf_type type_rrsig_wireformat[] = {
++	LDNS_RDF_TYPE_TYPE, LDNS_RDF_TYPE_ALG, LDNS_RDF_TYPE_INT8, LDNS_RDF_TYPE_INT32,
++	LDNS_RDF_TYPE_TIME, LDNS_RDF_TYPE_TIME, LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_DNAME, LDNS_RDF_TYPE_B64
++};
++static const ldns_rdf_type type_nsec_wireformat[] = {
++	LDNS_RDF_TYPE_DNAME, LDNS_RDF_TYPE_NSEC
++};
++static const ldns_rdf_type type_dhcid_wireformat[] = {
++	LDNS_RDF_TYPE_B64
++};
++static const ldns_rdf_type type_talink_wireformat[] = {
++	LDNS_RDF_TYPE_DNAME, LDNS_RDF_TYPE_DNAME
++};
++/*@unused@*/ static const ldns_rdf_type type_openpgpkey_wireformat[] = {
++	LDNS_RDF_TYPE_B64
++};
++/* nsec3 is some vars, followed by same type of data of nsec */
++static const ldns_rdf_type type_nsec3_wireformat[] = {
++/*	LDNS_RDF_TYPE_NSEC3_VARS, LDNS_RDF_TYPE_NSEC3_NEXT_OWNER, LDNS_RDF_TYPE_NSEC*/
++	LDNS_RDF_TYPE_INT8, LDNS_RDF_TYPE_INT8, LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_NSEC3_SALT, LDNS_RDF_TYPE_NSEC3_NEXT_OWNER, LDNS_RDF_TYPE_NSEC
++};
++
++static const ldns_rdf_type type_nsec3param_wireformat[] = {
++/*	LDNS_RDF_TYPE_NSEC3_PARAMS_VARS*/
++	LDNS_RDF_TYPE_INT8,
++	LDNS_RDF_TYPE_INT8,
++	LDNS_RDF_TYPE_INT16,
++	LDNS_RDF_TYPE_NSEC3_SALT
++};
++
++static const ldns_rdf_type type_dnskey_wireformat[] = {
++	LDNS_RDF_TYPE_INT16,
++	LDNS_RDF_TYPE_INT8,
++	LDNS_RDF_TYPE_ALG,
++	LDNS_RDF_TYPE_B64
++};
++static const ldns_rdf_type type_tkey_wireformat[] = {
++	LDNS_RDF_TYPE_DNAME,
++	LDNS_RDF_TYPE_TIME,
++	LDNS_RDF_TYPE_TIME,
++	LDNS_RDF_TYPE_INT16,
++	LDNS_RDF_TYPE_INT16,
++	LDNS_RDF_TYPE_INT16_DATA,
++	LDNS_RDF_TYPE_INT16_DATA,
++};
++static const ldns_rdf_type type_tsig_wireformat[] = {
++	LDNS_RDF_TYPE_DNAME,
++	LDNS_RDF_TYPE_TSIGTIME,
++	LDNS_RDF_TYPE_INT16,
++	LDNS_RDF_TYPE_INT16_DATA,
++	LDNS_RDF_TYPE_INT16,
++	LDNS_RDF_TYPE_INT16,
++	LDNS_RDF_TYPE_INT16_DATA
++};
++static const ldns_rdf_type type_tlsa_wireformat[] = {
++	LDNS_RDF_TYPE_CERTIFICATE_USAGE,
++	LDNS_RDF_TYPE_SELECTOR,
++	LDNS_RDF_TYPE_MATCHING_TYPE,
++	LDNS_RDF_TYPE_HEX
++};
++static const ldns_rdf_type type_hip_wireformat[] = {
++	LDNS_RDF_TYPE_HIP
++};
++static const ldns_rdf_type type_nid_wireformat[] = {
++	LDNS_RDF_TYPE_INT16,
++	LDNS_RDF_TYPE_ILNP64
++};
++static const ldns_rdf_type type_l32_wireformat[] = {
++	LDNS_RDF_TYPE_INT16,
++	LDNS_RDF_TYPE_A
++};
++static const ldns_rdf_type type_l64_wireformat[] = {
++	LDNS_RDF_TYPE_INT16,
++	LDNS_RDF_TYPE_ILNP64
++};
++static const ldns_rdf_type type_lp_wireformat[] = {
++	LDNS_RDF_TYPE_INT16,
++	LDNS_RDF_TYPE_DNAME
++};
++static const ldns_rdf_type type_eui48_wireformat[] = {
++	LDNS_RDF_TYPE_EUI48
++};
++static const ldns_rdf_type type_eui64_wireformat[] = {
++	LDNS_RDF_TYPE_EUI64
++};
++#ifdef RRTYPE_URI
++static const ldns_rdf_type type_uri_wireformat[] = {
++	LDNS_RDF_TYPE_INT16,
++	LDNS_RDF_TYPE_INT16,
++	LDNS_RDF_TYPE_LONG_STR
++};
++#endif
++static const ldns_rdf_type type_caa_wireformat[] = {
++	LDNS_RDF_TYPE_INT8,
++	LDNS_RDF_TYPE_TAG,
++	LDNS_RDF_TYPE_LONG_STR
++};
++/** \endcond */
++
++/** \cond */
++/* All RR's defined in 1035 are well known and can thus
++ * be compressed. See RFC3597. These RR's are:
++ * CNAME HINFO MB MD MF MG MINFO MR MX NULL NS PTR SOA TXT
++ */
++static ldns_rr_descriptor rdata_field_descriptors[] = {
++	/* 0 */
++	{ 0, NULL, 0, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++	/* 1 */
++	{LDNS_RR_TYPE_A, "A", 1, 1, type_a_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++	/* 2 */
++	{LDNS_RR_TYPE_NS, "NS", 1, 1, type_ns_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_COMPRESS, 1 },
++	/* 3 */
++	{LDNS_RR_TYPE_MD, "MD", 1, 1, type_md_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_COMPRESS, 1 },
++	/* 4 */
++	{LDNS_RR_TYPE_MF, "MF", 1, 1, type_mf_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_COMPRESS, 1 },
++	/* 5 */
++	{LDNS_RR_TYPE_CNAME, "CNAME", 1, 1, type_cname_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_COMPRESS, 1 },
++	/* 6 */
++	{LDNS_RR_TYPE_SOA, "SOA", 7, 7, type_soa_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_COMPRESS, 2 },
++	/* 7 */
++	{LDNS_RR_TYPE_MB, "MB", 1, 1, type_mb_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_COMPRESS, 1 },
++	/* 8 */
++	{LDNS_RR_TYPE_MG, "MG", 1, 1, type_mg_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_COMPRESS, 1 },
++	/* 9 */
++	{LDNS_RR_TYPE_MR, "MR", 1, 1, type_mr_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_COMPRESS, 1 },
++	/* 10 */
++	{LDNS_RR_TYPE_NULL, "NULL", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++	/* 11 */
++	{LDNS_RR_TYPE_WKS, "WKS", 2, 2, type_wks_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++	/* 12 */
++	{LDNS_RR_TYPE_PTR, "PTR", 1, 1, type_ptr_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_COMPRESS, 1 },
++	/* 13 */
++	{LDNS_RR_TYPE_HINFO, "HINFO", 2, 2, type_hinfo_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++	/* 14 */
++	{LDNS_RR_TYPE_MINFO, "MINFO", 2, 2, type_minfo_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_COMPRESS, 2 },
++	/* 15 */
++	{LDNS_RR_TYPE_MX, "MX", 2, 2, type_mx_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_COMPRESS, 1 },
++	/* 16 */
++	{LDNS_RR_TYPE_TXT, "TXT", 1, 0, NULL, LDNS_RDF_TYPE_STR, LDNS_RR_NO_COMPRESS, 0 },
++	/* 17 */
++	{LDNS_RR_TYPE_RP, "RP", 2, 2, type_rp_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 2 },
++	/* 18 */
++	{LDNS_RR_TYPE_AFSDB, "AFSDB", 2, 2, type_afsdb_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 1 },
++	/* 19 */
++	{LDNS_RR_TYPE_X25, "X25", 1, 1, type_x25_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++	/* 20 */
++	{LDNS_RR_TYPE_ISDN, "ISDN", 1, 2, type_isdn_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++	/* 21 */
++	{LDNS_RR_TYPE_RT, "RT", 2, 2, type_rt_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 1 },
++	/* 22 */
++	{LDNS_RR_TYPE_NSAP, "NSAP", 1, 1, type_nsap_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++	/* 23 */
++	{LDNS_RR_TYPE_NSAP_PTR, "NSAP-PTR", 1, 1, type_nsap_ptr_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++	/* 24 */
++	{LDNS_RR_TYPE_SIG, "SIG", 9, 9, type_sig_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 1 },
++	/* 25 */
++	{LDNS_RR_TYPE_KEY, "KEY", 4, 4, type_key_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++	/* 26 */
++	{LDNS_RR_TYPE_PX, "PX", 3, 3, type_px_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 2 },
++	/* 27 */
++	{LDNS_RR_TYPE_GPOS, "GPOS", 3, 3, type_gpos_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++	/* 28 */
++	{LDNS_RR_TYPE_AAAA, "AAAA", 1, 1, type_aaaa_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++	/* 29 */
++	{LDNS_RR_TYPE_LOC, "LOC", 1, 1, type_loc_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++	/* 30 */
++	{LDNS_RR_TYPE_NXT, "NXT", 2, 2, type_nxt_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 1 },
++	/* 31 */
++	{LDNS_RR_TYPE_EID, "EID", 1, 1, type_eid_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++	/* 32 */
++	{LDNS_RR_TYPE_NIMLOC, "NIMLOC", 1, 1, type_nimloc_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++	/* 33 */
++	{LDNS_RR_TYPE_SRV, "SRV", 4, 4, type_srv_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 1 },
++	/* 34 */
++	{LDNS_RR_TYPE_ATMA, "ATMA", 1, 1, type_atma_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++	/* 35 */
++	{LDNS_RR_TYPE_NAPTR, "NAPTR", 6, 6, type_naptr_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 1 },
++	/* 36 */
++	{LDNS_RR_TYPE_KX, "KX", 2, 2, type_kx_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 1 },
++	/* 37 */
++	{LDNS_RR_TYPE_CERT, "CERT", 4, 4, type_cert_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++	/* 38 */
++	{LDNS_RR_TYPE_A6, "A6", 1, 1, type_a6_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++	/* 39 */
++	{LDNS_RR_TYPE_DNAME, "DNAME", 1, 1, type_dname_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 1 },
++	/* 40 */
++	{LDNS_RR_TYPE_SINK, "SINK", 1, 1, type_sink_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++	/* 41 */
++	{LDNS_RR_TYPE_OPT, "OPT", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++	/* 42 */
++	{LDNS_RR_TYPE_APL, "APL", 0, 0, type_apl_wireformat, LDNS_RDF_TYPE_APL, LDNS_RR_NO_COMPRESS, 0 },
++	/* 43 */
++	{LDNS_RR_TYPE_DS, "DS", 4, 4, type_ds_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++	/* 44 */
++	{LDNS_RR_TYPE_SSHFP, "SSHFP", 3, 3, type_sshfp_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++	/* 45 */
++	{LDNS_RR_TYPE_IPSECKEY, "IPSECKEY", 1, 1, type_ipseckey_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++	/* 46 */
++	{LDNS_RR_TYPE_RRSIG, "RRSIG", 9, 9, type_rrsig_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 1 },
++	/* 47 */
++	{LDNS_RR_TYPE_NSEC, "NSEC", 1, 2, type_nsec_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 1 },
++	/* 48 */
++	{LDNS_RR_TYPE_DNSKEY, "DNSKEY", 4, 4, type_dnskey_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++	/* 49 */
++	{LDNS_RR_TYPE_DHCID, "DHCID", 1, 1, type_dhcid_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++	/* 50 */
++	{LDNS_RR_TYPE_NSEC3, "NSEC3", 5, 6, type_nsec3_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++	/* 51 */
++	{LDNS_RR_TYPE_NSEC3PARAM, "NSEC3PARAM", 4, 4, type_nsec3param_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++	/* 52 */
++	{LDNS_RR_TYPE_TLSA, "TLSA", 4, 4, type_tlsa_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++
++{LDNS_RR_TYPE_NULL, "TYPE53", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE54", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++
++	/* 55
++	 * Hip ends with 0 or more Rendezvous Servers represented as dname's.
++	 * Hence the LDNS_RDF_TYPE_DNAME _variable field and the _maximum field
++	 * set to 0.
++	 */
++	{LDNS_RR_TYPE_HIP, "HIP", 1, 1, type_hip_wireformat, LDNS_RDF_TYPE_DNAME, LDNS_RR_NO_COMPRESS, 0 },
++
++#ifdef RRTYPE_NINFO
++	/* 56 */
++	{LDNS_RR_TYPE_NINFO, "NINFO", 1, 0, NULL, LDNS_RDF_TYPE_STR, LDNS_RR_NO_COMPRESS, 0 },
++#else
++{LDNS_RR_TYPE_NULL, "TYPE56", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++#endif
++#ifdef RRTYPE_RKEY
++	/* 57 */
++	{LDNS_RR_TYPE_RKEY, "RKEY", 4, 4, type_key_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++#else
++{LDNS_RR_TYPE_NULL, "TYPE57", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++#endif
++	/* 58 */
++	{LDNS_RR_TYPE_TALINK, "TALINK", 2, 2, type_talink_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 2 },
++
++	/* 59 */
++	{LDNS_RR_TYPE_CDS, "CDS", 4, 4, type_ds_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++	/* 60 */
++	{LDNS_RR_TYPE_CDNSKEY, "CDNSKEY", 4, 4, type_dnskey_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++
++#ifdef RRTYPE_OPENPGPKEY
++	/* 61 */
++	{LDNS_RR_TYPE_OPENPGPKEY, "OPENPGPKEY", 1, 1, type_openpgpkey_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++#else
++{LDNS_RR_TYPE_NULL, "TYPE61", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++#endif
++
++{LDNS_RR_TYPE_NULL, "TYPE62", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE63", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE64", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE65", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE66", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE67", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE68", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE69", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE70", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE71", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE72", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE73", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE74", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE75", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE76", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE77", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE78", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE79", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE80", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE81", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE82", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE83", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE84", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE85", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE86", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE87", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE88", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE89", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE90", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE91", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE92", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE93", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE94", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE95", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE96", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE97", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE98", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++
++	/* 99 */
++	{LDNS_RR_TYPE_SPF,  "SPF", 1, 0, NULL, LDNS_RDF_TYPE_STR, LDNS_RR_NO_COMPRESS, 0 },
++
++	/* UINFO  [IANA-Reserved] */
++{LDNS_RR_TYPE_NULL, "TYPE100", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++	/* UID    [IANA-Reserved] */
++{LDNS_RR_TYPE_NULL, "TYPE101", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++	/* GID    [IANA-Reserved] */
++{LDNS_RR_TYPE_NULL, "TYPE102", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++	/* UNSPEC [IANA-Reserved] */
++{LDNS_RR_TYPE_NULL, "TYPE103", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++
++	/* 104 */
++	{LDNS_RR_TYPE_NID, "NID", 2, 2, type_nid_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++	/* 105 */
++	{LDNS_RR_TYPE_L32, "L32", 2, 2, type_l32_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++	/* 106 */
++	{LDNS_RR_TYPE_L64, "L64", 2, 2, type_l64_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++	/* 107 */
++	{LDNS_RR_TYPE_LP, "LP", 2, 2, type_lp_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 1 },
++	/* 108 */
++	{LDNS_RR_TYPE_EUI48, "EUI48", 1, 1, type_eui48_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++	/* 109 */
++	{LDNS_RR_TYPE_EUI64, "EUI64", 1, 1, type_eui64_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++
++{LDNS_RR_TYPE_NULL, "TYPE110", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE111", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE112", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE113", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE114", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE115", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE116", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE117", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE118", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE119", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE120", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE121", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE122", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE123", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE124", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE125", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE126", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE127", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE128", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE129", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE130", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE131", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE132", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE133", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE134", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE135", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE136", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE137", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE138", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE139", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE140", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE141", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE142", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE143", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE144", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE145", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE146", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE147", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE148", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE149", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE150", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE151", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE152", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE153", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE154", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE155", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE156", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE157", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE158", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE159", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE160", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE161", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE162", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE163", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE164", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE165", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE166", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE167", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE168", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE169", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE170", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE171", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE172", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE173", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE174", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE175", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE176", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE177", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE178", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE179", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE180", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE181", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE182", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE183", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE184", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE185", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE186", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE187", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE188", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE189", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE190", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE191", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE192", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE193", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE194", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE195", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE196", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE197", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE198", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE199", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE200", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE201", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE202", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE203", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE204", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE205", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE206", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE207", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE208", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE209", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE210", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE211", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE212", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE213", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE214", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE215", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE216", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE217", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE218", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE219", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE220", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE221", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE222", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE223", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE224", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE225", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE226", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE227", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE228", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE229", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE230", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE231", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE232", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE233", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE234", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE235", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE236", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE237", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE238", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE239", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE240", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE241", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE242", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE243", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE244", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE245", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE246", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE247", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++{LDNS_RR_TYPE_NULL, "TYPE248", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++
++	/* LDNS_RDF_TYPE_INT16_DATA takes two fields (length and data) as one.
++	 * So, unlike RFC 2930 spec, we have 7 min/max rdf's i.s.o. 8/9.
++	 */
++	/* 249 */
++	{LDNS_RR_TYPE_TKEY, "TKEY", 7, 7, type_tkey_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 1 },
++	/* LDNS_RDF_TYPE_INT16_DATA takes two fields (length and data) as one.
++	 * So, unlike RFC 2930 spec, we have 7 min/max rdf's i.s.o. 8/9.
++	 */
++	/* 250 */
++	{LDNS_RR_TYPE_TSIG, "TSIG", 7, 7, type_tsig_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 1 },
++
++	/* IXFR: A request for a transfer of an incremental zone transfer */
++{LDNS_RR_TYPE_NULL, "TYPE251", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++	/* AXFR: A request for a transfer of an entire zone */
++{LDNS_RR_TYPE_NULL, "TYPE252", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++	/* MAILB: A request for mailbox-related records (MB, MG or MR) */
++{LDNS_RR_TYPE_NULL, "TYPE253", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++	/* MAILA: A request for mail agent RRs (Obsolete - see MX) */
++{LDNS_RR_TYPE_NULL, "TYPE254", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++	/* ANY: A request for all (available) records */
++{LDNS_RR_TYPE_NULL, "TYPE255", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++
++#ifdef RRTYPE_URI
++	/* 256 */
++	{LDNS_RR_TYPE_URI, "URI", 3, 3, type_uri_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++#else
++{LDNS_RR_TYPE_NULL, "TYPE256", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++#endif
++	/* 257 */
++	{LDNS_RR_TYPE_CAA, "CAA", 3, 3, type_caa_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++
++/* split in array, no longer contiguous */
++
++#ifdef RRTYPE_TA
++	/* 32768 */
++	{LDNS_RR_TYPE_TA, "TA", 4, 4, type_ds_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++#else
++{LDNS_RR_TYPE_NULL, "TYPE32768", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
++#endif
++	/* 32769 */
++	{LDNS_RR_TYPE_DLV, "DLV", 4, 4, type_ds_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }
++};
++/** \endcond */
++
++/**
++ * \def LDNS_RDATA_FIELD_DESCRIPTORS_COUNT
++ * computes the number of rdata fields
++ */
++#define LDNS_RDATA_FIELD_DESCRIPTORS_COUNT \
++	(sizeof(rdata_field_descriptors)/sizeof(rdata_field_descriptors[0]))
++
++
++/*---------------------------------------------------------------------------*
++ * The functions below return an bitmap RDF with the space required to set
++ * or unset all known RR types. Arguably these functions are better situated
++ * in rdata.c, however for the space calculation it is necesarry to walk
++ * through rdata_field_descriptors which is not easily possible from anywhere
++ * other than rr.c where it is declared static.
++ *
++ * Alternatively rr.c could have provided an iterator for rr_type or 
++ * rdf_descriptors, but this seemed overkill for internal use only.
++ */
++static ldns_rr_descriptor* rdata_field_descriptors_end =
++	&rdata_field_descriptors[LDNS_RDATA_FIELD_DESCRIPTORS_COUNT];
++
++/* From RFC3845:
++ *
++ * 2.1.2.  The List of Type Bit Map(s) Field
++ * 
++ *    The RR type space is split into 256 window blocks, each representing
++ *    the low-order 8 bits of the 16-bit RR type space.  Each block that
++ *    has at least one active RR type is encoded using a single octet
++ *    window number (from 0 to 255), a single octet bitmap length (from 1
++ *    to 32) indicating the number of octets used for the window block's
++ *    bitmap, and up to 32 octets (256 bits) of bitmap.
++ * 
++ *    Window blocks are present in the NSEC RR RDATA in increasing
++ *    numerical order.
++ * 
++ *    "|" denotes concatenation
++ * 
++ *    Type Bit Map(s) Field = ( Window Block # | Bitmap Length | Bitmap ) +
++ * 
++ *    <cut>
++ * 
++ *    Blocks with no types present MUST NOT be included.  Trailing zero
++ *    octets in the bitmap MUST be omitted.  The length of each block's
++ *    bitmap is determined by the type code with the largest numerical
++ *    value within that block, among the set of RR types present at the
++ *    NSEC RR's owner name.  Trailing zero octets not specified MUST be
++ *    interpreted as zero octets.
++ */
++static ldns_status
++ldns_rdf_bitmap_known_rr_types_set(ldns_rdf** rdf, int value)
++{
++	uint8_t  window;		/*  most significant octet of type */
++	uint8_t  subtype;		/* least significant octet of type */
++	uint16_t windows[256]		/* Max subtype per window */
++#ifndef S_SPLINT_S
++	                      = { 0 }
++#endif
++	                             ;
++	ldns_rr_descriptor* d;	/* used to traverse rdata_field_descriptors */
++	size_t i;		/* used to traverse windows array */
++
++	size_t sz;			/* size needed for type bitmap rdf */
++	uint8_t* data = NULL;		/* rdf data */
++	uint8_t* dptr;			/* used to itraverse rdf data */
++
++	assert(rdf != NULL);
++
++	/* Which windows need to be in the bitmap rdf?
++	 */
++	for (d=rdata_field_descriptors; d < rdata_field_descriptors_end; d++) {
++		window  = d->_type >> 8;
++		subtype = d->_type & 0xff;
++		if (windows[window] < subtype) {
++			windows[window] = subtype;
++		}
++	}
++
++	/* How much space do we need in the rdf for those windows?
++	 */
++	sz = 0;
++	for (i = 0; i < 256; i++) {
++		if (windows[i]) {
++			sz += windows[i] / 8 + 3;
++		}
++	}
++	if (sz > 0) {
++		/* Format rdf data according RFC3845 Section 2.1.2 (see above)
++		 */
++		dptr = data = LDNS_XMALLOC(uint8_t, sz);
++		memset(data, value, sz);
++		if (!data) {
++			return LDNS_STATUS_MEM_ERR;
++		}
++		for (i = 0; i < 256; i++) {
++			if (windows[i]) {
++				*dptr++ = (uint8_t)i;
++				*dptr++ = (uint8_t)(windows[i] / 8 + 1);
++				dptr += dptr[-1];
++			}
++		}
++	}
++	/* Allocate and return rdf structure for the data
++	 */
++	*rdf = ldns_rdf_new(LDNS_RDF_TYPE_BITMAP, sz, data);
++	if (!*rdf) {
++		LDNS_FREE(data);
++		return LDNS_STATUS_MEM_ERR;
++	}
++	return LDNS_STATUS_OK;
++}
++
++ldns_status
++ldns_rdf_bitmap_known_rr_types_space(ldns_rdf** rdf)
++{
++	return ldns_rdf_bitmap_known_rr_types_set(rdf, 0);
++}
++
++ldns_status
++ldns_rdf_bitmap_known_rr_types(ldns_rdf** rdf)
++{
++	return ldns_rdf_bitmap_known_rr_types_set(rdf, 255);
++}
++/* End of RDF bitmap functions
++ *---------------------------------------------------------------------------*/
++
++
++const ldns_rr_descriptor *
++ldns_rr_descript(uint16_t type)
++{
++	size_t i;
++	if (type < LDNS_RDATA_FIELD_DESCRIPTORS_COMMON) {
++		return &rdata_field_descriptors[type];
++	} else {
++		/* because not all array index equals type code */
++		for (i = LDNS_RDATA_FIELD_DESCRIPTORS_COMMON;
++		     i < LDNS_RDATA_FIELD_DESCRIPTORS_COUNT;
++		     i++) {
++		        if (rdata_field_descriptors[i]._type == type) {
++		     		return &rdata_field_descriptors[i];
++			}
++		}
++                return &rdata_field_descriptors[0];
++	}
++}
++
++size_t
++ldns_rr_descriptor_minimum(const ldns_rr_descriptor *descriptor)
++{
++	if (descriptor) {
++		return descriptor->_minimum;
++	} else {
++		return 0;
++	}
++}
++
++size_t
++ldns_rr_descriptor_maximum(const ldns_rr_descriptor *descriptor)
++{
++	if (descriptor) {
++		if (descriptor->_variable != LDNS_RDF_TYPE_NONE) {
++			/* Should really be SIZE_MAX... bad FreeBSD.  */
++			return UINT_MAX;
++		} else {
++			return descriptor->_maximum;
++		}
++	} else {
++		return 0;
++	}
++}
++
++ldns_rdf_type
++ldns_rr_descriptor_field_type(const ldns_rr_descriptor *descriptor,
++                              size_t index)
++{
++	assert(descriptor != NULL);
++	assert(index < descriptor->_maximum
++	       || descriptor->_variable != LDNS_RDF_TYPE_NONE);
++	if (index < descriptor->_maximum) {
++		return descriptor->_wireformat[index];
++	} else {
++		return descriptor->_variable;
++	}
++}
++
++ldns_rr_type
++ldns_get_rr_type_by_name(const char *name)
++{
++	unsigned int i;
++	const char *desc_name;
++	const ldns_rr_descriptor *desc;
++
++	/* TYPEXX representation */
++	if (strlen(name) > 4 && strncasecmp(name, "TYPE", 4) == 0) {
++		return atoi(name + 4);
++	}
++
++	/* Normal types */
++	for (i = 0; i < (unsigned int) LDNS_RDATA_FIELD_DESCRIPTORS_COUNT; i++) {
++		desc = &rdata_field_descriptors[i];
++		desc_name = desc->_name;
++		if(desc_name &&
++		   strlen(name) == strlen(desc_name) &&
++		   strncasecmp(name, desc_name, strlen(desc_name)) == 0) {
++			/* because not all array index equals type code */
++			return desc->_type;
++		}
++	}
++
++	/* special cases for query types */
++	if (strlen(name) == 4 && strncasecmp(name, "IXFR", 4) == 0) {
++		return 251;
++	} else if (strlen(name) == 4 && strncasecmp(name, "AXFR", 4) == 0) {
++		return 252;
++	} else if (strlen(name) == 5 && strncasecmp(name, "MAILB", 5) == 0) {
++		return 253;
++	} else if (strlen(name) == 5 && strncasecmp(name, "MAILA", 5) == 0) {
++		return 254;
++	} else if (strlen(name) == 3 && strncasecmp(name, "ANY", 3) == 0) {
++		return 255;
++	}
++
++	return 0;
++}
++
++ldns_rr_class
++ldns_get_rr_class_by_name(const char *name)
++{
++	ldns_lookup_table *lt;
++
++	/* CLASSXX representation */
++	if (strlen(name) > 5 && strncasecmp(name, "CLASS", 5) == 0) {
++		return atoi(name + 5);
++	}
++
++	/* Normal types */
++	lt = ldns_lookup_by_name(ldns_rr_classes, name);
++
++	if (lt) {
++		return lt->id;
++	}
++	return 0;
++}
++
++
++ldns_rr_type
++ldns_rdf2rr_type(const ldns_rdf *rd)
++{
++        ldns_rr_type r;
++
++        if (!rd) {
++                return 0;
++        }
++
++        if (ldns_rdf_get_type(rd) != LDNS_RDF_TYPE_TYPE) {
++                return 0;
++        }
++
++        r = (ldns_rr_type) ldns_rdf2native_int16(rd);
++        return r;
++}
++
++ldns_rr_type
++ldns_rr_list_type(const ldns_rr_list *rr_list)
++{
++	if (rr_list && ldns_rr_list_rr_count(rr_list) > 0) {
++		return ldns_rr_get_type(ldns_rr_list_rr(rr_list, 0));
++	} else {
++		return 0;
++	}
++}
++
++ldns_rdf *
++ldns_rr_list_owner(const ldns_rr_list *rr_list)
++{
++	if (rr_list && ldns_rr_list_rr_count(rr_list) > 0) {
++		return ldns_rr_owner(ldns_rr_list_rr(rr_list, 0));
++	} else {
++		return NULL;
++	}
++}
+diff --git a/ldns/src/rr_functions.c b/ldns/src/rr_functions.c
+new file mode 100644
+index 0000000..b03751b
+--- /dev/null
++++ b/ldns/src/rr_functions.c
+@@ -0,0 +1,419 @@
++/*
++ * rr_function.c
++ *
++ * function that operate on specific rr types
++ *
++ * (c) NLnet Labs, 2004-2006
++ * See the file LICENSE for the license
++ */
++
++/*
++ * These come strait from perldoc Net::DNS::RR::xxx
++ * first the read variant, then the write. This is
++ * not complete.
++ */
++
++#include <ldns/config.h>
++
++#include <ldns/ldns.h>
++
++#include <limits.h>
++#include <strings.h>
++
++/**
++ * return a specific rdf
++ * \param[in] type type of RR
++ * \param[in] rr   the rr itself
++ * \param[in] pos  at which postion to get it
++ * \return the rdf sought
++ */
++static ldns_rdf *
++ldns_rr_function(ldns_rr_type type, const ldns_rr *rr, size_t pos)
++{
++        if (!rr || ldns_rr_get_type(rr) != type) {
++                return NULL;
++        }
++        return ldns_rr_rdf(rr, pos);
++}
++
++/**
++ * set a specific rdf
++ * \param[in] type type of RR
++ * \param[in] rr   the rr itself
++ * \param[in] rdf  the rdf to set
++ * \param[in] pos  at which postion to set it
++ * \return true or false
++ */
++static bool
++ldns_rr_set_function(ldns_rr_type type, ldns_rr *rr, ldns_rdf *rdf, size_t pos)
++{
++        ldns_rdf *pop;
++        if (!rr || ldns_rr_get_type(rr) != type) {
++                return false;
++        }
++        pop = ldns_rr_set_rdf(rr, rdf, pos);
++ 	ldns_rdf_deep_free(pop);
++        return true;
++}
++
++/* A/AAAA records */
++ldns_rdf *
++ldns_rr_a_address(const ldns_rr *r)
++{
++	/* 2 types to check, cannot use the macro */
++	if (!r || (ldns_rr_get_type(r) != LDNS_RR_TYPE_A &&
++			ldns_rr_get_type(r) != LDNS_RR_TYPE_AAAA)) {
++		return NULL;
++	}
++	return ldns_rr_rdf(r, 0);
++}
++
++bool
++ldns_rr_a_set_address(ldns_rr *r, ldns_rdf *f)
++{
++	/* 2 types to check, cannot use the macro... */
++	ldns_rdf *pop;
++	if (!r || (ldns_rr_get_type(r) != LDNS_RR_TYPE_A &&
++			ldns_rr_get_type(r) != LDNS_RR_TYPE_AAAA)) {
++		return false;
++	}
++	pop = ldns_rr_set_rdf(r, f, 0);
++	if (pop) {
++		LDNS_FREE(pop);
++		return true;
++	} else {
++		return false;
++	}
++}
++
++/* NS record */
++ldns_rdf *
++ldns_rr_ns_nsdname(const ldns_rr *r)
++{
++	return ldns_rr_function(LDNS_RR_TYPE_NS, r, 0);
++}
++
++/* MX record */
++ldns_rdf *
++ldns_rr_mx_preference(const ldns_rr *r)
++{
++	return ldns_rr_function(LDNS_RR_TYPE_MX, r, 0);
++}
++
++ldns_rdf *
++ldns_rr_mx_exchange(const ldns_rr *r)
++{
++	return ldns_rr_function(LDNS_RR_TYPE_MX, r, 1);
++}
++
++/* RRSIG record */
++ldns_rdf *
++ldns_rr_rrsig_typecovered(const ldns_rr *r)
++{
++	return ldns_rr_function(LDNS_RR_TYPE_RRSIG, r, 0);
++}
++
++bool
++ldns_rr_rrsig_set_typecovered(ldns_rr *r, ldns_rdf *f)
++{
++	return ldns_rr_set_function(LDNS_RR_TYPE_RRSIG, r, f, 0);
++}
++
++ldns_rdf *
++ldns_rr_rrsig_algorithm(const ldns_rr *r)
++{
++	return ldns_rr_function(LDNS_RR_TYPE_RRSIG, r, 1);
++}
++
++bool
++ldns_rr_rrsig_set_algorithm(ldns_rr *r, ldns_rdf *f)
++{
++	return ldns_rr_set_function(LDNS_RR_TYPE_RRSIG, r, f, 1);
++}
++
++ldns_rdf *
++ldns_rr_rrsig_labels(const ldns_rr *r)
++{
++	return ldns_rr_function(LDNS_RR_TYPE_RRSIG, r, 2);
++}
++
++bool
++ldns_rr_rrsig_set_labels(ldns_rr *r, ldns_rdf *f)
++{
++	return ldns_rr_set_function(LDNS_RR_TYPE_RRSIG, r, f, 2);
++}
++
++ldns_rdf *
++ldns_rr_rrsig_origttl(const ldns_rr *r)
++{
++	return ldns_rr_function(LDNS_RR_TYPE_RRSIG, r, 3);
++}
++
++bool
++ldns_rr_rrsig_set_origttl(ldns_rr *r, ldns_rdf *f)
++{
++	return ldns_rr_set_function(LDNS_RR_TYPE_RRSIG, r, f, 3);
++}
++
++ldns_rdf *
++ldns_rr_rrsig_expiration(const ldns_rr *r)
++{
++	return ldns_rr_function(LDNS_RR_TYPE_RRSIG, r, 4);
++}
++
++bool
++ldns_rr_rrsig_set_expiration(ldns_rr *r, ldns_rdf *f)
++{
++	return ldns_rr_set_function(LDNS_RR_TYPE_RRSIG, r, f, 4);
++}
++
++ldns_rdf *
++ldns_rr_rrsig_inception(const ldns_rr *r)
++{
++	return ldns_rr_function(LDNS_RR_TYPE_RRSIG, r, 5);
++}
++
++bool
++ldns_rr_rrsig_set_inception(ldns_rr *r, ldns_rdf *f)
++{
++	return ldns_rr_set_function(LDNS_RR_TYPE_RRSIG, r, f, 5);
++}
++
++ldns_rdf *
++ldns_rr_rrsig_keytag(const ldns_rr *r)
++{
++	return ldns_rr_function(LDNS_RR_TYPE_RRSIG, r, 6);
++}
++
++bool
++ldns_rr_rrsig_set_keytag(ldns_rr *r, ldns_rdf *f)
++{
++	return ldns_rr_set_function(LDNS_RR_TYPE_RRSIG, r, f, 6);
++}
++
++ldns_rdf *
++ldns_rr_rrsig_signame(const ldns_rr *r)
++{
++	return ldns_rr_function(LDNS_RR_TYPE_RRSIG, r, 7);
++}
++
++bool
++ldns_rr_rrsig_set_signame(ldns_rr *r, ldns_rdf *f)
++{
++	return ldns_rr_set_function(LDNS_RR_TYPE_RRSIG, r, f, 7);
++}
++
++ldns_rdf *
++ldns_rr_rrsig_sig(const ldns_rr *r)
++{
++	return ldns_rr_function(LDNS_RR_TYPE_RRSIG, r, 8);
++}
++
++bool
++ldns_rr_rrsig_set_sig(ldns_rr *r, ldns_rdf *f)
++{
++	return ldns_rr_set_function(LDNS_RR_TYPE_RRSIG, r, f, 8);
++}
++
++/* DNSKEY record */
++ldns_rdf *
++ldns_rr_dnskey_flags(const ldns_rr *r)
++{
++	return ldns_rr_function(LDNS_RR_TYPE_DNSKEY, r, 0);
++}
++
++bool
++ldns_rr_dnskey_set_flags(ldns_rr *r, ldns_rdf *f)
++{
++	return ldns_rr_set_function(LDNS_RR_TYPE_DNSKEY, r, f, 0);
++}
++
++ldns_rdf *
++ldns_rr_dnskey_protocol(const ldns_rr *r)
++{
++	return ldns_rr_function(LDNS_RR_TYPE_DNSKEY, r, 1);
++}
++
++bool
++ldns_rr_dnskey_set_protocol(ldns_rr *r, ldns_rdf *f)
++{
++	return ldns_rr_set_function(LDNS_RR_TYPE_DNSKEY, r, f, 1);
++}
++
++ldns_rdf *
++ldns_rr_dnskey_algorithm(const ldns_rr *r)
++{
++	return ldns_rr_function(LDNS_RR_TYPE_DNSKEY, r, 2);
++}
++
++bool
++ldns_rr_dnskey_set_algorithm(ldns_rr *r, ldns_rdf *f)
++{
++	return ldns_rr_set_function(LDNS_RR_TYPE_DNSKEY, r, f, 2);
++}
++
++ldns_rdf *
++ldns_rr_dnskey_key(const ldns_rr *r)
++{
++	return ldns_rr_function(LDNS_RR_TYPE_DNSKEY, r, 3);
++}
++
++bool
++ldns_rr_dnskey_set_key(ldns_rr *r, ldns_rdf *f)
++{
++	return ldns_rr_set_function(LDNS_RR_TYPE_DNSKEY, r, f, 3);
++}
++
++size_t
++ldns_rr_dnskey_key_size_raw(const unsigned char* keydata,
++                            const size_t len,
++                            const ldns_algorithm alg)
++{
++	/* for DSA keys */
++	uint8_t t;
++	
++	/* for RSA keys */
++	uint16_t exp;
++	uint16_t int16;
++	
++	switch ((ldns_signing_algorithm)alg) {
++	case LDNS_SIGN_DSA:
++	case LDNS_SIGN_DSA_NSEC3:
++		if (len > 0) {
++			t = keydata[0];
++			return (64 + t*8)*8;
++		} else {
++			return 0;
++		}
++		break;
++	case LDNS_SIGN_RSAMD5:
++	case LDNS_SIGN_RSASHA1:
++	case LDNS_SIGN_RSASHA1_NSEC3:
++#ifdef USE_SHA2
++	case LDNS_SIGN_RSASHA256:
++	case LDNS_SIGN_RSASHA512:
++#endif
++		if (len > 0) {
++			if (keydata[0] == 0) {
++				/* big exponent */
++				if (len > 3) {
++					memmove(&int16, keydata + 1, 2);
++					exp = ntohs(int16);
++					return (len - exp - 3)*8;
++				} else {
++					return 0;
++				}
++			} else {
++				exp = keydata[0];
++				return (len-exp-1)*8;
++			}
++		} else {
++			return 0;
++		}
++		break;
++#ifdef USE_GOST
++	case LDNS_SIGN_ECC_GOST:
++		return 512;
++#endif
++#ifdef USE_ECDSA
++        case LDNS_SIGN_ECDSAP256SHA256:
++                return 256;
++        case LDNS_SIGN_ECDSAP384SHA384:
++                return 384;
++#endif
++	case LDNS_SIGN_HMACMD5:
++		return len;
++	default:
++		return 0;
++	}
++}
++
++size_t 
++ldns_rr_dnskey_key_size(const ldns_rr *key) 
++{
++	if (!key || !ldns_rr_dnskey_key(key) 
++			|| !ldns_rr_dnskey_algorithm(key)) {
++		return 0;
++	}
++	return ldns_rr_dnskey_key_size_raw((unsigned char*)ldns_rdf_data(ldns_rr_dnskey_key(key)),
++	                                   ldns_rdf_size(ldns_rr_dnskey_key(key)),
++	                                   ldns_rdf2native_int8(ldns_rr_dnskey_algorithm(key))
++	                                  );
++}
++
++uint32_t ldns_soa_serial_identity(uint32_t ATTR_UNUSED(unused), void *data)
++{
++	return (uint32_t) (intptr_t) data;
++}
++
++uint32_t ldns_soa_serial_increment(uint32_t s, void *ATTR_UNUSED(unused))
++{
++	return ldns_soa_serial_increment_by(s, (void *)1);
++}
++
++uint32_t ldns_soa_serial_increment_by(uint32_t s, void *data)
++{
++	return s + (intptr_t) data;
++}
++
++uint32_t ldns_soa_serial_datecounter(uint32_t s, void *data)
++{
++	struct tm tm;
++	char s_str[11];
++	int32_t new_s;
++	time_t t = data ? (time_t) (intptr_t) data : ldns_time(NULL);
++
++	(void) strftime(s_str, 11, "%Y%m%d00", localtime_r(&t, &tm));
++	new_s = (int32_t) atoi(s_str);
++	return new_s - ((int32_t) s) <= 0 ? s+1 : ((uint32_t) new_s);
++}
++
++uint32_t ldns_soa_serial_unixtime(uint32_t s, void *data)
++{
++	int32_t new_s = data ? (int32_t) (intptr_t) data 
++			     : (int32_t) ldns_time(NULL);
++	return new_s - ((int32_t) s) <= 0 ? s+1 : ((uint32_t) new_s);
++}
++
++void
++ldns_rr_soa_increment(ldns_rr *soa)
++{
++	ldns_rr_soa_increment_func_data(soa, ldns_soa_serial_increment, NULL);
++}
++
++void
++ldns_rr_soa_increment_func(ldns_rr *soa, ldns_soa_serial_increment_func_t f)
++{
++	ldns_rr_soa_increment_func_data(soa, f, NULL);
++}
++
++void
++ldns_rr_soa_increment_func_data(ldns_rr *soa, 
++		ldns_soa_serial_increment_func_t f, void *data)
++{
++	ldns_rdf *prev_soa_serial_rdf;
++	if ( !soa || !f || ldns_rr_get_type(soa) != LDNS_RR_TYPE_SOA 
++			|| !ldns_rr_rdf(soa, 2)) {
++		return;
++	}
++	prev_soa_serial_rdf = ldns_rr_set_rdf(
++		  soa
++		, ldns_native2rdf_int32(
++			  LDNS_RDF_TYPE_INT32
++			, (*f)( ldns_rdf2native_int32(
++					ldns_rr_rdf(soa, 2))
++			      , data
++			)
++		)
++		, 2
++	);
++	LDNS_FREE(prev_soa_serial_rdf);
++}
++
++void
++ldns_rr_soa_increment_func_int(ldns_rr *soa, 
++		ldns_soa_serial_increment_func_t f, int data)
++{
++	ldns_rr_soa_increment_func_data(soa, f, (void *) (intptr_t) data);
++}
++
+diff --git a/ldns/src/sha1.c b/ldns/src/sha1.c
+new file mode 100644
+index 0000000..18a4dd2
+--- /dev/null
++++ b/ldns/src/sha1.c
+@@ -0,0 +1,177 @@
++/*
++ * modified for ldns by Jelte Jansen, original taken from OpenBSD:
++ * 
++ * SHA-1 in C
++ * By Steve Reid <steve at edmweb.com>
++ * 100% Public Domain
++ * 
++ * Test Vectors (from FIPS PUB 180-1)
++ * "abc"
++ *   A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
++ * "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
++ *   84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
++ * A million repetitions of "a"
++ *   34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
++*/
++
++/* #define LITTLE_ENDIAN * This should be #define'd already, if true. */
++
++#include <ldns/config.h>
++#include <ldns/ldns.h>
++#include <strings.h>
++
++#define SHA1HANDSOFF 1 /* Copies data before messing with it. */
++#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
++
++/* blk0() and blk() perform the initial expand. */
++/* I got the idea of expanding during the round function from SSLeay */
++#if BYTE_ORDER == LITTLE_ENDIAN
++#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
++    |(rol(block->l[i],8)&0x00FF00FF))
++#else
++#define blk0(i) block->l[i]
++#endif
++#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
++    ^block->l[(i+2)&15]^block->l[i&15],1))
++
++/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
++#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
++#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
++#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
++#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
++#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
++
++/* Hash a single 512-bit block. This is the core of the algorithm. */
++
++void
++ldns_sha1_transform(uint32_t state[5], const unsigned char buffer[LDNS_SHA1_BLOCK_LENGTH])
++{
++    uint32_t a, b, c, d, e;
++    typedef union {
++        unsigned char c[64];
++        unsigned int l[16];
++    } CHAR64LONG16;
++    CHAR64LONG16* block;
++#ifdef SHA1HANDSOFF
++    unsigned char workspace[LDNS_SHA1_BLOCK_LENGTH];
++
++    block = (CHAR64LONG16 *)workspace;
++    memmove(block, buffer, LDNS_SHA1_BLOCK_LENGTH);
++#else
++    block = (CHAR64LONG16 *)buffer;
++#endif
++    /* Copy context->state[] to working vars */
++    a = state[0];
++    b = state[1];
++    c = state[2];
++    d = state[3];
++    e = state[4];
++
++    /* 4 rounds of 20 operations each. Loop unrolled. */
++    R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
++    R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
++    R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
++    R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
++    R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
++    R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
++    R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
++    R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
++    R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
++    R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
++    R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
++    R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
++    R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
++    R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
++    R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
++    R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
++    R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
++    R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
++    R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
++    R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
++
++    /* Add the working vars back into context.state[] */
++    state[0] += a;
++    state[1] += b;
++    state[2] += c;
++    state[3] += d;
++    state[4] += e;
++    /* Wipe variables */
++    a = b = c = d = e = 0;
++}
++
++
++/* SHA1Init - Initialize new context */
++
++void
++ldns_sha1_init(ldns_sha1_ctx *context)
++{
++    /* SHA1 initialization constants */
++    context->count = 0;
++    context->state[0] = 0x67452301;
++    context->state[1] = 0xEFCDAB89;
++    context->state[2] = 0x98BADCFE;
++    context->state[3] = 0x10325476;
++    context->state[4] = 0xC3D2E1F0;
++}
++
++
++/* Run your data through this. */
++
++void
++ldns_sha1_update(ldns_sha1_ctx *context, const unsigned char *data, unsigned int len)
++{
++    unsigned int i;
++    unsigned int j;
++
++    j = (unsigned)(uint32_t)((context->count >> 3) & 63);
++    context->count += (len << 3);
++    if ((j + len) > 63) {
++        memmove(&context->buffer[j], data, (i = 64 - j));
++        ldns_sha1_transform(context->state, context->buffer);
++        for ( ; i + 63 < len; i += 64) {
++            ldns_sha1_transform(context->state, &data[i]);
++        }
++        j = 0;
++    }
++    else i = 0;
++    memmove(&context->buffer[j], &data[i], len - i);
++}
++
++
++/* Add padding and return the message digest. */
++
++void
++ldns_sha1_final(unsigned char digest[LDNS_SHA1_DIGEST_LENGTH], ldns_sha1_ctx *context)
++{
++    unsigned int i;
++    unsigned char finalcount[8];
++
++    for (i = 0; i < 8; i++) {
++        finalcount[i] = (unsigned char)((context->count >>
++            ((7 - (i & 7)) * 8)) & 255);  /* Endian independent */
++    }
++    ldns_sha1_update(context, (unsigned char *)"\200", 1);
++    while ((context->count & 504) != 448) {
++        ldns_sha1_update(context, (unsigned char *)"\0", 1);
++    }
++    ldns_sha1_update(context, finalcount, 8);  /* Should cause a SHA1Transform() */
++
++    if (digest != NULL)
++        for (i = 0; i < LDNS_SHA1_DIGEST_LENGTH; i++) {
++            digest[i] = (unsigned char)((context->state[i >> 2] >>
++                ((3 - (i & 3)) * 8)) & 255);
++      }
++#ifdef SHA1HANDSOFF  /* make SHA1Transform overwrite its own static vars */
++    ldns_sha1_transform(context->state, context->buffer);
++#endif
++}
++
++unsigned char *
++ldns_sha1(unsigned char *data, unsigned int data_len, unsigned char *digest)
++{
++    ldns_sha1_ctx ctx;
++    ldns_sha1_init(&ctx);
++    ldns_sha1_update(&ctx, data, data_len);
++    ldns_sha1_final(digest, &ctx);
++    return digest;
++}
+diff --git a/ldns/src/sha2.c b/ldns/src/sha2.c
+new file mode 100644
+index 0000000..9a27122
+--- /dev/null
++++ b/ldns/src/sha2.c
+@@ -0,0 +1,991 @@
++/*
++ * FILE:	sha2.c
++ * AUTHOR:	Aaron D. Gifford - http://www.aarongifford.com/
++ * 
++ * Copyright (c) 2000-2001, Aaron D. Gifford
++ * All rights reserved.
++ *
++ * Modified by Jelte Jansen to fit in ldns, and not clash with any
++ * system-defined SHA code.
++ * Changes:
++ * - Renamed (external) functions and constants to fit ldns style
++ * - Removed _End and _Data functions
++ * - Added ldns_shaX(data, len, digest) convenience functions
++ * - Removed prototypes of _Transform functions and made those static
++ * 
++ * 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.
++ * 3. Neither the name of the copyright holder nor the names of contributors
++ *    may be used to endorse or promote products derived from this software
++ *    without specific prior written permission.
++ * 
++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``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 OR CONTRIBUTOR(S) 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.
++ *
++ * $Id: sha2.c,v 1.1 2001/11/08 00:01:51 adg Exp adg $
++ */
++
++#include <ldns/config.h>
++#include <string.h>	/* memcpy()/memset() or bcopy()/bzero() */
++#include <assert.h>	/* assert() */
++#include <ldns/sha2.h>
++
++/*
++ * ASSERT NOTE:
++ * Some sanity checking code is included using assert().  On my FreeBSD
++ * system, this additional code can be removed by compiling with NDEBUG
++ * defined.  Check your own systems manpage on assert() to see how to
++ * compile WITHOUT the sanity checking code on your system.
++ *
++ * UNROLLED TRANSFORM LOOP NOTE:
++ * You can define SHA2_UNROLL_TRANSFORM to use the unrolled transform
++ * loop version for the hash transform rounds (defined using macros
++ * later in this file).  Either define on the command line, for example:
++ *
++ *   cc -DSHA2_UNROLL_TRANSFORM -o sha2 sha2.c sha2prog.c
++ *
++ * or define below:
++ *
++ *   #define SHA2_UNROLL_TRANSFORM
++ *
++ */
++
++
++/*** SHA-256/384/512 Machine Architecture Definitions *****************/
++/*
++ * BYTE_ORDER NOTE:
++ *
++ * Please make sure that your system defines BYTE_ORDER.  If your
++ * architecture is little-endian, make sure it also defines
++ * LITTLE_ENDIAN and that the two (BYTE_ORDER and LITTLE_ENDIAN) are
++ * equivilent.
++ *
++ * If your system does not define the above, then you can do so by
++ * hand like this:
++ *
++ *   #define LITTLE_ENDIAN 1234
++ *   #define BIG_ENDIAN    4321
++ *
++ * And for little-endian machines, add:
++ *
++ *   #define BYTE_ORDER LITTLE_ENDIAN 
++ *
++ * Or for big-endian machines:
++ *
++ *   #define BYTE_ORDER BIG_ENDIAN
++ *
++ * The FreeBSD machine this was written on defines BYTE_ORDER
++ * appropriately by including <sys/types.h> (which in turn includes
++ * <machine/endian.h> where the appropriate definitions are actually
++ * made).
++ */
++#if !defined(BYTE_ORDER) || (BYTE_ORDER != LITTLE_ENDIAN && BYTE_ORDER != BIG_ENDIAN)
++#error Define BYTE_ORDER to be equal to either LITTLE_ENDIAN or BIG_ENDIAN
++#endif
++
++typedef uint8_t  sha2_byte;	/* Exactly 1 byte */
++typedef uint32_t sha2_word32;	/* Exactly 4 bytes */
++#ifdef S_SPLINT_S
++typedef unsigned long long sha2_word64; /* lint 8 bytes */
++#else
++typedef uint64_t sha2_word64;	/* Exactly 8 bytes */
++#endif
++
++/*** SHA-256/384/512 Various Length Definitions ***********************/
++/* NOTE: Most of these are in sha2.h */
++#define ldns_sha256_SHORT_BLOCK_LENGTH	(LDNS_SHA256_BLOCK_LENGTH - 8)
++#define ldns_sha384_SHORT_BLOCK_LENGTH	(LDNS_SHA384_BLOCK_LENGTH - 16)
++#define ldns_sha512_SHORT_BLOCK_LENGTH	(LDNS_SHA512_BLOCK_LENGTH - 16)
++
++
++/*** ENDIAN REVERSAL MACROS *******************************************/
++#if BYTE_ORDER == LITTLE_ENDIAN
++#define REVERSE32(w,x)	{ \
++	sha2_word32 tmp = (w); \
++	tmp = (tmp >> 16) | (tmp << 16); \
++	(x) = ((tmp & 0xff00ff00UL) >> 8) | ((tmp & 0x00ff00ffUL) << 8); \
++}
++#ifndef S_SPLINT_S
++#define REVERSE64(w,x)	{ \
++	sha2_word64 tmp = (w); \
++	tmp = (tmp >> 32) | (tmp << 32); \
++	tmp = ((tmp & 0xff00ff00ff00ff00ULL) >> 8) | \
++	      ((tmp & 0x00ff00ff00ff00ffULL) << 8); \
++	(x) = ((tmp & 0xffff0000ffff0000ULL) >> 16) | \
++	      ((tmp & 0x0000ffff0000ffffULL) << 16); \
++}
++#else /* splint */
++#define REVERSE64(w,x) /* splint */
++#endif /* splint */
++#endif /* BYTE_ORDER == LITTLE_ENDIAN */
++
++/*
++ * Macro for incrementally adding the unsigned 64-bit integer n to the
++ * unsigned 128-bit integer (represented using a two-element array of
++ * 64-bit words):
++ */
++#define ADDINC128(w,n)	{ \
++	(w)[0] += (sha2_word64)(n); \
++	if ((w)[0] < (n)) { \
++		(w)[1]++; \
++	} \
++}
++#ifdef S_SPLINT_S
++#undef ADDINC128
++#define ADDINC128(w,n) /* splint */
++#endif
++
++/*
++ * Macros for copying blocks of memory and for zeroing out ranges
++ * of memory.  Using these macros makes it easy to switch from
++ * using memset()/memcpy() and using bzero()/bcopy().
++ *
++ * Please define either SHA2_USE_MEMSET_MEMCPY or define
++ * SHA2_USE_BZERO_BCOPY depending on which function set you
++ * choose to use:
++ */
++#if !defined(SHA2_USE_MEMSET_MEMCPY) && !defined(SHA2_USE_BZERO_BCOPY)
++/* Default to memset()/memcpy() if no option is specified */
++#define	SHA2_USE_MEMSET_MEMCPY	1
++#endif
++#if defined(SHA2_USE_MEMSET_MEMCPY) && defined(SHA2_USE_BZERO_BCOPY)
++/* Abort with an error if BOTH options are defined */
++#error Define either SHA2_USE_MEMSET_MEMCPY or SHA2_USE_BZERO_BCOPY, not both!
++#endif
++
++#ifdef SHA2_USE_MEMSET_MEMCPY
++#define MEMSET_BZERO(p,l)	memset((p), 0, (l))
++#define MEMCPY_BCOPY(d,s,l)	memcpy((d), (s), (l))
++#endif
++#ifdef SHA2_USE_BZERO_BCOPY
++#define MEMSET_BZERO(p,l)	bzero((p), (l))
++#define MEMCPY_BCOPY(d,s,l)	bcopy((s), (d), (l))
++#endif
++
++
++/*** THE SIX LOGICAL FUNCTIONS ****************************************/
++/*
++ * Bit shifting and rotation (used by the six SHA-XYZ logical functions:
++ *
++ *   NOTE:  The naming of R and S appears backwards here (R is a SHIFT and
++ *   S is a ROTATION) because the SHA-256/384/512 description document
++ *   (see http://csrc.nist.gov/cryptval/shs/sha256-384-512.pdf) uses this
++ *   same "backwards" definition.
++ */
++/* Shift-right (used in SHA-256, SHA-384, and SHA-512): */
++#define R(b,x) 		((x) >> (b))
++/* 32-bit Rotate-right (used in SHA-256): */
++#define S32(b,x)	(((x) >> (b)) | ((x) << (32 - (b))))
++/* 64-bit Rotate-right (used in SHA-384 and SHA-512): */
++#define S64(b,x)	(((x) >> (b)) | ((x) << (64 - (b))))
++
++/* Two of six logical functions used in SHA-256, SHA-384, and SHA-512: */
++#define Ch(x,y,z)	(((x) & (y)) ^ ((~(x)) & (z)))
++#define Maj(x,y,z)	(((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
++
++/* Four of six logical functions used in SHA-256: */
++#define Sigma0_256(x)	(S32(2,  (x)) ^ S32(13, (x)) ^ S32(22, (x)))
++#define Sigma1_256(x)	(S32(6,  (x)) ^ S32(11, (x)) ^ S32(25, (x)))
++#define sigma0_256(x)	(S32(7,  (x)) ^ S32(18, (x)) ^ R(3 ,   (x)))
++#define sigma1_256(x)	(S32(17, (x)) ^ S32(19, (x)) ^ R(10,   (x)))
++
++/* Four of six logical functions used in SHA-384 and SHA-512: */
++#define Sigma0_512(x)	(S64(28, (x)) ^ S64(34, (x)) ^ S64(39, (x)))
++#define Sigma1_512(x)	(S64(14, (x)) ^ S64(18, (x)) ^ S64(41, (x)))
++#define sigma0_512(x)	(S64( 1, (x)) ^ S64( 8, (x)) ^ R( 7,   (x)))
++#define sigma1_512(x)	(S64(19, (x)) ^ S64(61, (x)) ^ R( 6,   (x)))
++
++/*** SHA-XYZ INITIAL HASH VALUES AND CONSTANTS ************************/
++/* Hash constant words K for SHA-256: */
++static const sha2_word32 K256[64] = {
++	0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL,
++	0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL,
++	0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL,
++	0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL,
++	0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
++	0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL,
++	0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL,
++	0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL,
++	0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL,
++	0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
++	0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL,
++	0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL,
++	0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL,
++	0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL,
++	0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
++	0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL
++};
++
++/* initial hash value H for SHA-256: */
++static const sha2_word32 ldns_sha256_initial_hash_value[8] = {
++	0x6a09e667UL,
++	0xbb67ae85UL,
++	0x3c6ef372UL,
++	0xa54ff53aUL,
++	0x510e527fUL,
++	0x9b05688cUL,
++	0x1f83d9abUL,
++	0x5be0cd19UL
++};
++
++/* Hash constant words K for SHA-384 and SHA-512: */
++static const sha2_word64 K512[80] = {
++	0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL,
++	0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,
++	0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
++	0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,
++	0xd807aa98a3030242ULL, 0x12835b0145706fbeULL,
++	0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
++	0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL,
++	0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,
++	0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
++	0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
++	0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL,
++	0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
++	0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL,
++	0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,
++	0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
++	0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,
++	0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL,
++	0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
++	0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL,
++	0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
++	0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
++	0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,
++	0xd192e819d6ef5218ULL, 0xd69906245565a910ULL,
++	0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
++	0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL,
++	0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,
++	0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
++	0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,
++	0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL,
++	0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
++	0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL,
++	0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,
++	0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
++	0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,
++	0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL,
++	0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
++	0x28db77f523047d84ULL, 0x32caab7b40c72493ULL,
++	0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,
++	0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
++	0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL
++};
++
++/* initial hash value H for SHA-384 */
++static const sha2_word64 sha384_initial_hash_value[8] = {
++	0xcbbb9d5dc1059ed8ULL,
++	0x629a292a367cd507ULL,
++	0x9159015a3070dd17ULL,
++	0x152fecd8f70e5939ULL,
++	0x67332667ffc00b31ULL,
++	0x8eb44a8768581511ULL,
++	0xdb0c2e0d64f98fa7ULL,
++	0x47b5481dbefa4fa4ULL
++};
++
++/* initial hash value H for SHA-512 */
++static const sha2_word64 sha512_initial_hash_value[8] = {
++	0x6a09e667f3bcc908ULL,
++	0xbb67ae8584caa73bULL,
++	0x3c6ef372fe94f82bULL,
++	0xa54ff53a5f1d36f1ULL,
++	0x510e527fade682d1ULL,
++	0x9b05688c2b3e6c1fULL,
++	0x1f83d9abfb41bd6bULL,
++	0x5be0cd19137e2179ULL
++};
++
++/*** SHA-256: *********************************************************/
++void ldns_sha256_init(ldns_sha256_CTX* context) {
++	if (context == (ldns_sha256_CTX*)0) {
++		return;
++	}
++	MEMCPY_BCOPY(context->state, ldns_sha256_initial_hash_value, LDNS_SHA256_DIGEST_LENGTH);
++	MEMSET_BZERO(context->buffer, LDNS_SHA256_BLOCK_LENGTH);
++	context->bitcount = 0;
++}
++
++#ifdef SHA2_UNROLL_TRANSFORM
++
++/* Unrolled SHA-256 round macros: */
++
++#if BYTE_ORDER == LITTLE_ENDIAN
++
++#define ROUND256_0_TO_15(a,b,c,d,e,f,g,h)	\
++	REVERSE32(*data++, W256[j]); \
++	T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + \
++             K256[j] + W256[j]; \
++	(d) += T1; \
++	(h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \
++	j++
++
++
++#else /* BYTE_ORDER == LITTLE_ENDIAN */
++
++#define ROUND256_0_TO_15(a,b,c,d,e,f,g,h)	\
++	T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + \
++	     K256[j] + (W256[j] = *data++); \
++	(d) += T1; \
++	(h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \
++	j++
++
++#endif /* BYTE_ORDER == LITTLE_ENDIAN */
++
++#define ROUND256(a,b,c,d,e,f,g,h)	\
++	s0 = W256[(j+1)&0x0f]; \
++	s0 = sigma0_256(s0); \
++	s1 = W256[(j+14)&0x0f]; \
++	s1 = sigma1_256(s1); \
++	T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + K256[j] + \
++	     (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0); \
++	(d) += T1; \
++	(h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \
++	j++
++
++static void ldns_sha256_Transform(ldns_sha256_CTX* context,
++                                  const sha2_word32* data) {
++	sha2_word32	a, b, c, d, e, f, g, h, s0, s1;
++	sha2_word32	T1, *W256;
++	int		j;
++
++	W256 = (sha2_word32*)context->buffer;
++
++	/* initialize registers with the prev. intermediate value */
++	a = context->state[0];
++	b = context->state[1];
++	c = context->state[2];
++	d = context->state[3];
++	e = context->state[4];
++	f = context->state[5];
++	g = context->state[6];
++	h = context->state[7];
++
++	j = 0;
++	do {
++		/* Rounds 0 to 15 (unrolled): */
++		ROUND256_0_TO_15(a,b,c,d,e,f,g,h);
++		ROUND256_0_TO_15(h,a,b,c,d,e,f,g);
++		ROUND256_0_TO_15(g,h,a,b,c,d,e,f);
++		ROUND256_0_TO_15(f,g,h,a,b,c,d,e);
++		ROUND256_0_TO_15(e,f,g,h,a,b,c,d);
++		ROUND256_0_TO_15(d,e,f,g,h,a,b,c);
++		ROUND256_0_TO_15(c,d,e,f,g,h,a,b);
++		ROUND256_0_TO_15(b,c,d,e,f,g,h,a);
++	} while (j < 16);
++
++	/* Now for the remaining rounds to 64: */
++	do {
++		ROUND256(a,b,c,d,e,f,g,h);
++		ROUND256(h,a,b,c,d,e,f,g);
++		ROUND256(g,h,a,b,c,d,e,f);
++		ROUND256(f,g,h,a,b,c,d,e);
++		ROUND256(e,f,g,h,a,b,c,d);
++		ROUND256(d,e,f,g,h,a,b,c);
++		ROUND256(c,d,e,f,g,h,a,b);
++		ROUND256(b,c,d,e,f,g,h,a);
++	} while (j < 64);
++
++	/* Compute the current intermediate hash value */
++	context->state[0] += a;
++	context->state[1] += b;
++	context->state[2] += c;
++	context->state[3] += d;
++	context->state[4] += e;
++	context->state[5] += f;
++	context->state[6] += g;
++	context->state[7] += h;
++
++	/* Clean up */
++	a = b = c = d = e = f = g = h = T1 = 0;
++}
++
++#else /* SHA2_UNROLL_TRANSFORM */
++
++static void ldns_sha256_Transform(ldns_sha256_CTX* context,
++                                  const sha2_word32* data) {
++	sha2_word32	a, b, c, d, e, f, g, h, s0, s1;
++	sha2_word32	T1, T2, *W256;
++	int		j;
++
++	W256 = (sha2_word32*)context->buffer;
++
++	/* initialize registers with the prev. intermediate value */
++	a = context->state[0];
++	b = context->state[1];
++	c = context->state[2];
++	d = context->state[3];
++	e = context->state[4];
++	f = context->state[5];
++	g = context->state[6];
++	h = context->state[7];
++
++	j = 0;
++	do {
++#if BYTE_ORDER == LITTLE_ENDIAN
++		/* Copy data while converting to host byte order */
++		REVERSE32(*data++,W256[j]);
++		/* Apply the SHA-256 compression function to update a..h */
++		T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + W256[j];
++#else /* BYTE_ORDER == LITTLE_ENDIAN */
++		/* Apply the SHA-256 compression function to update a..h with copy */
++		T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + (W256[j] = *data++);
++#endif /* BYTE_ORDER == LITTLE_ENDIAN */
++		T2 = Sigma0_256(a) + Maj(a, b, c);
++		h = g;
++		g = f;
++		f = e;
++		e = d + T1;
++		d = c;
++		c = b;
++		b = a;
++		a = T1 + T2;
++
++		j++;
++	} while (j < 16);
++
++	do {
++		/* Part of the message block expansion: */
++		s0 = W256[(j+1)&0x0f];
++		s0 = sigma0_256(s0);
++		s1 = W256[(j+14)&0x0f];	
++		s1 = sigma1_256(s1);
++
++		/* Apply the SHA-256 compression function to update a..h */
++		T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + 
++		     (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0);
++		T2 = Sigma0_256(a) + Maj(a, b, c);
++		h = g;
++		g = f;
++		f = e;
++		e = d + T1;
++		d = c;
++		c = b;
++		b = a;
++		a = T1 + T2;
++
++		j++;
++	} while (j < 64);
++
++	/* Compute the current intermediate hash value */
++	context->state[0] += a;
++	context->state[1] += b;
++	context->state[2] += c;
++	context->state[3] += d;
++	context->state[4] += e;
++	context->state[5] += f;
++	context->state[6] += g;
++	context->state[7] += h;
++
++	/* Clean up */
++	a = b = c = d = e = f = g = h = T1 = T2 = 0;
++}
++
++#endif /* SHA2_UNROLL_TRANSFORM */
++
++void ldns_sha256_update(ldns_sha256_CTX* context, const sha2_byte *data, size_t len) {
++	size_t freespace, usedspace;
++
++	if (len == 0) {
++		/* Calling with no data is valid - we do nothing */
++		return;
++	}
++
++	/* Sanity check: */
++	assert(context != (ldns_sha256_CTX*)0 && data != (sha2_byte*)0);
++
++	usedspace = (context->bitcount >> 3) % LDNS_SHA256_BLOCK_LENGTH;
++	if (usedspace > 0) {
++		/* Calculate how much free space is available in the buffer */
++		freespace = LDNS_SHA256_BLOCK_LENGTH - usedspace;
++
++		if (len >= freespace) {
++			/* Fill the buffer completely and process it */
++			MEMCPY_BCOPY(&context->buffer[usedspace], data, freespace);
++			context->bitcount += freespace << 3;
++			len -= freespace;
++			data += freespace;
++			ldns_sha256_Transform(context, (sha2_word32*)context->buffer);
++		} else {
++			/* The buffer is not yet full */
++			MEMCPY_BCOPY(&context->buffer[usedspace], data, len);
++			context->bitcount += len << 3;
++			/* Clean up: */
++			usedspace = freespace = 0;
++			return;
++		}
++	}
++	while (len >= LDNS_SHA256_BLOCK_LENGTH) {
++		/* Process as many complete blocks as we can */
++		ldns_sha256_Transform(context, (sha2_word32*)data);
++		context->bitcount += LDNS_SHA256_BLOCK_LENGTH << 3;
++		len -= LDNS_SHA256_BLOCK_LENGTH;
++		data += LDNS_SHA256_BLOCK_LENGTH;
++	}
++	if (len > 0) {
++		/* There's left-overs, so save 'em */
++		MEMCPY_BCOPY(context->buffer, data, len);
++		context->bitcount += len << 3;
++	}
++	/* Clean up: */
++	usedspace = freespace = 0;
++}
++
++typedef union _ldns_sha2_buffer_union {
++        uint8_t*  theChars;
++        uint64_t* theLongs;
++} ldns_sha2_buffer_union;
++
++void ldns_sha256_final(sha2_byte digest[], ldns_sha256_CTX* context) {
++	sha2_word32	*d = (sha2_word32*)digest;
++	size_t usedspace;
++	ldns_sha2_buffer_union cast_var;
++
++	/* Sanity check: */
++	assert(context != (ldns_sha256_CTX*)0);
++
++	/* If no digest buffer is passed, we don't bother doing this: */
++	if (digest != (sha2_byte*)0) {
++		usedspace = (context->bitcount >> 3) % LDNS_SHA256_BLOCK_LENGTH;
++#if BYTE_ORDER == LITTLE_ENDIAN
++		/* Convert FROM host byte order */
++		REVERSE64(context->bitcount,context->bitcount);
++#endif
++		if (usedspace > 0) {
++			/* Begin padding with a 1 bit: */
++			context->buffer[usedspace++] = 0x80;
++
++			if (usedspace <= ldns_sha256_SHORT_BLOCK_LENGTH) {
++				/* Set-up for the last transform: */
++				MEMSET_BZERO(&context->buffer[usedspace], ldns_sha256_SHORT_BLOCK_LENGTH - usedspace);
++			} else {
++				if (usedspace < LDNS_SHA256_BLOCK_LENGTH) {
++					MEMSET_BZERO(&context->buffer[usedspace], LDNS_SHA256_BLOCK_LENGTH - usedspace);
++				}
++				/* Do second-to-last transform: */
++				ldns_sha256_Transform(context, (sha2_word32*)context->buffer);
++
++				/* And set-up for the last transform: */
++				MEMSET_BZERO(context->buffer, ldns_sha256_SHORT_BLOCK_LENGTH);
++			}
++		} else {
++			/* Set-up for the last transform: */
++			MEMSET_BZERO(context->buffer, ldns_sha256_SHORT_BLOCK_LENGTH);
++
++			/* Begin padding with a 1 bit: */
++			*context->buffer = 0x80;
++		}
++		/* Set the bit count: */
++		cast_var.theChars = context->buffer;
++		cast_var.theLongs[ldns_sha256_SHORT_BLOCK_LENGTH / 8] = context->bitcount;
++
++		/* final transform: */
++		ldns_sha256_Transform(context, (sha2_word32*)context->buffer);
++
++#if BYTE_ORDER == LITTLE_ENDIAN
++		{
++			/* Convert TO host byte order */
++			int	j;
++			for (j = 0; j < 8; j++) {
++				REVERSE32(context->state[j],context->state[j]);
++				*d++ = context->state[j];
++			}
++		}
++#else
++		MEMCPY_BCOPY(d, context->state, LDNS_SHA256_DIGEST_LENGTH);
++#endif
++	}
++
++	/* Clean up state data: */
++	MEMSET_BZERO(context, sizeof(ldns_sha256_CTX));
++	usedspace = 0;
++}
++
++unsigned char *
++ldns_sha256(unsigned char *data, unsigned int data_len, unsigned char *digest)
++{
++    ldns_sha256_CTX ctx;
++    ldns_sha256_init(&ctx);
++    ldns_sha256_update(&ctx, data, data_len);
++    ldns_sha256_final(digest, &ctx);
++    return digest;
++}
++
++/*** SHA-512: *********************************************************/
++void ldns_sha512_init(ldns_sha512_CTX* context) {
++	if (context == (ldns_sha512_CTX*)0) {
++		return;
++	}
++	MEMCPY_BCOPY(context->state, sha512_initial_hash_value, LDNS_SHA512_DIGEST_LENGTH);
++	MEMSET_BZERO(context->buffer, LDNS_SHA512_BLOCK_LENGTH);
++	context->bitcount[0] = context->bitcount[1] =  0;
++}
++
++#ifdef SHA2_UNROLL_TRANSFORM
++
++/* Unrolled SHA-512 round macros: */
++#if BYTE_ORDER == LITTLE_ENDIAN
++
++#define ROUND512_0_TO_15(a,b,c,d,e,f,g,h)	\
++	REVERSE64(*data++, W512[j]); \
++	T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + \
++             K512[j] + W512[j]; \
++	(d) += T1, \
++	(h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)), \
++	j++
++
++
++#else /* BYTE_ORDER == LITTLE_ENDIAN */
++
++#define ROUND512_0_TO_15(a,b,c,d,e,f,g,h)	\
++	T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + \
++             K512[j] + (W512[j] = *data++); \
++	(d) += T1; \
++	(h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)); \
++	j++
++
++#endif /* BYTE_ORDER == LITTLE_ENDIAN */
++
++#define ROUND512(a,b,c,d,e,f,g,h)	\
++	s0 = W512[(j+1)&0x0f]; \
++	s0 = sigma0_512(s0); \
++	s1 = W512[(j+14)&0x0f]; \
++	s1 = sigma1_512(s1); \
++	T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + K512[j] + \
++             (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0); \
++	(d) += T1; \
++	(h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)); \
++	j++
++
++static void ldns_sha512_Transform(ldns_sha512_CTX* context,
++                                  const sha2_word64* data) {
++	sha2_word64	a, b, c, d, e, f, g, h, s0, s1;
++	sha2_word64	T1, *W512 = (sha2_word64*)context->buffer;
++	int		j;
++
++	/* initialize registers with the prev. intermediate value */
++	a = context->state[0];
++	b = context->state[1];
++	c = context->state[2];
++	d = context->state[3];
++	e = context->state[4];
++	f = context->state[5];
++	g = context->state[6];
++	h = context->state[7];
++
++	j = 0;
++	do {
++		ROUND512_0_TO_15(a,b,c,d,e,f,g,h);
++		ROUND512_0_TO_15(h,a,b,c,d,e,f,g);
++		ROUND512_0_TO_15(g,h,a,b,c,d,e,f);
++		ROUND512_0_TO_15(f,g,h,a,b,c,d,e);
++		ROUND512_0_TO_15(e,f,g,h,a,b,c,d);
++		ROUND512_0_TO_15(d,e,f,g,h,a,b,c);
++		ROUND512_0_TO_15(c,d,e,f,g,h,a,b);
++		ROUND512_0_TO_15(b,c,d,e,f,g,h,a);
++	} while (j < 16);
++
++	/* Now for the remaining rounds up to 79: */
++	do {
++		ROUND512(a,b,c,d,e,f,g,h);
++		ROUND512(h,a,b,c,d,e,f,g);
++		ROUND512(g,h,a,b,c,d,e,f);
++		ROUND512(f,g,h,a,b,c,d,e);
++		ROUND512(e,f,g,h,a,b,c,d);
++		ROUND512(d,e,f,g,h,a,b,c);
++		ROUND512(c,d,e,f,g,h,a,b);
++		ROUND512(b,c,d,e,f,g,h,a);
++	} while (j < 80);
++
++	/* Compute the current intermediate hash value */
++	context->state[0] += a;
++	context->state[1] += b;
++	context->state[2] += c;
++	context->state[3] += d;
++	context->state[4] += e;
++	context->state[5] += f;
++	context->state[6] += g;
++	context->state[7] += h;
++
++	/* Clean up */
++	a = b = c = d = e = f = g = h = T1 = 0;
++}
++
++#else /* SHA2_UNROLL_TRANSFORM */
++
++static void ldns_sha512_Transform(ldns_sha512_CTX* context,
++                                  const sha2_word64* data) {
++	sha2_word64	a, b, c, d, e, f, g, h, s0, s1;
++	sha2_word64	T1, T2, *W512 = (sha2_word64*)context->buffer;
++	int		j;
++
++	/* initialize registers with the prev. intermediate value */
++	a = context->state[0];
++	b = context->state[1];
++	c = context->state[2];
++	d = context->state[3];
++	e = context->state[4];
++	f = context->state[5];
++	g = context->state[6];
++	h = context->state[7];
++
++	j = 0;
++	do {
++#if BYTE_ORDER == LITTLE_ENDIAN
++		/* Convert TO host byte order */
++		REVERSE64(*data++, W512[j]);
++		/* Apply the SHA-512 compression function to update a..h */
++		T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + W512[j];
++#else /* BYTE_ORDER == LITTLE_ENDIAN */
++		/* Apply the SHA-512 compression function to update a..h with copy */
++		T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + (W512[j] = *data++);
++#endif /* BYTE_ORDER == LITTLE_ENDIAN */
++		T2 = Sigma0_512(a) + Maj(a, b, c);
++		h = g;
++		g = f;
++		f = e;
++		e = d + T1;
++		d = c;
++		c = b;
++		b = a;
++		a = T1 + T2;
++
++		j++;
++	} while (j < 16);
++
++	do {
++		/* Part of the message block expansion: */
++		s0 = W512[(j+1)&0x0f];
++		s0 = sigma0_512(s0);
++		s1 = W512[(j+14)&0x0f];
++		s1 =  sigma1_512(s1);
++
++		/* Apply the SHA-512 compression function to update a..h */
++		T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] +
++		     (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0);
++		T2 = Sigma0_512(a) + Maj(a, b, c);
++		h = g;
++		g = f;
++		f = e;
++		e = d + T1;
++		d = c;
++		c = b;
++		b = a;
++		a = T1 + T2;
++
++		j++;
++	} while (j < 80);
++
++	/* Compute the current intermediate hash value */
++	context->state[0] += a;
++	context->state[1] += b;
++	context->state[2] += c;
++	context->state[3] += d;
++	context->state[4] += e;
++	context->state[5] += f;
++	context->state[6] += g;
++	context->state[7] += h;
++
++	/* Clean up */
++	a = b = c = d = e = f = g = h = T1 = T2 = 0;
++}
++
++#endif /* SHA2_UNROLL_TRANSFORM */
++
++void ldns_sha512_update(ldns_sha512_CTX* context, const sha2_byte *data, size_t len) {
++	size_t freespace, usedspace;
++
++	if (len == 0) {
++		/* Calling with no data is valid - we do nothing */
++		return;
++	}
++
++	/* Sanity check: */
++	assert(context != (ldns_sha512_CTX*)0 && data != (sha2_byte*)0);
++
++	usedspace = (context->bitcount[0] >> 3) % LDNS_SHA512_BLOCK_LENGTH;
++	if (usedspace > 0) {
++		/* Calculate how much free space is available in the buffer */
++		freespace = LDNS_SHA512_BLOCK_LENGTH - usedspace;
++
++		if (len >= freespace) {
++			/* Fill the buffer completely and process it */
++			MEMCPY_BCOPY(&context->buffer[usedspace], data, freespace);
++			ADDINC128(context->bitcount, freespace << 3);
++			len -= freespace;
++			data += freespace;
++			ldns_sha512_Transform(context, (sha2_word64*)context->buffer);
++		} else {
++			/* The buffer is not yet full */
++			MEMCPY_BCOPY(&context->buffer[usedspace], data, len);
++			ADDINC128(context->bitcount, len << 3);
++			/* Clean up: */
++			usedspace = freespace = 0;
++			return;
++		}
++	}
++	while (len >= LDNS_SHA512_BLOCK_LENGTH) {
++		/* Process as many complete blocks as we can */
++		ldns_sha512_Transform(context, (sha2_word64*)data);
++		ADDINC128(context->bitcount, LDNS_SHA512_BLOCK_LENGTH << 3);
++		len -= LDNS_SHA512_BLOCK_LENGTH;
++		data += LDNS_SHA512_BLOCK_LENGTH;
++	}
++	if (len > 0) {
++		/* There's left-overs, so save 'em */
++		MEMCPY_BCOPY(context->buffer, data, len);
++		ADDINC128(context->bitcount, len << 3);
++	}
++	/* Clean up: */
++	usedspace = freespace = 0;
++}
++
++static void ldns_sha512_Last(ldns_sha512_CTX* context) {
++	size_t usedspace;
++	ldns_sha2_buffer_union cast_var;
++
++	usedspace = (context->bitcount[0] >> 3) % LDNS_SHA512_BLOCK_LENGTH;
++#if BYTE_ORDER == LITTLE_ENDIAN
++	/* Convert FROM host byte order */
++	REVERSE64(context->bitcount[0],context->bitcount[0]);
++	REVERSE64(context->bitcount[1],context->bitcount[1]);
++#endif
++	if (usedspace > 0) {
++		/* Begin padding with a 1 bit: */
++		context->buffer[usedspace++] = 0x80;
++
++		if (usedspace <= ldns_sha512_SHORT_BLOCK_LENGTH) {
++			/* Set-up for the last transform: */
++			MEMSET_BZERO(&context->buffer[usedspace], ldns_sha512_SHORT_BLOCK_LENGTH - usedspace);
++		} else {
++			if (usedspace < LDNS_SHA512_BLOCK_LENGTH) {
++				MEMSET_BZERO(&context->buffer[usedspace], LDNS_SHA512_BLOCK_LENGTH - usedspace);
++			}
++			/* Do second-to-last transform: */
++			ldns_sha512_Transform(context, (sha2_word64*)context->buffer);
++
++			/* And set-up for the last transform: */
++			MEMSET_BZERO(context->buffer, LDNS_SHA512_BLOCK_LENGTH - 2);
++		}
++	} else {
++		/* Prepare for final transform: */
++		MEMSET_BZERO(context->buffer, ldns_sha512_SHORT_BLOCK_LENGTH);
++
++		/* Begin padding with a 1 bit: */
++		*context->buffer = 0x80;
++	}
++	/* Store the length of input data (in bits): */
++	cast_var.theChars = context->buffer;
++	cast_var.theLongs[ldns_sha512_SHORT_BLOCK_LENGTH / 8] = context->bitcount[1];
++	cast_var.theLongs[ldns_sha512_SHORT_BLOCK_LENGTH / 8 + 1] = context->bitcount[0];
++
++	/* final transform: */
++	ldns_sha512_Transform(context, (sha2_word64*)context->buffer);
++}
++
++void ldns_sha512_final(sha2_byte digest[], ldns_sha512_CTX* context) {
++	sha2_word64	*d = (sha2_word64*)digest;
++
++	/* Sanity check: */
++	assert(context != (ldns_sha512_CTX*)0);
++
++	/* If no digest buffer is passed, we don't bother doing this: */
++	if (digest != (sha2_byte*)0) {
++		ldns_sha512_Last(context);
++
++		/* Save the hash data for output: */
++#if BYTE_ORDER == LITTLE_ENDIAN
++		{
++			/* Convert TO host byte order */
++			int	j;
++			for (j = 0; j < 8; j++) {
++				REVERSE64(context->state[j],context->state[j]);
++				*d++ = context->state[j];
++			}
++		}
++#else
++		MEMCPY_BCOPY(d, context->state, LDNS_SHA512_DIGEST_LENGTH);
++#endif
++	}
++
++	/* Zero out state data */
++	MEMSET_BZERO(context, sizeof(ldns_sha512_CTX));
++}
++
++unsigned char *
++ldns_sha512(unsigned char *data, unsigned int data_len, unsigned char *digest)
++{
++    ldns_sha512_CTX ctx;
++    ldns_sha512_init(&ctx);
++    ldns_sha512_update(&ctx, data, data_len);
++    ldns_sha512_final(digest, &ctx);
++    return digest;
++}
++
++/*** SHA-384: *********************************************************/
++void ldns_sha384_init(ldns_sha384_CTX* context) {
++	if (context == (ldns_sha384_CTX*)0) {
++		return;
++	}
++	MEMCPY_BCOPY(context->state, sha384_initial_hash_value, LDNS_SHA512_DIGEST_LENGTH);
++	MEMSET_BZERO(context->buffer, LDNS_SHA384_BLOCK_LENGTH);
++	context->bitcount[0] = context->bitcount[1] = 0;
++}
++
++void ldns_sha384_update(ldns_sha384_CTX* context, const sha2_byte* data, size_t len) {
++	ldns_sha512_update((ldns_sha512_CTX*)context, data, len);
++}
++
++void ldns_sha384_final(sha2_byte digest[], ldns_sha384_CTX* context) {
++	sha2_word64	*d = (sha2_word64*)digest;
++
++	/* Sanity check: */
++	assert(context != (ldns_sha384_CTX*)0);
++
++	/* If no digest buffer is passed, we don't bother doing this: */
++	if (digest != (sha2_byte*)0) {
++		ldns_sha512_Last((ldns_sha512_CTX*)context);
++
++		/* Save the hash data for output: */
++#if BYTE_ORDER == LITTLE_ENDIAN
++		{
++			/* Convert TO host byte order */
++			int	j;
++			for (j = 0; j < 6; j++) {
++				REVERSE64(context->state[j],context->state[j]);
++				*d++ = context->state[j];
++			}
++		}
++#else
++		MEMCPY_BCOPY(d, context->state, LDNS_SHA384_DIGEST_LENGTH);
++#endif
++	}
++
++	/* Zero out state data */
++	MEMSET_BZERO(context, sizeof(ldns_sha384_CTX));
++}
++
++unsigned char *
++ldns_sha384(unsigned char *data, unsigned int data_len, unsigned char *digest)
++{
++    ldns_sha384_CTX ctx;
++    ldns_sha384_init(&ctx);
++    ldns_sha384_update(&ctx, data, data_len);
++    ldns_sha384_final(digest, &ctx);
++    return digest;
++}
+diff --git a/ldns/src/str2host.c b/ldns/src/str2host.c
+new file mode 100644
+index 0000000..cd07c89
+--- /dev/null
++++ b/ldns/src/str2host.c
+@@ -0,0 +1,1604 @@
++/*
++ * str2host.c
++ *
++ * conversion routines from the presentation format
++ * to the host format
++ *
++ * a Net::DNS like library for C
++ *
++ * (c) NLnet Labs, 2004-2006
++ *
++ * See the file LICENSE for the license
++ */
++#include <ldns/config.h>
++
++#include <ldns/ldns.h>
++
++#ifdef HAVE_SYS_SOCKET_H
++#include <sys/socket.h>
++#endif
++#ifdef HAVE_ARPA_INET_H
++#include <arpa/inet.h>
++#endif
++#include <time.h>
++
++#include <errno.h>
++#ifdef HAVE_NETDB_H
++#include <netdb.h>
++#endif
++
++#include <limits.h>
++#ifdef HAVE_SYS_PARAM_H
++#include <sys/param.h>
++#endif
++
++ldns_status
++ldns_str2rdf_int16(ldns_rdf **rd, const char *shortstr)
++{
++	char *end = NULL;
++	uint16_t *r;
++	r = LDNS_MALLOC(uint16_t);
++        if(!r) return LDNS_STATUS_MEM_ERR;
++
++	*r = htons((uint16_t)strtol((char *)shortstr, &end, 10));
++
++	if(*end != 0) {
++		LDNS_FREE(r);
++		return LDNS_STATUS_INVALID_INT;
++	} else {
++		*rd = ldns_rdf_new_frm_data(
++			LDNS_RDF_TYPE_INT16, sizeof(uint16_t), r);
++		LDNS_FREE(r);
++		return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
++	}
++}
++
++ldns_status
++ldns_str2rdf_time(ldns_rdf **rd, const char *time)
++{
++	/* convert a time YYYYDDMMHHMMSS to wireformat */
++	uint16_t *r = NULL;
++	struct tm tm;
++	uint32_t l;
++	char *end;
++
++	/* Try to scan the time... */
++	r = (uint16_t*)LDNS_MALLOC(uint32_t);
++        if(!r) return LDNS_STATUS_MEM_ERR;
++
++	memset(&tm, 0, sizeof(tm));
++
++	if (strlen(time) == 14 &&
++	    sscanf(time, "%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 values */
++		if (tm.tm_year < 70) {
++			goto bad_format;
++		}
++		if (tm.tm_mon < 0 || tm.tm_mon > 11) {
++			goto bad_format;
++		}
++		if (tm.tm_mday < 1 || tm.tm_mday > 31) {
++			goto bad_format;
++		}
++
++		if (tm.tm_hour < 0 || tm.tm_hour > 23) {
++			goto bad_format;
++		}
++
++		if (tm.tm_min < 0 || tm.tm_min > 59) {
++			goto bad_format;
++		}
++
++		if (tm.tm_sec < 0 || tm.tm_sec > 59) {
++			goto bad_format;
++		}
++
++		l = htonl(ldns_mktime_from_utc(&tm));
++		memcpy(r, &l, sizeof(uint32_t));
++		*rd = ldns_rdf_new_frm_data(
++			LDNS_RDF_TYPE_TIME, sizeof(uint32_t), r);
++		LDNS_FREE(r);
++		return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
++	} else {
++		/* handle it as 32 bits timestamp */
++		l = htonl((uint32_t)strtol((char*)time, &end, 10));
++		if(*end != 0) {
++			LDNS_FREE(r);
++			return LDNS_STATUS_ERR;
++		} else {
++			memcpy(r, &l, sizeof(uint32_t));
++			*rd = ldns_rdf_new_frm_data(
++				LDNS_RDF_TYPE_INT32, sizeof(uint32_t), r);
++			LDNS_FREE(r);
++		        return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
++		}
++	}
++
++	bad_format:
++	LDNS_FREE(r);
++	return LDNS_STATUS_INVALID_TIME;
++}
++
++ldns_status
++ldns_str2rdf_nsec3_salt(ldns_rdf **rd, const char *salt_str)
++{
++	uint8_t salt_length;
++	int c;
++	int salt_length_str;
++
++	uint8_t *salt;
++	uint8_t *data;
++	if(rd == NULL) {
++		return LDNS_STATUS_NULL;
++	}
++
++	salt_length_str = (int)strlen(salt_str);
++	if (salt_length_str == 1 && salt_str[0] == '-') {
++		salt_length_str = 0;
++	} else if (salt_length_str % 2 != 0) {
++		return LDNS_STATUS_INVALID_HEX;
++	}
++	if (salt_length_str > 512) {
++		return LDNS_STATUS_INVALID_HEX;
++	}
++
++	salt = LDNS_XMALLOC(uint8_t, salt_length_str / 2);
++        if(!salt) {
++                return LDNS_STATUS_MEM_ERR;
++        }
++	for (c = 0; c < salt_length_str; c += 2) {
++		if (isxdigit((int) salt_str[c]) && isxdigit((int) salt_str[c+1])) {
++			salt[c/2] = (uint8_t) ldns_hexdigit_to_int(salt_str[c]) * 16 +
++					  ldns_hexdigit_to_int(salt_str[c+1]);
++		} else {
++			LDNS_FREE(salt);
++			return LDNS_STATUS_INVALID_HEX;
++		}
++	}
++	salt_length = (uint8_t) (salt_length_str / 2);
++
++	data = LDNS_XMALLOC(uint8_t, 1 + salt_length);
++        if(!data) {
++	        LDNS_FREE(salt);
++                return LDNS_STATUS_MEM_ERR;
++        }
++	data[0] = salt_length;
++	memcpy(&data[1], salt, salt_length);
++	*rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_NSEC3_SALT, 1 + salt_length, data);
++	LDNS_FREE(data);
++	LDNS_FREE(salt);
++
++	return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
++}
++
++ldns_status
++ldns_str2rdf_period(ldns_rdf **rd,const char *period)
++{
++        uint32_t p;
++        const char *end;
++
++        /* Allocate required space... */
++        p = ldns_str2period(period, &end);
++
++        if (*end != 0) {
++		return LDNS_STATUS_ERR;
++        } else {
++                p = (uint32_t) htonl(p);
++		*rd = ldns_rdf_new_frm_data(
++			LDNS_RDF_TYPE_PERIOD, sizeof(uint32_t), &p);
++        }
++	return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
++}
++
++ldns_status
++ldns_str2rdf_int32(ldns_rdf **rd, const char *longstr)
++{
++	char *end;
++	uint16_t *r = NULL;
++	uint32_t l;
++
++	r = (uint16_t*)LDNS_MALLOC(uint32_t);
++        if(!r) return LDNS_STATUS_MEM_ERR;
++	errno = 0; /* must set to zero before call,
++			note race condition on errno */
++	if(*longstr == '-')
++		l = htonl((uint32_t)strtol((char*)longstr, &end, 10));
++	else	l = htonl((uint32_t)strtoul((char*)longstr, &end, 10));
++
++	if(*end != 0) {
++		LDNS_FREE(r);
++		return LDNS_STATUS_ERR;
++     } else {
++		if (errno == ERANGE) {
++			LDNS_FREE(r);
++			return LDNS_STATUS_SYNTAX_INTEGER_OVERFLOW;
++		}
++		memcpy(r, &l, sizeof(uint32_t));
++		*rd = ldns_rdf_new_frm_data(
++			LDNS_RDF_TYPE_INT32, sizeof(uint32_t), r);
++		LDNS_FREE(r);
++	        return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
++	}
++}
++
++ldns_status
++ldns_str2rdf_int8(ldns_rdf **rd, const char *bytestr)
++{
++	char *end;
++	uint8_t *r = NULL;
++
++	r = LDNS_MALLOC(uint8_t);
++        if(!r) return LDNS_STATUS_MEM_ERR;
++
++	*r = (uint8_t)strtol((char*)bytestr, &end, 10);
++
++        if(*end != 0) {
++		LDNS_FREE(r);
++		return LDNS_STATUS_ERR;
++        } else {
++		*rd = ldns_rdf_new_frm_data(
++			LDNS_RDF_TYPE_INT8, sizeof(uint8_t), r);
++		LDNS_FREE(r);
++	        return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
++        }
++}
++
++
++/*
++ * Checks whether the escaped value at **s is an decimal value or
++ * a 'normally' escaped character (and not eos)
++ *
++ * The string pointer at *s is increased by either 0 (on error), 1 (on
++ * normal escapes), or 3 (on decimals)
++ *
++ * Returns the number of bytes read from the escaped string, or
++ * 0 on error
++ */
++INLINE bool
++parse_escape(uint8_t *ch_p, const char** str_p)
++{
++	uint16_t val;
++
++	if ((*str_p)[0] && isdigit((*str_p)[0])  &&
++	    (*str_p)[1] && isdigit((*str_p)[1])  &&
++	    (*str_p)[2] && isdigit((*str_p)[2]))  {
++
++		val = (uint16_t)(((*str_p)[0] - '0') * 100 +
++				 ((*str_p)[1] - '0') *  10 +
++				 ((*str_p)[2] - '0'));
++
++		if (val > 255) {
++			goto error;
++		}
++		*ch_p = (uint8_t)val;
++		*str_p += 3;
++		return true;
++
++	} else if ((*str_p)[0] && !isdigit((*str_p)[0])) {
++
++		*ch_p = (uint8_t)*(*str_p)++;
++		return true;
++	}
++error:
++	*str_p = NULL;
++	return false; /* LDNS_STATUS_SYNTAX_BAD_ESCAPE */
++}
++
++INLINE bool
++parse_char(uint8_t *ch_p, const char** str_p)
++{
++	switch (**str_p) {
++
++	case '\0':	return false;
++
++	case '\\':	*str_p += 1;
++			return parse_escape(ch_p, str_p);
++
++	default:	*ch_p = (uint8_t)*(*str_p)++;
++			return true;
++	}
++}
++
++/*
++ * No special care is taken, all dots are translated into
++ * label seperators.
++ * Could be made more efficient....we do 3 memcpy's in total...
++ */
++ldns_status
++ldns_str2rdf_dname(ldns_rdf **d, const char *str)
++{
++	size_t len;
++
++	const char *s;
++	uint8_t *q, *pq, label_len;
++	uint8_t buf[LDNS_MAX_DOMAINLEN + 1];
++	*d = NULL;
++
++	len = strlen((char*)str);
++	/* octet representation can make strings a lot longer than actual length */
++	if (len > LDNS_MAX_DOMAINLEN * 4) {
++		return LDNS_STATUS_DOMAINNAME_OVERFLOW;
++	}
++	if (0 == len) {
++		return LDNS_STATUS_DOMAINNAME_UNDERFLOW;
++	}
++
++	/* root label */
++	if (1 == len && *str == '.') {
++		*d = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_DNAME, 1, "\0");
++		return LDNS_STATUS_OK;
++	}
++
++	/* get on with the rest */
++
++	/* s is on the current character in the string
++         * pq points to where the labellength is going to go
++         * label_len keeps track of the current label's length
++	 * q builds the dname inside the buf array
++	 */
++	len = 0;
++	q = buf+1;
++	pq = buf;
++	label_len = 0;
++	for (s = str; *s; s++, q++) {
++		if (q > buf + LDNS_MAX_DOMAINLEN) {
++			return LDNS_STATUS_DOMAINNAME_OVERFLOW;
++		}
++		*q = 0;
++		switch (*s) {
++		case '.':
++			if (label_len > LDNS_MAX_LABELLEN) {
++				return LDNS_STATUS_LABEL_OVERFLOW;
++			}
++			if (label_len == 0) {
++				return LDNS_STATUS_EMPTY_LABEL;
++			}
++			len += label_len + 1;
++			*pq = label_len;
++			label_len = 0;
++			pq = q;
++			break;
++		case '\\':
++			/* octet value or literal char */
++			s += 1;
++			if (! parse_escape(q, &s)) {
++				return LDNS_STATUS_SYNTAX_BAD_ESCAPE;
++			}
++			s -= 1;
++			label_len++;
++			break;
++		default:
++			*q = (uint8_t)*s;
++			label_len++;
++		}
++	}
++
++	/* add root label if last char was not '.' */
++	if (!ldns_dname_str_absolute(str)) {
++		if (q > buf + LDNS_MAX_DOMAINLEN) {
++			return LDNS_STATUS_DOMAINNAME_OVERFLOW;
++		}
++                if (label_len > LDNS_MAX_LABELLEN) {
++                        return LDNS_STATUS_LABEL_OVERFLOW;
++                }
++                if (label_len == 0) { /* label_len 0 but not . at end? */
++                        return LDNS_STATUS_EMPTY_LABEL;
++                }
++		len += label_len + 1;
++		*pq = label_len;
++		*q = 0;
++	}
++	len++;
++
++	*d = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_DNAME, len, buf);
++	return LDNS_STATUS_OK;
++}
++
++ldns_status
++ldns_str2rdf_a(ldns_rdf **rd, const char *str)
++{
++	in_addr_t address;
++        if (inet_pton(AF_INET, (char*)str, &address) != 1) {
++                return LDNS_STATUS_INVALID_IP4;
++        } else {
++		*rd = ldns_rdf_new_frm_data(
++			LDNS_RDF_TYPE_A, sizeof(address), &address);
++        }
++	return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
++}
++
++ldns_status
++ldns_str2rdf_aaaa(ldns_rdf **rd, const char *str)
++{
++	uint8_t address[LDNS_IP6ADDRLEN + 1];
++
++	if (inet_pton(AF_INET6, (char*)str, address) != 1) {
++		return LDNS_STATUS_INVALID_IP6;
++	} else {
++		*rd = ldns_rdf_new_frm_data(
++			LDNS_RDF_TYPE_AAAA, sizeof(address) - 1, &address);
++	}
++	return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
++}
++
++ldns_status
++ldns_str2rdf_str(ldns_rdf **rd, const char *str)
++{
++	uint8_t *data, *dp, ch = 0;
++	size_t length;
++
++	/* Worst case space requirement. We'll realloc to actual size later. */
++	dp = data = LDNS_XMALLOC(uint8_t, strlen(str) > 255 ? 256 : (strlen(str) + 1));
++	if (! data) {
++		return LDNS_STATUS_MEM_ERR;
++	}
++
++	/* Fill data (up to 255 characters) */
++	while (parse_char(&ch, &str)) {
++		if (dp - data >= 255) {
++			LDNS_FREE(data);
++			return LDNS_STATUS_INVALID_STR;
++		}
++		*++dp = ch;
++	}
++	if (! str) {
++		return LDNS_STATUS_SYNTAX_BAD_ESCAPE;
++	}
++	length = (size_t)(dp - data);
++	/* Fix last length byte */
++	data[0] = (uint8_t)length;
++
++	/* Lose the overmeasure */
++	data = LDNS_XREALLOC(dp = data, uint8_t, length + 1);
++	if (! data) {
++		LDNS_FREE(dp);
++		return LDNS_STATUS_MEM_ERR;
++	}
++
++	/* Create rdf */
++	*rd = ldns_rdf_new(LDNS_RDF_TYPE_STR, length + 1, data);
++	if (! *rd) {
++		LDNS_FREE(data);
++		return LDNS_STATUS_MEM_ERR;
++	}
++	return LDNS_STATUS_OK;
++}
++
++ldns_status
++ldns_str2rdf_apl(ldns_rdf **rd, const char *str)
++{
++	const char *my_str = str;
++
++	char *my_ip_str;
++	size_t ip_str_len;
++
++	uint16_t family;
++	bool negation;
++	uint8_t afdlength = 0;
++	uint8_t *afdpart;
++	uint8_t prefix;
++
++	uint8_t *data;
++
++	size_t i = 0;
++
++	/* [!]afi:address/prefix */
++	if (strlen(my_str) < 2
++			|| strchr(my_str, ':') == NULL
++			|| strchr(my_str, '/') == NULL
++			|| strchr(my_str, ':') > strchr(my_str, '/')) {
++		return LDNS_STATUS_INVALID_STR;
++	}
++
++	if (my_str[0] == '!') {
++		negation = true;
++		my_str += 1;
++	} else {
++		negation = false;
++	}
++
++	family = (uint16_t) atoi(my_str);
++
++	my_str = strchr(my_str, ':') + 1;
++
++	/* need ip addr and only ip addr for inet_pton */
++	ip_str_len = (size_t) (strchr(my_str, '/') - my_str);
++	my_ip_str = LDNS_XMALLOC(char, ip_str_len + 1);
++        if(!my_ip_str) return LDNS_STATUS_MEM_ERR;
++	strncpy(my_ip_str, my_str, ip_str_len + 1);
++	my_ip_str[ip_str_len] = '\0';
++
++	if (family == 1) {
++		/* ipv4 */
++		afdpart = LDNS_XMALLOC(uint8_t, 4);
++                if(!afdpart) {
++                        LDNS_FREE(my_ip_str);
++                        return LDNS_STATUS_MEM_ERR;
++                }
++		if (inet_pton(AF_INET, my_ip_str, afdpart) == 0) {
++                        LDNS_FREE(my_ip_str);
++                        LDNS_FREE(afdpart);
++			return LDNS_STATUS_INVALID_STR;
++		}
++		for (i = 0; i < 4; i++) {
++			if (afdpart[i] != 0) {
++				afdlength = i + 1;
++			}
++		}
++	} else if (family == 2) {
++		/* ipv6 */
++		afdpart = LDNS_XMALLOC(uint8_t, 16);
++                if(!afdpart) {
++                        LDNS_FREE(my_ip_str);
++                        return LDNS_STATUS_MEM_ERR;
++                }
++		if (inet_pton(AF_INET6, my_ip_str, afdpart) == 0) {
++                        LDNS_FREE(my_ip_str);
++                        LDNS_FREE(afdpart);
++			return LDNS_STATUS_INVALID_STR;
++		}
++		for (i = 0; i < 16; i++) {
++			if (afdpart[i] != 0) {
++				afdlength = i + 1;
++			}
++		}
++	} else {
++		/* unknown family */
++		LDNS_FREE(my_ip_str);
++		return LDNS_STATUS_INVALID_STR;
++	}
++
++	my_str = strchr(my_str, '/') + 1;
++	prefix = (uint8_t) atoi(my_str);
++
++	data = LDNS_XMALLOC(uint8_t, 4 + afdlength);
++        if(!data) {
++		LDNS_FREE(afdpart);
++		LDNS_FREE(my_ip_str);
++		return LDNS_STATUS_INVALID_STR;
++        }
++	ldns_write_uint16(data, family);
++	data[2] = prefix;
++	data[3] = afdlength;
++	if (negation) {
++		/* set bit 1 of byte 3 */
++		data[3] = data[3] | 0x80;
++	}
++
++	memcpy(data + 4, afdpart, afdlength);
++
++	*rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_APL, afdlength + 4, data);
++	LDNS_FREE(afdpart);
++	LDNS_FREE(data);
++	LDNS_FREE(my_ip_str);
++
++	return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
++}
++
++ldns_status
++ldns_str2rdf_b64(ldns_rdf **rd, const char *str)
++{
++	uint8_t *buffer;
++	int16_t i;
++
++	buffer = LDNS_XMALLOC(uint8_t, ldns_b64_ntop_calculate_size(strlen(str)));
++        if(!buffer) {
++                return LDNS_STATUS_MEM_ERR;
++        }
++
++	i = (uint16_t)ldns_b64_pton((const char*)str, buffer,
++						   ldns_b64_ntop_calculate_size(strlen(str)));
++	if (-1 == i) {
++		LDNS_FREE(buffer);
++		return LDNS_STATUS_INVALID_B64;
++	} else {
++		*rd = ldns_rdf_new_frm_data(
++			LDNS_RDF_TYPE_B64, (uint16_t) i, buffer);
++	}
++	LDNS_FREE(buffer);
++
++	return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
++}
++
++ldns_status
++ldns_str2rdf_b32_ext(ldns_rdf **rd, const char *str)
++{
++	uint8_t *buffer;
++	int i;
++	/* first byte contains length of actual b32 data */
++	uint8_t len = ldns_b32_pton_calculate_size(strlen(str));
++	buffer = LDNS_XMALLOC(uint8_t, len + 1);
++        if(!buffer) {
++                return LDNS_STATUS_MEM_ERR;
++        }
++	buffer[0] = len;
++
++	i = ldns_b32_pton_extended_hex((const char*)str, strlen(str), buffer + 1,
++							 ldns_b32_ntop_calculate_size(strlen(str)));
++	if (i < 0) {
++                LDNS_FREE(buffer);
++		return LDNS_STATUS_INVALID_B32_EXT;
++	} else {
++		*rd = ldns_rdf_new_frm_data(
++			LDNS_RDF_TYPE_B32_EXT, (uint16_t) i + 1, buffer);
++	}
++	LDNS_FREE(buffer);
++
++	return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
++}
++
++ldns_status
++ldns_str2rdf_hex(ldns_rdf **rd, const char *str)
++{
++	uint8_t *t, *t_orig;
++	int i;
++	size_t len;
++
++	len = strlen(str);
++
++	if (len > LDNS_MAX_RDFLEN * 2) {
++		return LDNS_STATUS_LABEL_OVERFLOW;
++	} else {
++		t = LDNS_XMALLOC(uint8_t, (len / 2) + 1);
++                if(!t) {
++                        return LDNS_STATUS_MEM_ERR;
++                }
++		t_orig = t;
++		/* Now process octet by octet... */
++		while (*str) {
++			*t = 0;
++			if (isspace((int) *str)) {
++				str++;
++			} else {
++				for (i = 16; i >= 1; i -= 15) {
++					while (*str && isspace((int) *str)) { str++; }
++					if (*str) {
++						if (isxdigit((int) *str)) {
++							*t += ldns_hexdigit_to_int(*str) * i;
++						} else {
++                                                        LDNS_FREE(t_orig);
++							return LDNS_STATUS_ERR;
++						}
++						++str;
++					}
++				}
++				++t;
++			}
++		}
++		*rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_HEX,
++		                            (size_t) (t - t_orig),
++		                            t_orig);
++		LDNS_FREE(t_orig);
++	}
++	return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
++}
++
++ldns_status
++ldns_str2rdf_nsec(ldns_rdf **rd, const char *str)
++{
++	const char *delimiters = "\n\t ";
++	char *token = LDNS_XMALLOC(char, LDNS_MAX_RDFLEN);
++	ldns_buffer *str_buf;
++	ssize_t c;
++	uint16_t cur_type;
++	size_t type_count = 0;
++	ldns_rr_type type_list[65536];
++	if(!token) return LDNS_STATUS_MEM_ERR;
++	if(rd == NULL) {
++		LDNS_FREE(token);
++		return LDNS_STATUS_NULL;
++	}
++
++	str_buf = LDNS_MALLOC(ldns_buffer);
++	if(!str_buf) {
++		LDNS_FREE(token);
++		return LDNS_STATUS_MEM_ERR;
++	}
++	ldns_buffer_new_frm_data(str_buf, (char *)str, strlen(str));
++	if(ldns_buffer_status(str_buf) != LDNS_STATUS_OK) {
++		LDNS_FREE(str_buf);
++		LDNS_FREE(token);
++		return LDNS_STATUS_MEM_ERR;
++	}
++
++	while ((c = ldns_bget_token(str_buf, token, delimiters, LDNS_MAX_RDFLEN)) != -1 && c != 0) {
++                if(type_count >= sizeof(type_list)) {
++		        LDNS_FREE(str_buf);
++		        LDNS_FREE(token);
++                        return LDNS_STATUS_ERR;
++                }
++		cur_type = ldns_get_rr_type_by_name(token);
++		type_list[type_count] = cur_type;
++		type_count++;
++	}
++
++	*rd = ldns_dnssec_create_nsec_bitmap(type_list,
++	                                     type_count,
++	                                     LDNS_RR_TYPE_NSEC);
++
++	LDNS_FREE(token);
++	ldns_buffer_free(str_buf);
++	return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
++}
++
++ldns_status
++ldns_str2rdf_type(ldns_rdf **rd, const char *str)
++{
++	uint16_t type;
++	type = htons(ldns_get_rr_type_by_name(str));
++	/* ldns_rr_type is a 16 bit value */
++	*rd = ldns_rdf_new_frm_data(
++		LDNS_RDF_TYPE_TYPE, sizeof(uint16_t), &type);
++	return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
++}
++
++ldns_status
++ldns_str2rdf_class(ldns_rdf **rd, const char *str)
++{
++	uint16_t klass;
++	klass = htons(ldns_get_rr_class_by_name(str));
++	/* class is 16 bit */
++	*rd = ldns_rdf_new_frm_data(
++		LDNS_RDF_TYPE_CLASS, sizeof(uint16_t), &klass);
++	return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
++}
++
++/* An certificate alg field can either be specified as a 8 bits number
++ * or by its symbolic name. Handle both
++ */
++ldns_status
++ldns_str2rdf_cert_alg(ldns_rdf **rd, const char *str)
++{
++	ldns_lookup_table *lt;
++	ldns_status st;
++	uint8_t idd[2];
++	lt = ldns_lookup_by_name(ldns_cert_algorithms, str);
++	st = LDNS_STATUS_OK;
++
++	if (lt) {
++		ldns_write_uint16(idd, (uint16_t) lt->id);
++		*rd = ldns_rdf_new_frm_data(
++			LDNS_RDF_TYPE_INT16, sizeof(uint16_t), idd);
++		if (!*rd) {
++			st = LDNS_STATUS_ERR;
++		}
++	} else {
++		/* try as-is (a number) */
++		st = ldns_str2rdf_int16(rd, str);
++		if (st == LDNS_STATUS_OK &&
++		    ldns_rdf2native_int16(*rd) == 0) {
++			st = LDNS_STATUS_CERT_BAD_ALGORITHM;
++		}
++	}
++
++	return st;
++}
++
++static ldns_lookup_table ldns_tlsa_certificate_usages[] = {
++	{ LDNS_TLSA_USAGE_PKIX_TA		, "PKIX-TA"  },
++	{ LDNS_TLSA_USAGE_PKIX_EE		, "PKIX-EE"  },
++	{ LDNS_TLSA_USAGE_DANE_TA		, "DANE-TA"  },
++	{ LDNS_TLSA_USAGE_DANE_EE		, "DANE-EE"  },
++	{ LDNS_TLSA_USAGE_PRIVCERT		, "PrivCert" }
++};
++
++static ldns_lookup_table ldns_tlsa_selectors[] = {
++	{ LDNS_TLSA_SELECTOR_CERT		, "Cert" },
++	{ LDNS_TLSA_SELECTOR_SPKI		, "SPKI" },
++	{ LDNS_TLSA_SELECTOR_PRIVSEL		, "PrivSel" }
++};
++
++static ldns_lookup_table ldns_tlsa_matching_types[] = {
++	{ LDNS_TLSA_MATCHING_TYPE_FULL		, "Full"      },
++	{ LDNS_TLSA_MATCHING_TYPE_SHA2_256	, "SHA2-256"  },
++	{ LDNS_TLSA_MATCHING_TYPE_SHA2_512	, "SHA2-512"  },
++	{ LDNS_TLSA_MATCHING_TYPE_PRIVMATCH	, "PrivMatch" }
++};
++
++static ldns_status
++ldns_str2rdf_mnemonic4int8(ldns_lookup_table *lt,
++		ldns_rdf **rd, const char *str)
++{
++	if ((lt = ldns_lookup_by_name(lt, str))) {
++		/* it was given as a integer */
++		*rd = ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8, (uint8_t) lt->id);
++		if (!*rd)
++			return LDNS_STATUS_ERR;
++		else
++			return LDNS_STATUS_OK;
++	}
++	return ldns_str2rdf_int8(rd, str);
++}
++
++/* An alg field can either be specified as a 8 bits number
++ * or by its symbolic name. Handle both
++ */
++ldns_status
++ldns_str2rdf_alg(ldns_rdf **rd, const char *str)
++{
++	return ldns_str2rdf_mnemonic4int8(ldns_algorithms, rd, str);
++}
++
++ldns_status
++ldns_str2rdf_certificate_usage(ldns_rdf **rd, const char *str)
++{
++	return ldns_str2rdf_mnemonic4int8(
++			ldns_tlsa_certificate_usages, rd, str);
++}
++
++ldns_status
++ldns_str2rdf_selector(ldns_rdf **rd, const char *str)
++{
++	return ldns_str2rdf_mnemonic4int8(ldns_tlsa_selectors, rd, str);
++}
++
++ldns_status
++ldns_str2rdf_matching_type(ldns_rdf **rd, const char *str)
++{
++	return ldns_str2rdf_mnemonic4int8(ldns_tlsa_matching_types, rd, str);
++}
++
++ldns_status
++ldns_str2rdf_unknown( ATTR_UNUSED(ldns_rdf **rd)
++		    , ATTR_UNUSED(const char *str)
++		    )
++{
++	/* this should be caught in an earlier time (general str2host for
++	   rr's */
++	return LDNS_STATUS_NOT_IMPL;
++}
++
++ldns_status
++ldns_str2rdf_service( ATTR_UNUSED(ldns_rdf **rd)
++		    , ATTR_UNUSED(const char *str)
++		    )
++{
++	/* is this used? is this actually WKS? or SRV? */
++	return LDNS_STATUS_NOT_IMPL;
++}
++
++static int
++loc_parse_cm(char* my_str, char** endstr, uint8_t* m, uint8_t* e)
++{
++	/* read <digits>[.<digits>][mM] */
++	/* into mantissa exponent format for LOC type */
++	uint32_t meters = 0, cm = 0, val;
++	while (isblank(*my_str)) {
++		my_str++;
++	}
++	meters = (uint32_t)strtol(my_str, &my_str, 10);
++	if (*my_str == '.') {
++		my_str++;
++		cm = (uint32_t)strtol(my_str, &my_str, 10);
++	}
++	if (meters >= 1) {
++		*e = 2;
++		val = meters;
++	} else	{
++		*e = 0;
++		val = cm;
++	}
++	while(val >= 10) {
++		(*e)++;
++		val /= 10;
++	}
++	*m = (uint8_t)val;
++
++	if (*e > 9)
++		return 0;
++	if (*my_str == 'm' || *my_str == 'M') {
++		my_str++;
++	}
++	*endstr = my_str;
++	return 1;
++}
++
++ldns_status
++ldns_str2rdf_loc(ldns_rdf **rd, const char *str)
++{
++	uint32_t latitude = 0;
++	uint32_t longitude = 0;
++	uint32_t altitude = 0;
++
++	uint8_t *data;
++	uint32_t equator = (uint32_t) ldns_power(2, 31);
++
++	uint32_t h = 0;
++	uint32_t m = 0;
++	uint8_t size_b = 1, size_e = 2;
++	uint8_t horiz_pre_b = 1, horiz_pre_e = 6;
++	uint8_t vert_pre_b = 1, vert_pre_e = 3;
++
++	double s = 0.0;
++	bool northerness;
++	bool easterness;
++
++	char *my_str = (char *) str;
++
++	/* only support version 0 */
++	if (isdigit((int) *my_str)) {
++		h = (uint32_t) strtol(my_str, &my_str, 10);
++	} else {
++		return LDNS_STATUS_INVALID_STR;
++	}
++
++	while (isblank((int) *my_str)) {
++		my_str++;
++	}
++
++	if (isdigit((int) *my_str)) {
++		m = (uint32_t) strtol(my_str, &my_str, 10);
++	} else if (*my_str == 'N' || *my_str == 'S') {
++		goto north;
++	} else {
++		return LDNS_STATUS_INVALID_STR;
++	}
++
++	while (isblank((int) *my_str)) {
++		my_str++;
++	}
++
++	if (isdigit((int) *my_str)) {
++		s = strtod(my_str, &my_str);
++	}
++north:
++	while (isblank((int) *my_str)) {
++		my_str++;
++	}
++
++	if (*my_str == 'N') {
++		northerness = true;
++	} else if (*my_str == 'S') {
++		northerness = false;
++	} else {
++		return LDNS_STATUS_INVALID_STR;
++	}
++
++	my_str++;
++
++	/* store number */
++	s = 1000.0 * s;
++	/* add a little to make floor in conversion a round */
++	s += 0.0005;
++	latitude = (uint32_t) s;
++	latitude += 1000 * 60 * m;
++	latitude += 1000 * 60 * 60 * h;
++	if (northerness) {
++		latitude = equator + latitude;
++	} else {
++		latitude = equator - latitude;
++	}
++	while (isblank(*my_str)) {
++		my_str++;
++	}
++
++	if (isdigit((int) *my_str)) {
++		h = (uint32_t) strtol(my_str, &my_str, 10);
++	} else {
++		return LDNS_STATUS_INVALID_STR;
++	}
++
++	while (isblank((int) *my_str)) {
++		my_str++;
++	}
++
++	if (isdigit((int) *my_str)) {
++		m = (uint32_t) strtol(my_str, &my_str, 10);
++	} else if (*my_str == 'E' || *my_str == 'W') {
++		goto east;
++	} else {
++		return LDNS_STATUS_INVALID_STR;
++	}
++
++	while (isblank(*my_str)) {
++		my_str++;
++	}
++
++	if (isdigit((int) *my_str)) {
++		s = strtod(my_str, &my_str);
++	}
++
++east:
++	while (isblank(*my_str)) {
++		my_str++;
++	}
++
++	if (*my_str == 'E') {
++		easterness = true;
++	} else if (*my_str == 'W') {
++		easterness = false;
++	} else {
++		return LDNS_STATUS_INVALID_STR;
++	}
++
++	my_str++;
++
++	/* store number */
++	s *= 1000.0;
++	/* add a little to make floor in conversion a round */
++	s += 0.0005;
++	longitude = (uint32_t) s;
++	longitude += 1000 * 60 * m;
++	longitude += 1000 * 60 * 60 * h;
++
++	if (easterness) {
++		longitude += equator;
++	} else {
++		longitude = equator - longitude;
++	}
++
++	altitude = (uint32_t)(strtod(my_str, &my_str)*100.0 +
++		10000000.0 + 0.5);
++	if (*my_str == 'm' || *my_str == 'M') {
++		my_str++;
++	}
++
++	if (strlen(my_str) > 0) {
++		if(!loc_parse_cm(my_str, &my_str, &size_b, &size_e))
++			return LDNS_STATUS_INVALID_STR;
++	}
++
++	if (strlen(my_str) > 0) {
++		if(!loc_parse_cm(my_str, &my_str, &horiz_pre_b, &horiz_pre_e))
++			return LDNS_STATUS_INVALID_STR;
++	}
++
++	if (strlen(my_str) > 0) {
++		if(!loc_parse_cm(my_str, &my_str, &vert_pre_b, &vert_pre_e))
++			return LDNS_STATUS_INVALID_STR;
++	}
++
++	data = LDNS_XMALLOC(uint8_t, 16);
++        if(!data) {
++                return LDNS_STATUS_MEM_ERR;
++        }
++	data[0] = 0;
++	data[1] = 0;
++	data[1] = ((size_b << 4) & 0xf0) | (size_e & 0x0f);
++	data[2] = ((horiz_pre_b << 4) & 0xf0) | (horiz_pre_e & 0x0f);
++	data[3] = ((vert_pre_b << 4) & 0xf0) | (vert_pre_e & 0x0f);
++	ldns_write_uint32(data + 4, latitude);
++	ldns_write_uint32(data + 8, longitude);
++	ldns_write_uint32(data + 12, altitude);
++
++	*rd = ldns_rdf_new_frm_data(
++		LDNS_RDF_TYPE_LOC, 16, data);
++
++	LDNS_FREE(data);
++	return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
++}
++
++ldns_status
++ldns_str2rdf_wks(ldns_rdf **rd, const char *str)
++{
++	uint8_t *bitmap = NULL;
++	uint8_t *data;
++	int bm_len = 0;
++
++	struct protoent *proto = NULL;
++	struct servent *serv = NULL;
++	int serv_port;
++
++	ldns_buffer *str_buf;
++
++	char *proto_str = NULL;
++	char *token;
++	if(strlen(str) == 0)
++		token = LDNS_XMALLOC(char, 50);
++	else 	token = LDNS_XMALLOC(char, strlen(str)+2);
++	if(!token) return LDNS_STATUS_MEM_ERR;
++
++	str_buf = LDNS_MALLOC(ldns_buffer);
++	if(!str_buf) {LDNS_FREE(token); return LDNS_STATUS_MEM_ERR;}
++	ldns_buffer_new_frm_data(str_buf, (char *)str, strlen(str));
++	if(ldns_buffer_status(str_buf) != LDNS_STATUS_OK) {
++		LDNS_FREE(str_buf);
++		LDNS_FREE(token);
++		return LDNS_STATUS_MEM_ERR;
++	}
++
++	while(ldns_bget_token(str_buf, token, "\t\n ", strlen(str)) > 0) {
++		if (!proto_str) {
++			proto_str = strdup(token);
++			if (!proto_str) {
++				LDNS_FREE(bitmap);
++				LDNS_FREE(token);
++	                        ldns_buffer_free(str_buf);
++				return LDNS_STATUS_INVALID_STR;
++			}
++		} else {
++			serv = getservbyname(token, proto_str);
++			if (serv) {
++				serv_port = (int) ntohs((uint16_t) serv->s_port);
++			} else {
++				serv_port = atoi(token);
++			}
++			if (serv_port / 8 >= bm_len) {
++				uint8_t *b2 = LDNS_XREALLOC(bitmap, uint8_t, (serv_port / 8) + 1);
++                                if(!b2) {
++					LDNS_FREE(bitmap);
++				        LDNS_FREE(token);
++	                                ldns_buffer_free(str_buf);
++				        free(proto_str);
++				        return LDNS_STATUS_INVALID_STR;
++                                }
++				bitmap = b2;
++				/* set to zero to be sure */
++				for (; bm_len <= serv_port / 8; bm_len++) {
++					bitmap[bm_len] = 0;
++				}
++			}
++			ldns_set_bit(bitmap + (serv_port / 8), 7 - (serv_port % 8), true);
++		}
++	}
++
++	if (!proto_str || !bitmap) {
++		LDNS_FREE(bitmap);
++		LDNS_FREE(token);
++	        ldns_buffer_free(str_buf);
++	        free(proto_str);
++		return LDNS_STATUS_INVALID_STR;
++	}
++
++	data = LDNS_XMALLOC(uint8_t, bm_len + 1);
++        if(!data) {
++	        LDNS_FREE(token);
++	        ldns_buffer_free(str_buf);
++	        LDNS_FREE(bitmap);
++	        free(proto_str);
++	        return LDNS_STATUS_INVALID_STR;
++        }
++    if (proto_str)
++		proto = getprotobyname(proto_str);
++	if (proto) {
++		data[0] = (uint8_t) proto->p_proto;
++	} else if (proto_str) {
++		data[0] = (uint8_t) atoi(proto_str);
++	}
++	memcpy(data + 1, bitmap, (size_t) bm_len);
++
++	*rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_WKS, (uint16_t) (bm_len + 1), data);
++
++	LDNS_FREE(data);
++	LDNS_FREE(token);
++	ldns_buffer_free(str_buf);
++	LDNS_FREE(bitmap);
++	free(proto_str);
++#ifdef HAVE_ENDSERVENT
++	endservent();
++#endif
++#ifdef HAVE_ENDPROTOENT
++	endprotoent();
++#endif
++
++	if(!*rd) return LDNS_STATUS_MEM_ERR;
++
++	return LDNS_STATUS_OK;
++}
++
++ldns_status
++ldns_str2rdf_nsap(ldns_rdf **rd, const char *str)
++{
++    size_t len, i;
++    char* nsap_str = (char*) str;
++
++	/* just a hex string with optional dots? */
++	if (str[0] != '0' || str[1] != 'x') {
++		return LDNS_STATUS_INVALID_STR;
++	} else {
++		len = strlen(str);
++		for (i=0; i < len; i++) {
++			if (nsap_str[i] == '.')
++				nsap_str[i] = ' ';
++        }
++		return ldns_str2rdf_hex(rd, str+2);
++	}
++}
++
++ldns_status
++ldns_str2rdf_atma(ldns_rdf **rd, const char *str)
++{
++    size_t len, i;
++    char* atma_str = (char*) str;
++	ldns_status status;
++
++	/* just a hex string with optional dots? */
++	len = strlen(str);
++	for (i=0; i < len; i++) {
++		if (atma_str[i] == '.')
++			atma_str[i] = ' ';
++	}
++	status = ldns_str2rdf_hex(rd, str);
++    if (status != LDNS_STATUS_OK) {
++		; /* probably in e.164 format than */
++	}
++	return status;
++}
++
++ldns_status
++ldns_str2rdf_ipseckey(ldns_rdf **rd, const char *str)
++{
++	uint8_t precedence = 0;
++	uint8_t gateway_type = 0;
++	uint8_t algorithm = 0;
++	char* gateway = NULL;
++	char* publickey = NULL;
++	uint8_t *data;
++	ldns_buffer *str_buf;
++	char *token;
++	int token_count = 0;
++	int ipseckey_len = 0;
++	ldns_rdf* gateway_rdf = NULL;
++	ldns_rdf* publickey_rdf = NULL;
++	ldns_status status = LDNS_STATUS_OK;
++	
++	if(strlen(str) == 0)
++		token = LDNS_XMALLOC(char, 256);
++	else	token = LDNS_XMALLOC(char, strlen(str)+2);
++	if(!token) return LDNS_STATUS_MEM_ERR;
++
++	str_buf = LDNS_MALLOC(ldns_buffer);
++	if(!str_buf) {LDNS_FREE(token); return LDNS_STATUS_MEM_ERR;}
++	ldns_buffer_new_frm_data(str_buf, (char *)str, strlen(str));
++	if(ldns_buffer_status(str_buf) != LDNS_STATUS_OK) {
++		LDNS_FREE(str_buf);
++		LDNS_FREE(token);
++		return LDNS_STATUS_MEM_ERR;
++	}
++	while(ldns_bget_token(str_buf, token, "\t\n ", strlen(str)) > 0) {
++		switch (token_count) {
++				case 0:
++					precedence = (uint8_t)atoi(token);
++					break;
++				case 1:
++					gateway_type = (uint8_t)atoi(token);
++					break;
++				case 2:
++					algorithm = (uint8_t)atoi(token);
++					break;
++				case 3:
++					gateway = strdup(token);
++					if (!gateway || (gateway_type == 0 &&
++							(token[0] != '.' || token[1] != '\0'))) {
++						LDNS_FREE(gateway);
++						LDNS_FREE(token);
++						ldns_buffer_free(str_buf);
++						return LDNS_STATUS_INVALID_STR;
++					}
++					break;
++				case 4:
++					publickey = strdup(token);
++					break;
++				default:
++					LDNS_FREE(token);
++					ldns_buffer_free(str_buf);
++					return LDNS_STATUS_INVALID_STR;
++					break;
++		}
++		token_count++;
++	}
++
++	if (!gateway || !publickey) {
++		if (gateway)
++			LDNS_FREE(gateway);
++		if (publickey)
++			LDNS_FREE(publickey);
++		LDNS_FREE(token);
++		ldns_buffer_free(str_buf);
++		return LDNS_STATUS_INVALID_STR;
++	}
++
++	if (gateway_type == 1) {
++		status = ldns_str2rdf_a(&gateway_rdf, gateway);
++	} else if (gateway_type == 2) {
++		status = ldns_str2rdf_aaaa(&gateway_rdf, gateway);
++	} else if (gateway_type == 3) {
++		status = ldns_str2rdf_dname(&gateway_rdf, gateway);
++	}
++
++	if (status != LDNS_STATUS_OK) {
++		if (gateway)
++			LDNS_FREE(gateway);
++		if (publickey)
++			LDNS_FREE(publickey);
++		LDNS_FREE(token);
++		ldns_buffer_free(str_buf);
++		return LDNS_STATUS_INVALID_STR;
++	}
++
++	status = ldns_str2rdf_b64(&publickey_rdf, publickey);
++
++	if (status != LDNS_STATUS_OK) {
++		if (gateway)
++			LDNS_FREE(gateway);
++		if (publickey)
++			LDNS_FREE(publickey);
++		LDNS_FREE(token);
++		ldns_buffer_free(str_buf);
++		if (gateway_rdf) ldns_rdf_free(gateway_rdf);
++		return LDNS_STATUS_INVALID_STR;
++	}
++
++	/* now copy all into one ipseckey rdf */
++	if (gateway_type)
++		ipseckey_len = 3 + (int)ldns_rdf_size(gateway_rdf) + (int)ldns_rdf_size(publickey_rdf);
++	else
++		ipseckey_len = 3 + (int)ldns_rdf_size(publickey_rdf);
++
++	data = LDNS_XMALLOC(uint8_t, ipseckey_len);
++	if(!data) {
++		if (gateway)
++			LDNS_FREE(gateway);
++		if (publickey)
++			LDNS_FREE(publickey);
++		LDNS_FREE(token);
++		ldns_buffer_free(str_buf);
++		if (gateway_rdf) ldns_rdf_free(gateway_rdf);
++		if (publickey_rdf) ldns_rdf_free(publickey_rdf);
++		return LDNS_STATUS_MEM_ERR;
++	}
++
++	data[0] = precedence;
++	data[1] = gateway_type;
++	data[2] = algorithm;
++
++	if (gateway_type) {
++		memcpy(data + 3,
++			ldns_rdf_data(gateway_rdf), ldns_rdf_size(gateway_rdf));
++		memcpy(data + 3 + ldns_rdf_size(gateway_rdf),
++			ldns_rdf_data(publickey_rdf), ldns_rdf_size(publickey_rdf));
++	} else {
++		memcpy(data + 3,
++			ldns_rdf_data(publickey_rdf), ldns_rdf_size(publickey_rdf));
++	}
++
++	*rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_IPSECKEY, (uint16_t) ipseckey_len, data);
++
++	if (gateway)
++		LDNS_FREE(gateway);
++	if (publickey)
++		LDNS_FREE(publickey);
++	LDNS_FREE(token);
++	ldns_buffer_free(str_buf);
++	ldns_rdf_free(gateway_rdf);
++	ldns_rdf_free(publickey_rdf);
++	LDNS_FREE(data);
++	if(!*rd) return LDNS_STATUS_MEM_ERR;
++	return LDNS_STATUS_OK;
++}
++
++ldns_status
++ldns_str2rdf_ilnp64(ldns_rdf **rd, const char *str)
++{
++	unsigned int a, b, c, d;
++	uint16_t shorts[4];
++	int l;
++
++	if (sscanf(str, "%4x:%4x:%4x:%4x%n", &a, &b, &c, &d, &l) != 4 ||
++			l != (int)strlen(str) || /* more data to read */
++			strpbrk(str, "+-")       /* signed hexes */
++			) {
++		return LDNS_STATUS_INVALID_ILNP64;
++	} else {
++		shorts[0] = htons(a);
++		shorts[1] = htons(b);
++		shorts[2] = htons(c);
++		shorts[3] = htons(d);
++		*rd = ldns_rdf_new_frm_data(
++			LDNS_RDF_TYPE_ILNP64, 4 * sizeof(uint16_t), &shorts);
++	}
++	return *rd ? LDNS_STATUS_OK : LDNS_STATUS_MEM_ERR;
++}
++
++ldns_status
++ldns_str2rdf_eui48(ldns_rdf **rd, const char *str)
++{
++	unsigned int a, b, c, d, e, f;
++	uint8_t bytes[6];
++	int l;
++
++	if (sscanf(str, "%2x-%2x-%2x-%2x-%2x-%2x%n",
++			&a, &b, &c, &d, &e, &f, &l) != 6 ||
++			l != (int)strlen(str)) {
++		return LDNS_STATUS_INVALID_EUI48;
++	} else {
++		bytes[0] = a;
++		bytes[1] = b;
++		bytes[2] = c;
++		bytes[3] = d;
++		bytes[4] = e;
++		bytes[5] = f;
++		*rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_EUI48, 6, &bytes);
++	}
++	return *rd ? LDNS_STATUS_OK : LDNS_STATUS_MEM_ERR;
++}
++
++ldns_status
++ldns_str2rdf_eui64(ldns_rdf **rd, const char *str)
++{
++	unsigned int a, b, c, d, e, f, g, h;
++	uint8_t bytes[8];
++	int l;
++
++	if (sscanf(str, "%2x-%2x-%2x-%2x-%2x-%2x-%2x-%2x%n",
++			&a, &b, &c, &d, &e, &f, &g, &h, &l) != 8 ||
++			l != (int)strlen(str)) {
++		return LDNS_STATUS_INVALID_EUI64;
++	} else {
++		bytes[0] = a;
++		bytes[1] = b;
++		bytes[2] = c;
++		bytes[3] = d;
++		bytes[4] = e;
++		bytes[5] = f;
++		bytes[6] = g;
++		bytes[7] = h;
++		*rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_EUI64, 8, &bytes);
++	}
++	return *rd ? LDNS_STATUS_OK : LDNS_STATUS_MEM_ERR;
++}
++
++ldns_status
++ldns_str2rdf_tag(ldns_rdf **rd, const char *str)
++{
++	uint8_t *data;
++	const char* ptr;
++
++	if (strlen(str) > 255) {
++		return LDNS_STATUS_INVALID_TAG;
++	}
++	for (ptr = str; *ptr; ptr++) {
++		if (! isalnum(*ptr)) {
++			return LDNS_STATUS_INVALID_TAG;
++		}
++	}
++	data = LDNS_XMALLOC(uint8_t, strlen(str) + 1);
++        if (!data) {
++		return LDNS_STATUS_MEM_ERR;
++	}
++	data[0] = strlen(str);
++	memcpy(data + 1, str, strlen(str));
++
++	*rd = ldns_rdf_new(LDNS_RDF_TYPE_TAG, strlen(str) + 1, data);
++	if (!*rd) {
++		LDNS_FREE(data);
++		return LDNS_STATUS_MEM_ERR;
++	}
++	return LDNS_STATUS_OK;
++}
++
++ldns_status
++ldns_str2rdf_long_str(ldns_rdf **rd, const char *str)
++{
++	uint8_t *data, *dp, ch = 0;
++	size_t length;
++
++	/* Worst case space requirement. We'll realloc to actual size later. */
++	dp = data = LDNS_XMALLOC(uint8_t, strlen(str));
++        if (! data) {
++		return LDNS_STATUS_MEM_ERR;
++	}
++
++	/* Fill data with parsed bytes */
++	while (parse_char(&ch, &str)) {
++		*dp++ = ch;
++		if (dp - data > LDNS_MAX_RDFLEN) {
++			LDNS_FREE(data);
++			return LDNS_STATUS_INVALID_STR;
++		}
++	}
++	if (! str) {
++		return LDNS_STATUS_SYNTAX_BAD_ESCAPE;
++	}
++	length = (size_t)(dp - data);
++
++	/* Lose the overmeasure */
++	data = LDNS_XREALLOC(dp = data, uint8_t, length);
++	if (! data) {
++		LDNS_FREE(dp);
++		return LDNS_STATUS_MEM_ERR;
++	}
++
++	/* Create rdf */
++	*rd = ldns_rdf_new(LDNS_RDF_TYPE_LONG_STR, length, data);
++	if (! *rd) {
++		LDNS_FREE(data);
++		return LDNS_STATUS_MEM_ERR;
++	}
++	return LDNS_STATUS_OK;
++}
++
++ldns_status
++ldns_str2rdf_hip(ldns_rdf **rd, const char *str)
++{
++	const char *hit = strchr(str, ' ') + 1;
++	const char *pk  = hit == NULL ? NULL : strchr(hit, ' ') + 1;
++	size_t hit_size = hit == NULL ? 0
++	                : pk  == NULL ? strlen(hit) : (size_t) (pk - hit) - 1;
++	size_t  pk_size = pk  == NULL ? 0 : strlen(pk);
++	size_t hit_wire_size = (hit_size + 1) / 2;
++	size_t  pk_wire_size = ldns_b64_pton_calculate_size(pk_size);
++	size_t rdf_size = 4 + hit_wire_size + pk_wire_size;
++
++	char *endptr; /* utility var for strtol usage */
++	int algorithm = strtol(str, &endptr, 10);
++
++	uint8_t *data, *dp;
++	int hi, lo, written;
++
++	if (hit_size == 0 || pk_size == 0 || (hit_size + 1) / 2 > 255
++			|| rdf_size > LDNS_MAX_RDFLEN
++			|| algorithm < 0 || algorithm > 255
++			|| (errno != 0 && algorithm == 0) /* out of range */
++			|| endptr == str                  /* no digits    */) {
++
++		return LDNS_STATUS_SYNTAX_ERR;
++	}
++	if ((data = LDNS_XMALLOC(uint8_t, rdf_size)) == NULL) {
++
++		return LDNS_STATUS_MEM_ERR;
++	}
++	/* From RFC 5205 section 5. HIP RR Storage Format:
++	 *************************************************
++
++	0                   1                   2                   3
++	0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
++	+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
++	|  HIT length   | PK algorithm  |          PK length            |
++	+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
++	|                                                               |
++	~                           HIT                                 ~
++	|                                                               |
++	+                     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
++	|                     |                                         |
++	+-+-+-+-+-+-+-+-+-+-+-+                                         +
++	|                           Public Key                          |
++	~                                                               ~
++	|                                                               |
++	+                               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
++	|                               |                               |
++	+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               +
++	|                                                               |
++	~                       Rendezvous Servers                      ~
++	|                                                               |
++	+             +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
++	|             |
++	+-+-+-+-+-+-+-+                                                    */
++
++	data[0] = (uint8_t) hit_wire_size;
++	data[1] = (uint8_t) algorithm;
++
++	for (dp = data + 4; *hit && *hit != ' '; dp++) {
++
++		if ((hi = ldns_hexdigit_to_int(*hit++)) == -1 ||
++		    (lo = ldns_hexdigit_to_int(*hit++)) == -1) {
++
++			LDNS_FREE(data);
++			return LDNS_STATUS_INVALID_HEX;
++		}
++		*dp = (uint8_t) hi << 4 | lo;
++	}
++	if ((written = ldns_b64_pton(pk, dp, pk_wire_size)) <= 0) {
++
++		LDNS_FREE(data);
++		return LDNS_STATUS_INVALID_B64;
++	}
++
++	/* Because ldns_b64_pton_calculate_size isn't always correct:
++	 * (we have to fix it at some point)
++	 */
++	pk_wire_size = (uint16_t) written;
++	ldns_write_uint16(data + 2, pk_wire_size);
++	rdf_size = 4 + hit_wire_size + pk_wire_size;
++
++	/* Create rdf */
++	if (! (*rd = ldns_rdf_new(LDNS_RDF_TYPE_HIP, rdf_size, data))) {
++
++		LDNS_FREE(data);
++		return LDNS_STATUS_MEM_ERR;
++	}
++	return LDNS_STATUS_OK;
++}
+diff --git a/ldns/src/tsig.c b/ldns/src/tsig.c
+new file mode 100644
+index 0000000..53aa85e
+--- /dev/null
++++ b/ldns/src/tsig.c
+@@ -0,0 +1,470 @@
++/*
++ * tsig.c
++ *
++ * contains the functions needed for TSIG [RFC2845]
++ *
++ * (c) 2005-2006 NLnet Labs
++ * See the file LICENSE for the license
++ */
++
++#include <ldns/config.h>
++
++#include <ldns/ldns.h>
++
++#include <strings.h>
++
++#ifdef HAVE_SSL
++#include <openssl/hmac.h>
++#include <openssl/md5.h>
++#endif /* HAVE_SSL */
++
++char *
++ldns_tsig_algorithm(ldns_tsig_credentials *tc)
++{
++	return tc->algorithm;
++}
++
++char *
++ldns_tsig_keyname(ldns_tsig_credentials *tc)
++{
++	return tc->keyname;
++}
++
++char *
++ldns_tsig_keydata(ldns_tsig_credentials *tc)
++{
++	return tc->keydata;
++}
++
++char *
++ldns_tsig_keyname_clone(ldns_tsig_credentials *tc)
++{
++	return strdup(tc->keyname);
++}
++
++char *
++ldns_tsig_keydata_clone(ldns_tsig_credentials *tc)
++{
++	return strdup(tc->keydata);
++}
++
++/*
++ *  Makes an exact copy of the wire, but with the tsig rr removed
++ */
++static uint8_t *
++ldns_tsig_prepare_pkt_wire(uint8_t *wire, size_t wire_len, size_t *result_len)
++{
++	uint8_t *wire2 = NULL;
++	uint16_t qd_count;
++	uint16_t an_count;
++	uint16_t ns_count;
++	uint16_t ar_count;
++	ldns_rr *rr;
++
++	size_t pos;
++	uint16_t i;
++
++	ldns_status status;
++
++	if(wire_len < LDNS_HEADER_SIZE) {
++		return NULL;
++	}
++	/* fake parse the wire */
++	qd_count = LDNS_QDCOUNT(wire);
++	an_count = LDNS_ANCOUNT(wire);
++	ns_count = LDNS_NSCOUNT(wire);
++	ar_count = LDNS_ARCOUNT(wire);
++
++	if (ar_count > 0) {
++		ar_count--;
++	} else {
++		return NULL;
++	}
++
++	pos = LDNS_HEADER_SIZE;
++
++	for (i = 0; i < qd_count; i++) {
++		status = ldns_wire2rr(&rr, wire, wire_len, &pos, LDNS_SECTION_QUESTION);
++		if (status != LDNS_STATUS_OK) {
++			return NULL;
++		}
++		ldns_rr_free(rr);
++	}
++
++	for (i = 0; i < an_count; i++) {
++		status = ldns_wire2rr(&rr, wire, wire_len, &pos, LDNS_SECTION_ANSWER);
++		if (status != LDNS_STATUS_OK) {
++			return NULL;
++		}
++		ldns_rr_free(rr);
++	}
++
++	for (i = 0; i < ns_count; i++) {
++		status = ldns_wire2rr(&rr, wire, wire_len, &pos, LDNS_SECTION_AUTHORITY);
++		if (status != LDNS_STATUS_OK) {
++			return NULL;
++		}
++		ldns_rr_free(rr);
++	}
++
++	for (i = 0; i < ar_count; i++) {
++		status = ldns_wire2rr(&rr, wire, wire_len, &pos,
++				LDNS_SECTION_ADDITIONAL);
++		if (status != LDNS_STATUS_OK) {
++			return NULL;
++		}
++		ldns_rr_free(rr);
++	}
++
++	*result_len = pos;
++	wire2 = LDNS_XMALLOC(uint8_t, *result_len);
++	if(!wire2) {
++		return NULL;
++	}
++	memcpy(wire2, wire, *result_len);
++
++	ldns_write_uint16(wire2 + LDNS_ARCOUNT_OFF, ar_count);
++
++	return wire2;
++}
++
++#ifdef HAVE_SSL
++static const EVP_MD *
++ldns_digest_function(char *name)
++{
++	/* these are the mandatory algorithms from RFC4635 */
++	/* The optional algorithms are not yet implemented */
++	if (strcasecmp(name, "hmac-sha256.") == 0) {
++#ifdef HAVE_EVP_SHA256
++		return EVP_sha256();
++#else
++		return NULL;
++#endif
++	} else if (strcasecmp(name, "hmac-sha1.") == 0) {
++		return EVP_sha1();
++	} else if (strcasecmp(name, "hmac-md5.sig-alg.reg.int.") == 0) {
++		return EVP_md5();
++	} else {
++		return NULL;
++	}
++}
++#endif
++
++#ifdef HAVE_SSL
++static ldns_status
++ldns_tsig_mac_new(ldns_rdf **tsig_mac, uint8_t *pkt_wire, size_t pkt_wire_size,
++		const char *key_data, ldns_rdf *key_name_rdf, ldns_rdf *fudge_rdf,
++		ldns_rdf *algorithm_rdf, ldns_rdf *time_signed_rdf, ldns_rdf *error_rdf,
++		ldns_rdf *other_data_rdf, ldns_rdf *orig_mac_rdf, int tsig_timers_only)
++{
++	ldns_status status;
++	char *wireformat;
++	int wiresize;
++	unsigned char *mac_bytes = NULL;
++	unsigned char *key_bytes = NULL;
++	int key_size;
++	const EVP_MD *digester;
++	char *algorithm_name = NULL;
++	unsigned int md_len = EVP_MAX_MD_SIZE;
++	ldns_rdf *result = NULL;
++	ldns_buffer *data_buffer = NULL;
++	ldns_rdf *canonical_key_name_rdf = NULL;
++	ldns_rdf *canonical_algorithm_rdf = NULL;
++	
++	if (key_name_rdf == NULL || algorithm_rdf == NULL) {
++		return LDNS_STATUS_NULL;
++	}
++	canonical_key_name_rdf  = ldns_rdf_clone(key_name_rdf);
++	if (canonical_key_name_rdf == NULL) {
++		return LDNS_STATUS_MEM_ERR;
++	}
++	canonical_algorithm_rdf = ldns_rdf_clone(algorithm_rdf);
++	if (canonical_algorithm_rdf == NULL) {
++		ldns_rdf_deep_free(canonical_key_name_rdf);
++		return LDNS_STATUS_MEM_ERR;
++	}
++	/*
++	 * prepare the digestable information
++	 */
++	data_buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN);
++	if (!data_buffer) {
++		status = LDNS_STATUS_MEM_ERR;
++		goto clean;
++	}
++	/* if orig_mac is not NULL, add it too */
++	if (orig_mac_rdf) {
++		(void) ldns_rdf2buffer_wire(data_buffer, orig_mac_rdf);
++ 	}
++	ldns_buffer_write(data_buffer, pkt_wire, pkt_wire_size);
++	if (!tsig_timers_only) {
++		ldns_dname2canonical(canonical_key_name_rdf);
++		(void)ldns_rdf2buffer_wire(data_buffer, 
++				canonical_key_name_rdf);
++		ldns_buffer_write_u16(data_buffer, LDNS_RR_CLASS_ANY);
++		ldns_buffer_write_u32(data_buffer, 0);
++		ldns_dname2canonical(canonical_algorithm_rdf);
++		(void)ldns_rdf2buffer_wire(data_buffer, 
++				canonical_algorithm_rdf);
++	}
++	(void)ldns_rdf2buffer_wire(data_buffer, time_signed_rdf);
++	(void)ldns_rdf2buffer_wire(data_buffer, fudge_rdf);
++	if (!tsig_timers_only) {
++		(void)ldns_rdf2buffer_wire(data_buffer, error_rdf);
++		(void)ldns_rdf2buffer_wire(data_buffer, other_data_rdf);
++	}
++
++	wireformat = (char *) data_buffer->_data;
++	wiresize = (int) ldns_buffer_position(data_buffer);
++
++	algorithm_name = ldns_rdf2str(algorithm_rdf);
++	if(!algorithm_name) {
++		status = LDNS_STATUS_MEM_ERR;
++		goto clean;
++	}
++
++	/* prepare the key */
++	key_bytes = LDNS_XMALLOC(unsigned char,
++			ldns_b64_pton_calculate_size(strlen(key_data)));
++	if(!key_bytes) {
++		status = LDNS_STATUS_MEM_ERR;
++		goto clean;
++	}
++	key_size = ldns_b64_pton(key_data, key_bytes,
++	ldns_b64_pton_calculate_size(strlen(key_data)));
++	if (key_size < 0) {
++		status = LDNS_STATUS_INVALID_B64;
++		goto clean;
++	}
++	/* hmac it */
++	/* 2 spare bytes for the length */
++	mac_bytes = LDNS_XMALLOC(unsigned char, md_len+2);
++	if(!mac_bytes) {
++		status = LDNS_STATUS_MEM_ERR;
++		goto clean;
++	}
++	memset(mac_bytes, 0, md_len+2);
++
++	digester = ldns_digest_function(algorithm_name);
++
++	if (digester) {
++		(void) HMAC(digester, key_bytes, key_size, (void *)wireformat,
++		            (size_t) wiresize, mac_bytes + 2, &md_len);
++
++		ldns_write_uint16(mac_bytes, md_len);
++		result = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_INT16_DATA, md_len + 2,
++				mac_bytes);
++	} else {
++		status = LDNS_STATUS_CRYPTO_UNKNOWN_ALGO;
++		goto clean;
++	}
++	*tsig_mac = result;
++	status = LDNS_STATUS_OK;
++  clean:
++	LDNS_FREE(mac_bytes);
++	LDNS_FREE(key_bytes);
++	LDNS_FREE(algorithm_name);
++	ldns_buffer_free(data_buffer);
++	ldns_rdf_deep_free(canonical_algorithm_rdf);
++	ldns_rdf_deep_free(canonical_key_name_rdf);
++	return status;
++}
++#endif /*  HAVE_SSL */
++
++
++#ifdef HAVE_SSL
++bool
++ldns_pkt_tsig_verify(ldns_pkt *pkt, uint8_t *wire, size_t wirelen, const char *key_name,
++	const char *key_data, ldns_rdf *orig_mac_rdf)
++{
++	return ldns_pkt_tsig_verify_next(pkt, wire, wirelen, key_name, key_data, orig_mac_rdf, 0);
++}
++
++bool
++ldns_pkt_tsig_verify_next(ldns_pkt *pkt, uint8_t *wire, size_t wirelen, const char* key_name,
++	const char *key_data, ldns_rdf *orig_mac_rdf, int tsig_timers_only)
++{
++	ldns_rdf *fudge_rdf;
++	ldns_rdf *algorithm_rdf;
++	ldns_rdf *time_signed_rdf;
++	ldns_rdf *orig_id_rdf;
++	ldns_rdf *error_rdf;
++	ldns_rdf *other_data_rdf;
++	ldns_rdf *pkt_mac_rdf;
++	ldns_rdf *my_mac_rdf;
++	ldns_rdf *key_name_rdf = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, key_name);
++	uint16_t pkt_id, orig_pkt_id;
++	ldns_status status;
++
++	uint8_t *prepared_wire = NULL;
++	size_t prepared_wire_size = 0;
++
++	ldns_rr *orig_tsig = ldns_pkt_tsig(pkt);
++
++	if (!orig_tsig || ldns_rr_rd_count(orig_tsig) <= 6) {
++		ldns_rdf_deep_free(key_name_rdf);
++		return false;
++	}
++	algorithm_rdf = ldns_rr_rdf(orig_tsig, 0);
++	time_signed_rdf = ldns_rr_rdf(orig_tsig, 1);
++	fudge_rdf = ldns_rr_rdf(orig_tsig, 2);
++	pkt_mac_rdf = ldns_rr_rdf(orig_tsig, 3);
++	orig_id_rdf = ldns_rr_rdf(orig_tsig, 4);
++	error_rdf = ldns_rr_rdf(orig_tsig, 5);
++	other_data_rdf = ldns_rr_rdf(orig_tsig, 6);
++
++	/* remove temporarily */
++	ldns_pkt_set_tsig(pkt, NULL);
++	/* temporarily change the id to the original id */
++	pkt_id = ldns_pkt_id(pkt);
++	orig_pkt_id = ldns_rdf2native_int16(orig_id_rdf);
++	ldns_pkt_set_id(pkt, orig_pkt_id);
++
++	prepared_wire = ldns_tsig_prepare_pkt_wire(wire, wirelen, &prepared_wire_size);
++
++	status = ldns_tsig_mac_new(&my_mac_rdf, prepared_wire, prepared_wire_size,
++			key_data, key_name_rdf, fudge_rdf, algorithm_rdf,
++			time_signed_rdf, error_rdf, other_data_rdf, orig_mac_rdf, tsig_timers_only);
++
++	LDNS_FREE(prepared_wire);
++
++	if (status != LDNS_STATUS_OK) {
++		ldns_rdf_deep_free(key_name_rdf);
++		return false;
++	}
++	/* Put back the values */
++	ldns_pkt_set_tsig(pkt, orig_tsig);
++	ldns_pkt_set_id(pkt, pkt_id);
++
++	ldns_rdf_deep_free(key_name_rdf);
++
++	if (ldns_rdf_compare(pkt_mac_rdf, my_mac_rdf) == 0) {
++		ldns_rdf_deep_free(my_mac_rdf);
++		return true;
++	} else {
++		ldns_rdf_deep_free(my_mac_rdf);
++		return false;
++	}
++}
++#endif /* HAVE_SSL */
++
++#ifdef HAVE_SSL
++ldns_status
++ldns_pkt_tsig_sign(ldns_pkt *pkt, const char *key_name, const char *key_data,
++	uint16_t fudge, const char *algorithm_name, ldns_rdf *query_mac)
++{
++	return ldns_pkt_tsig_sign_next(pkt, key_name, key_data, fudge, algorithm_name, query_mac, 0);
++}
++
++ldns_status
++ldns_pkt_tsig_sign_next(ldns_pkt *pkt, const char *key_name, const char *key_data,
++	uint16_t fudge, const char *algorithm_name, ldns_rdf *query_mac, int tsig_timers_only)
++{
++	ldns_rr *tsig_rr;
++	ldns_rdf *key_name_rdf = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, key_name);
++	ldns_rdf *fudge_rdf = NULL;
++	ldns_rdf *orig_id_rdf = NULL;
++	ldns_rdf *algorithm_rdf;
++	ldns_rdf *error_rdf = NULL;
++	ldns_rdf *mac_rdf = NULL;
++	ldns_rdf *other_data_rdf = NULL;
++
++	ldns_status status = LDNS_STATUS_OK;
++
++	uint8_t *pkt_wire = NULL;
++	size_t pkt_wire_len;
++
++	struct timeval tv_time_signed;
++	uint8_t *time_signed = NULL;
++	ldns_rdf *time_signed_rdf = NULL;
++
++	algorithm_rdf = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, algorithm_name);
++	if(!key_name_rdf || !algorithm_rdf) {
++		status = LDNS_STATUS_MEM_ERR;
++		goto clean;
++	}
++
++	/* eww don't have create tsigtime rdf yet :( */
++	/* bleh :p */
++	if (gettimeofday(&tv_time_signed, NULL) == 0) {
++		time_signed = LDNS_XMALLOC(uint8_t, 6);
++		if(!time_signed) {
++			status = LDNS_STATUS_MEM_ERR;
++			goto clean;
++		}
++		ldns_write_uint64_as_uint48(time_signed,
++				(uint64_t)tv_time_signed.tv_sec);
++	} else {
++		status = LDNS_STATUS_INTERNAL_ERR;
++		goto clean;
++	}
++
++	time_signed_rdf = ldns_rdf_new(LDNS_RDF_TYPE_TSIGTIME, 6, time_signed);
++	if(!time_signed_rdf) {
++		LDNS_FREE(time_signed);
++		status = LDNS_STATUS_MEM_ERR;
++		goto clean;
++	}
++
++	fudge_rdf = ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16, fudge);
++
++	orig_id_rdf = ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16, ldns_pkt_id(pkt));
++
++	error_rdf = ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16, 0);
++
++	other_data_rdf = ldns_native2rdf_int16_data(0, NULL);
++
++	if(!fudge_rdf || !orig_id_rdf || !error_rdf || !other_data_rdf) {
++		status = LDNS_STATUS_MEM_ERR;
++		goto clean;
++	}
++
++	if (ldns_pkt2wire(&pkt_wire, pkt, &pkt_wire_len) != LDNS_STATUS_OK) {
++		status = LDNS_STATUS_ERR;
++		goto clean;
++	}
++
++	status = ldns_tsig_mac_new(&mac_rdf, pkt_wire, pkt_wire_len,
++			key_data, key_name_rdf, fudge_rdf, algorithm_rdf,
++			time_signed_rdf, error_rdf, other_data_rdf, query_mac, tsig_timers_only);
++
++	if (!mac_rdf) {
++		goto clean;
++	}
++
++	LDNS_FREE(pkt_wire);
++
++	/* Create the TSIG RR */
++	tsig_rr = ldns_rr_new();
++	if(!tsig_rr) {
++		status = LDNS_STATUS_MEM_ERR;
++		goto clean;
++	}
++	ldns_rr_set_owner(tsig_rr, key_name_rdf);
++	ldns_rr_set_class(tsig_rr, LDNS_RR_CLASS_ANY);
++	ldns_rr_set_type(tsig_rr, LDNS_RR_TYPE_TSIG);
++	ldns_rr_set_ttl(tsig_rr, 0);
++
++	ldns_rr_push_rdf(tsig_rr, algorithm_rdf);
++	ldns_rr_push_rdf(tsig_rr, time_signed_rdf);
++	ldns_rr_push_rdf(tsig_rr, fudge_rdf);
++	ldns_rr_push_rdf(tsig_rr, mac_rdf);
++	ldns_rr_push_rdf(tsig_rr, orig_id_rdf);
++	ldns_rr_push_rdf(tsig_rr, error_rdf);
++	ldns_rr_push_rdf(tsig_rr, other_data_rdf);
++
++	ldns_pkt_set_tsig(pkt, tsig_rr);
++
++	return status;
++
++  clean:
++	LDNS_FREE(pkt_wire);
++	ldns_rdf_free(key_name_rdf);
++	ldns_rdf_free(algorithm_rdf);
++	ldns_rdf_free(time_signed_rdf);
++	ldns_rdf_free(fudge_rdf);
++	ldns_rdf_free(orig_id_rdf);
++	ldns_rdf_free(error_rdf);
++	ldns_rdf_free(other_data_rdf);
++	return status;
++}
++#endif /* HAVE_SSL */
+diff --git a/ldns/src/update.c b/ldns/src/update.c
+new file mode 100644
+index 0000000..74e9d19
+--- /dev/null
++++ b/ldns/src/update.c
+@@ -0,0 +1,325 @@
++/* update.c
++ *
++ * Functions for RFC 2136 Dynamic Update
++ *
++ * Copyright (c) 2005-2008, NLnet Labs. All rights reserved.
++ *
++ * See LICENSE for the license.
++ */
++
++#include <ldns/config.h>
++
++#include <ldns/ldns.h>
++
++#include <strings.h>
++#include <stdlib.h>
++#include <limits.h>
++
++/*
++ * RFC 2136 sections mapped to RFC 1035:
++ *              zone/ZO -- QD/question
++ *     prerequisites/PR -- AN/answers
++ *           updates/UP -- NS/authority records
++ *   additional data/AD -- AR/additional records
++ */
++
++ldns_pkt *
++ldns_update_pkt_new(ldns_rdf *zone_rdf, ldns_rr_class c,
++    ldns_rr_list *pr_rrlist, ldns_rr_list *up_rrlist, ldns_rr_list *ad_rrlist)
++{
++	ldns_pkt *p;
++
++	if (!zone_rdf || !up_rrlist) {
++		return NULL;
++	}
++
++	if (c == 0) { 
++		c = LDNS_RR_CLASS_IN;
++	}
++
++	/* Create packet, fill in Zone Section. */
++	p = ldns_pkt_query_new(zone_rdf, LDNS_RR_TYPE_SOA, c, LDNS_RD);
++	if (!p) {
++		return NULL;
++	}
++	zone_rdf = NULL; /* No longer safe to use. */
++
++	ldns_pkt_set_opcode(p, LDNS_PACKET_UPDATE);
++
++	ldns_rr_list_deep_free(p->_authority);
++
++	ldns_pkt_set_authority(p, ldns_rr_list_clone(up_rrlist));
++
++	ldns_update_set_upcount(p, ldns_rr_list_rr_count(up_rrlist));
++
++	if (pr_rrlist) {
++		ldns_rr_list_deep_free(p->_answer); /*XXX access function */
++		ldns_pkt_set_answer(p, ldns_rr_list_clone(pr_rrlist));
++		ldns_update_set_prcount(p, ldns_rr_list_rr_count(pr_rrlist));
++	}
++
++	if (ad_rrlist) {
++		ldns_rr_list_deep_free(p->_additional);
++		ldns_pkt_set_additional(p, ldns_rr_list_clone(ad_rrlist));
++		ldns_update_set_adcount(p, ldns_rr_list_rr_count(ad_rrlist));
++	}
++	return p;
++}
++
++ldns_status
++ldns_update_pkt_tsig_add(ldns_pkt *p, ldns_resolver *r)
++{
++#ifdef HAVE_SSL
++	uint16_t fudge = 300; /* Recommended fudge. [RFC2845 6.4]  */
++	if (ldns_resolver_tsig_keyname(r) && ldns_resolver_tsig_keydata(r))
++		return ldns_pkt_tsig_sign(p, ldns_resolver_tsig_keyname(r),
++		    ldns_resolver_tsig_keydata(r), fudge,
++		    ldns_resolver_tsig_algorithm(r), NULL);
++#else
++	/* do nothing */
++	(void)p;
++	(void)r;
++#endif /* HAVE_SSL */
++	/* No TSIG to do. */
++	return LDNS_STATUS_OK;
++}
++
++/* Move to higher.c or similar? */
++/* XXX doc */
++ldns_status
++ldns_update_soa_mname(ldns_rdf *zone, ldns_resolver *r,
++    ldns_rr_class c, ldns_rdf **mname)
++{
++	ldns_rr		*soa_rr;
++	ldns_pkt	*query, *resp;
++
++	/* Nondestructive, so clone 'zone' here */
++	query = ldns_pkt_query_new(ldns_rdf_clone(zone), LDNS_RR_TYPE_SOA,
++	    c, LDNS_RD);
++	if (!query) {
++		return LDNS_STATUS_ERR;
++	}
++
++	ldns_pkt_set_random_id(query);
++	if (ldns_resolver_send_pkt(&resp, r, query) != LDNS_STATUS_OK) {
++		ldns_pkt_free(query);
++		return LDNS_STATUS_ERR;
++	}
++	ldns_pkt_free(query);
++	if (!resp) {
++		return LDNS_STATUS_ERR;
++	}
++
++	/* Expect a SOA answer. */
++	*mname = NULL;
++	while ((soa_rr = ldns_rr_list_pop_rr(ldns_pkt_answer(resp)))) {
++		if (ldns_rr_get_type(soa_rr) != LDNS_RR_TYPE_SOA
++				|| ldns_rr_rdf(soa_rr, 0) == NULL)
++			continue;
++		/* [RFC1035 3.3.13] */
++		*mname = ldns_rdf_clone(ldns_rr_rdf(soa_rr, 0));
++		break;
++	}
++	ldns_pkt_free(resp);
++
++	return *mname ? LDNS_STATUS_OK : LDNS_STATUS_ERR;
++}
++
++/* Try to get zone and MNAME from SOA queries. */
++ldns_status
++ldns_update_soa_zone_mname(const char *fqdn, ldns_resolver *r,
++    ldns_rr_class c, ldns_rdf **zone_rdf, ldns_rdf **mname_rdf)
++{
++	ldns_rr		*soa_rr, *rr;
++	ldns_rdf	*soa_zone = NULL, *soa_mname = NULL;
++	ldns_rdf	*ipaddr, *fqdn_rdf, *tmp;
++	ldns_rdf	**nslist;
++	ldns_pkt	*query, *resp;
++	ldns_resolver   *tmp_r;
++	size_t		i;
++
++	/* 
++	 * XXX Ok, this cannot be the best way to find this...?
++	 * XXX (I run into weird cache-related stuff here)
++	 */
++
++	/* Step 1 - first find a nameserver that should know *something* */
++	fqdn_rdf = ldns_dname_new_frm_str(fqdn);
++	query = ldns_pkt_query_new(fqdn_rdf, LDNS_RR_TYPE_SOA, c, LDNS_RD);
++	if (!query) {
++		return LDNS_STATUS_ERR;
++	}
++	fqdn_rdf = NULL;
++
++	ldns_pkt_set_random_id(query);
++	if (ldns_resolver_send_pkt(&resp, r, query) != LDNS_STATUS_OK) {
++		ldns_pkt_free(query);
++		return LDNS_STATUS_ERR;
++	}
++	ldns_pkt_free(query);
++	if (!resp) {
++		return LDNS_STATUS_ERR;
++	}
++
++	/* XXX Is it safe to only look in authority section here? */
++	while ((soa_rr = ldns_rr_list_pop_rr(ldns_pkt_authority(resp)))) {
++		if (ldns_rr_get_type(soa_rr) != LDNS_RR_TYPE_SOA
++				|| ldns_rr_rdf(soa_rr, 0) == NULL)
++			continue;
++		/* [RFC1035 3.3.13] */
++		soa_mname = ldns_rdf_clone(ldns_rr_rdf(soa_rr, 0));
++		break;
++	}
++	ldns_pkt_free(resp);
++	if (!soa_rr) {
++		return LDNS_STATUS_ERR;
++	}
++
++	/* Step 2 - find SOA MNAME IP address, add to resolver */
++	query = ldns_pkt_query_new(soa_mname, LDNS_RR_TYPE_A, c, LDNS_RD);
++	if (!query) {
++		return LDNS_STATUS_ERR;
++	}
++	soa_mname = NULL;
++
++	ldns_pkt_set_random_id(query);
++	if (ldns_resolver_send_pkt(&resp, r, query) != LDNS_STATUS_OK) {
++		ldns_pkt_free(query);
++		return LDNS_STATUS_ERR;
++	}
++	ldns_pkt_free(query);
++	if (!resp) {
++		return LDNS_STATUS_ERR;
++	}
++
++	if (ldns_pkt_ancount(resp) == 0) {
++		ldns_pkt_free(resp);
++		return LDNS_STATUS_ERR;
++	}
++
++	/* XXX There may be more than one answer RR here. */
++	rr = ldns_rr_list_pop_rr(ldns_pkt_answer(resp));
++	ipaddr = ldns_rr_rdf(rr, 0);
++
++	/* Put the SOA mname IP first in the nameserver list. */
++	if (!(tmp_r = ldns_resolver_clone(r))) {
++		return LDNS_STATUS_MEM_ERR;
++	}
++	nslist = ldns_resolver_nameservers(tmp_r);
++	for (i = 0; i < ldns_resolver_nameserver_count(tmp_r); i++) {
++		if (ldns_rdf_compare(ipaddr, nslist[i]) == 0) {
++			if (i) {
++				tmp = nslist[0];
++				nslist[0] = nslist[i];
++				nslist[i] = tmp;
++			}
++			break;
++		}
++	}
++	if (i >= ldns_resolver_nameserver_count(tmp_r)) {
++		/* SOA mname was not part of the resolver so add it first. */
++		(void) ldns_resolver_push_nameserver(tmp_r, ipaddr);
++		nslist = ldns_resolver_nameservers(tmp_r);
++		i = ldns_resolver_nameserver_count(tmp_r) - 1;
++		tmp = nslist[0];
++		nslist[0] = nslist[i];
++		nslist[i] = tmp;
++	}
++	ldns_pkt_free(resp);
++
++	/* Make sure to ask the first in the list, i.e SOA mname */
++	ldns_resolver_set_random(tmp_r, false);
++
++	/* Step 3 - Redo SOA query, sending to SOA MNAME directly. */
++	fqdn_rdf = ldns_dname_new_frm_str(fqdn);
++	query = ldns_pkt_query_new(fqdn_rdf, LDNS_RR_TYPE_SOA, c, LDNS_RD);
++	if (!query) {
++		ldns_resolver_free(tmp_r);
++		return LDNS_STATUS_ERR;
++	}
++	fqdn_rdf = NULL;
++
++	ldns_pkt_set_random_id(query);
++	if (ldns_resolver_send_pkt(&resp, tmp_r, query) != LDNS_STATUS_OK) {
++		ldns_pkt_free(query);
++		ldns_resolver_free(tmp_r);
++		return LDNS_STATUS_ERR;
++	}
++	ldns_resolver_free(tmp_r);
++	ldns_pkt_free(query);
++	if (!resp) {
++		return LDNS_STATUS_ERR;
++	}
++
++	/* XXX Is it safe to only look in authority section here, too? */
++	while ((soa_rr = ldns_rr_list_pop_rr(ldns_pkt_authority(resp)))) {
++		if (ldns_rr_get_type(soa_rr) != LDNS_RR_TYPE_SOA
++				|| ldns_rr_rdf(soa_rr, 0) == NULL)
++			continue;
++		/* [RFC1035 3.3.13] */
++		soa_mname = ldns_rdf_clone(ldns_rr_rdf(soa_rr, 0));
++		soa_zone = ldns_rdf_clone(ldns_rr_owner(soa_rr));
++		break;
++	}
++	ldns_pkt_free(resp);
++	if (!soa_rr) {
++		return LDNS_STATUS_ERR;
++	}
++
++	/* That seems to have worked, pass results to caller. */
++	*zone_rdf = soa_zone;
++	*mname_rdf = soa_mname;
++	return LDNS_STATUS_OK;
++}	
++
++/*
++ * ldns_update_{get,set}_{zo,pr,up,ad}count
++ */
++
++uint16_t
++ldns_update_zocount(const ldns_pkt *p)
++{
++	return ldns_pkt_qdcount(p);
++}
++
++uint16_t
++ldns_update_prcount(const ldns_pkt *p)
++{
++	return ldns_pkt_ancount(p);
++}
++
++uint16_t
++ldns_update_upcount(const ldns_pkt *p)
++{
++	return ldns_pkt_nscount(p);
++}
++
++uint16_t
++ldns_update_ad(const ldns_pkt *p)
++{
++	return ldns_pkt_arcount(p);
++}
++
++void
++ldns_update_set_zo(ldns_pkt *p, uint16_t v)
++{
++	ldns_pkt_set_qdcount(p, v);
++}
++
++void
++ldns_update_set_prcount(ldns_pkt *p, uint16_t v)
++{
++	ldns_pkt_set_ancount(p, v);
++}
++
++void
++ldns_update_set_upcount(ldns_pkt *p, uint16_t v)
++{
++	ldns_pkt_set_nscount(p, v);
++}
++
++void
++ldns_update_set_adcount(ldns_pkt *p, uint16_t v)
++{
++	ldns_pkt_set_arcount(p, v);
++}
+diff --git a/ldns/src/util.c b/ldns/src/util.c
+new file mode 100644
+index 0000000..33060d9
+--- /dev/null
++++ b/ldns/src/util.c
+@@ -0,0 +1,773 @@
++/*
++ * util.c
++ *
++ * some general memory functions
++ *
++ * a Net::DNS like library for C
++ *
++ * (c) NLnet Labs, 2004-2006
++ *
++ * See the file LICENSE for the license
++ */
++
++#include <ldns/config.h>
++
++#include <ldns/rdata.h>
++#include <ldns/rr.h>
++#include <ldns/util.h>
++#include <strings.h>
++#include <stdlib.h>
++#include <stdio.h>
++#include <sys/time.h>
++#include <time.h>
++#include <ctype.h>
++
++#ifdef HAVE_SSL
++#include <openssl/rand.h>
++#endif
++
++ldns_lookup_table *
++ldns_lookup_by_name(ldns_lookup_table *table, const char *name)
++{
++	while (table->name != NULL) {
++		if (strcasecmp(name, table->name) == 0)
++			return table;
++		table++;
++	}
++	return NULL;
++}
++
++ldns_lookup_table *
++ldns_lookup_by_id(ldns_lookup_table *table, int id)
++{
++	while (table->name != NULL) {
++		if (table->id == id)
++			return table;
++		table++;
++	}
++	return NULL;
++}
++
++int
++ldns_get_bit(uint8_t bits[], size_t index)
++{
++	/*
++	 * The bits are counted from left to right, so bit #0 is the
++	 * left most bit.
++	 */
++	return (int) (bits[index / 8] & (1 << (7 - index % 8)));
++}
++
++int
++ldns_get_bit_r(uint8_t bits[], size_t index)
++{
++	/*
++	 * The bits are counted from right to left, so bit #0 is the
++	 * right most bit.
++	 */
++	return (int) bits[index / 8] & (1 << (index % 8));
++}
++
++void
++ldns_set_bit(uint8_t *byte, int bit_nr, bool value)
++{
++	/*
++	 * The bits are counted from right to left, so bit #0 is the
++	 * right most bit.
++	 */
++	if (bit_nr >= 0 && bit_nr < 8) {
++		if (value) {
++			*byte = *byte | (0x01 << bit_nr);
++		} else {
++			*byte = *byte & ~(0x01 << bit_nr);
++		}
++	}
++}
++
++int
++ldns_hexdigit_to_int(char ch)
++{
++	switch (ch) {
++	case '0': return 0;
++	case '1': return 1;
++	case '2': return 2;
++	case '3': return 3;
++	case '4': return 4;
++	case '5': return 5;
++	case '6': return 6;
++	case '7': return 7;
++	case '8': return 8;
++	case '9': return 9;
++	case 'a': case 'A': return 10;
++	case 'b': case 'B': return 11;
++	case 'c': case 'C': return 12;
++	case 'd': case 'D': return 13;
++	case 'e': case 'E': return 14;
++	case 'f': case 'F': return 15;
++	default:
++		return -1;
++	}
++}
++
++char
++ldns_int_to_hexdigit(int i)
++{
++	switch (i) {
++	case 0: return '0';
++	case 1: return '1';
++	case 2: return '2';
++	case 3: return '3';
++	case 4: return '4';
++	case 5: return '5';
++	case 6: return '6';
++	case 7: return '7';
++	case 8: return '8';
++	case 9: return '9';
++	case 10: return 'a';
++	case 11: return 'b';
++	case 12: return 'c';
++	case 13: return 'd';
++	case 14: return 'e';
++	case 15: return 'f';
++	default:
++		abort();
++	}
++}
++
++int
++ldns_hexstring_to_data(uint8_t *data, const char *str)
++{
++	size_t i;
++
++	if (!str || !data) {
++		return -1;
++	}
++
++	if (strlen(str) % 2 != 0) {
++		return -2;
++	}
++
++	for (i = 0; i < strlen(str) / 2; i++) {
++		data[i] =
++			16 * (uint8_t) ldns_hexdigit_to_int(str[i*2]) +
++			(uint8_t) ldns_hexdigit_to_int(str[i*2 + 1]);
++	}
++
++	return (int) i;
++}
++
++const char *
++ldns_version(void)
++{
++	return (char*)LDNS_VERSION;
++}
++
++/* 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
++};
++
++#define LDNS_MOD(x,y) (((x) % (y) < 0) ? ((x) % (y) + (y)) : ((x) % (y)))
++#define LDNS_DIV(x,y) (((x) % (y) < 0) ? ((x) / (y) -  1 ) : ((x) / (y)))
++
++static int
++is_leap_year(int year)
++{
++	return LDNS_MOD(year,   4) == 0 && (LDNS_MOD(year, 100) != 0 
++	    || LDNS_MOD(year, 400) == 0);
++}
++
++static int
++leap_days(int y1, int y2)
++{
++	--y1;
++	--y2;
++	return (LDNS_DIV(y2,   4) - LDNS_DIV(y1,   4)) - 
++	       (LDNS_DIV(y2, 100) - LDNS_DIV(y1, 100)) +
++	       (LDNS_DIV(y2, 400) - LDNS_DIV(y1, 400));
++}
++
++/*
++ * Code adapted from Python 2.4.1 sources (Lib/calendar.py).
++ */
++time_t
++ldns_mktime_from_utc(const struct tm *tm)
++{
++	int year = 1900 + tm->tm_year;
++	time_t days = 365 * ((time_t) 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;
++}
++
++time_t
++mktime_from_utc(const struct tm *tm)
++{
++	return ldns_mktime_from_utc(tm);
++}
++
++#if SIZEOF_TIME_T <= 4
++
++static void
++ldns_year_and_yday_from_days_since_epoch(int64_t days, struct tm *result)
++{
++	int year = 1970;
++	int new_year;
++
++	while (days < 0 || days >= (int64_t) (is_leap_year(year) ? 366 : 365)) {
++		new_year = year + (int) LDNS_DIV(days, 365);
++		days -= (new_year - year) * 365;
++		days -= leap_days(year, new_year);
++		year  = new_year;
++	}
++	result->tm_year = year;
++	result->tm_yday = (int) days;
++}
++
++/* Number of days per month in a leap year. */
++static const int leap_year_mdays[] = {
++	31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
++};
++
++static void
++ldns_mon_and_mday_from_year_and_yday(struct tm *result)
++{
++	int idays = result->tm_yday;
++	const int *mon_lengths = is_leap_year(result->tm_year) ? 
++					leap_year_mdays : mdays;
++
++	result->tm_mon = 0;
++	while  (idays >= mon_lengths[result->tm_mon]) {
++		idays -= mon_lengths[result->tm_mon++];
++	}
++	result->tm_mday = idays + 1;
++}
++
++static void
++ldns_wday_from_year_and_yday(struct tm *result)
++{
++	result->tm_wday = 4 /* 1-1-1970 was a thursday */
++			+ LDNS_MOD((result->tm_year - 1970), 7) * LDNS_MOD(365, 7)
++			+ leap_days(1970, result->tm_year)
++			+ result->tm_yday;
++	result->tm_wday = LDNS_MOD(result->tm_wday, 7);
++	if (result->tm_wday < 0) {
++		result->tm_wday += 7;
++	}
++}
++
++static struct tm *
++ldns_gmtime64_r(int64_t clock, struct tm *result)
++{
++	result->tm_isdst = 0;
++	result->tm_sec   = (int) LDNS_MOD(clock, 60);
++	clock            =       LDNS_DIV(clock, 60);
++	result->tm_min   = (int) LDNS_MOD(clock, 60);
++	clock            =       LDNS_DIV(clock, 60);
++	result->tm_hour  = (int) LDNS_MOD(clock, 24);
++	clock            =       LDNS_DIV(clock, 24);
++
++	ldns_year_and_yday_from_days_since_epoch(clock, result);
++	ldns_mon_and_mday_from_year_and_yday(result);
++	ldns_wday_from_year_and_yday(result);
++	result->tm_year -= 1900;
++
++	return result;
++}
++
++#endif /* SIZEOF_TIME_T <= 4 */
++
++static int64_t
++ldns_serial_arithmitics_time(int32_t time, time_t now)
++{
++	int32_t offset = time - (int32_t) now;
++	return (int64_t) now + offset;
++}
++
++
++struct tm *
++ldns_serial_arithmitics_gmtime_r(int32_t time, time_t now, struct tm *result)
++{
++#if SIZEOF_TIME_T <= 4
++	int64_t secs_since_epoch = ldns_serial_arithmitics_time(time, now);
++	return  ldns_gmtime64_r(secs_since_epoch, result);
++#else
++	time_t  secs_since_epoch = ldns_serial_arithmitics_time(time, now);
++	return  gmtime_r(&secs_since_epoch, result);
++#endif
++}
++
++/**
++ * Init the random source
++ * applications should call this if they need entropy data within ldns
++ * If openSSL is available, it is automatically seeded from /dev/urandom
++ * or /dev/random
++ *
++ * If you need more entropy, or have no openssl available, this function
++ * MUST be called at the start of the program
++ *
++ * If openssl *is* available, this function just adds more entropy
++ **/
++int
++ldns_init_random(FILE *fd, unsigned int size)
++{
++	/* if fp is given, seed srandom with data from file
++	   otherwise use /dev/urandom */
++	FILE *rand_f;
++	uint8_t *seed;
++	size_t read = 0;
++	unsigned int seed_i;
++	struct timeval tv;
++
++	/* we'll need at least sizeof(unsigned int) bytes for the
++	   standard prng seed */
++	if (size < (unsigned int) sizeof(seed_i)){
++		size = (unsigned int) sizeof(seed_i);
++	}
++
++	seed = LDNS_XMALLOC(uint8_t, size);
++        if(!seed) {
++		return 1;
++        }
++
++	if (!fd) {
++		if ((rand_f = fopen("/dev/urandom", "r")) == NULL) {
++			/* no readable /dev/urandom, try /dev/random */
++			if ((rand_f = fopen("/dev/random", "r")) == NULL) {
++				/* no readable /dev/random either, and no entropy
++				   source given. we'll have to improvise */
++				for (read = 0; read < size; read++) {
++					gettimeofday(&tv, NULL);
++					seed[read] = (uint8_t) (tv.tv_usec % 256);
++				}
++			} else {
++				read = fread(seed, 1, size, rand_f);
++			}
++		} else {
++			read = fread(seed, 1, size, rand_f);
++		}
++	} else {
++		rand_f = fd;
++		read = fread(seed, 1, size, rand_f);
++	}
++
++	if (read < size) {
++		LDNS_FREE(seed);
++		if (!fd) fclose(rand_f);
++		return 1;
++	} else {
++#ifdef HAVE_SSL
++		/* Seed the OpenSSL prng (most systems have it seeded
++		   automatically, in that case this call just adds entropy */
++		RAND_seed(seed, (int) size);
++#else
++		/* Seed the standard prng, only uses the first
++		 * unsigned sizeof(unsiged int) bytes found in the entropy pool
++		 */
++		memcpy(&seed_i, seed, sizeof(seed_i));
++		srandom(seed_i);
++#endif
++		LDNS_FREE(seed);
++	}
++
++	if (!fd) {
++                if (rand_f) fclose(rand_f);
++	}
++
++	return 0;
++}
++
++/**
++ * Get random number.
++ *
++ */
++uint16_t
++ldns_get_random(void)
++{
++        uint16_t rid = 0;
++#ifdef HAVE_SSL
++        if (RAND_bytes((unsigned char*)&rid, 2) != 1) {
++                rid = (uint16_t) random();
++        }
++#else
++        rid = (uint16_t) random();
++#endif
++	return rid;
++}
++
++/*
++ * BubbleBabble code taken from OpenSSH
++ * Copyright (c) 2001 Carsten Raskgaard.  All rights reserved.
++ */
++char *
++ldns_bubblebabble(uint8_t *data, size_t len)
++{
++	char vowels[] = { 'a', 'e', 'i', 'o', 'u', 'y' };
++	char consonants[] = { 'b', 'c', 'd', 'f', 'g', 'h', 'k', 'l', 'm',
++	    'n', 'p', 'r', 's', 't', 'v', 'z', 'x' };
++	size_t i, j = 0, rounds, seed = 1;
++	char *retval;
++
++	rounds = (len / 2) + 1;
++	retval = LDNS_XMALLOC(char, rounds * 6);
++	if(!retval) return NULL;
++	retval[j++] = 'x';
++	for (i = 0; i < rounds; i++) {
++		size_t idx0, idx1, idx2, idx3, idx4;
++		if ((i + 1 < rounds) || (len % 2 != 0)) {
++			idx0 = (((((size_t)(data[2 * i])) >> 6) & 3) +
++			    seed) % 6;
++			idx1 = (((size_t)(data[2 * i])) >> 2) & 15;
++			idx2 = ((((size_t)(data[2 * i])) & 3) +
++			    (seed / 6)) % 6;
++			retval[j++] = vowels[idx0];
++			retval[j++] = consonants[idx1];
++			retval[j++] = vowels[idx2];
++			if ((i + 1) < rounds) {
++				idx3 = (((size_t)(data[(2 * i) + 1])) >> 4) & 15;
++				idx4 = (((size_t)(data[(2 * i) + 1]))) & 15;
++				retval[j++] = consonants[idx3];
++				retval[j++] = '-';
++				retval[j++] = consonants[idx4];
++				seed = ((seed * 5) +
++				    ((((size_t)(data[2 * i])) * 7) +
++				    ((size_t)(data[(2 * i) + 1])))) % 36;
++			}
++		} else {
++			idx0 = seed % 6;
++			idx1 = 16;
++			idx2 = seed / 6;
++			retval[j++] = vowels[idx0];
++			retval[j++] = consonants[idx1];
++			retval[j++] = vowels[idx2];
++		}
++	}
++	retval[j++] = 'x';
++	retval[j++] = '\0';
++	return retval;
++}
++
++/*
++ * For backwards compatibility, because we have always exported this symbol.
++ */
++#ifdef HAVE_B64_NTOP
++int ldns_b64_ntop(const uint8_t* src, size_t srclength,
++		char *target, size_t targsize);
++{
++	return b64_ntop(src, srclength, target, targsize);
++}
++#endif
++
++/*
++ * For backwards compatibility, because we have always exported this symbol.
++ */
++#ifdef HAVE_B64_PTON
++int ldns_b64_pton(const char* src, uint8_t *target, size_t targsize)
++{
++	return b64_pton(src, target, targsize);
++}
++#endif
++
++
++static int
++ldns_b32_ntop_base(const uint8_t* src, size_t src_sz,
++		char* dst, size_t dst_sz,
++		bool extended_hex, bool add_padding)
++{
++	size_t ret_sz;
++	const char* b32 = extended_hex ? "0123456789abcdefghijklmnopqrstuv"
++	                               : "abcdefghijklmnopqrstuvwxyz234567";
++
++	size_t c = 0; /* c is used to carry partial base32 character over 
++	               * byte boundaries for sizes with a remainder.
++		       * (i.e. src_sz % 5 != 0)
++		       */
++
++	ret_sz = add_padding ? ldns_b32_ntop_calculate_size(src_sz)
++	                     : ldns_b32_ntop_calculate_size_no_padding(src_sz);
++	
++	/* Do we have enough space? */
++	if (dst_sz < ret_sz + 1)
++		return -1;
++
++	/* We know the size; terminate the string */
++	dst[ret_sz] = '\0';
++
++	/* First process all chunks of five */
++	while (src_sz >= 5) {
++		/* 00000... ........ ........ ........ ........ */
++		dst[0] = b32[(src[0]       ) >> 3];
++
++		/* .....111 11...... ........ ........ ........ */
++		dst[1] = b32[(src[0] & 0x07) << 2 | src[1] >> 6];
++
++		/* ........ ..22222. ........ ........ ........ */
++		dst[2] = b32[(src[1] & 0x3e) >> 1];
++
++		/* ........ .......3 3333.... ........ ........ */
++		dst[3] = b32[(src[1] & 0x01) << 4 | src[2] >> 4];
++
++		/* ........ ........ ....4444 4....... ........ */
++		dst[4] = b32[(src[2] & 0x0f) << 1 | src[3] >> 7];
++
++		/* ........ ........ ........ .55555.. ........ */
++		dst[5] = b32[(src[3] & 0x7c) >> 2];
++
++		/* ........ ........ ........ ......66 666..... */
++		dst[6] = b32[(src[3] & 0x03) << 3 | src[4] >> 5];
++
++		/* ........ ........ ........ ........ ...77777 */
++		dst[7] = b32[(src[4] & 0x1f)     ];
++
++		src_sz -= 5;
++		src    += 5;
++		dst    += 8;
++	}
++	/* Process what remains */
++	switch (src_sz) {
++	case 4: /* ........ ........ ........ ......66 666..... */
++		dst[6] = b32[(src[3] & 0x03) << 3];
++
++		/* ........ ........ ........ .55555.. ........ */
++		dst[5] = b32[(src[3] & 0x7c) >> 2];
++
++		/* ........ ........ ....4444 4....... ........ */
++		         c =  src[3]         >> 7 ;
++	case 3: dst[4] = b32[(src[2] & 0x0f) << 1 | c];
++
++		/* ........ .......3 3333.... ........ ........ */
++			 c =  src[2]         >> 4 ;
++	case 2:	dst[3] = b32[(src[1] & 0x01) << 4 | c];
++
++		/* ........ ..22222. ........ ........ ........ */
++		dst[2] = b32[(src[1] & 0x3e) >> 1];
++
++		/* .....111 11...... ........ ........ ........ */
++	                 c =  src[1]         >> 6 ;
++	case 1:	dst[1] = b32[(src[0] & 0x07) << 2 | c];
++
++		/* 00000... ........ ........ ........ ........ */
++		dst[0] = b32[ src[0]         >> 3];
++	}
++	/* Add padding */
++	if (add_padding) {
++		switch (src_sz) {
++			case 1: dst[2] = '=';
++				dst[3] = '=';
++			case 2: dst[4] = '=';
++			case 3: dst[5] = '=';
++				dst[6] = '=';
++			case 4: dst[7] = '=';
++		}
++	}
++	return (int)ret_sz;
++}
++
++int 
++ldns_b32_ntop(const uint8_t* src, size_t src_sz, char* dst, size_t dst_sz)
++{
++	return ldns_b32_ntop_base(src, src_sz, dst, dst_sz, false, true);
++}
++
++int 
++ldns_b32_ntop_extended_hex(const uint8_t* src, size_t src_sz,
++		char* dst, size_t dst_sz)
++{
++	return ldns_b32_ntop_base(src, src_sz, dst, dst_sz, true, true);
++}
++
++#ifndef HAVE_B32_NTOP
++
++int 
++b32_ntop(const uint8_t* src, size_t src_sz, char* dst, size_t dst_sz)
++{
++	return ldns_b32_ntop_base(src, src_sz, dst, dst_sz, false, true);
++}
++
++int 
++b32_ntop_extended_hex(const uint8_t* src, size_t src_sz,
++		char* dst, size_t dst_sz)
++{
++	return ldns_b32_ntop_base(src, src_sz, dst, dst_sz, true, true);
++}
++
++#endif /* ! HAVE_B32_NTOP */
++
++static int
++ldns_b32_pton_base(const char* src, size_t src_sz,
++		uint8_t* dst, size_t dst_sz,
++		bool extended_hex, bool check_padding)
++{
++	size_t i = 0;
++	char ch = '\0';
++	uint8_t buf[8];
++	uint8_t* start = dst;
++
++	while (src_sz) {
++		/* Collect 8 characters in buf (if possible) */
++		for (i = 0; i < 8; i++) {
++
++			do {
++				ch = *src++;
++				--src_sz;
++
++			} while (isspace(ch) && src_sz > 0);
++
++			if (ch == '=' || ch == '\0')
++				break;
++
++			else if (extended_hex)
++
++				if (ch >= '0' && ch <= '9')
++					buf[i] = (uint8_t)ch - '0';
++				else if (ch >= 'a' && ch <= 'v')
++					buf[i] = (uint8_t)ch - 'a' + 10;
++				else if (ch >= 'A' && ch <= 'V')
++					buf[i] = (uint8_t)ch - 'A' + 10;
++				else
++					return -1;
++
++			else if (ch >= 'a' && ch <= 'z')
++				buf[i] = (uint8_t)ch - 'a';
++			else if (ch >= 'A' && ch <= 'Z')
++				buf[i] = (uint8_t)ch - 'A';
++			else if (ch >= '2' && ch <= '7')
++				buf[i] = (uint8_t)ch - '2' + 26;
++			else
++				return -1;
++		}
++		/* Less that 8 characters. We're done. */
++		if (i < 8)
++			break;
++
++		/* Enough space available at the destination? */
++		if (dst_sz < 5)
++			return -1;
++
++		/* 00000... ........ ........ ........ ........ */
++		/* .....111 11...... ........ ........ ........ */
++		dst[0] = buf[0] << 3 | buf[1] >> 2;
++
++		/* .....111 11...... ........ ........ ........ */
++		/* ........ ..22222. ........ ........ ........ */
++		/* ........ .......3 3333.... ........ ........ */
++		dst[1] = buf[1] << 6 | buf[2] << 1 | buf[3] >> 4;
++
++		/* ........ .......3 3333.... ........ ........ */
++		/* ........ ........ ....4444 4....... ........ */
++		dst[2] = buf[3] << 4 | buf[4] >> 1;
++
++		/* ........ ........ ....4444 4....... ........ */
++		/* ........ ........ ........ .55555.. ........ */
++		/* ........ ........ ........ ......66 666..... */
++		dst[3] = buf[4] << 7 | buf[5] << 2 | buf[6] >> 3;
++
++		/* ........ ........ ........ ......66 666..... */
++		/* ........ ........ ........ ........ ...77777 */
++		dst[4] = buf[6] << 5 | buf[7];
++
++		dst += 5;
++		dst_sz -= 5;
++	}
++	/* Not ending on a eight byte boundary? */
++	if (i > 0 && i < 8) {
++
++		/* Enough space available at the destination? */
++		if (dst_sz < (i + 1) / 2)
++			return -1;
++
++		switch (i) {
++		case 7: /* ........ ........ ........ ......66 666..... */
++			/* ........ ........ ........ .55555.. ........ */
++			/* ........ ........ ....4444 4....... ........ */
++			dst[3] = buf[4] << 7 | buf[5] << 2 | buf[6] >> 3;
++
++		case 5: /* ........ ........ ....4444 4....... ........ */
++			/* ........ .......3 3333.... ........ ........ */
++			dst[2] = buf[3] << 4 | buf[4] >> 1;
++
++		case 4: /* ........ .......3 3333.... ........ ........ */
++			/* ........ ..22222. ........ ........ ........ */
++			/* .....111 11...... ........ ........ ........ */
++			dst[1] = buf[1] << 6 | buf[2] << 1 | buf[3] >> 4;
++
++		case 2: /* .....111 11...... ........ ........ ........ */
++			/* 00000... ........ ........ ........ ........ */
++			dst[0] = buf[0] << 3 | buf[1] >> 2;
++
++			break;
++
++		default:
++			return -1;
++		}
++		dst += (i + 1) / 2;
++
++		if (check_padding) {
++			/* Check remaining padding characters */
++			if (ch != '=')
++				return -1;
++
++			/* One down, 8 - i - 1 more to come... */
++			for (i = 8 - i - 1; i > 0; i--) {
++
++				do {
++					if (src_sz == 0)
++						return -1;
++					ch = *src++;
++					src_sz--;
++
++				} while (isspace(ch));
++
++				if (ch != '=')
++					return -1;
++			}
++		}
++	}
++	return dst - start;
++}
++
++int
++ldns_b32_pton(const char* src, size_t src_sz, uint8_t* dst, size_t dst_sz)
++{
++	return ldns_b32_pton_base(src, src_sz, dst, dst_sz, false, true);
++}
++
++int
++ldns_b32_pton_extended_hex(const char* src, size_t src_sz, 
++		uint8_t* dst, size_t dst_sz)
++{
++	return ldns_b32_pton_base(src, src_sz, dst, dst_sz, true, true);
++}
++
++#ifndef HAVE_B32_PTON
++
++int
++b32_pton(const char* src, size_t src_sz, uint8_t* dst, size_t dst_sz)
++{
++	return ldns_b32_pton_base(src, src_sz, dst, dst_sz, false, true);
++}
++
++int
++b32_pton_extended_hex(const char* src, size_t src_sz, 
++		uint8_t* dst, size_t dst_sz)
++{
++	return ldns_b32_pton_base(src, src_sz, dst, dst_sz, true, true);
++}
++
++#endif /* ! HAVE_B32_PTON */
++
+diff --git a/ldns/src/wire2host.c b/ldns/src/wire2host.c
+new file mode 100644
+index 0000000..e492215
+--- /dev/null
++++ b/ldns/src/wire2host.c
+@@ -0,0 +1,491 @@
++/*
++ * wire2host.c
++ *
++ * conversion routines from the wire to the host
++ * format.
++ * This will usually just a re-ordering of the
++ * data (as we store it in network format)
++ *
++ * a Net::DNS like library for C
++ *
++ * (c) NLnet Labs, 2004-2006
++ *
++ * See the file LICENSE for the license
++ */
++
++
++#include <ldns/config.h>
++
++#include <ldns/ldns.h>
++/*#include <ldns/wire2host.h>*/
++
++#include <strings.h>
++#include <limits.h>
++
++
++
++/*
++ * Set of macro's to deal with the dns message header as specified
++ * in RFC1035 in portable way.
++ *
++ */
++
++/*
++ *
++ *                                    1  1  1  1  1  1
++ *      0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
++ *    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
++ *    |                      ID                       |
++ *    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
++ *    |QR|   Opcode  |AA|TC|RD|RA| Z|AD|CD|   RCODE   |
++ *    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
++ *    |                    QDCOUNT                    |
++ *    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
++ *    |                    ANCOUNT                    |
++ *    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
++ *    |                    NSCOUNT                    |
++ *    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
++ *    |                    ARCOUNT                    |
++ *    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
++ *
++ */
++
++
++/* allocates memory to *dname! */
++ldns_status
++ldns_wire2dname(ldns_rdf **dname, const uint8_t *wire, size_t max, size_t *pos)
++{
++	uint8_t label_size;
++	uint16_t pointer_target;
++	uint8_t pointer_target_buf[2];
++	size_t dname_pos = 0;
++	size_t uncompressed_length = 0;
++	size_t compression_pos = 0;
++	uint8_t tmp_dname[LDNS_MAX_DOMAINLEN];
++	unsigned int pointer_count = 0;
++
++	if (pos == NULL) {
++		return LDNS_STATUS_WIRE_RDATA_ERR;
++	}
++	if (*pos >= max) {
++		return LDNS_STATUS_PACKET_OVERFLOW;
++	}
++	label_size = wire[*pos];
++	while (label_size > 0) {
++		/* compression */
++		while (label_size >= 192) {
++			if (compression_pos == 0) {
++				compression_pos = *pos + 2;
++			}
++
++			pointer_count++;
++
++			/* remove first two bits */
++			if (*pos + 2 > max) {
++				return LDNS_STATUS_PACKET_OVERFLOW;
++			}
++			pointer_target_buf[0] = wire[*pos] & 63;
++			pointer_target_buf[1] = wire[*pos + 1];
++			pointer_target = ldns_read_uint16(pointer_target_buf);
++
++			if (pointer_target == 0) {
++				return LDNS_STATUS_INVALID_POINTER;
++			} else if (pointer_target >= max) {
++				return LDNS_STATUS_INVALID_POINTER;
++			} else if (pointer_count > LDNS_MAX_POINTERS) {
++				return LDNS_STATUS_INVALID_POINTER;
++			}
++			*pos = pointer_target;
++			label_size = wire[*pos];
++		}
++		if(label_size == 0)
++			break; /* break from pointer to 0 byte */
++		if (label_size > LDNS_MAX_LABELLEN) {
++			return LDNS_STATUS_LABEL_OVERFLOW;
++		}
++		if (*pos + 1 + label_size > max) {
++			return LDNS_STATUS_LABEL_OVERFLOW;
++		}
++
++		/* check space for labelcount itself */
++		if (dname_pos + 1 > LDNS_MAX_DOMAINLEN) {
++			return LDNS_STATUS_DOMAINNAME_OVERFLOW;
++		}
++		tmp_dname[dname_pos] = label_size;
++		if (label_size > 0) {
++			dname_pos++;
++		}
++		*pos = *pos + 1;
++		if (dname_pos + label_size > LDNS_MAX_DOMAINLEN) {
++			return LDNS_STATUS_DOMAINNAME_OVERFLOW;
++		}
++		memcpy(&tmp_dname[dname_pos], &wire[*pos], label_size);
++		uncompressed_length += label_size + 1;
++		dname_pos += label_size;
++		*pos = *pos + label_size;
++
++		if (*pos < max) {
++			label_size = wire[*pos];
++		}
++	}
++
++	if (compression_pos > 0) {
++		*pos = compression_pos;
++	} else {
++		*pos = *pos + 1;
++	}
++
++	if (dname_pos >= LDNS_MAX_DOMAINLEN) {
++		return LDNS_STATUS_DOMAINNAME_OVERFLOW;
++	}
++
++	tmp_dname[dname_pos] = 0;
++	dname_pos++;
++
++	*dname = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_DNAME,
++			(uint16_t) dname_pos, tmp_dname);
++	if (!*dname) {
++		return LDNS_STATUS_MEM_ERR;
++	}
++	return LDNS_STATUS_OK;
++}
++
++/* maybe make this a goto error so data can be freed or something/ */
++#define LDNS_STATUS_CHECK_RETURN(st) {if (st != LDNS_STATUS_OK) { return st; }}
++#define LDNS_STATUS_CHECK_GOTO(st, label) {if (st != LDNS_STATUS_OK) { /*printf("STG %s:%d: status code %d\n", __FILE__, __LINE__, st);*/  goto label; }}
++
++ldns_status
++ldns_wire2rdf(ldns_rr *rr, const uint8_t *wire, size_t max, size_t *pos)
++{
++	size_t end;
++	size_t cur_rdf_length;
++	uint8_t rdf_index;
++	uint8_t *data;
++	uint16_t rd_length;
++	ldns_rdf *cur_rdf = NULL;
++	ldns_rdf_type cur_rdf_type;
++	const ldns_rr_descriptor *descriptor;
++	ldns_status status;
++
++	assert(rr != NULL);
++
++	descriptor = ldns_rr_descript(ldns_rr_get_type(rr));
++
++	if (*pos + 2 > max) {
++		return LDNS_STATUS_PACKET_OVERFLOW;
++	}
++
++	rd_length = ldns_read_uint16(&wire[*pos]);
++	*pos = *pos + 2;
++
++	if (*pos + rd_length > max) {
++		return LDNS_STATUS_PACKET_OVERFLOW;
++	}
++
++	end = *pos + (size_t) rd_length;
++
++	rdf_index = 0;
++	while (*pos < end &&
++			rdf_index < ldns_rr_descriptor_maximum(descriptor)) {
++
++		cur_rdf_length = 0;
++
++		cur_rdf_type = ldns_rr_descriptor_field_type(
++				descriptor, rdf_index);
++
++		/* handle special cases immediately, set length
++		   for fixed length rdata and do them below */
++		switch (cur_rdf_type) {
++		case LDNS_RDF_TYPE_DNAME:
++			status = ldns_wire2dname(&cur_rdf, wire, max, pos);
++			LDNS_STATUS_CHECK_RETURN(status);
++			break;
++		case LDNS_RDF_TYPE_CLASS:
++		case LDNS_RDF_TYPE_ALG:
++		case LDNS_RDF_TYPE_CERTIFICATE_USAGE:
++		case LDNS_RDF_TYPE_SELECTOR:
++		case LDNS_RDF_TYPE_MATCHING_TYPE:
++		case LDNS_RDF_TYPE_INT8:
++			cur_rdf_length = LDNS_RDF_SIZE_BYTE;
++			break;
++		case LDNS_RDF_TYPE_TYPE:
++		case LDNS_RDF_TYPE_INT16:
++		case LDNS_RDF_TYPE_CERT_ALG:
++			cur_rdf_length = LDNS_RDF_SIZE_WORD;
++			break;
++		case LDNS_RDF_TYPE_TIME:
++		case LDNS_RDF_TYPE_INT32:
++		case LDNS_RDF_TYPE_A:
++		case LDNS_RDF_TYPE_PERIOD:
++			cur_rdf_length = LDNS_RDF_SIZE_DOUBLEWORD;
++			break;
++		case LDNS_RDF_TYPE_TSIGTIME:
++		case LDNS_RDF_TYPE_EUI48:
++			cur_rdf_length = LDNS_RDF_SIZE_6BYTES;
++			break;
++		case LDNS_RDF_TYPE_ILNP64:
++		case LDNS_RDF_TYPE_EUI64:
++			cur_rdf_length = LDNS_RDF_SIZE_8BYTES;
++			break;
++		case LDNS_RDF_TYPE_AAAA:
++			cur_rdf_length = LDNS_RDF_SIZE_16BYTES;
++			break;
++		case LDNS_RDF_TYPE_STR:
++		case LDNS_RDF_TYPE_NSEC3_SALT:
++		case LDNS_RDF_TYPE_TAG:
++			/* len is stored in first byte
++			 * it should be in the rdf too, so just
++			 * copy len+1 from this position
++			 */
++			cur_rdf_length = ((size_t) wire[*pos]) + 1;
++			break;
++
++		case LDNS_RDF_TYPE_INT16_DATA:
++			if (*pos + 2 > end) {
++				return LDNS_STATUS_PACKET_OVERFLOW;
++			}
++			cur_rdf_length =
++				(size_t) ldns_read_uint16(&wire[*pos]) + 2;
++			break;
++		case LDNS_RDF_TYPE_HIP:
++			if (*pos + 4 > end) {
++				return LDNS_STATUS_PACKET_OVERFLOW;
++			}
++			cur_rdf_length =
++				(size_t) wire[*pos] + 
++				(size_t) ldns_read_uint16(&wire[*pos + 2]) + 4;
++			break;
++		case LDNS_RDF_TYPE_B32_EXT:
++		case LDNS_RDF_TYPE_NSEC3_NEXT_OWNER:
++			/* length is stored in first byte */
++			cur_rdf_length = ((size_t) wire[*pos]) + 1;
++			break;
++		case LDNS_RDF_TYPE_APL:
++		case LDNS_RDF_TYPE_B64:
++		case LDNS_RDF_TYPE_HEX:
++		case LDNS_RDF_TYPE_NSEC:
++		case LDNS_RDF_TYPE_UNKNOWN:
++		case LDNS_RDF_TYPE_SERVICE:
++		case LDNS_RDF_TYPE_LOC:
++		case LDNS_RDF_TYPE_WKS:
++		case LDNS_RDF_TYPE_NSAP:
++		case LDNS_RDF_TYPE_ATMA:
++		case LDNS_RDF_TYPE_IPSECKEY:
++		case LDNS_RDF_TYPE_LONG_STR:
++		case LDNS_RDF_TYPE_NONE:
++			/*
++			 * Read to end of rr rdata
++			 */
++			cur_rdf_length = end - *pos;
++			break;
++		}
++
++		/* fixed length rdata */
++		if (cur_rdf_length > 0) {
++			if (cur_rdf_length + *pos > end) {
++				return LDNS_STATUS_PACKET_OVERFLOW;
++			}
++			data = LDNS_XMALLOC(uint8_t, rd_length);
++			if (!data) {
++				return LDNS_STATUS_MEM_ERR;
++			}
++			memcpy(data, &wire[*pos], cur_rdf_length);
++
++			cur_rdf = ldns_rdf_new(cur_rdf_type,
++					cur_rdf_length, data);
++			*pos = *pos + cur_rdf_length;
++		}
++
++		if (cur_rdf) {
++			ldns_rr_push_rdf(rr, cur_rdf);
++			cur_rdf = NULL;
++		}
++
++		rdf_index++;
++
++	} /* while (rdf_index < ldns_rr_descriptor_maximum(descriptor)) */
++
++
++	return LDNS_STATUS_OK;
++}
++
++
++/* TODO:
++         can *pos be incremented at READ_INT? or maybe use something like
++         RR_CLASS(wire)?
++	 uhhm Jelte??
++*/
++ldns_status
++ldns_wire2rr(ldns_rr **rr_p, const uint8_t *wire, size_t max,
++             size_t *pos, ldns_pkt_section section)
++{
++	ldns_rdf *owner = NULL;
++	ldns_rr *rr = ldns_rr_new();
++	ldns_status status;
++
++	status = ldns_wire2dname(&owner, wire, max, pos);
++	LDNS_STATUS_CHECK_GOTO(status, status_error);
++
++	ldns_rr_set_owner(rr, owner);
++
++	if (*pos + 4 > max) {
++		status = LDNS_STATUS_PACKET_OVERFLOW;
++		goto status_error;
++	}
++
++	ldns_rr_set_type(rr, ldns_read_uint16(&wire[*pos]));
++	*pos = *pos + 2;
++
++	ldns_rr_set_class(rr, ldns_read_uint16(&wire[*pos]));
++	*pos = *pos + 2;
++
++	if (section != LDNS_SECTION_QUESTION) {
++		if (*pos + 4 > max) {
++			status = LDNS_STATUS_PACKET_OVERFLOW;
++			goto status_error;
++		}
++		ldns_rr_set_ttl(rr, ldns_read_uint32(&wire[*pos]));
++
++		*pos = *pos + 4;
++		status = ldns_wire2rdf(rr, wire, max, pos);
++
++		LDNS_STATUS_CHECK_GOTO(status, status_error);
++        ldns_rr_set_question(rr, false);
++	} else {
++        ldns_rr_set_question(rr, true);
++    }
++
++	*rr_p = rr;
++	return LDNS_STATUS_OK;
++
++status_error:
++	ldns_rr_free(rr);
++	return status;
++}
++
++static ldns_status
++ldns_wire2pkt_hdr(ldns_pkt *packet, const uint8_t *wire, size_t max, size_t *pos)
++{
++	if (*pos + LDNS_HEADER_SIZE > max) {
++		return LDNS_STATUS_WIRE_INCOMPLETE_HEADER;
++	} else {
++		ldns_pkt_set_id(packet, LDNS_ID_WIRE(wire));
++		ldns_pkt_set_qr(packet, LDNS_QR_WIRE(wire));
++		ldns_pkt_set_opcode(packet, LDNS_OPCODE_WIRE(wire));
++		ldns_pkt_set_aa(packet, LDNS_AA_WIRE(wire));
++		ldns_pkt_set_tc(packet, LDNS_TC_WIRE(wire));
++		ldns_pkt_set_rd(packet, LDNS_RD_WIRE(wire));
++		ldns_pkt_set_ra(packet, LDNS_RA_WIRE(wire));
++		ldns_pkt_set_ad(packet, LDNS_AD_WIRE(wire));
++		ldns_pkt_set_cd(packet, LDNS_CD_WIRE(wire));
++		ldns_pkt_set_rcode(packet, LDNS_RCODE_WIRE(wire));
++
++		ldns_pkt_set_qdcount(packet, LDNS_QDCOUNT(wire));
++		ldns_pkt_set_ancount(packet, LDNS_ANCOUNT(wire));
++		ldns_pkt_set_nscount(packet, LDNS_NSCOUNT(wire));
++		ldns_pkt_set_arcount(packet, LDNS_ARCOUNT(wire));
++
++		*pos += LDNS_HEADER_SIZE;
++
++		return LDNS_STATUS_OK;
++	}
++}
++
++ldns_status
++ldns_buffer2pkt_wire(ldns_pkt **packet, ldns_buffer *buffer)
++{
++	/* lazy */
++	return ldns_wire2pkt(packet, ldns_buffer_begin(buffer),
++				ldns_buffer_limit(buffer));
++
++}
++
++ldns_status
++ldns_wire2pkt(ldns_pkt **packet_p, const uint8_t *wire, size_t max)
++{
++	size_t pos = 0;
++	uint16_t i;
++	ldns_rr *rr;
++	ldns_pkt *packet = ldns_pkt_new();
++	ldns_status status = LDNS_STATUS_OK;
++	uint8_t have_edns = 0;
++
++	uint8_t data[4];
++
++	status = ldns_wire2pkt_hdr(packet, wire, max, &pos);
++	LDNS_STATUS_CHECK_GOTO(status, status_error);
++
++	for (i = 0; i < ldns_pkt_qdcount(packet); i++) {
++
++		status = ldns_wire2rr(&rr, wire, max, &pos, LDNS_SECTION_QUESTION);
++		if (status == LDNS_STATUS_PACKET_OVERFLOW) {
++			status = LDNS_STATUS_WIRE_INCOMPLETE_QUESTION;
++		}
++		LDNS_STATUS_CHECK_GOTO(status, status_error);
++		if (!ldns_rr_list_push_rr(ldns_pkt_question(packet), rr)) {
++			ldns_pkt_free(packet);
++			return LDNS_STATUS_INTERNAL_ERR;
++		}
++	}
++	for (i = 0; i < ldns_pkt_ancount(packet); i++) {
++		status = ldns_wire2rr(&rr, wire, max, &pos, LDNS_SECTION_ANSWER);
++		if (status == LDNS_STATUS_PACKET_OVERFLOW) {
++			status = LDNS_STATUS_WIRE_INCOMPLETE_ANSWER;
++		}
++		LDNS_STATUS_CHECK_GOTO(status, status_error);
++		if (!ldns_rr_list_push_rr(ldns_pkt_answer(packet), rr)) {
++			ldns_pkt_free(packet);
++			return LDNS_STATUS_INTERNAL_ERR;
++		}
++	}
++	for (i = 0; i < ldns_pkt_nscount(packet); i++) {
++		status = ldns_wire2rr(&rr, wire, max, &pos, LDNS_SECTION_AUTHORITY);
++		if (status == LDNS_STATUS_PACKET_OVERFLOW) {
++			status = LDNS_STATUS_WIRE_INCOMPLETE_AUTHORITY;
++		}
++		LDNS_STATUS_CHECK_GOTO(status, status_error);
++		if (!ldns_rr_list_push_rr(ldns_pkt_authority(packet), rr)) {
++			ldns_pkt_free(packet);
++			return LDNS_STATUS_INTERNAL_ERR;
++		}
++	}
++	for (i = 0; i < ldns_pkt_arcount(packet); i++) {
++		status = ldns_wire2rr(&rr, wire, max, &pos, LDNS_SECTION_ADDITIONAL);
++		if (status == LDNS_STATUS_PACKET_OVERFLOW) {
++			status = LDNS_STATUS_WIRE_INCOMPLETE_ADDITIONAL;
++		}
++		LDNS_STATUS_CHECK_GOTO(status, status_error);
++
++		if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_OPT) {
++			ldns_pkt_set_edns_udp_size(packet, ldns_rr_get_class(rr));
++			ldns_write_uint32(data, ldns_rr_ttl(rr));
++			ldns_pkt_set_edns_extended_rcode(packet, data[0]);
++			ldns_pkt_set_edns_version(packet, data[1]);
++			ldns_pkt_set_edns_z(packet, ldns_read_uint16(&data[2]));
++			/* edns might not have rdfs */
++			if (ldns_rr_rdf(rr, 0)) {
++				ldns_pkt_set_edns_data(packet, ldns_rdf_clone(ldns_rr_rdf(rr, 0)));
++			}
++			ldns_rr_free(rr);
++			have_edns += 1;
++		} else if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_TSIG) {
++			ldns_pkt_set_tsig(packet, rr);
++			ldns_pkt_set_arcount(packet, ldns_pkt_arcount(packet) - 1);
++		} else if (!ldns_rr_list_push_rr(ldns_pkt_additional(packet), rr)) {
++			ldns_pkt_free(packet);
++			return LDNS_STATUS_INTERNAL_ERR;
++		}
++	}
++	ldns_pkt_set_size(packet, max);
++	if(have_edns)
++		ldns_pkt_set_arcount(packet, ldns_pkt_arcount(packet)
++                        - have_edns);
++        packet->_edns_present = have_edns;
++
++	*packet_p = packet;
++	return status;
++
++status_error:
++	ldns_pkt_free(packet);
++	return status;
++}
+diff --git a/ldns/src/zone.c b/ldns/src/zone.c
+new file mode 100644
+index 0000000..d97a81e
+--- /dev/null
++++ b/ldns/src/zone.c
+@@ -0,0 +1,318 @@
++/* zone.c
++ *
++ * Functions for ldns_zone structure
++ * a Net::DNS like library for C
++ *
++ * (c) NLnet Labs, 2005-2006
++ * See the file LICENSE for the license
++ */
++#include <ldns/config.h>
++
++#include <ldns/ldns.h>
++
++#include <strings.h>
++#include <limits.h>
++
++ldns_rr *
++ldns_zone_soa(const ldns_zone *z)
++{
++        return z->_soa;
++}
++
++size_t
++ldns_zone_rr_count(const ldns_zone *z)
++{
++	return ldns_rr_list_rr_count(z->_rrs);
++}
++
++void
++ldns_zone_set_soa(ldns_zone *z, ldns_rr *soa)
++{
++	z->_soa = soa;
++}
++
++ldns_rr_list *
++ldns_zone_rrs(const ldns_zone *z)
++{
++	return z->_rrs;
++}
++
++void
++ldns_zone_set_rrs(ldns_zone *z, ldns_rr_list *rrlist)
++{
++	z->_rrs = rrlist;
++}
++
++bool
++ldns_zone_push_rr_list(ldns_zone *z, ldns_rr_list *list)
++{
++	return ldns_rr_list_cat(ldns_zone_rrs(z), list);
++
++}
++
++bool
++ldns_zone_push_rr(ldns_zone *z, ldns_rr *rr)
++{
++	return ldns_rr_list_push_rr( ldns_zone_rrs(z), rr);
++}
++
++
++/*
++ * Get the list of glue records in a zone
++ * XXX: there should be a way for this to return error, other than NULL, 
++ *      since NULL is a valid return
++ */
++ldns_rr_list *
++ldns_zone_glue_rr_list(const ldns_zone *z)
++{
++	/* when do we find glue? It means we find an IP address
++	 * (AAAA/A) for a nameserver listed in the zone
++	 *
++	 * Alg used here:
++	 * first find all the zonecuts (NS records)
++	 * find all the AAAA or A records (can be done it the 
++	 * above loop).
++	 *
++	 * Check if the aaaa/a list are subdomains under the
++	 * NS domains.
++	 * If yes -> glue, if no -> not glue
++	 */
++
++	ldns_rr_list *zone_cuts;
++	ldns_rr_list *addr;
++	ldns_rr_list *glue;
++	ldns_rr *r, *ns, *a;
++	ldns_rdf *dname_a, *ns_owner;
++	size_t i,j;
++
++	zone_cuts = NULL;
++	addr = NULL;
++	glue = NULL;
++
++	/* we cannot determine glue in a 'zone' without a SOA */
++	if (!ldns_zone_soa(z)) {
++		return NULL;
++	}
++
++	zone_cuts = ldns_rr_list_new();
++	if (!zone_cuts) goto memory_error;
++	addr = ldns_rr_list_new();
++	if (!addr) goto memory_error;
++	glue = ldns_rr_list_new();
++	if (!glue) goto memory_error;
++
++	for(i = 0; i < ldns_zone_rr_count(z); i++) {
++		r = ldns_rr_list_rr(ldns_zone_rrs(z), i);
++		if (ldns_rr_get_type(r) == LDNS_RR_TYPE_A ||
++				ldns_rr_get_type(r) == LDNS_RR_TYPE_AAAA) {
++			/* possibly glue */
++			if (!ldns_rr_list_push_rr(addr, r)) goto memory_error;
++			continue;
++		}
++		if (ldns_rr_get_type(r) == LDNS_RR_TYPE_NS) {
++			/* multiple zones will end up here -
++			 * for now; not a problem
++			 */
++			/* don't add NS records for the current zone itself */
++			if (ldns_rdf_compare(ldns_rr_owner(r), 
++						ldns_rr_owner(ldns_zone_soa(z))) != 0) {
++				if (!ldns_rr_list_push_rr(zone_cuts, r)) goto memory_error;
++			}
++			continue;
++		}
++	}
++
++	/* will sorting make it quicker ?? */
++	for(i = 0; i < ldns_rr_list_rr_count(zone_cuts); i++) {
++		ns = ldns_rr_list_rr(zone_cuts, i);
++		ns_owner = ldns_rr_owner(ns);
++
++		for(j = 0; j < ldns_rr_list_rr_count(addr); j++) {
++			a = ldns_rr_list_rr(addr, j);
++			dname_a = ldns_rr_owner(a);
++
++			if (ldns_dname_is_subdomain(dname_a, ns_owner) ||
++				ldns_dname_compare(dname_a, ns_owner) == 0) {
++				/* GLUE! */
++				if (!ldns_rr_list_push_rr(glue, a)) goto memory_error;
++			}
++		}
++	}
++	
++	ldns_rr_list_free(addr);
++	ldns_rr_list_free(zone_cuts);
++
++	if (ldns_rr_list_rr_count(glue) == 0) {
++		ldns_rr_list_free(glue);
++		return NULL;
++	} else {
++		return glue;
++	}
++
++memory_error:
++	if (zone_cuts) {
++		LDNS_FREE(zone_cuts);
++	}
++	if (addr) {
++		ldns_rr_list_free(addr);
++	}
++	if (glue) {
++		ldns_rr_list_free(glue);
++	}
++	return NULL;
++}
++
++ldns_zone *
++ldns_zone_new(void)
++{
++	ldns_zone *z;
++
++	z = LDNS_MALLOC(ldns_zone);
++	if (!z) {
++		return NULL;
++	}
++
++	z->_rrs = ldns_rr_list_new();
++	if (!z->_rrs) {
++		LDNS_FREE(z);
++		return NULL;
++	}
++	ldns_zone_set_soa(z, NULL);
++	return z;
++}
++
++/* we regocnize:
++ * $TTL, $ORIGIN
++ */
++ldns_status
++ldns_zone_new_frm_fp(ldns_zone **z, FILE *fp, ldns_rdf *origin, uint32_t ttl, ldns_rr_class c)
++{
++	return ldns_zone_new_frm_fp_l(z, fp, origin, ttl, c, NULL);
++}
++
++/* XXX: class is never used */
++ldns_status
++ldns_zone_new_frm_fp_l(ldns_zone **z, FILE *fp, ldns_rdf *origin, uint32_t ttl, 
++        ldns_rr_class ATTR_UNUSED(c), int *line_nr)
++{
++	ldns_zone *newzone;
++	ldns_rr *rr;
++	uint32_t my_ttl;
++	ldns_rdf *my_origin;
++	ldns_rdf *my_prev;
++	bool soa_seen = false; 	/* 2 soa are an error */
++	ldns_status s;
++	ldns_status ret;
++
++	/* most cases of error are memory problems */
++	ret = LDNS_STATUS_MEM_ERR;
++
++	newzone = NULL;
++	my_origin = NULL;
++	my_prev = NULL;
++
++	my_ttl    = ttl;
++	
++	if (origin) {
++		my_origin = ldns_rdf_clone(origin);
++		if (!my_origin) goto error;
++		/* also set the prev */
++		my_prev   = ldns_rdf_clone(origin);
++		if (!my_prev) goto error;
++	}
++
++	newzone = ldns_zone_new();
++	if (!newzone) goto error;
++
++	while(!feof(fp)) {
++		s = ldns_rr_new_frm_fp_l(&rr, fp, &my_ttl, &my_origin, &my_prev, line_nr);
++		switch (s) {
++		case LDNS_STATUS_OK:
++			if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_SOA) {
++				if (soa_seen) {
++					/* second SOA 
++					 * just skip, maybe we want to say
++					 * something??? */
++					ldns_rr_free(rr);
++					continue;
++				}
++				soa_seen = true;
++				ldns_zone_set_soa(newzone, rr);
++				/* set origin to soa if not specified */
++				if (!my_origin) {
++					my_origin = ldns_rdf_clone(ldns_rr_owner(rr));
++				}
++				continue;
++			}
++			
++			/* a normal RR - as sofar the DNS is normal */
++			if (!ldns_zone_push_rr(newzone, rr)) goto error;
++
++		case LDNS_STATUS_SYNTAX_EMPTY:
++			/* empty line was seen */
++		case LDNS_STATUS_SYNTAX_TTL:
++			/* the function set the ttl */
++			break;
++		case LDNS_STATUS_SYNTAX_ORIGIN:
++			/* the function set the origin */
++			break;
++		case LDNS_STATUS_SYNTAX_INCLUDE:
++			ret = LDNS_STATUS_SYNTAX_INCLUDE_ERR_NOTIMPL;
++			break;
++		default:
++			ret = s;
++			goto error;
++		}
++	}
++
++	if (my_origin) {
++		ldns_rdf_deep_free(my_origin);
++	}
++	if (my_prev) {
++		ldns_rdf_deep_free(my_prev);
++	}
++	if (z) {
++		*z = newzone;
++	} else {
++		ldns_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_zone_free(newzone);
++	}
++	return ret;
++}
++
++void
++ldns_zone_sort(ldns_zone *zone)
++{
++	ldns_rr_list *zrr;
++	assert(zone != NULL);
++
++	zrr = ldns_zone_rrs(zone);
++	ldns_rr_list_sort(zrr);
++}
++
++void
++ldns_zone_free(ldns_zone *zone) 
++{
++	ldns_rr_list_free(zone->_rrs);
++	LDNS_FREE(zone);
++}
++
++void
++ldns_zone_deep_free(ldns_zone *zone) 
++{
++	ldns_rr_free(zone->_soa);
++	ldns_rr_list_deep_free(zone->_rrs);
++	LDNS_FREE(zone);
++}
+diff --git a/src/ldns/buffer.c b/src/ldns/buffer.c
+deleted file mode 100644
+index fc6c17e..0000000
+--- a/src/ldns/buffer.c
++++ /dev/null
+@@ -1,177 +0,0 @@
+-/*
+- * buffer.c -- generic memory buffer .
+- *
+- * Copyright (c) 2001-2008, NLnet Labs. All rights reserved.
+- *
+- * See LICENSE for the license.
+- *
+- */
+-
+-#include <ldns/config.h>
+-
+-#include <ldns/ldns.h>
+-#include <ldns/buffer.h>
+-
+-ldns_buffer *
+-ldns_buffer_new(size_t capacity)
+-{
+-	ldns_buffer *buffer = LDNS_MALLOC(ldns_buffer);
+-
+-	if (!buffer) {
+-		return NULL;
+-	}
+-	
+-	buffer->_data = (uint8_t *) LDNS_XMALLOC(uint8_t, capacity);
+-	if (!buffer->_data) {
+-		LDNS_FREE(buffer);
+-		return NULL;
+-	}
+-	
+-	buffer->_position = 0;
+-	buffer->_limit = buffer->_capacity = capacity;
+-	buffer->_fixed = 0;
+-	buffer->_status = LDNS_STATUS_OK;
+-	
+-	ldns_buffer_invariant(buffer);
+-	
+-	return buffer;
+-}
+-
+-void
+-ldns_buffer_new_frm_data(ldns_buffer *buffer, void *data, size_t size)
+-{
+-	assert(data != NULL);
+-
+-	buffer->_position = 0; 
+-	buffer->_limit = buffer->_capacity = size;
+-	buffer->_fixed = 0;
+-	buffer->_data = LDNS_XMALLOC(uint8_t, size);
+-	if(!buffer->_data) {
+-		buffer->_status = LDNS_STATUS_MEM_ERR;
+-		return;
+-	}
+-	memcpy(buffer->_data, data, size);
+-	buffer->_status = LDNS_STATUS_OK;
+-	
+-	ldns_buffer_invariant(buffer);
+-}
+-
+-bool
+-ldns_buffer_set_capacity(ldns_buffer *buffer, size_t capacity)
+-{
+-	void *data;
+-	
+-	ldns_buffer_invariant(buffer);
+-	assert(buffer->_position <= capacity);
+-
+-	data = (uint8_t *) LDNS_XREALLOC(buffer->_data, uint8_t, capacity);
+-	if (!data) {
+-		buffer->_status = LDNS_STATUS_MEM_ERR;
+-		return false;
+-	} else {
+-		buffer->_data = data;
+-		buffer->_limit = buffer->_capacity = capacity;
+-		return true;
+-	}
+-}
+-
+-bool
+-ldns_buffer_reserve(ldns_buffer *buffer, size_t amount)
+-{
+-	ldns_buffer_invariant(buffer);
+-	assert(!buffer->_fixed);
+-	if (buffer->_capacity < buffer->_position + amount) {
+-		size_t new_capacity = buffer->_capacity * 3 / 2;
+-
+-		if (new_capacity < buffer->_position + amount) {
+-			new_capacity = buffer->_position + amount;
+-		}
+-		if (!ldns_buffer_set_capacity(buffer, new_capacity)) {
+-			buffer->_status = LDNS_STATUS_MEM_ERR;
+-			return false;
+-		}
+-	}
+-	buffer->_limit = buffer->_capacity;
+-	return true;
+-}
+-
+-int
+-ldns_buffer_printf(ldns_buffer *buffer, const char *format, ...)
+-{
+-	va_list args;
+-	int written = 0;
+-	size_t remaining;
+-	
+-	if (ldns_buffer_status_ok(buffer)) {
+-		ldns_buffer_invariant(buffer);
+-		assert(buffer->_limit == buffer->_capacity);
+-
+-		remaining = ldns_buffer_remaining(buffer);
+-		va_start(args, format);
+-		written = vsnprintf((char *) ldns_buffer_current(buffer), remaining,
+-				    format, args);
+-		va_end(args);
+-		if (written == -1) {
+-			buffer->_status = LDNS_STATUS_INTERNAL_ERR;
+-			return -1;
+-		} else if ((size_t) written >= remaining) {
+-			if (!ldns_buffer_reserve(buffer, (size_t) written + 1)) {
+-				buffer->_status = LDNS_STATUS_MEM_ERR;
+-				return -1;
+-			}
+-			va_start(args, format);
+-			written = vsnprintf((char *) ldns_buffer_current(buffer),
+-			    ldns_buffer_remaining(buffer), format, args);
+-			va_end(args);
+-			if (written == -1) {
+-				buffer->_status = LDNS_STATUS_INTERNAL_ERR;
+-				return -1;
+-			}
+-		}
+-		buffer->_position += written;
+-	}
+-	return written;
+-}
+-
+-void
+-ldns_buffer_free(ldns_buffer *buffer)
+-{
+-	if (!buffer) {
+-		return;
+-	}
+-
+-	if (!buffer->_fixed)
+-		LDNS_FREE(buffer->_data);
+-
+-	LDNS_FREE(buffer);
+-}
+-
+-void *
+-ldns_buffer_export(ldns_buffer *buffer)
+-{
+-	buffer->_fixed = 1;
+-	return buffer->_data;
+-}
+-
+-int
+-ldns_bgetc(ldns_buffer *buffer)
+-{
+-	if (!ldns_buffer_available_at(buffer, buffer->_position, sizeof(uint8_t))) {
+-		ldns_buffer_set_position(buffer, ldns_buffer_limit(buffer));
+-		/* ldns_buffer_rewind(buffer);*/
+-		return EOF;
+-	}
+-	return (int)ldns_buffer_read_u8(buffer);
+-}
+-
+-void 
+-ldns_buffer_copy(ldns_buffer* result, ldns_buffer* from)
+-{
+-	size_t tocopy = ldns_buffer_limit(from);
+-
+-	if(tocopy > ldns_buffer_capacity(result))
+-		tocopy = ldns_buffer_capacity(result);
+-	ldns_buffer_clear(result);
+-	ldns_buffer_write(result, ldns_buffer_begin(from), tocopy);
+-	ldns_buffer_flip(result);
+-}
+diff --git a/src/ldns/compat/b64_ntop.c b/src/ldns/compat/b64_ntop.c
+deleted file mode 100644
+index 6895aca..0000000
+--- a/src/ldns/compat/b64_ntop.c
++++ /dev/null
+@@ -1,185 +0,0 @@
+-/*
+- * Copyright (c) 1996, 1998 by Internet Software Consortium.
+- *
+- * Permission to use, copy, modify, and distribute this software for any
+- * purpose with or without fee is hereby granted, provided that the above
+- * copyright notice and this permission notice appear in all copies.
+- *
+- * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+- * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+- * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+- * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+- * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+- * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+- * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+- * SOFTWARE.
+- */
+-
+-/*
+- * Portions Copyright (c) 1995 by International Business Machines, Inc.
+- *
+- * International Business Machines, Inc. (hereinafter called IBM) grants
+- * permission under its copyrights to use, copy, modify, and distribute this
+- * Software with or without fee, provided that the above copyright notice and
+- * all paragraphs of this notice appear in all copies, and that the name of IBM
+- * not be used in connection with the marketing of any product incorporating
+- * the Software or modifications thereof, without specific, written prior
+- * permission.
+- *
+- * To the extent it has a right to do so, IBM grants an immunity from suit
+- * under its patents, if any, for the use, sale or manufacture of products to
+- * the extent that such products are used for performing Domain Name System
+- * dynamic updates in TCP/IP networks by means of the Software.  No immunity is
+- * granted for any product per se or for any other function of any product.
+- *
+- * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
+- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+- * PARTICULAR PURPOSE.  IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
+- * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
+- * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
+- * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
+- */
+-#include <ldns/config.h>
+-#include <ctype.h>
+-#include <stdlib.h>
+-#include <string.h>
+-
+-static const char Base64[] =
+-	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+-static const char Pad64 = '=';
+-
+-/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt)
+-   The following encoding technique is taken from RFC 1521 by Borenstein
+-   and Freed.  It is reproduced here in a slightly edited form for
+-   convenience.
+-
+-   A 65-character subset of US-ASCII is used, enabling 6 bits to be
+-   represented per printable character. (The extra 65th character, "=",
+-   is used to signify a special processing function.)
+-
+-   The encoding process represents 24-bit groups of input bits as output
+-   strings of 4 encoded characters. Proceeding from left to right, a
+-   24-bit input group is formed by concatenating 3 8-bit input groups.
+-   These 24 bits are then treated as 4 concatenated 6-bit groups, each
+-   of which is translated into a single digit in the base64 alphabet.
+-
+-   Each 6-bit group is used as an index into an array of 64 printable
+-   characters. The character referenced by the index is placed in the
+-   output string.
+-
+-                         Table 1: The Base64 Alphabet
+-
+-      Value Encoding  Value Encoding  Value Encoding  Value Encoding
+-          0 A            17 R            34 i            51 z
+-          1 B            18 S            35 j            52 0
+-          2 C            19 T            36 k            53 1
+-          3 D            20 U            37 l            54 2
+-          4 E            21 V            38 m            55 3
+-          5 F            22 W            39 n            56 4
+-          6 G            23 X            40 o            57 5
+-          7 H            24 Y            41 p            58 6
+-          8 I            25 Z            42 q            59 7
+-          9 J            26 a            43 r            60 8
+-         10 K            27 b            44 s            61 9
+-         11 L            28 c            45 t            62 +
+-         12 M            29 d            46 u            63 /
+-         13 N            30 e            47 v
+-         14 O            31 f            48 w         (pad) =
+-         15 P            32 g            49 x
+-         16 Q            33 h            50 y
+-
+-   Special processing is performed if fewer than 24 bits are available
+-   at the end of the data being encoded.  A full encoding quantum is
+-   always completed at the end of a quantity.  When fewer than 24 input
+-   bits are available in an input group, zero bits are added (on the
+-   right) to form an integral number of 6-bit groups.  Padding at the
+-   end of the data is performed using the '=' character.
+-
+-   Since all base64 input is an integral number of octets, only the
+-         -------------------------------------------------                       
+-   following cases can arise:
+-   
+-       (1) the final quantum of encoding input is an integral
+-           multiple of 24 bits; here, the final unit of encoded
+-	   output will be an integral multiple of 4 characters
+-	   with no "=" padding,
+-       (2) the final quantum of encoding input is exactly 8 bits;
+-           here, the final unit of encoded output will be two
+-	   characters followed by two "=" padding characters, or
+-       (3) the final quantum of encoding input is exactly 16 bits;
+-           here, the final unit of encoded output will be three
+-	   characters followed by one "=" padding character.
+-   */
+-
+-int
+-ldns_b64_ntop(uint8_t const *src, size_t srclength, char *target, size_t targsize) {
+-	size_t datalength = 0;
+-	uint8_t input[3];
+-	uint8_t output[4];
+-	size_t i;
+-	
+-	if (srclength == 0) {
+-		if (targsize > 0) {
+-			target[0] = '\0';
+-			return 0;
+-		} else {
+-			return -1;
+-		}
+-	}
+-
+-	while (2 < srclength) {
+-		input[0] = *src++;
+-		input[1] = *src++;
+-		input[2] = *src++;
+-		srclength -= 3;
+-
+-		output[0] = input[0] >> 2;
+-		output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
+-		output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
+-		output[3] = input[2] & 0x3f;
+-		assert(output[0] < 64);
+-		assert(output[1] < 64);
+-		assert(output[2] < 64);
+-		assert(output[3] < 64);
+-
+-		if (datalength + 4 > targsize) {
+-			return (-1);
+-		}
+-		target[datalength++] = Base64[output[0]];
+-		target[datalength++] = Base64[output[1]];
+-		target[datalength++] = Base64[output[2]];
+-		target[datalength++] = Base64[output[3]];
+-	}
+-    
+-	/* Now we worry about padding. */
+-	if (0 != srclength) {
+-		/* Get what's left. */
+-		input[0] = input[1] = input[2] = (uint8_t) '\0';
+-		for (i = 0; i < srclength; i++)
+-			input[i] = *src++;
+-	
+-		output[0] = input[0] >> 2;
+-		output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
+-		output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
+-		assert(output[0] < 64);
+-		assert(output[1] < 64);
+-		assert(output[2] < 64);
+-
+-		if (datalength + 4 > targsize) {
+-			return (-2);
+-		}
+-		target[datalength++] = Base64[output[0]];
+-		target[datalength++] = Base64[output[1]];
+-		if (srclength == 1) {
+-			target[datalength++] = Pad64;
+-		} else {
+-			target[datalength++] = Base64[output[2]];
+-		}
+-		target[datalength++] = Pad64;
+-	}
+-	if (datalength >= targsize) {
+-		return (-3);
+-	}
+-	target[datalength] = '\0';	/* Returned value doesn't count \0. */
+-	return (int) (datalength);
+-}
+diff --git a/src/ldns/compat/b64_pton.c b/src/ldns/compat/b64_pton.c
+deleted file mode 100644
+index 18d8c8e..0000000
+--- a/src/ldns/compat/b64_pton.c
++++ /dev/null
+@@ -1,244 +0,0 @@
+-/*
+- * Copyright (c) 1996, 1998 by Internet Software Consortium.
+- *
+- * Permission to use, copy, modify, and distribute this software for any
+- * purpose with or without fee is hereby granted, provided that the above
+- * copyright notice and this permission notice appear in all copies.
+- *
+- * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+- * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+- * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+- * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+- * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+- * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+- * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+- * SOFTWARE.
+- */
+-
+-/*
+- * Portions Copyright (c) 1995 by International Business Machines, Inc.
+- *
+- * International Business Machines, Inc. (hereinafter called IBM) grants
+- * permission under its copyrights to use, copy, modify, and distribute this
+- * Software with or without fee, provided that the above copyright notice and
+- * all paragraphs of this notice appear in all copies, and that the name of IBM
+- * not be used in connection with the marketing of any product incorporating
+- * the Software or modifications thereof, without specific, written prior
+- * permission.
+- *
+- * To the extent it has a right to do so, IBM grants an immunity from suit
+- * under its patents, if any, for the use, sale or manufacture of products to
+- * the extent that such products are used for performing Domain Name System
+- * dynamic updates in TCP/IP networks by means of the Software.  No immunity is
+- * granted for any product per se or for any other function of any product.
+- *
+- * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
+- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+- * PARTICULAR PURPOSE.  IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
+- * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
+- * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
+- * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
+- */
+-#include <ldns/config.h>
+-#include <ctype.h>
+-#include <stdlib.h>
+-#include <string.h>
+-
+-static const char Base64[] =
+-	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+-static const char Pad64 = '=';
+-
+-/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt)
+-   The following encoding technique is taken from RFC 1521 by Borenstein
+-   and Freed.  It is reproduced here in a slightly edited form for
+-   convenience.
+-
+-   A 65-character subset of US-ASCII is used, enabling 6 bits to be
+-   represented per printable character. (The extra 65th character, "=",
+-   is used to signify a special processing function.)
+-
+-   The encoding process represents 24-bit groups of input bits as output
+-   strings of 4 encoded characters. Proceeding from left to right, a
+-   24-bit input group is formed by concatenating 3 8-bit input groups.
+-   These 24 bits are then treated as 4 concatenated 6-bit groups, each
+-   of which is translated into a single digit in the base64 alphabet.
+-
+-   Each 6-bit group is used as an index into an array of 64 printable
+-   characters. The character referenced by the index is placed in the
+-   output string.
+-
+-                         Table 1: The Base64 Alphabet
+-
+-      Value Encoding  Value Encoding  Value Encoding  Value Encoding
+-          0 A            17 R            34 i            51 z
+-          1 B            18 S            35 j            52 0
+-          2 C            19 T            36 k            53 1
+-          3 D            20 U            37 l            54 2
+-          4 E            21 V            38 m            55 3
+-          5 F            22 W            39 n            56 4
+-          6 G            23 X            40 o            57 5
+-          7 H            24 Y            41 p            58 6
+-          8 I            25 Z            42 q            59 7
+-          9 J            26 a            43 r            60 8
+-         10 K            27 b            44 s            61 9
+-         11 L            28 c            45 t            62 +
+-         12 M            29 d            46 u            63 /
+-         13 N            30 e            47 v
+-         14 O            31 f            48 w         (pad) =
+-         15 P            32 g            49 x
+-         16 Q            33 h            50 y
+-
+-   Special processing is performed if fewer than 24 bits are available
+-   at the end of the data being encoded.  A full encoding quantum is
+-   always completed at the end of a quantity.  When fewer than 24 input
+-   bits are available in an input group, zero bits are added (on the
+-   right) to form an integral number of 6-bit groups.  Padding at the
+-   end of the data is performed using the '=' character.
+-
+-   Since all base64 input is an integral number of octets, only the
+-         -------------------------------------------------                       
+-   following cases can arise:
+-   
+-       (1) the final quantum of encoding input is an integral
+-           multiple of 24 bits; here, the final unit of encoded
+-	   output will be an integral multiple of 4 characters
+-	   with no "=" padding,
+-       (2) the final quantum of encoding input is exactly 8 bits;
+-           here, the final unit of encoded output will be two
+-	   characters followed by two "=" padding characters, or
+-       (3) the final quantum of encoding input is exactly 16 bits;
+-           here, the final unit of encoded output will be three
+-	   characters followed by one "=" padding character.
+-   */
+-
+-/* skips all whitespace anywhere.
+-   converts characters, four at a time, starting at (or after)
+-   src from base - 64 numbers into three 8 bit bytes in the target area.
+-   it returns the number of data bytes stored at the target, or -1 on error.
+- */
+-
+-int
+-ldns_b64_pton(char const *origsrc, uint8_t *target, size_t targsize)
+-{
+-	unsigned char const* src = (unsigned char*)origsrc;
+-	int tarindex, state, ch;
+-	char *pos;
+-
+-	state = 0;
+-	tarindex = 0;
+-
+-	if (strlen(origsrc) == 0) {
+-		return 0;
+-	}
+-
+-	while ((ch = *src++) != '\0') {
+-		if (isspace((unsigned char)ch))        /* Skip whitespace anywhere. */
+-			continue;
+-
+-		if (ch == Pad64)
+-			break;
+-
+-		pos = strchr(Base64, ch);
+-		if (pos == 0) {
+-			/* A non-base64 character. */
+-			return (-1);
+-		}
+-
+-		switch (state) {
+-		case 0:
+-			if (target) {
+-				if ((size_t)tarindex >= targsize)
+-					return (-1);
+-				target[tarindex] = (pos - Base64) << 2;
+-			}
+-			state = 1;
+-			break;
+-		case 1:
+-			if (target) {
+-				if ((size_t)tarindex + 1 >= targsize)
+-					return (-1);
+-				target[tarindex]   |=  (pos - Base64) >> 4;
+-				target[tarindex+1]  = ((pos - Base64) & 0x0f)
+-							<< 4 ;
+-			}
+-			tarindex++;
+-			state = 2;
+-			break;
+-		case 2:
+-			if (target) {
+-				if ((size_t)tarindex + 1 >= targsize)
+-					return (-1);
+-				target[tarindex]   |=  (pos - Base64) >> 2;
+-				target[tarindex+1]  = ((pos - Base64) & 0x03)
+-							<< 6;
+-			}
+-			tarindex++;
+-			state = 3;
+-			break;
+-		case 3:
+-			if (target) {
+-				if ((size_t)tarindex >= targsize)
+-					return (-1);
+-				target[tarindex] |= (pos - Base64);
+-			}
+-			tarindex++;
+-			state = 0;
+-			break;
+-		default:
+-			abort();
+-		}
+-	}
+-
+-	/*
+-	 * We are done decoding Base-64 chars.  Let's see if we ended
+-	 * on a byte boundary, and/or with erroneous trailing characters.
+-	 */
+-
+-	if (ch == Pad64) {		/* We got a pad char. */
+-		ch = *src++;		/* Skip it, get next. */
+-		switch (state) {
+-		case 0:		/* Invalid = in first position */
+-		case 1:		/* Invalid = in second position */
+-			return (-1);
+-
+-		case 2:		/* Valid, means one byte of info */
+-			/* Skip any number of spaces. */
+-			for ((void)NULL; ch != '\0'; ch = *src++)
+-				if (!isspace((unsigned char)ch))
+-					break;
+-			/* Make sure there is another trailing = sign. */
+-			if (ch != Pad64)
+-				return (-1);
+-			ch = *src++;		/* Skip the = */
+-			/* Fall through to "single trailing =" case. */
+-			/* FALLTHROUGH */
+-
+-		case 3:		/* Valid, means two bytes of info */
+-			/*
+-			 * We know this char is an =.  Is there anything but
+-			 * whitespace after it?
+-			 */
+-			for ((void)NULL; ch != '\0'; ch = *src++)
+-				if (!isspace((unsigned char)ch))
+-					return (-1);
+-
+-			/*
+-			 * Now make sure for cases 2 and 3 that the "extra"
+-			 * bits that slopped past the last full byte were
+-			 * zeros.  If we don't check them, they become a
+-			 * subliminal channel.
+-			 */
+-			if (target && target[tarindex] != 0)
+-				return (-1);
+-		}
+-	} else {
+-		/*
+-		 * We ended by seeing the end of the string.  Make sure we
+-		 * have no partial bytes lying around.
+-		 */
+-		if (state != 0)
+-			return (-1);
+-	}
+-
+-	return (tarindex);
+-}
+diff --git a/src/ldns/compat/strlcpy.c b/src/ldns/compat/strlcpy.c
+deleted file mode 100644
+index d6c34c1..0000000
+--- a/src/ldns/compat/strlcpy.c
++++ /dev/null
+@@ -1,57 +0,0 @@
+-/* from openssh 4.3p2 compat/strlcpy.c */
+-/*
+- * Copyright (c) 1998 Todd C. Miller <Todd.Miller at courtesan.com>
+- *
+- * Permission to use, copy, modify, and distribute this software for any
+- * purpose with or without fee is hereby granted, provided that the above
+- * copyright notice and this permission notice appear in all copies.
+- *
+- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+- */
+-
+-/* OPENBSD ORIGINAL: lib/libc/string/strlcpy.c */
+-
+-#include <ldns/config.h>
+-#ifndef HAVE_STRLCPY
+-
+-#include <sys/types.h>
+-#include <string.h>
+-
+-/*
+- * Copy src to string dst of size siz.  At most siz-1 characters
+- * will be copied.  Always NUL terminates (unless siz == 0).
+- * Returns strlen(src); if retval >= siz, truncation occurred.
+- */
+-size_t
+-strlcpy(char *dst, const char *src, size_t siz)
+-{
+-	char *d = dst;
+-	const char *s = src;
+-	size_t n = siz;
+-
+-	/* Copy as many bytes as will fit */
+-	if (n != 0 && --n != 0) {
+-		do {
+-			if ((*d++ = *s++) == 0)
+-				break;
+-		} while (--n != 0);
+-	}
+-
+-	/* Not enough room in dst, add NUL and traverse rest of src */
+-	if (n == 0) {
+-		if (siz != 0)
+-			*d = '\0';		/* NUL-terminate dst */
+-		while (*s++)
+-			;
+-	}
+-
+-	return(s - src - 1);	/* count does not include NUL */
+-}
+-
+-#endif /* !HAVE_STRLCPY */
+diff --git a/src/ldns/dane.c b/src/ldns/dane.c
+deleted file mode 100644
+index 675dfa8..0000000
+--- a/src/ldns/dane.c
++++ /dev/null
+@@ -1,748 +0,0 @@
+-/*
+- * Verify or create TLS authentication with DANE (RFC6698)
+- *
+- * (c) NLnetLabs 2012
+- *
+- * See the file LICENSE for the license.
+- *
+- */
+-
+-#include <ldns/config.h>
+-#ifdef USE_DANE
+-
+-#include <ldns/ldns.h>
+-#include <ldns/dane.h>
+-
+-#include <unistd.h>
+-#include <stdlib.h>
+-#include <sys/types.h>
+-#ifdef HAVE_SYS_SOCKET_H
+-#include <sys/socket.h>
+-#endif
+-#ifdef HAVE_NETDB_H
+-#include <netdb.h>
+-#endif
+-
+-#ifdef HAVE_SSL
+-#include <openssl/ssl.h>
+-#include <openssl/err.h>
+-#include <openssl/x509v3.h>
+-#endif
+-
+-ldns_status
+-ldns_dane_create_tlsa_owner(ldns_rdf** tlsa_owner, const ldns_rdf* name,
+-		uint16_t port, ldns_dane_transport transport)
+-{
+-	char buf[LDNS_MAX_DOMAINLEN];
+-	size_t s;
+-
+-	assert(tlsa_owner != NULL);
+-	assert(name != NULL);
+-	assert(ldns_rdf_get_type(name) == LDNS_RDF_TYPE_DNAME);
+-
+-	s = (size_t)snprintf(buf, LDNS_MAX_DOMAINLEN, "X_%d", (int)port);
+-	buf[0] = (char)(s - 1);
+-
+-	switch(transport) {
+-	case LDNS_DANE_TRANSPORT_TCP:
+-		s += snprintf(buf + s, LDNS_MAX_DOMAINLEN - s, "\004_tcp");
+-		break;
+-	
+-	case LDNS_DANE_TRANSPORT_UDP:
+-		s += snprintf(buf + s, LDNS_MAX_DOMAINLEN - s, "\004_udp");
+-		break;
+-
+-	case LDNS_DANE_TRANSPORT_SCTP:
+-		s += snprintf(buf + s, LDNS_MAX_DOMAINLEN - s, "\005_sctp");
+-		break;
+-	
+-	default:
+-		return LDNS_STATUS_DANE_UNKNOWN_TRANSPORT;
+-	}
+-	if (s + ldns_rdf_size(name) > LDNS_MAX_DOMAINLEN) {
+-		return LDNS_STATUS_DOMAINNAME_OVERFLOW;
+-	}
+-	memcpy(buf + s, ldns_rdf_data(name), ldns_rdf_size(name));
+-	*tlsa_owner = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_DNAME,
+-			s + ldns_rdf_size(name), buf);
+-	if (*tlsa_owner == NULL) {
+-		return LDNS_STATUS_MEM_ERR;
+-	}
+-	return LDNS_STATUS_OK;
+-}
+-
+-
+-#ifdef HAVE_SSL
+-ldns_status
+-ldns_dane_cert2rdf(ldns_rdf** rdf, X509* cert,
+-		ldns_tlsa_selector      selector,
+-		ldns_tlsa_matching_type matching_type)
+-{
+-	unsigned char* buf = NULL;
+-	size_t len;
+-
+-	X509_PUBKEY* xpubkey;
+-	EVP_PKEY* epubkey;
+-
+-	unsigned char* digest;
+-
+-	assert(rdf != NULL);
+-	assert(cert != NULL);
+-
+-	switch(selector) {
+-	case LDNS_TLSA_SELECTOR_FULL_CERTIFICATE:
+-
+-		len = (size_t)i2d_X509(cert, &buf);
+-		break;
+-
+-	case LDNS_TLSA_SELECTOR_SUBJECTPUBLICKEYINFO:
+-
+-#ifndef S_SPLINT_S
+-		xpubkey = X509_get_X509_PUBKEY(cert);
+-#endif
+-		if (! xpubkey) {
+-			return LDNS_STATUS_SSL_ERR;
+-		}
+-		epubkey = X509_PUBKEY_get(xpubkey);
+-		if (! epubkey) {
+-			return LDNS_STATUS_SSL_ERR;
+-		}
+-		len = (size_t)i2d_PUBKEY(epubkey, &buf);
+-		break;
+-	
+-	default:
+-		return LDNS_STATUS_DANE_UNKNOWN_SELECTOR;
+-	}
+-
+-	switch(matching_type) {
+-	case LDNS_TLSA_MATCHING_TYPE_NO_HASH_USED:
+-
+-		*rdf = ldns_rdf_new(LDNS_RDF_TYPE_HEX, len, buf);
+-		
+-		return *rdf ? LDNS_STATUS_OK : LDNS_STATUS_MEM_ERR;
+-		break;
+-	
+-	case LDNS_TLSA_MATCHING_TYPE_SHA256:
+-
+-		digest = LDNS_XMALLOC(unsigned char, LDNS_SHA256_DIGEST_LENGTH);
+-		if (digest == NULL) {
+-			LDNS_FREE(buf);
+-			return LDNS_STATUS_MEM_ERR;
+-		}
+-		(void) ldns_sha256(buf, (unsigned int)len, digest);
+-		*rdf = ldns_rdf_new(LDNS_RDF_TYPE_HEX, LDNS_SHA256_DIGEST_LENGTH,
+-				digest);
+-		LDNS_FREE(buf);
+-
+-		return *rdf ? LDNS_STATUS_OK : LDNS_STATUS_MEM_ERR;
+-		break;
+-
+-	case LDNS_TLSA_MATCHING_TYPE_SHA512:
+-
+-		digest = LDNS_XMALLOC(unsigned char, LDNS_SHA512_DIGEST_LENGTH);
+-		if (digest == NULL) {
+-			LDNS_FREE(buf);
+-			return LDNS_STATUS_MEM_ERR;
+-		}
+-		(void) ldns_sha512(buf, (unsigned int)len, digest);
+-		*rdf = ldns_rdf_new(LDNS_RDF_TYPE_HEX, LDNS_SHA512_DIGEST_LENGTH,
+-				digest);
+-		LDNS_FREE(buf);
+-
+-		return *rdf ? LDNS_STATUS_OK : LDNS_STATUS_MEM_ERR;
+-		break;
+-	
+-	default:
+-		LDNS_FREE(buf);
+-		return LDNS_STATUS_DANE_UNKNOWN_MATCHING_TYPE;
+-	}
+-}
+-
+-
+-/* Ordinary PKIX validation of cert (with extra_certs to help)
+- * against the CA's in store
+- */
+-static ldns_status
+-ldns_dane_pkix_validate(X509* cert, STACK_OF(X509)* extra_certs,
+-		X509_STORE* store)
+-{
+-	X509_STORE_CTX* vrfy_ctx;
+-	ldns_status s;
+-
+-	if (! store) {
+-		return LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE;
+-	}
+-	vrfy_ctx = X509_STORE_CTX_new();
+-	if (! vrfy_ctx) {
+-
+-		return LDNS_STATUS_SSL_ERR;
+-
+-	} else if (X509_STORE_CTX_init(vrfy_ctx, store,
+-				cert, extra_certs) != 1) {
+-		s = LDNS_STATUS_SSL_ERR;
+-
+-	} else if (X509_verify_cert(vrfy_ctx) == 1) {
+-
+-		s = LDNS_STATUS_OK;
+-
+-	} else {
+-		s = LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE;
+-	}
+-	X509_STORE_CTX_free(vrfy_ctx);
+-	return s;
+-}
+-
+-
+-/* Orinary PKIX validation of cert (with extra_certs to help)
+- * against the CA's in store, but also return the validation chain.
+- */
+-static ldns_status
+-ldns_dane_pkix_validate_and_get_chain(STACK_OF(X509)** chain, X509* cert,
+-		STACK_OF(X509)* extra_certs, X509_STORE* store)
+-{
+-	ldns_status s;
+-	X509_STORE* empty_store = NULL;
+-	X509_STORE_CTX* vrfy_ctx;
+-
+-	assert(chain != NULL);
+-
+-	if (! store) {
+-		store = empty_store = X509_STORE_new();
+-	}
+-	s = LDNS_STATUS_SSL_ERR;
+-	vrfy_ctx = X509_STORE_CTX_new();
+-	if (! vrfy_ctx) {
+-
+-		goto exit_free_empty_store;
+-
+-	} else if (X509_STORE_CTX_init(vrfy_ctx, store,
+-					cert, extra_certs) != 1) {
+-		goto exit_free_vrfy_ctx;
+-
+-	} else if (X509_verify_cert(vrfy_ctx) == 1) {
+-
+-		s = LDNS_STATUS_OK;
+-
+-	} else {
+-		s = LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE;
+-	}
+-	*chain = X509_STORE_CTX_get1_chain(vrfy_ctx);
+-	if (! *chain) {
+-		s = LDNS_STATUS_SSL_ERR;
+-	}
+-
+-exit_free_vrfy_ctx:
+-	X509_STORE_CTX_free(vrfy_ctx);
+-
+-exit_free_empty_store:
+-	if (empty_store) {
+-		X509_STORE_free(empty_store);
+-	}
+-	return s;
+-}
+-
+-
+-/* Return the validation chain that can be build out of cert, with extra_certs.
+- */
+-static ldns_status
+-ldns_dane_pkix_get_chain(STACK_OF(X509)** chain,
+-		X509* cert, STACK_OF(X509)* extra_certs)
+-{
+-	ldns_status s;
+-	X509_STORE* empty_store = NULL;
+-	X509_STORE_CTX* vrfy_ctx;
+-
+-	assert(chain != NULL);
+-
+-	empty_store = X509_STORE_new();
+-	s = LDNS_STATUS_SSL_ERR;
+-	vrfy_ctx = X509_STORE_CTX_new();
+-	if (! vrfy_ctx) {
+-
+-		goto exit_free_empty_store;
+-
+-	} else if (X509_STORE_CTX_init(vrfy_ctx, empty_store,
+-					cert, extra_certs) != 1) {
+-		goto exit_free_vrfy_ctx;
+-	}
+-	(void) X509_verify_cert(vrfy_ctx);
+-	*chain = X509_STORE_CTX_get1_chain(vrfy_ctx);
+-	if (! *chain) {
+-		s = LDNS_STATUS_SSL_ERR;
+-	} else {
+-		s = LDNS_STATUS_OK;
+-	}
+-exit_free_vrfy_ctx:
+-	X509_STORE_CTX_free(vrfy_ctx);
+-
+-exit_free_empty_store:
+-	X509_STORE_free(empty_store);
+-	return s;
+-}
+-
+-
+-/* Pop n+1 certs and return the last popped.
+- */
+-static ldns_status
+-ldns_dane_get_nth_cert_from_validation_chain(
+-		X509** cert, STACK_OF(X509)* chain, int n, bool ca)
+-{
+-	if (n >= sk_X509_num(chain) || n < 0) {
+-		return LDNS_STATUS_DANE_OFFSET_OUT_OF_RANGE;
+-	}
+-	*cert = sk_X509_pop(chain);
+-	while (n-- > 0) {
+-		X509_free(*cert);
+-		*cert = sk_X509_pop(chain);
+-	}
+-	if (ca && ! X509_check_ca(*cert)) {
+-		return LDNS_STATUS_DANE_NON_CA_CERTIFICATE;
+-	}
+-	return LDNS_STATUS_OK;
+-}
+-
+-
+-/* Create validation chain with cert and extra_certs and returns the last
+- * self-signed (if present).
+- */
+-static ldns_status
+-ldns_dane_pkix_get_last_self_signed(X509** out_cert,
+-		X509* cert, STACK_OF(X509)* extra_certs)
+-{
+-	ldns_status s;
+-	X509_STORE* empty_store = NULL;
+-	X509_STORE_CTX* vrfy_ctx;
+-
+-	assert(out_cert != NULL);
+-
+-	empty_store = X509_STORE_new();
+-	s = LDNS_STATUS_SSL_ERR;
+-	vrfy_ctx = X509_STORE_CTX_new();
+-	if (! vrfy_ctx) {
+-		goto exit_free_empty_store;
+-
+-	} else if (X509_STORE_CTX_init(vrfy_ctx, empty_store,
+-					cert, extra_certs) != 1) {
+-		goto exit_free_vrfy_ctx;
+-
+-	}
+-	(void) X509_verify_cert(vrfy_ctx);
+-	if (vrfy_ctx->error == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN ||
+-	    vrfy_ctx->error == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT){
+-
+-		*out_cert = X509_STORE_CTX_get_current_cert( vrfy_ctx);
+-		s = LDNS_STATUS_OK;
+-	} else {
+-		s = LDNS_STATUS_DANE_PKIX_NO_SELF_SIGNED_TRUST_ANCHOR;
+-	}
+-exit_free_vrfy_ctx:
+-	X509_STORE_CTX_free(vrfy_ctx);
+-
+-exit_free_empty_store:
+-	X509_STORE_free(empty_store);
+-	return s;
+-}
+-
+-
+-ldns_status
+-ldns_dane_select_certificate(X509** selected_cert,
+-		X509* cert, STACK_OF(X509)* extra_certs,
+-		X509_STORE* pkix_validation_store,
+-		ldns_tlsa_certificate_usage cert_usage, int offset)
+-{
+-	ldns_status s;
+-	STACK_OF(X509)* pkix_validation_chain = NULL;
+-
+-	assert(selected_cert != NULL);
+-	assert(cert != NULL);
+-
+-	/* With PKIX validation explicitely turned off (pkix_validation_store
+-	 *  == NULL), treat the "CA constraint" and "Service certificate
+-	 * constraint" the same as "Trust anchor assertion" and "Domain issued
+-	 * certificate" respectively.
+-	 */
+-	if (pkix_validation_store == NULL) {
+-		switch (cert_usage) {
+-
+-		case LDNS_TLSA_USAGE_CA_CONSTRAINT:
+-
+-			cert_usage = LDNS_TLSA_USAGE_TRUST_ANCHOR_ASSERTION;
+-			break;
+-
+-		case LDNS_TLSA_USAGE_SERVICE_CERTIFICATE_CONSTRAINT:
+-
+-			cert_usage = LDNS_TLSA_USAGE_DOMAIN_ISSUED_CERTIFICATE;
+-			break;
+-
+-		default:
+-			break;
+-		}
+-	}
+-
+-	/* Now what to do with each Certificate usage...
+-	 */
+-	switch (cert_usage) {
+-
+-	case LDNS_TLSA_USAGE_CA_CONSTRAINT:
+-
+-		s = ldns_dane_pkix_validate_and_get_chain(
+-				&pkix_validation_chain,
+-				cert, extra_certs,
+-				pkix_validation_store);
+-		if (! pkix_validation_chain) {
+-			return s;
+-		}
+-		if (s == LDNS_STATUS_OK) {
+-			if (offset == -1) {
+-				offset = 0;
+-			}
+-			s = ldns_dane_get_nth_cert_from_validation_chain(
+-					selected_cert, pkix_validation_chain,
+-					offset, true);
+-		}
+-		sk_X509_pop_free(pkix_validation_chain, X509_free);
+-		return s;
+-		break;
+-
+-
+-	case LDNS_TLSA_USAGE_SERVICE_CERTIFICATE_CONSTRAINT:
+-
+-		*selected_cert = cert;
+-		return ldns_dane_pkix_validate(cert, extra_certs,
+-				pkix_validation_store);
+-		break;
+-
+-
+-	case LDNS_TLSA_USAGE_TRUST_ANCHOR_ASSERTION:
+-
+-		if (offset == -1) {
+-			s = ldns_dane_pkix_get_last_self_signed(
+-					selected_cert, cert, extra_certs);
+-			return s;
+-		} else {
+-			s = ldns_dane_pkix_get_chain(
+-					&pkix_validation_chain,
+-					cert, extra_certs);
+-			if (s == LDNS_STATUS_OK) {
+-				s =
+-				ldns_dane_get_nth_cert_from_validation_chain(
+-					selected_cert, pkix_validation_chain,
+-					offset, false);
+-			} else if (! pkix_validation_chain) {
+-				return s;
+-			}
+-			sk_X509_pop_free(pkix_validation_chain, X509_free);
+-			return s;
+-		}
+-		break;
+-
+-
+-	case LDNS_TLSA_USAGE_DOMAIN_ISSUED_CERTIFICATE:
+-
+-		*selected_cert = cert;
+-		return LDNS_STATUS_OK;
+-		break;
+-	
+-	default:
+-		return LDNS_STATUS_DANE_UNKNOWN_CERTIFICATE_USAGE;
+-		break;
+-	}
+-}
+-
+-
+-ldns_status
+-ldns_dane_create_tlsa_rr(ldns_rr** tlsa,
+-		ldns_tlsa_certificate_usage certificate_usage,
+-		ldns_tlsa_selector          selector,
+-		ldns_tlsa_matching_type     matching_type,
+-		X509* cert)
+-{
+-	ldns_rdf* rdf;
+-	ldns_status s;
+-
+-	assert(tlsa != NULL);
+-	assert(cert != NULL);
+-
+-	/* create rr */
+-	*tlsa = ldns_rr_new_frm_type(LDNS_RR_TYPE_TLSA);
+-	if (*tlsa == NULL) {
+-		return LDNS_STATUS_MEM_ERR;
+-	}
+-
+-	rdf = ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8,
+-			(uint8_t)certificate_usage);
+-	if (rdf == NULL) {
+-		goto memerror;
+-	}
+-	(void) ldns_rr_set_rdf(*tlsa, rdf, 0);
+-
+-	rdf = ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8, (uint8_t)selector);
+-	if (rdf == NULL) {
+-		goto memerror;
+-	}
+-	(void) ldns_rr_set_rdf(*tlsa, rdf, 1);
+-
+-	rdf = ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8, (uint8_t)matching_type);
+-	if (rdf == NULL) {
+-		goto memerror;
+-	}
+-	(void) ldns_rr_set_rdf(*tlsa, rdf, 2);
+-
+-	s = ldns_dane_cert2rdf(&rdf, cert, selector, matching_type);
+-	if (s == LDNS_STATUS_OK) {
+-		(void) ldns_rr_set_rdf(*tlsa, rdf, 3);
+-		return LDNS_STATUS_OK;
+-	}
+-	ldns_rr_free(*tlsa);
+-	*tlsa = NULL;
+-	return s;
+-
+-memerror:
+-	ldns_rr_free(*tlsa);
+-	*tlsa = NULL;
+-	return LDNS_STATUS_MEM_ERR;
+-}
+-
+-
+-/* Return tlsas that actually are TLSA resource records with known values
+- * for the Certificate usage, Selector and Matching type rdata fields.
+- */
+-static ldns_rr_list*
+-ldns_dane_filter_unusable_records(const ldns_rr_list* tlsas)
+-{
+-	size_t i;
+-	ldns_rr_list* r = ldns_rr_list_new();
+-	ldns_rr* tlsa_rr;
+-
+-	if (! r) {
+-		return NULL;
+-	}
+-	for (i = 0; i < ldns_rr_list_rr_count(tlsas); i++) {
+-		tlsa_rr = ldns_rr_list_rr(tlsas, i);
+-		if (ldns_rr_get_type(tlsa_rr) == LDNS_RR_TYPE_TLSA &&
+-		    ldns_rr_rd_count(tlsa_rr) == 4 &&
+-		    ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr, 0)) <= 3 &&
+-		    ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr, 1)) <= 1 &&
+-		    ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr, 2)) <= 2) {
+-
+-			if (! ldns_rr_list_push_rr(r, tlsa_rr)) {
+-				ldns_rr_list_free(r);
+-				return NULL;
+-			}
+-		}
+-	}
+-	return r;
+-}
+-
+-
+-/* Return whether cert/selector/matching_type matches data.
+- */
+-static ldns_status
+-ldns_dane_match_cert_with_data(X509* cert, ldns_tlsa_selector selector,
+-		ldns_tlsa_matching_type matching_type, ldns_rdf* data)
+-{
+-	ldns_status s;
+-	ldns_rdf* match_data;
+-
+-	s = ldns_dane_cert2rdf(&match_data, cert, selector, matching_type);
+-	if (s == LDNS_STATUS_OK) {
+-		if (ldns_rdf_compare(data, match_data) != 0) {
+-			s = LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH;
+-		}
+-		ldns_rdf_free(match_data);
+-	}
+-	return s;
+-}
+-
+-
+-/* Return whether any certificate from the chain with selector/matching_type
+- * matches data.
+- * ca should be true if the certificate has to be a CA certificate too.
+- */
+-static ldns_status
+-ldns_dane_match_any_cert_with_data(STACK_OF(X509)* chain,
+-		ldns_tlsa_selector      selector,
+-		ldns_tlsa_matching_type matching_type,
+-		ldns_rdf* data, bool ca)
+-{
+-	ldns_status s = LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH;
+-	size_t n, i;
+-	X509* cert;
+-
+-	n = (size_t)sk_X509_num(chain);
+-	for (i = 0; i < n; i++) {
+-		cert = sk_X509_pop(chain);
+-		if (! cert) {
+-			s = LDNS_STATUS_SSL_ERR;
+-			break;
+-		}
+-		s = ldns_dane_match_cert_with_data(cert,
+-				selector, matching_type, data);
+-		if (ca && s == LDNS_STATUS_OK && ! X509_check_ca(cert)) {
+-			s = LDNS_STATUS_DANE_NON_CA_CERTIFICATE;
+-		}
+-		X509_free(cert);
+-		if (s != LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH) {
+-			break;
+-		}
+-		/* when s == LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH,
+-		 * try to match the next certificate
+-		 */
+-	}
+-	return s;
+-}
+-
+-
+-ldns_status
+-ldns_dane_verify_rr(const ldns_rr* tlsa_rr,
+-		X509* cert, STACK_OF(X509)* extra_certs,
+-		X509_STORE* pkix_validation_store)
+-{
+-	ldns_status s;
+-
+-	STACK_OF(X509)* pkix_validation_chain = NULL;
+-
+-	ldns_tlsa_certificate_usage cert_usage;
+-	ldns_tlsa_selector          selector;
+-	ldns_tlsa_matching_type     matching_type;
+-	ldns_rdf*                   data;
+-
+-	if (! tlsa_rr) {
+-		/* No TLSA, so regular PKIX validation
+-		 */
+-		return ldns_dane_pkix_validate(cert, extra_certs,
+-				pkix_validation_store);
+-	}
+-	cert_usage    = ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr, 0));
+-	selector      = ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr, 1));
+-	matching_type = ldns_rdf2native_int8(ldns_rr_rdf(tlsa_rr, 2));
+-	data          =                      ldns_rr_rdf(tlsa_rr, 3) ;
+-
+-	switch (cert_usage) {
+-	case LDNS_TLSA_USAGE_CA_CONSTRAINT:
+-		s = ldns_dane_pkix_validate_and_get_chain(
+-				&pkix_validation_chain, 
+-				cert, extra_certs,
+-				pkix_validation_store);
+-		if (! pkix_validation_chain) {
+-			return s;
+-		}
+-		if (s == LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE) {
+-			/*
+-			 * NO PKIX validation. We still try to match *any*
+-			 * certificate from the chain, so we return
+-			 * TLSA errors over PKIX errors.
+-			 *
+-			 * i.e. When the TLSA matches no certificate, we return
+-			 * TLSA_DID_NOT_MATCH and not PKIX_DID_NOT_VALIDATE
+-			 */
+-			s = ldns_dane_match_any_cert_with_data(
+-					pkix_validation_chain,
+-					selector, matching_type, data, true);
+-
+-			if (s == LDNS_STATUS_OK) {
+-				/* A TLSA record did match a cert from the
+-				 * chain, thus the error is failed PKIX
+-				 * validation.
+-				 */
+-				s = LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE;
+-			}
+-
+-		} else if (s == LDNS_STATUS_OK) { 
+-			/* PKIX validated, does the TLSA match too? */
+-
+-			s = ldns_dane_match_any_cert_with_data(
+-					pkix_validation_chain,
+-					selector, matching_type, data, true);
+-		}
+-		sk_X509_pop_free(pkix_validation_chain, X509_free);
+-		return s;
+-		break;
+-
+-	case LDNS_TLSA_USAGE_SERVICE_CERTIFICATE_CONSTRAINT:
+-		s = ldns_dane_match_cert_with_data(cert,
+-				selector, matching_type, data);
+-
+-		if (s == LDNS_STATUS_OK) {
+-			return ldns_dane_pkix_validate(cert, extra_certs,
+-					pkix_validation_store);
+-		}
+-		return s;
+-		break;
+-
+-	case LDNS_TLSA_USAGE_TRUST_ANCHOR_ASSERTION:
+-		s = ldns_dane_pkix_get_chain(&pkix_validation_chain,
+-				cert, extra_certs);
+-
+-		if (s == LDNS_STATUS_OK) {
+-			s = ldns_dane_match_any_cert_with_data(
+-					pkix_validation_chain,
+-					selector, matching_type, data, false);
+-
+-		} else if (! pkix_validation_chain) {
+-			return s;
+-		}
+-		sk_X509_pop_free(pkix_validation_chain, X509_free);
+-		return s;
+-		break;
+-
+-	case LDNS_TLSA_USAGE_DOMAIN_ISSUED_CERTIFICATE:
+-		return ldns_dane_match_cert_with_data(cert,
+-				selector, matching_type, data);
+-		break;
+-
+-	default:
+-		break;
+-	}
+-	return LDNS_STATUS_DANE_UNKNOWN_CERTIFICATE_USAGE;
+-}
+-
+-
+-ldns_status
+-ldns_dane_verify(ldns_rr_list* tlsas,
+-		X509* cert, STACK_OF(X509)* extra_certs,
+-		X509_STORE* pkix_validation_store)
+-{
+-	size_t i;
+-	ldns_rr* tlsa_rr;
+-	ldns_status s = LDNS_STATUS_OK, ps;
+-
+-	assert(cert != NULL);
+-
+-	if (tlsas && ldns_rr_list_rr_count(tlsas) > 0) {
+-		tlsas = ldns_dane_filter_unusable_records(tlsas);
+-		if (! tlsas) {
+-			return LDNS_STATUS_MEM_ERR;
+-		}
+-	}
+-	if (! tlsas || ldns_rr_list_rr_count(tlsas) == 0) {
+-		/* No TLSA's, so regular PKIX validation
+-		 */
+-		return ldns_dane_pkix_validate(cert, extra_certs,
+-				pkix_validation_store);
+-	} else {
+-		for (i = 0; i < ldns_rr_list_rr_count(tlsas); i++) {
+-			tlsa_rr = ldns_rr_list_rr(tlsas, i);
+-			ps = s;
+-			s = ldns_dane_verify_rr(tlsa_rr, cert, extra_certs,
+-					pkix_validation_store);
+-
+-			if (s != LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH &&
+-			    s != LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE) {
+-
+-				/* which would be LDNS_STATUS_OK (match)
+-				 * or some fatal error preventing use from
+-				 * trying the next TLSA record.
+-				 */
+-				break;
+-			}
+-			s = (s > ps ? s : ps); /* prefer PKIX_DID_NOT_VALIDATE
+-						* over   TLSA_DID_NOT_MATCH
+-						*/
+-		}
+-		ldns_rr_list_free(tlsas);
+-	}
+-	return s;
+-}
+-#endif /* HAVE_SSL */
+-#endif /* USE_DANE */
+diff --git a/src/ldns/dname.c b/src/ldns/dname.c
+deleted file mode 100644
+index 55aba5d..0000000
+--- a/src/ldns/dname.c
++++ /dev/null
+@@ -1,598 +0,0 @@
+-/*
+- * dname.c
+- *
+- * dname specific rdata implementations
+- * A dname is a rdf structure with type LDNS_RDF_TYPE_DNAME
+- * It is not a /real/ type! All function must therefor check
+- * for LDNS_RDF_TYPE_DNAME.
+- *
+- * a Net::DNS like library for C
+- *
+- * (c) NLnet Labs, 2004-2006
+- *
+- * See the file LICENSE for the license
+- */
+-
+-#include <ldns/config.h>
+-
+-#include <ldns/ldns.h>
+-
+-#ifdef HAVE_NETINET_IN_H
+-#include <netinet/in.h>
+-#endif
+-#ifdef HAVE_SYS_SOCKET_H
+-#include <sys/socket.h>
+-#endif
+-#ifdef HAVE_NETDB_H
+-#include <netdb.h>
+-#endif
+-#ifdef HAVE_ARPA_INET_H
+-#include <arpa/inet.h>
+-#endif
+-
+-/* Returns whether the last label in the name is a root label (a empty label).
+- * Note that it is not enough to just test the last character to be 0,
+- * because it may be part of the last label itself.
+- */
+-static bool
+-ldns_dname_last_label_is_root_label(const ldns_rdf* dname)
+-{
+-	size_t src_pos;
+-	size_t len = 0;
+-
+-	for (src_pos = 0; src_pos < ldns_rdf_size(dname); src_pos += len + 1) {
+-		len = ldns_rdf_data(dname)[src_pos];
+-	}
+-	assert(src_pos == ldns_rdf_size(dname));
+-
+-	return src_pos > 0 && len == 0;
+-}
+-
+-ldns_rdf *
+-ldns_dname_cat_clone(const ldns_rdf *rd1, const ldns_rdf *rd2)
+-{
+-	ldns_rdf *new;
+-	uint16_t new_size;
+-	uint8_t *buf;
+-	uint16_t left_size;
+-
+-	if (ldns_rdf_get_type(rd1) != LDNS_RDF_TYPE_DNAME ||
+-			ldns_rdf_get_type(rd2) != LDNS_RDF_TYPE_DNAME) {
+-		return NULL;
+-	}
+-
+-	/* remove root label if it is present at the end of the left
+-	 * rd, by reducing the size with 1
+-	 */
+-	left_size = ldns_rdf_size(rd1);
+-	if (ldns_dname_last_label_is_root_label(rd1)) {
+-		left_size--;
+-	}
+-
+-	/* we overwrite the nullbyte of rd1 */
+-	new_size = left_size + ldns_rdf_size(rd2);
+-	buf = LDNS_XMALLOC(uint8_t, new_size);
+-	if (!buf) {
+-		return NULL;
+-	}
+-
+-	/* put the two dname's after each other */
+-	memcpy(buf, ldns_rdf_data(rd1), left_size);
+-	memcpy(buf + left_size, ldns_rdf_data(rd2), ldns_rdf_size(rd2));
+-
+-	new = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_DNAME, new_size, buf);
+-
+-	LDNS_FREE(buf);
+-	return new;
+-}
+-
+-ldns_status
+-ldns_dname_cat(ldns_rdf *rd1, ldns_rdf *rd2)
+-{
+-	uint16_t left_size;
+-	uint16_t size;
+-	uint8_t* newd;
+-
+-	if (ldns_rdf_get_type(rd1) != LDNS_RDF_TYPE_DNAME ||
+-			ldns_rdf_get_type(rd2) != LDNS_RDF_TYPE_DNAME) {
+-		return LDNS_STATUS_ERR;
+-	}
+-
+-	/* remove root label if it is present at the end of the left
+-	 * rd, by reducing the size with 1
+-	 */
+-	left_size = ldns_rdf_size(rd1);
+-	if (ldns_dname_last_label_is_root_label(rd1)) {
+-		left_size--;
+-	}
+-
+-	size = left_size + ldns_rdf_size(rd2);
+-	newd = LDNS_XREALLOC(ldns_rdf_data(rd1), uint8_t, size);
+-	if(!newd) {
+-		return LDNS_STATUS_MEM_ERR;
+-	}
+-
+-	ldns_rdf_set_data(rd1, newd);
+-	memcpy(ldns_rdf_data(rd1) + left_size, ldns_rdf_data(rd2),
+-			ldns_rdf_size(rd2));
+-	ldns_rdf_set_size(rd1, size);
+-
+-	return LDNS_STATUS_OK;
+-}
+-
+-ldns_rdf*
+-ldns_dname_reverse(const ldns_rdf *dname)
+-{
+-	size_t rd_size;
+-	uint8_t* buf;
+-	ldns_rdf* new;
+-	size_t src_pos;
+-	size_t len ;
+-
+-	assert(ldns_rdf_get_type(dname) == LDNS_RDF_TYPE_DNAME);
+-	
+-	rd_size = ldns_rdf_size(dname);
+-	buf = LDNS_XMALLOC(uint8_t, rd_size);
+-	if (! buf) {
+-		return NULL;
+-	}
+-	new = ldns_rdf_new(LDNS_RDF_TYPE_DNAME, rd_size, buf);
+-	if (! new) {
+-		LDNS_FREE(buf);
+-		return NULL;
+-	}
+-	
+-	/* If dname ends in a root label, the reverse should too.
+-	 */
+-	if (ldns_dname_last_label_is_root_label(dname)) {
+-		buf[rd_size - 1] = 0;
+-		rd_size -= 1;
+-	}
+-	for (src_pos = 0; src_pos < rd_size; src_pos += len + 1) {
+-		len = ldns_rdf_data(dname)[src_pos];
+-		memcpy(&buf[rd_size - src_pos - len - 1],
+-				&ldns_rdf_data(dname)[src_pos], len + 1);
+-	}
+-	return new;
+-}
+-
+-ldns_rdf *
+-ldns_dname_clone_from(const ldns_rdf *d, uint16_t n)
+-{
+-	uint8_t *data;
+-	uint8_t label_size;
+-	size_t data_size;
+-
+-	if (!d ||
+-	    ldns_rdf_get_type(d) != LDNS_RDF_TYPE_DNAME ||
+-	    ldns_dname_label_count(d) < n) {
+-		return NULL;
+-	}
+-
+-	data = ldns_rdf_data(d);
+-	data_size = ldns_rdf_size(d);
+-	while (n > 0) {
+-		label_size = data[0] + 1;
+-		data += label_size;
+-		if (data_size < label_size) {
+-			/* this label is very broken */
+-			return NULL;
+-		}
+-		data_size -= label_size;
+-		n--;
+-	}
+-
+-	return ldns_dname_new_frm_data(data_size, data);
+-}
+-
+-ldns_rdf *
+-ldns_dname_left_chop(const ldns_rdf *d)
+-{
+-	uint8_t label_pos;
+-	ldns_rdf *chop;
+-
+-	if (!d) {
+-		return NULL;
+-	}
+-
+-	if (ldns_rdf_get_type(d) != LDNS_RDF_TYPE_DNAME) {
+-		return NULL;
+-	}
+-	if (ldns_dname_label_count(d) == 0) {
+-		/* root label */
+-		return NULL;
+-	}
+-	/* 05blaat02nl00 */
+-	label_pos = ldns_rdf_data(d)[0];
+-
+-	chop = ldns_dname_new_frm_data(ldns_rdf_size(d) - label_pos - 1,
+-			ldns_rdf_data(d) + label_pos + 1);
+-	return chop;
+-}
+-
+-uint8_t
+-ldns_dname_label_count(const ldns_rdf *r)
+-{
+-        uint16_t src_pos;
+-        uint16_t len;
+-        uint8_t i;
+-        size_t r_size;
+-
+-	if (!r) {
+-		return 0;
+-	}
+-
+-	i = 0;
+-	src_pos = 0;
+-	r_size = ldns_rdf_size(r);
+-
+-	if (ldns_rdf_get_type(r) != LDNS_RDF_TYPE_DNAME) {
+-		return 0;
+-	} else {
+-		len = ldns_rdf_data(r)[src_pos]; /* start of the label */
+-
+-		/* single root label */
+-		if (1 == r_size) {
+-			return 0;
+-		} else {
+-			while ((len > 0) && src_pos < r_size) {
+-				src_pos++;
+-				src_pos += len;
+-				len = ldns_rdf_data(r)[src_pos];
+-				i++;
+-			}
+-		}
+-	}
+-	return i;
+-}
+-
+-ldns_rdf *
+-ldns_dname_new(uint16_t s, void *d)
+-{
+-        ldns_rdf *rd;
+-
+-        rd = LDNS_MALLOC(ldns_rdf);
+-        if (!rd) {
+-                return NULL;
+-        }
+-        ldns_rdf_set_size(rd, s);
+-        ldns_rdf_set_type(rd, LDNS_RDF_TYPE_DNAME);
+-        ldns_rdf_set_data(rd, d);
+-        return rd;
+-}
+-
+-ldns_rdf *
+-ldns_dname_new_frm_str(const char *str)
+-{
+-	return ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, str);
+-}
+-
+-ldns_rdf *
+-ldns_dname_new_frm_data(uint16_t size, const void *data)
+-{
+-	return ldns_rdf_new_frm_data(LDNS_RDF_TYPE_DNAME, size, data);
+-}
+-
+-void
+-ldns_dname2canonical(const ldns_rdf *rd)
+-{
+-	uint8_t *rdd;
+-	uint16_t i;
+-
+-	if (ldns_rdf_get_type(rd) != LDNS_RDF_TYPE_DNAME) {
+-		return;
+-	}
+-
+-	rdd = (uint8_t*)ldns_rdf_data(rd);
+-	for (i = 0; i < ldns_rdf_size(rd); i++, rdd++) {
+-		*rdd = (uint8_t)LDNS_DNAME_NORMALIZE((int)*rdd);
+-	}
+-}
+-
+-bool
+-ldns_dname_is_subdomain(const ldns_rdf *sub, const ldns_rdf *parent)
+-{
+-	uint8_t sub_lab;
+-	uint8_t par_lab;
+-	int8_t i, j;
+-	ldns_rdf *tmp_sub = NULL;
+-	ldns_rdf *tmp_par = NULL;
+-    ldns_rdf *sub_clone;
+-    ldns_rdf *parent_clone;
+-    bool result = true;
+-
+-	if (ldns_rdf_get_type(sub) != LDNS_RDF_TYPE_DNAME ||
+-			ldns_rdf_get_type(parent) != LDNS_RDF_TYPE_DNAME ||
+-			ldns_rdf_compare(sub, parent) == 0) {
+-		return false;
+-	}
+-
+-    /* would be nicer if we do not have to clone... */
+-    sub_clone = ldns_dname_clone_from(sub, 0);
+-    parent_clone = ldns_dname_clone_from(parent, 0);
+-    ldns_dname2canonical(sub_clone);
+-    ldns_dname2canonical(parent_clone);
+-
+-	sub_lab = ldns_dname_label_count(sub_clone);
+-	par_lab = ldns_dname_label_count(parent_clone);
+-
+-	/* if sub sits above parent, it cannot be a child/sub domain */
+-	if (sub_lab < par_lab) {
+-		result = false;
+-	} else {
+-		/* check all labels the from the parent labels, from right to left.
+-		 * When they /all/ match we have found a subdomain
+-		 */
+-		j = sub_lab - 1; /* we count from zero, thank you */
+-		for (i = par_lab -1; i >= 0; i--) {
+-			tmp_sub = ldns_dname_label(sub_clone, j);
+-			tmp_par = ldns_dname_label(parent_clone, i);
+-			if (!tmp_sub || !tmp_par) {
+-				/* deep free does null check */
+-				ldns_rdf_deep_free(tmp_sub);
+-				ldns_rdf_deep_free(tmp_par);
+-				result = false;
+-				break;
+-			}
+-
+-			if (ldns_rdf_compare(tmp_sub, tmp_par) != 0) {
+-				/* they are not equal */
+-				ldns_rdf_deep_free(tmp_sub);
+-				ldns_rdf_deep_free(tmp_par);
+-				result = false;
+-				break;
+-			}
+-			ldns_rdf_deep_free(tmp_sub);
+-			ldns_rdf_deep_free(tmp_par);
+-			j--;
+-		}
+-	}
+-	ldns_rdf_deep_free(sub_clone);
+-	ldns_rdf_deep_free(parent_clone);
+-	return result;
+-}
+-
+-int
+-ldns_dname_compare(const ldns_rdf *dname1, const ldns_rdf *dname2)
+-{
+-	size_t lc1, lc2, lc1f, lc2f;
+-	size_t i;
+-	int result = 0;
+-	uint8_t *lp1, *lp2;
+-
+-	/* see RFC4034 for this algorithm */
+-	/* this algorithm assumes the names are normalized to case */
+-
+-        /* only when both are not NULL we can say anything about them */
+-        if (!dname1 && !dname2) {
+-                return 0;
+-        }
+-        if (!dname1 || !dname2) {
+-                return -1;
+-        }
+-	/* asserts must happen later as we are looking in the
+-	 * dname, which could be NULL. But this case is handled
+-	 * above
+-	 */
+-	assert(ldns_rdf_get_type(dname1) == LDNS_RDF_TYPE_DNAME);
+-	assert(ldns_rdf_get_type(dname2) == LDNS_RDF_TYPE_DNAME);
+-
+-	lc1 = ldns_dname_label_count(dname1);
+-	lc2 = ldns_dname_label_count(dname2);
+-
+-	if (lc1 == 0 && lc2 == 0) {
+-		return 0;
+-	}
+-	if (lc1 == 0) {
+-		return -1;
+-	}
+-	if (lc2 == 0) {
+-		return 1;
+-	}
+-	lc1--;
+-	lc2--;
+-	/* we start at the last label */
+-	while (true) {
+-		/* find the label first */
+-		lc1f = lc1;
+-		lp1 = ldns_rdf_data(dname1);
+-		while (lc1f > 0) {
+-			lp1 += *lp1 + 1;
+-			lc1f--;
+-		}
+-
+-		/* and find the other one */
+-		lc2f = lc2;
+-		lp2 = ldns_rdf_data(dname2);
+-		while (lc2f > 0) {
+-			lp2 += *lp2 + 1;
+-			lc2f--;
+-		}
+-
+-		/* now check the label character for character. */
+-		for (i = 1; i < (size_t)(*lp1 + 1); i++) {
+-			if (i > *lp2) {
+-				/* apparently label 1 is larger */
+-				result = 1;
+-				goto done;
+-			}
+-			if (LDNS_DNAME_NORMALIZE((int) *(lp1 + i)) <
+-			    LDNS_DNAME_NORMALIZE((int) *(lp2 + i))) {
+-			    result = -1;
+-			    goto done;
+-			} else if (LDNS_DNAME_NORMALIZE((int) *(lp1 + i)) >
+-			    LDNS_DNAME_NORMALIZE((int) *(lp2 + i))) {
+-			    result = 1;
+-			    goto done;
+-			}
+-		}
+-		if (*lp1 < *lp2) {
+-			/* apparently label 2 is larger */
+-			result = -1;
+-			goto done;
+-		}
+-		if (lc1 == 0 && lc2 > 0) {
+-			result = -1;
+-			goto done;
+-		} else if (lc1 > 0 && lc2 == 0) {
+-			result = 1;
+-			goto done;
+-		} else if (lc1 == 0 && lc2 == 0) {
+-			result = 0;
+-			goto done;
+-		}
+-		lc1--;
+-		lc2--;
+-	}
+-
+-	done:
+-	return result;
+-}
+-
+-int
+-ldns_dname_is_wildcard(const ldns_rdf* dname)
+-{
+-	return ( ldns_dname_label_count(dname) > 0 &&
+-		 ldns_rdf_data(dname)[0] == 1 &&
+-		 ldns_rdf_data(dname)[1] == '*');
+-}
+-
+-int
+-ldns_dname_match_wildcard(const ldns_rdf *dname, const ldns_rdf *wildcard)
+-{
+-	ldns_rdf *wc_chopped;
+-	int result;
+-	/* check whether it really is a wildcard */
+-	if (ldns_dname_is_wildcard(wildcard)) {
+-		/* ok, so the dname needs to be a subdomain of the wildcard
+-		 * without the *
+-		 */
+-		wc_chopped = ldns_dname_left_chop(wildcard);
+-		result = (int) ldns_dname_is_subdomain(dname, wc_chopped);
+-		ldns_rdf_deep_free(wc_chopped);
+-	} else {
+-		result = (ldns_dname_compare(dname, wildcard) == 0);
+-	}
+-	return result;
+-}
+-
+-/* nsec test: does prev <= middle < next
+- * -1 = yes
+- * 0 = error/can't tell
+- * 1 = no
+- */
+-int
+-ldns_dname_interval(const ldns_rdf *prev, const ldns_rdf *middle,
+-		const ldns_rdf *next)
+-{
+-	int prev_check, next_check;
+-
+-	assert(ldns_rdf_get_type(prev) == LDNS_RDF_TYPE_DNAME);
+-	assert(ldns_rdf_get_type(middle) == LDNS_RDF_TYPE_DNAME);
+-	assert(ldns_rdf_get_type(next) == LDNS_RDF_TYPE_DNAME);
+-
+-	prev_check = ldns_dname_compare(prev, middle);
+-	next_check = ldns_dname_compare(middle, next);
+-	/* <= next. This cannot be the case for nsec, because then we would
+-	 * have gotten the nsec of next...
+-	 */
+-	if (next_check == 0) {
+-		return 0;
+-	}
+-
+-			/* <= */
+-	if ((prev_check == -1 || prev_check == 0) &&
+-			/* < */
+-			next_check == -1) {
+-		return -1;
+-	} else {
+-		return 1;
+-	}
+-}
+-
+-
+-bool
+-ldns_dname_str_absolute(const char *dname_str)
+-{
+-        const char* s;
+-	if(dname_str && strcmp(dname_str, ".") == 0)
+-		return 1;
+-        if(!dname_str || strlen(dname_str) < 2)
+-                return 0;
+-        if(dname_str[strlen(dname_str) - 1] != '.')
+-                return 0;
+-        if(dname_str[strlen(dname_str) - 2] != '\\')
+-                return 1; /* ends in . and no \ before it */
+-        /* so we have the case of ends in . and there is \ before it */
+-        for(s=dname_str; *s; s++) {
+-                if(*s == '\\') {
+-                        if(s[1] && s[2] && s[3] /* check length */
+-                                && isdigit(s[1]) && isdigit(s[2]) && 
+-                                isdigit(s[3]))
+-                                s += 3;
+-                        else if(!s[1] || isdigit(s[1])) /* escape of nul,0-9 */
+-                                return 0; /* parse error */
+-                        else s++; /* another character escaped */
+-                }
+-                else if(!*(s+1) && *s == '.')
+-                        return 1; /* trailing dot, unescaped */
+-        }
+-        return 0;
+-}
+-
+-bool
+-ldns_dname_absolute(const ldns_rdf *rdf)
+-{
+-	char *str = ldns_rdf2str(rdf);
+-	if (str) {
+-		bool r = ldns_dname_str_absolute(str);
+-		LDNS_FREE(str);
+-		return r;
+-	}
+-	return false;
+-}
+-
+-ldns_rdf *
+-ldns_dname_label(const ldns_rdf *rdf, uint8_t labelpos)
+-{
+-	uint8_t labelcnt;
+-	uint16_t src_pos;
+-	uint16_t len;
+-	ldns_rdf *tmpnew;
+-	size_t s;
+-	uint8_t *data;
+-
+-	if (ldns_rdf_get_type(rdf) != LDNS_RDF_TYPE_DNAME) {
+-		return NULL;
+-	}
+-
+-	labelcnt = 0;
+-	src_pos = 0;
+-	s = ldns_rdf_size(rdf);
+-
+-	len = ldns_rdf_data(rdf)[src_pos]; /* label start */
+-	while ((len > 0) && src_pos < s) {
+-		if (labelcnt == labelpos) {
+-			/* found our label */
+-			data = LDNS_XMALLOC(uint8_t, len + 2);
+-			if (!data) {
+-				return NULL;
+-			}
+-			memcpy(data, ldns_rdf_data(rdf) + src_pos, len + 1);
+-			data[len + 2 - 1] = 0;
+-
+-			tmpnew = ldns_rdf_new( LDNS_RDF_TYPE_DNAME
+-					     , len + 2, data);
+-			if (!tmpnew) {
+-				LDNS_FREE(data);
+-				return NULL;
+-			}
+-			return tmpnew;
+-		}
+-		src_pos++;
+-		src_pos += len;
+-		len = ldns_rdf_data(rdf)[src_pos];
+-		labelcnt++;
+-	}
+-	return NULL;
+-}
+diff --git a/src/ldns/dnssec.c b/src/ldns/dnssec.c
+deleted file mode 100644
+index a41a9f6..0000000
+--- a/src/ldns/dnssec.c
++++ /dev/null
+@@ -1,1869 +0,0 @@
+-/*
+- * dnssec.c
+- *
+- * contains the cryptographic function needed for DNSSEC in ldns
+- * The crypto library used is openssl
+- *
+- * (c) NLnet Labs, 2004-2008
+- *
+- * See the file LICENSE for the license
+- */
+-
+-#include <ldns/config.h>
+-
+-#include <ldns/ldns.h>
+-#include <ldns/dnssec.h>
+-
+-#include <strings.h>
+-#include <time.h>
+-
+-#ifdef HAVE_SSL
+-#include <openssl/ssl.h>
+-#include <openssl/evp.h>
+-#include <openssl/rand.h>
+-#include <openssl/err.h>
+-#include <openssl/md5.h>
+-#endif
+-
+-ldns_rr *
+-ldns_dnssec_get_rrsig_for_name_and_type(const ldns_rdf *name,
+-                                        const ldns_rr_type type,
+-                                        const ldns_rr_list *rrs)
+-{
+-	size_t i;
+-	ldns_rr *candidate;
+-
+-	if (!name || !rrs) {
+-		return NULL;
+-	}
+-
+-	for (i = 0; i < ldns_rr_list_rr_count(rrs); i++) {
+-		candidate = ldns_rr_list_rr(rrs, i);
+-		if (ldns_rr_get_type(candidate) == LDNS_RR_TYPE_RRSIG) {
+-			if (ldns_dname_compare(ldns_rr_owner(candidate),
+-			                       name) == 0 &&
+-			    ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(candidate))
+-			    == type
+-			    ) {
+-				return candidate;
+-			}
+-		}
+-	}
+-
+-	return NULL;
+-}
+-
+-ldns_rr *
+-ldns_dnssec_get_dnskey_for_rrsig(const ldns_rr *rrsig,
+-						   const ldns_rr_list *rrs)
+-{
+-	size_t i;
+-	ldns_rr *candidate;
+-
+-	if (!rrsig || !rrs) {
+-		return NULL;
+-	}
+-
+-	for (i = 0; i < ldns_rr_list_rr_count(rrs); i++) {
+-		candidate = ldns_rr_list_rr(rrs, i);
+-		if (ldns_rr_get_type(candidate) == LDNS_RR_TYPE_DNSKEY) {
+-			if (ldns_dname_compare(ldns_rr_owner(candidate),
+-			                       ldns_rr_rrsig_signame(rrsig)) == 0 &&
+-			    ldns_rdf2native_int16(ldns_rr_rrsig_keytag(rrsig)) ==
+-			    ldns_calc_keytag(candidate)
+-			    ) {
+-				return candidate;
+-			}
+-		}
+-	}
+-
+-	return NULL;
+-}
+-
+-ldns_rdf *
+-ldns_nsec_get_bitmap(ldns_rr *nsec) {
+-	if (ldns_rr_get_type(nsec) == LDNS_RR_TYPE_NSEC) {
+-		return ldns_rr_rdf(nsec, 1);
+-	} else if (ldns_rr_get_type(nsec) == LDNS_RR_TYPE_NSEC3) {
+-		return ldns_rr_rdf(nsec, 5);
+-	} else {
+-		return NULL;
+-	}
+-}
+-
+-/*return the owner name of the closest encloser for name from the list of rrs */
+-/* this is NOT the hash, but the original name! */
+-ldns_rdf *
+-ldns_dnssec_nsec3_closest_encloser(ldns_rdf *qname,
+-                                   ATTR_UNUSED(ldns_rr_type qtype),
+-                                   ldns_rr_list *nsec3s)
+-{
+-	/* remember parameters, they must match */
+-	uint8_t algorithm;
+-	uint32_t iterations;
+-	uint8_t salt_length;
+-	uint8_t *salt;
+-
+-	ldns_rdf *sname, *hashed_sname, *tmp;
+-	bool flag;
+-
+-	bool exact_match_found;
+-	bool in_range_found;
+-
+-	ldns_status status;
+-	ldns_rdf *zone_name;
+-
+-	size_t nsec_i;
+-	ldns_rr *nsec;
+-	ldns_rdf *result = NULL;
+-
+-	if (!qname || !nsec3s || ldns_rr_list_rr_count(nsec3s) < 1) {
+-		return NULL;
+-	}
+-
+-	nsec = ldns_rr_list_rr(nsec3s, 0);
+-	algorithm = ldns_nsec3_algorithm(nsec);
+-	salt_length = ldns_nsec3_salt_length(nsec);
+-	salt = ldns_nsec3_salt_data(nsec);
+-	iterations = ldns_nsec3_iterations(nsec);
+-
+-	sname = ldns_rdf_clone(qname);
+-
+-	flag = false;
+-
+-	zone_name = ldns_dname_left_chop(ldns_rr_owner(nsec));
+-
+-	/* algorithm from nsec3-07 8.3 */
+-	while (ldns_dname_label_count(sname) > 0) {
+-		exact_match_found = false;
+-		in_range_found = false;
+-
+-		hashed_sname = ldns_nsec3_hash_name(sname,
+-									 algorithm,
+-									 iterations,
+-									 salt_length,
+-									 salt);
+-
+-		status = ldns_dname_cat(hashed_sname, zone_name);
+-                if(status != LDNS_STATUS_OK) {
+-	                LDNS_FREE(salt);
+-	                ldns_rdf_deep_free(zone_name);
+-	                ldns_rdf_deep_free(sname);
+-                        return NULL;
+-                }
+-
+-		for (nsec_i = 0; nsec_i < ldns_rr_list_rr_count(nsec3s); nsec_i++) {
+-			nsec = ldns_rr_list_rr(nsec3s, nsec_i);
+-
+-			/* check values of iterations etc! */
+-
+-			/* exact match? */
+-			if (ldns_dname_compare(ldns_rr_owner(nsec), hashed_sname) == 0) {
+-			 	exact_match_found = true;
+-			} else if (ldns_nsec_covers_name(nsec, hashed_sname)) {
+-				in_range_found = true;
+-			}
+-
+-		}
+-		if (!exact_match_found && in_range_found) {
+-			flag = true;
+-		} else if (exact_match_found && flag) {
+-			result = ldns_rdf_clone(sname);
+-			/* RFC 5155: 8.3. 2.** "The proof is complete" */
+-			ldns_rdf_deep_free(hashed_sname);
+-			goto done;
+-		} else if (exact_match_found && !flag) {
+-			/* error! */
+-			ldns_rdf_deep_free(hashed_sname);
+-			goto done;
+-		} else {
+-			flag = false;
+-		}
+-
+-		ldns_rdf_deep_free(hashed_sname);
+-		tmp = sname;
+-		sname = ldns_dname_left_chop(sname);
+-		ldns_rdf_deep_free(tmp);
+-	}
+-
+-	done:
+-	LDNS_FREE(salt);
+-	ldns_rdf_deep_free(zone_name);
+-	ldns_rdf_deep_free(sname);
+-
+-	return result;
+-}
+-
+-bool
+-ldns_dnssec_pkt_has_rrsigs(const ldns_pkt *pkt)
+-{
+-	size_t i;
+-	for (i = 0; i < ldns_pkt_ancount(pkt); i++) {
+-		if (ldns_rr_get_type(ldns_rr_list_rr(ldns_pkt_answer(pkt), i)) ==
+-		    LDNS_RR_TYPE_RRSIG) {
+-			return true;
+-		}
+-	}
+-	for (i = 0; i < ldns_pkt_nscount(pkt); i++) {
+-		if (ldns_rr_get_type(ldns_rr_list_rr(ldns_pkt_authority(pkt), i)) ==
+-		    LDNS_RR_TYPE_RRSIG) {
+-			return true;
+-		}
+-	}
+-	return false;
+-}
+-
+-ldns_rr_list *
+-ldns_dnssec_pkt_get_rrsigs_for_name_and_type(const ldns_pkt *pkt,
+-									ldns_rdf *name,
+-									ldns_rr_type type)
+-{
+-	uint16_t t_netorder;
+-	ldns_rr_list *sigs;
+-	ldns_rr_list *sigs_covered;
+-	ldns_rdf *rdf_t;
+-	
+-	sigs = ldns_pkt_rr_list_by_name_and_type(pkt,
+-									 name,
+-									 LDNS_RR_TYPE_RRSIG,
+-									 LDNS_SECTION_ANY_NOQUESTION
+-									 );
+-
+-	t_netorder = htons(type); /* rdf are in network order! */
+-	rdf_t = ldns_rdf_new(LDNS_RDF_TYPE_TYPE, LDNS_RDF_SIZE_WORD, &t_netorder);
+-	sigs_covered = ldns_rr_list_subtype_by_rdf(sigs, rdf_t, 0);
+-	
+-	ldns_rdf_free(rdf_t);
+-	ldns_rr_list_deep_free(sigs);
+-
+-	return sigs_covered;
+-
+-}
+-
+-ldns_rr_list *
+-ldns_dnssec_pkt_get_rrsigs_for_type(const ldns_pkt *pkt, ldns_rr_type type)
+-{
+-	uint16_t t_netorder;
+-	ldns_rr_list *sigs;
+-	ldns_rr_list *sigs_covered;
+-	ldns_rdf *rdf_t;
+-
+-	sigs = ldns_pkt_rr_list_by_type(pkt,
+-	                                LDNS_RR_TYPE_RRSIG,
+-	                                LDNS_SECTION_ANY_NOQUESTION
+-							  );
+-
+-	t_netorder = htons(type); /* rdf are in network order! */
+-	rdf_t = ldns_rdf_new(LDNS_RDF_TYPE_TYPE,
+-					 2,
+-					 &t_netorder);
+-	sigs_covered = ldns_rr_list_subtype_by_rdf(sigs, rdf_t, 0);
+-
+-	ldns_rdf_free(rdf_t);
+-	ldns_rr_list_deep_free(sigs);
+-
+-	return sigs_covered;
+-
+-}
+-
+-/* used only on the public key RR */
+-uint16_t
+-ldns_calc_keytag(const ldns_rr *key)
+-{
+-	uint16_t ac16;
+-	ldns_buffer *keybuf;
+-	size_t keysize;
+-
+-	if (!key) {
+-		return 0;
+-	}
+-
+-	if (ldns_rr_get_type(key) != LDNS_RR_TYPE_DNSKEY &&
+-	    ldns_rr_get_type(key) != LDNS_RR_TYPE_KEY
+-	    ) {
+-		return 0;
+-	}
+-
+-	/* rdata to buf - only put the rdata in a buffer */
+-	keybuf = ldns_buffer_new(LDNS_MIN_BUFLEN); /* grows */
+-	if (!keybuf) {
+-		return 0;
+-	}
+-	(void)ldns_rr_rdata2buffer_wire(keybuf, key);
+-	/* the current pos in the buffer is the keysize */
+-	keysize= ldns_buffer_position(keybuf);
+-
+-	ac16 = ldns_calc_keytag_raw(ldns_buffer_begin(keybuf), keysize);
+-	ldns_buffer_free(keybuf);
+-	return ac16;
+-}
+-
+-uint16_t ldns_calc_keytag_raw(uint8_t* key, size_t keysize)
+-{
+-	unsigned int i;
+-	uint32_t ac32;
+-	uint16_t ac16;
+-
+-	if(keysize < 4) {
+-		return 0;
+-	}
+-	/* look at the algorithm field, copied from 2535bis */
+-	if (key[3] == LDNS_RSAMD5) {
+-		ac16 = 0;
+-		if (keysize > 4) {
+-			memmove(&ac16, key + keysize - 3, 2);
+-		}
+-		ac16 = ntohs(ac16);
+-		return (uint16_t) ac16;
+-	} else {
+-		ac32 = 0;
+-		for (i = 0; (size_t)i < keysize; ++i) {
+-			ac32 += (i & 1) ? key[i] : key[i] << 8;
+-		}
+-		ac32 += (ac32 >> 16) & 0xFFFF;
+-		return (uint16_t) (ac32 & 0xFFFF);
+-	}
+-}
+-
+-#ifdef HAVE_SSL
+-DSA *
+-ldns_key_buf2dsa(ldns_buffer *key)
+-{
+-	return ldns_key_buf2dsa_raw((unsigned char*)ldns_buffer_begin(key),
+-						   ldns_buffer_position(key));
+-}
+-
+-DSA *
+-ldns_key_buf2dsa_raw(unsigned char* key, size_t len)
+-{
+-	uint8_t T;
+-	uint16_t length;
+-	uint16_t offset;
+-	DSA *dsa;
+-	BIGNUM *Q; BIGNUM *P;
+-	BIGNUM *G; BIGNUM *Y;
+-
+-	if(len == 0)
+-		return NULL;
+-	T = (uint8_t)key[0];
+-	length = (64 + T * 8);
+-	offset = 1;
+-
+-	if (T > 8) {
+-		return NULL;
+-	}
+-	if(len < (size_t)1 + SHA_DIGEST_LENGTH + 3*length)
+-		return NULL;
+-
+-	Q = BN_bin2bn(key+offset, SHA_DIGEST_LENGTH, NULL);
+-	offset += SHA_DIGEST_LENGTH;
+-
+-	P = BN_bin2bn(key+offset, (int)length, NULL);
+-	offset += length;
+-
+-	G = BN_bin2bn(key+offset, (int)length, NULL);
+-	offset += length;
+-
+-	Y = BN_bin2bn(key+offset, (int)length, NULL);
+-	offset += length;
+-
+-	/* create the key and set its properties */
+-	if(!Q || !P || !G || !Y || !(dsa = DSA_new())) {
+-		BN_free(Q);
+-		BN_free(P);
+-		BN_free(G);
+-		BN_free(Y);
+-		return NULL;
+-	}
+-#ifndef S_SPLINT_S
+-	dsa->p = P;
+-	dsa->q = Q;
+-	dsa->g = G;
+-	dsa->pub_key = Y;
+-#endif /* splint */
+-
+-	return dsa;
+-}
+-
+-RSA *
+-ldns_key_buf2rsa(ldns_buffer *key)
+-{
+-	return ldns_key_buf2rsa_raw((unsigned char*)ldns_buffer_begin(key),
+-						   ldns_buffer_position(key));
+-}
+-
+-RSA *
+-ldns_key_buf2rsa_raw(unsigned char* key, size_t len)
+-{
+-	uint16_t offset;
+-	uint16_t exp;
+-	uint16_t int16;
+-	RSA *rsa;
+-	BIGNUM *modulus;
+-	BIGNUM *exponent;
+-
+-	if (len == 0)
+-		return NULL;
+-	if (key[0] == 0) {
+-		if(len < 3)
+-			return NULL;
+-		/* need some smart comment here XXX*/
+-		/* the exponent is too large so it's places
+-		 * futher...???? */
+-		memmove(&int16, key+1, 2);
+-		exp = ntohs(int16);
+-		offset = 3;
+-	} else {
+-		exp = key[0];
+-		offset = 1;
+-	}
+-
+-	/* key length at least one */
+-	if(len < (size_t)offset + exp + 1)
+-		return NULL;
+-
+-	/* Exponent */
+-	exponent = BN_new();
+-	if(!exponent) return NULL;
+-	(void) BN_bin2bn(key+offset, (int)exp, exponent);
+-	offset += exp;
+-
+-	/* Modulus */
+-	modulus = BN_new();
+-	if(!modulus) {
+-		BN_free(exponent);
+-		return NULL;
+-	}
+-	/* length of the buffer must match the key length! */
+-	(void) BN_bin2bn(key+offset, (int)(len - offset), modulus);
+-
+-	rsa = RSA_new();
+-	if(!rsa) {
+-		BN_free(exponent);
+-		BN_free(modulus);
+-		return NULL;
+-	}
+-#ifndef S_SPLINT_S
+-	rsa->n = modulus;
+-	rsa->e = exponent;
+-#endif /* splint */
+-
+-	return rsa;
+-}
+-
+-int
+-ldns_digest_evp(unsigned char* data, unsigned int len, unsigned char* dest,
+-	const EVP_MD* md)
+-{
+-	EVP_MD_CTX* ctx;
+-	ctx = EVP_MD_CTX_create();
+-	if(!ctx)
+-		return false;
+-	if(!EVP_DigestInit_ex(ctx, md, NULL) ||
+-		!EVP_DigestUpdate(ctx, data, len) ||
+-		!EVP_DigestFinal_ex(ctx, dest, NULL)) {
+-		EVP_MD_CTX_destroy(ctx);
+-		return false;
+-	}
+-	EVP_MD_CTX_destroy(ctx);
+-	return true;
+-}
+-#endif /* HAVE_SSL */
+-
+-ldns_rr *
+-ldns_key_rr2ds(const ldns_rr *key, ldns_hash h)
+-{
+-	ldns_rdf *tmp;
+-	ldns_rr *ds;
+-	uint16_t keytag;
+-	uint8_t  sha1hash;
+-	uint8_t *digest;
+-	ldns_buffer *data_buf;
+-#ifdef USE_GOST
+-	const EVP_MD* md = NULL;
+-#endif
+-
+-	if (ldns_rr_get_type(key) != LDNS_RR_TYPE_DNSKEY) {
+-		return NULL;
+-	}
+-
+-	ds = ldns_rr_new();
+-	if (!ds) {
+-		return NULL;
+-	}
+-	ldns_rr_set_type(ds, LDNS_RR_TYPE_DS);
+-	ldns_rr_set_owner(ds, ldns_rdf_clone(
+-								  ldns_rr_owner(key)));
+-	ldns_rr_set_ttl(ds, ldns_rr_ttl(key));
+-	ldns_rr_set_class(ds, ldns_rr_get_class(key));
+-
+-	switch(h) {
+-	default:
+-	case LDNS_SHA1:
+-		digest = LDNS_XMALLOC(uint8_t, LDNS_SHA1_DIGEST_LENGTH);
+-		if (!digest) {
+-			ldns_rr_free(ds);
+-			return NULL;
+-		}
+-		break;
+-	case LDNS_SHA256:
+-		digest = LDNS_XMALLOC(uint8_t, LDNS_SHA256_DIGEST_LENGTH);
+-		if (!digest) {
+-			ldns_rr_free(ds);
+-			return NULL;
+-		}
+-		break;
+-	case LDNS_HASH_GOST:
+-#ifdef USE_GOST
+-		(void)ldns_key_EVP_load_gost_id();
+-		md = EVP_get_digestbyname("md_gost94");
+-		if(!md) {
+-			ldns_rr_free(ds);
+-			return NULL;
+-		}
+-		digest = LDNS_XMALLOC(uint8_t, EVP_MD_size(md));
+-		if (!digest) {
+-			ldns_rr_free(ds);
+-			return NULL;
+-		}
+-                break;
+-#else
+-		/* not implemented */
+-		ldns_rr_free(ds);
+-		return NULL;
+-#endif
+-	case LDNS_SHA384:
+-#ifdef USE_ECDSA
+-		digest = LDNS_XMALLOC(uint8_t, SHA384_DIGEST_LENGTH);
+-		if (!digest) {
+-			ldns_rr_free(ds);
+-			return NULL;
+-		}
+-                break;
+-#else
+-		/* not implemented */
+-		ldns_rr_free(ds);
+-		return NULL;
+-#endif
+-	}
+-
+-	data_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN);
+-	if (!data_buf) {
+-		LDNS_FREE(digest);
+-		ldns_rr_free(ds);
+-		return NULL;
+-	}
+-
+-	/* keytag */
+-	keytag = htons(ldns_calc_keytag((ldns_rr*)key));
+-	tmp = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_INT16,
+-						   sizeof(uint16_t),
+-						   &keytag);
+-	ldns_rr_push_rdf(ds, tmp);
+-
+-	/* copy the algorithm field */
+-	if ((tmp = ldns_rr_rdf(key, 2)) == NULL) {
+-		LDNS_FREE(digest);
+-		ldns_buffer_free(data_buf);
+-		ldns_rr_free(ds);
+-		return NULL;
+-	} else {
+-		ldns_rr_push_rdf(ds, ldns_rdf_clone( tmp )); 
+-	}
+-
+-	/* digest hash type */
+-	sha1hash = (uint8_t)h;
+-	tmp = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_INT8,
+-						   sizeof(uint8_t),
+-						   &sha1hash);
+-	ldns_rr_push_rdf(ds, tmp);
+-
+-	/* digest */
+-	/* owner name */
+-	tmp = ldns_rdf_clone(ldns_rr_owner(key));
+-	ldns_dname2canonical(tmp);
+-	if (ldns_rdf2buffer_wire(data_buf, tmp) != LDNS_STATUS_OK) {
+-		LDNS_FREE(digest);
+-		ldns_buffer_free(data_buf);
+-		ldns_rr_free(ds);
+-		ldns_rdf_deep_free(tmp);
+-		return NULL;
+-	}
+-	ldns_rdf_deep_free(tmp);
+-
+-	/* all the rdata's */
+-	if (ldns_rr_rdata2buffer_wire(data_buf,
+-							(ldns_rr*)key) != LDNS_STATUS_OK) {
+-		LDNS_FREE(digest);
+-		ldns_buffer_free(data_buf);
+-		ldns_rr_free(ds);
+-		return NULL;
+-	}
+-	switch(h) {
+-	case LDNS_SHA1:
+-		(void) ldns_sha1((unsigned char *) ldns_buffer_begin(data_buf),
+-		                 (unsigned int) ldns_buffer_position(data_buf),
+-		                 (unsigned char *) digest);
+-
+-		tmp = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_HEX,
+-		                            LDNS_SHA1_DIGEST_LENGTH,
+-		                            digest);
+-		ldns_rr_push_rdf(ds, tmp);
+-
+-		break;
+-	case LDNS_SHA256:
+-		(void) ldns_sha256((unsigned char *) ldns_buffer_begin(data_buf),
+-		                   (unsigned int) ldns_buffer_position(data_buf),
+-		                   (unsigned char *) digest);
+-		tmp = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_HEX,
+-		                            LDNS_SHA256_DIGEST_LENGTH,
+-		                            digest);
+-		ldns_rr_push_rdf(ds, tmp);
+-		break;
+-	case LDNS_HASH_GOST:
+-#ifdef USE_GOST
+-		if(!ldns_digest_evp((unsigned char *) ldns_buffer_begin(data_buf),
+-				(unsigned int) ldns_buffer_position(data_buf),
+-				(unsigned char *) digest, md)) {
+-			LDNS_FREE(digest);
+-			ldns_buffer_free(data_buf);
+-			ldns_rr_free(ds);
+-			return NULL;
+-		}
+-		tmp = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_HEX,
+-		                            (size_t)EVP_MD_size(md),
+-		                            digest);
+-		ldns_rr_push_rdf(ds, tmp);
+-#endif
+-		break;
+-	case LDNS_SHA384:
+-#ifdef USE_ECDSA
+-		(void) SHA384((unsigned char *) ldns_buffer_begin(data_buf),
+-		                 (unsigned int) ldns_buffer_position(data_buf),
+-		                 (unsigned char *) digest);
+-		tmp = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_HEX,
+-		                            SHA384_DIGEST_LENGTH,
+-		                            digest);
+-		ldns_rr_push_rdf(ds, tmp);
+-#endif
+-		break;
+-	}
+-
+-	LDNS_FREE(digest);
+-	ldns_buffer_free(data_buf);
+-	return ds;
+-}
+-
+-/* From RFC3845:
+- *
+- * 2.1.2.  The List of Type Bit Map(s) Field
+- * 
+- *    The RR type space is split into 256 window blocks, each representing
+- *    the low-order 8 bits of the 16-bit RR type space.  Each block that
+- *    has at least one active RR type is encoded using a single octet
+- *    window number (from 0 to 255), a single octet bitmap length (from 1
+- *    to 32) indicating the number of octets used for the window block's
+- *    bitmap, and up to 32 octets (256 bits) of bitmap.
+- * 
+- *    Window blocks are present in the NSEC RR RDATA in increasing
+- *    numerical order.
+- * 
+- *    "|" denotes concatenation
+- * 
+- *    Type Bit Map(s) Field = ( Window Block # | Bitmap Length | Bitmap ) +
+- * 
+- *    <cut>
+- * 
+- *    Blocks with no types present MUST NOT be included.  Trailing zero
+- *    octets in the bitmap MUST be omitted.  The length of each block's
+- *    bitmap is determined by the type code with the largest numerical
+- *    value within that block, among the set of RR types present at the
+- *    NSEC RR's owner name.  Trailing zero octets not specified MUST be
+- *    interpreted as zero octets.
+- */
+-ldns_rdf *
+-ldns_dnssec_create_nsec_bitmap(ldns_rr_type rr_type_list[],
+-                               size_t size,
+-                               ldns_rr_type nsec_type)
+-{
+-	uint8_t  window;		/*  most significant octet of type */
+-	uint8_t  subtype;		/* least significant octet of type */
+-	uint16_t windows[256]		/* Max subtype per window */
+-#ifndef S_SPLINT_S
+-	                      = { 0 }	/* Initialize ALL elements with 0 */
+-#endif
+-	                             ;
+-	ldns_rr_type* d;	/* used to traverse rr_type_list*/
+-	size_t i;		/* used to traverse windows array */
+-
+-	size_t sz;			/* size needed for type bitmap rdf */
+-	uint8_t* data = NULL;		/* rdf data */
+-	uint8_t* dptr;			/* used to itraverse rdf data */
+-	ldns_rdf* rdf;			/* bitmap rdf to return */
+-
+-	if (nsec_type != LDNS_RR_TYPE_NSEC &&
+-	    nsec_type != LDNS_RR_TYPE_NSEC3) {
+-		return NULL;
+-	}
+-
+-	/* Which other windows need to be in the bitmap rdf?
+-	 */
+-	for (d = rr_type_list; d < rr_type_list + size; d++) {
+-		window  = *d >> 8;
+-		subtype = *d & 0xff;
+-		if (windows[window] < subtype) {
+-			windows[window] = subtype;
+-		}
+-	}
+-
+-	/* How much space do we need in the rdf for those windows?
+-	 */
+-	sz = 0;
+-	for (i = 0; i < 256; i++) {
+-		if (windows[i]) {
+-			sz += windows[i] / 8 + 3;
+-		}
+-	}
+-	if (sz > 0) {
+-		/* Format rdf data according RFC3845 Section 2.1.2 (see above)
+-		 */
+-		dptr = data = LDNS_CALLOC(uint8_t, sz);
+-		if (!data) {
+-			return NULL;
+-		}
+-		for (i = 0; i < 256; i++) {
+-			if (windows[i]) {
+-				*dptr++ = (uint8_t)i;
+-				*dptr++ = (uint8_t)(windows[i] / 8 + 1);
+-
+-				/* Now let windows[i] index the bitmap
+-				 * within data
+-				 */
+-				windows[i] = (uint16_t)(dptr - data);
+-
+-				dptr += dptr[-1];
+-			}
+-		}
+-	}
+-
+-	/* Set the bits?
+-	 */
+-	for (d = rr_type_list; d < rr_type_list + size; d++) {
+-		subtype = *d & 0xff;
+-		data[windows[*d >> 8] + subtype/8] |= (0x80 >> (subtype % 8));
+-	}
+-
+-	/* Allocate and return rdf structure for the data
+-	 */
+-	rdf = ldns_rdf_new(LDNS_RDF_TYPE_BITMAP, sz, data);
+-	if (!rdf) {
+-		LDNS_FREE(data);
+-		return NULL;
+-	}
+-	return rdf;
+-}
+-
+-int
+-ldns_dnssec_rrsets_contains_type(ldns_dnssec_rrsets *rrsets,
+-                                 ldns_rr_type type)
+-{
+-	ldns_dnssec_rrsets *cur_rrset = rrsets;
+-	while (cur_rrset) {
+-		if (cur_rrset->type == type) {
+-			return 1;
+-		}
+-		cur_rrset = cur_rrset->next;
+-	}
+-	return 0;
+-}
+-
+-ldns_rr *
+-ldns_dnssec_create_nsec(ldns_dnssec_name *from,
+-                        ldns_dnssec_name *to,
+-                        ldns_rr_type nsec_type)
+-{
+-	ldns_rr *nsec_rr;
+-	ldns_rr_type types[65536];
+-	size_t type_count = 0;
+-	ldns_dnssec_rrsets *cur_rrsets;
+-	int on_delegation_point;
+-
+-	if (!from || !to || (nsec_type != LDNS_RR_TYPE_NSEC)) {
+-		return NULL;
+-	}
+-
+-	nsec_rr = ldns_rr_new();
+-	ldns_rr_set_type(nsec_rr, nsec_type);
+-	ldns_rr_set_owner(nsec_rr, ldns_rdf_clone(ldns_dnssec_name_name(from)));
+-	ldns_rr_push_rdf(nsec_rr, ldns_rdf_clone(ldns_dnssec_name_name(to)));
+-
+-	on_delegation_point = ldns_dnssec_rrsets_contains_type(
+-			from->rrsets, LDNS_RR_TYPE_NS)
+-		&& !ldns_dnssec_rrsets_contains_type(
+-			from->rrsets, LDNS_RR_TYPE_SOA);
+-
+-	cur_rrsets = from->rrsets;
+-	while (cur_rrsets) {
+-		/* Do not include non-authoritative rrsets on the delegation point
+-		 * in the type bitmap */
+-		if ((on_delegation_point && (
+-				cur_rrsets->type == LDNS_RR_TYPE_NS 
+-			     || cur_rrsets->type == LDNS_RR_TYPE_DS))
+-			|| (!on_delegation_point &&
+-				cur_rrsets->type != LDNS_RR_TYPE_RRSIG
+-			     && cur_rrsets->type != LDNS_RR_TYPE_NSEC)) {
+-
+-			types[type_count] = cur_rrsets->type;
+-			type_count++;
+-		}
+-		cur_rrsets = cur_rrsets->next;
+-
+-	}
+-	types[type_count] = LDNS_RR_TYPE_RRSIG;
+-	type_count++;
+-	types[type_count] = LDNS_RR_TYPE_NSEC;
+-	type_count++;
+-
+-	ldns_rr_push_rdf(nsec_rr, ldns_dnssec_create_nsec_bitmap(types,
+-	                               type_count,
+-	                               nsec_type));
+-
+-	return nsec_rr;
+-}
+-
+-ldns_rr *
+-ldns_dnssec_create_nsec3(ldns_dnssec_name *from,
+-					ldns_dnssec_name *to,
+-					ldns_rdf *zone_name,
+-					uint8_t algorithm,
+-					uint8_t flags,
+-					uint16_t iterations,
+-					uint8_t salt_length,
+-					uint8_t *salt)
+-{
+-	ldns_rr *nsec_rr;
+-	ldns_rr_type types[65536];
+-	size_t type_count = 0;
+-	ldns_dnssec_rrsets *cur_rrsets;
+-	ldns_status status;
+-	int on_delegation_point;
+-
+-	if (!from) {
+-		return NULL;
+-	}
+-
+-	nsec_rr = ldns_rr_new_frm_type(LDNS_RR_TYPE_NSEC3);
+-	ldns_rr_set_owner(nsec_rr,
+-	                  ldns_nsec3_hash_name(ldns_dnssec_name_name(from),
+-	                  algorithm,
+-	                  iterations,
+-	                  salt_length,
+-	                  salt));
+-	status = ldns_dname_cat(ldns_rr_owner(nsec_rr), zone_name);
+-        if(status != LDNS_STATUS_OK) {
+-                ldns_rr_free(nsec_rr);
+-                return NULL;
+-        }
+-	ldns_nsec3_add_param_rdfs(nsec_rr,
+-	                          algorithm,
+-	                          flags,
+-	                          iterations,
+-	                          salt_length,
+-	                          salt);
+-
+-	on_delegation_point = ldns_dnssec_rrsets_contains_type(
+-			from->rrsets, LDNS_RR_TYPE_NS)
+-		&& !ldns_dnssec_rrsets_contains_type(
+-			from->rrsets, LDNS_RR_TYPE_SOA);
+-	cur_rrsets = from->rrsets;
+-	while (cur_rrsets) {
+-		/* Do not include non-authoritative rrsets on the delegation point
+-		 * in the type bitmap. Potentionally not skipping insecure
+-		 * delegation should have been done earlier, in function
+-		 * ldns_dnssec_zone_create_nsec3s, or even earlier in:
+-		 * ldns_dnssec_zone_sign_nsec3_flg .
+-		 */
+-		if ((on_delegation_point && (
+-				cur_rrsets->type == LDNS_RR_TYPE_NS
+-			     || cur_rrsets->type == LDNS_RR_TYPE_DS))
+-			|| (!on_delegation_point &&
+-				cur_rrsets->type != LDNS_RR_TYPE_RRSIG)) {
+-
+-			types[type_count] = cur_rrsets->type;
+-			type_count++;
+-		}
+-		cur_rrsets = cur_rrsets->next;
+-	}
+-	/* always add rrsig type if this is not an unsigned
+-	 * delegation
+-	 */
+-	if (type_count > 0 &&
+-	    !(type_count == 1 && types[0] == LDNS_RR_TYPE_NS)) {
+-		types[type_count] = LDNS_RR_TYPE_RRSIG;
+-		type_count++;
+-	}
+-
+-	/* leave next rdata empty if they weren't precomputed yet */
+-	if (to && to->hashed_name) {
+-		(void) ldns_rr_set_rdf(nsec_rr,
+-		                       ldns_rdf_clone(to->hashed_name),
+-		                       4);
+-	} else {
+-		(void) ldns_rr_set_rdf(nsec_rr, NULL, 4);
+-	}
+-
+-	ldns_rr_push_rdf(nsec_rr,
+-	                 ldns_dnssec_create_nsec_bitmap(types,
+-	                 type_count,
+-	                 LDNS_RR_TYPE_NSEC3));
+-
+-	return nsec_rr;
+-}
+-
+-ldns_rr *
+-ldns_create_nsec(ldns_rdf *cur_owner, ldns_rdf *next_owner, ldns_rr_list *rrs)
+-{
+-	/* we do not do any check here - garbage in, garbage out */
+-
+-	/* the the start and end names - get the type from the
+-	 * before rrlist */
+-
+-	/* inefficient, just give it a name, a next name, and a list of rrs */
+-	/* we make 1 big uberbitmap first, then windows */
+-	/* todo: make something more efficient :) */
+-	uint16_t i;
+-	ldns_rr *i_rr;
+-	uint16_t i_type;
+-
+-	ldns_rr *nsec = NULL;
+-	ldns_rr_type i_type_list[65536];
+-	size_t type_count = 0;
+-
+-	nsec = ldns_rr_new();
+-	ldns_rr_set_type(nsec, LDNS_RR_TYPE_NSEC);
+-	ldns_rr_set_owner(nsec, ldns_rdf_clone(cur_owner));
+-	ldns_rr_push_rdf(nsec, ldns_rdf_clone(next_owner));
+-
+-	for (i = 0; i < ldns_rr_list_rr_count(rrs); i++) {
+-		i_rr = ldns_rr_list_rr(rrs, i);
+-		if (ldns_rdf_compare(cur_owner,
+-						 ldns_rr_owner(i_rr)) == 0) {
+-			i_type = ldns_rr_get_type(i_rr);
+-			if (i_type != LDNS_RR_TYPE_RRSIG && i_type != LDNS_RR_TYPE_NSEC) {
+-				if (type_count == 0 || i_type_list[type_count-1] != i_type) {
+-					i_type_list[type_count] = i_type;
+-					type_count++;
+-				}
+-			}
+-		}
+-	}
+-
+-	i_type_list[type_count] = LDNS_RR_TYPE_RRSIG;
+-	type_count++;
+-	i_type_list[type_count] = LDNS_RR_TYPE_NSEC;
+-	type_count++;
+-
+-	ldns_rr_push_rdf(nsec,
+-				  ldns_dnssec_create_nsec_bitmap(i_type_list,
+-						type_count, LDNS_RR_TYPE_NSEC));
+-
+-	return nsec;
+-}
+-
+-ldns_rdf *
+-ldns_nsec3_hash_name(ldns_rdf *name,
+-				 uint8_t algorithm,
+-				 uint16_t iterations,
+-				 uint8_t salt_length,
+-				 uint8_t *salt)
+-{
+-	size_t hashed_owner_str_len;
+-	ldns_rdf *cann;
+-	ldns_rdf *hashed_owner;
+-	unsigned char *hashed_owner_str;
+-	char *hashed_owner_b32;
+-	size_t hashed_owner_b32_len;
+-	uint32_t cur_it;
+-	/* define to contain the largest possible hash, which is
+-	 * sha1 at the moment */
+-	unsigned char hash[LDNS_SHA1_DIGEST_LENGTH];
+-	ldns_status status;
+-
+-	/* TODO: mnemonic list for hash algs SHA-1, default to 1 now (sha1) */
+-	if (algorithm != LDNS_SHA1) {
+-		return NULL;
+-	}
+-
+-	/* prepare the owner name according to the draft section bla */
+-	cann = ldns_rdf_clone(name);
+-	if(!cann) {
+-#ifdef STDERR_MSGS
+-		fprintf(stderr, "Memory error\n");
+-#endif
+-		return NULL;
+-	}
+-	ldns_dname2canonical(cann);
+-
+-	hashed_owner_str_len = salt_length + ldns_rdf_size(cann);
+-	hashed_owner_str = LDNS_XMALLOC(unsigned char, hashed_owner_str_len);
+-        if(!hashed_owner_str) {
+-	        ldns_rdf_deep_free(cann);
+-                return NULL;
+-        }
+-	memcpy(hashed_owner_str, ldns_rdf_data(cann), ldns_rdf_size(cann));
+-	memcpy(hashed_owner_str + ldns_rdf_size(cann), salt, salt_length);
+-	ldns_rdf_deep_free(cann);
+-
+-	for (cur_it = iterations + 1; cur_it > 0; cur_it--) {
+-		(void) ldns_sha1((unsigned char *) hashed_owner_str,
+-		                 (unsigned int) hashed_owner_str_len, hash);
+-
+-		LDNS_FREE(hashed_owner_str);
+-		hashed_owner_str_len = salt_length + LDNS_SHA1_DIGEST_LENGTH;
+-		hashed_owner_str = LDNS_XMALLOC(unsigned char, hashed_owner_str_len);
+-		if (!hashed_owner_str) {
+-			return NULL;
+-		}
+-		memcpy(hashed_owner_str, hash, LDNS_SHA1_DIGEST_LENGTH);
+-		memcpy(hashed_owner_str + LDNS_SHA1_DIGEST_LENGTH, salt, salt_length);
+-		hashed_owner_str_len = LDNS_SHA1_DIGEST_LENGTH + salt_length;
+-	}
+-
+-	LDNS_FREE(hashed_owner_str);
+-	hashed_owner_str = hash;
+-	hashed_owner_str_len = LDNS_SHA1_DIGEST_LENGTH;
+-
+-	hashed_owner_b32 = LDNS_XMALLOC(char,
+-                  ldns_b32_ntop_calculate_size(hashed_owner_str_len) + 1);
+-        if(!hashed_owner_b32) {
+-                return NULL;
+-        }
+-        hashed_owner_b32_len = (size_t) ldns_b32_ntop_extended_hex(
+-                (uint8_t *) hashed_owner_str,
+-                hashed_owner_str_len,
+-                hashed_owner_b32,
+-                ldns_b32_ntop_calculate_size(hashed_owner_str_len)+1);
+-	if (hashed_owner_b32_len < 1) {
+-#ifdef STDERR_MSGS
+-		fprintf(stderr, "Error in base32 extended hex encoding ");
+-		fprintf(stderr, "of hashed owner name (name: ");
+-		ldns_rdf_print(stderr, name);
+-		fprintf(stderr, ", return code: %u)\n",
+-		        (unsigned int) hashed_owner_b32_len);
+-#endif
+-		LDNS_FREE(hashed_owner_b32);
+-		return NULL;
+-	}
+-	hashed_owner_b32[hashed_owner_b32_len] = '\0';
+-
+-	status = ldns_str2rdf_dname(&hashed_owner, hashed_owner_b32);
+-	if (status != LDNS_STATUS_OK) {
+-#ifdef STDERR_MSGS
+-		fprintf(stderr, "Error creating rdf from %s\n", hashed_owner_b32);
+-#endif
+-		LDNS_FREE(hashed_owner_b32);
+-		return NULL;
+-	}
+-
+-	LDNS_FREE(hashed_owner_b32);
+-	return hashed_owner;
+-}
+-
+-void
+-ldns_nsec3_add_param_rdfs(ldns_rr *rr,
+-					 uint8_t algorithm,
+-					 uint8_t flags,
+-					 uint16_t iterations,
+-					 uint8_t salt_length,
+-					 uint8_t *salt)
+-{
+-	ldns_rdf *salt_rdf = NULL;
+-	uint8_t *salt_data = NULL;
+-	ldns_rdf *old;
+-
+-	old = ldns_rr_set_rdf(rr,
+-	                      ldns_rdf_new_frm_data(LDNS_RDF_TYPE_INT8,
+-	                                            1, (void*)&algorithm),
+-	                      0);
+-	if (old) ldns_rdf_deep_free(old);
+-
+-	old = ldns_rr_set_rdf(rr,
+-	                      ldns_rdf_new_frm_data(LDNS_RDF_TYPE_INT8,
+-	                                            1, (void*)&flags),
+-	                      1);
+-	if (old) ldns_rdf_deep_free(old);
+-
+-	old = ldns_rr_set_rdf(rr,
+-                          ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16,
+-                                                iterations),
+-	                      2);
+-	if (old) ldns_rdf_deep_free(old);
+-
+-	salt_data = LDNS_XMALLOC(uint8_t, salt_length + 1);
+-        if(!salt_data) {
+-                /* no way to return error */
+-                return;
+-        }
+-	salt_data[0] = salt_length;
+-	memcpy(salt_data + 1, salt, salt_length);
+-	salt_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_NSEC3_SALT,
+-							   salt_length + 1,
+-							   salt_data);
+-        if(!salt_rdf) {
+-                LDNS_FREE(salt_data);
+-                /* no way to return error */
+-                return;
+-        }
+-
+-	old = ldns_rr_set_rdf(rr, salt_rdf, 3);
+-	if (old) ldns_rdf_deep_free(old);
+-	LDNS_FREE(salt_data);
+-}
+-
+-static int
+-rr_list_delegation_only(ldns_rdf *origin, ldns_rr_list *rr_list)
+-{
+-	size_t i;
+-	ldns_rr *cur_rr;
+-	if (!origin || !rr_list) return 0;
+-	for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
+-		cur_rr = ldns_rr_list_rr(rr_list, i);
+-		if (ldns_dname_compare(ldns_rr_owner(cur_rr), origin) == 0) {
+-			return 0;
+-		}
+-		if (ldns_rr_get_type(cur_rr) != LDNS_RR_TYPE_NS) {
+-			return 0;
+-		}
+-	}
+-	return 1;
+-}
+-
+-/* this will NOT return the NSEC3  completed, you will have to run the
+-   finalize function on the rrlist later! */
+-ldns_rr *
+-ldns_create_nsec3(ldns_rdf *cur_owner,
+-                  ldns_rdf *cur_zone,
+-                  ldns_rr_list *rrs,
+-                  uint8_t algorithm,
+-                  uint8_t flags,
+-                  uint16_t iterations,
+-                  uint8_t salt_length,
+-                  uint8_t *salt,
+-                  bool emptynonterminal)
+-{
+-	size_t i;
+-	ldns_rr *i_rr;
+-	uint16_t i_type;
+-
+-	ldns_rr *nsec = NULL;
+-	ldns_rdf *hashed_owner = NULL;
+-
+-	ldns_status status;
+-
+-    ldns_rr_type i_type_list[1024];
+-	size_t type_count = 0;
+-
+-	hashed_owner = ldns_nsec3_hash_name(cur_owner,
+-								 algorithm,
+-								 iterations,
+-								 salt_length,
+-								 salt);
+-	status = ldns_dname_cat(hashed_owner, cur_zone);
+-        if(status != LDNS_STATUS_OK) {
+-		ldns_rdf_deep_free(hashed_owner);
+-                return NULL;
+-	}
+-	nsec = ldns_rr_new_frm_type(LDNS_RR_TYPE_NSEC3);
+-        if(!nsec) {
+-		ldns_rdf_deep_free(hashed_owner);
+-                return NULL;
+-	}
+-	ldns_rr_set_type(nsec, LDNS_RR_TYPE_NSEC3);
+-	ldns_rr_set_owner(nsec, hashed_owner);
+-
+-	ldns_nsec3_add_param_rdfs(nsec,
+-						 algorithm,
+-						 flags,
+-						 iterations,
+-						 salt_length,
+-						 salt);
+-	(void) ldns_rr_set_rdf(nsec, NULL, 4);
+-
+-
+-	for (i = 0; i < ldns_rr_list_rr_count(rrs); i++) {
+-		i_rr = ldns_rr_list_rr(rrs, i);
+-		if (ldns_rdf_compare(cur_owner,
+-						 ldns_rr_owner(i_rr)) == 0) {
+-			i_type = ldns_rr_get_type(i_rr);
+-			if (type_count == 0 || i_type_list[type_count-1] != i_type) {
+-				i_type_list[type_count] = i_type;
+-				type_count++;
+-			}
+-		}
+-	}
+-
+-	/* add RRSIG anyway, but only if this is not an ENT or
+-	 * an unsigned delegation */
+-	if (!emptynonterminal && !rr_list_delegation_only(cur_zone, rrs)) {
+-		i_type_list[type_count] = LDNS_RR_TYPE_RRSIG;
+-		type_count++;
+-	}
+-
+-	/* and SOA if owner == zone */
+-	if (ldns_dname_compare(cur_zone, cur_owner) == 0) {
+-		i_type_list[type_count] = LDNS_RR_TYPE_SOA;
+-		type_count++;
+-	}
+-
+-	ldns_rr_push_rdf(nsec,
+-				  ldns_dnssec_create_nsec_bitmap(i_type_list,
+-						type_count, LDNS_RR_TYPE_NSEC3));
+-
+-	return nsec;
+-}
+-
+-uint8_t
+-ldns_nsec3_algorithm(const ldns_rr *nsec3_rr)
+-{
+-	if (nsec3_rr && 
+-	      (ldns_rr_get_type(nsec3_rr) == LDNS_RR_TYPE_NSEC3 ||
+-	       ldns_rr_get_type(nsec3_rr) == LDNS_RR_TYPE_NSEC3PARAM)
+-	    && (ldns_rr_rdf(nsec3_rr, 0) != NULL)
+-	    && ldns_rdf_size(ldns_rr_rdf(nsec3_rr, 0)) > 0) {
+-		return ldns_rdf2native_int8(ldns_rr_rdf(nsec3_rr, 0));
+-	}
+-	return 0;
+-}
+-
+-uint8_t
+-ldns_nsec3_flags(const ldns_rr *nsec3_rr)
+-{
+-	if (nsec3_rr && 
+-	      (ldns_rr_get_type(nsec3_rr) == LDNS_RR_TYPE_NSEC3 ||
+-	       ldns_rr_get_type(nsec3_rr) == LDNS_RR_TYPE_NSEC3PARAM)
+-	    && (ldns_rr_rdf(nsec3_rr, 1) != NULL)
+-	    && ldns_rdf_size(ldns_rr_rdf(nsec3_rr, 1)) > 0) {
+-		return ldns_rdf2native_int8(ldns_rr_rdf(nsec3_rr, 1));
+-	}
+-	return 0;
+-}
+-
+-bool
+-ldns_nsec3_optout(const ldns_rr *nsec3_rr)
+-{
+-	return (ldns_nsec3_flags(nsec3_rr) & LDNS_NSEC3_VARS_OPTOUT_MASK);
+-}
+-
+-uint16_t
+-ldns_nsec3_iterations(const ldns_rr *nsec3_rr)
+-{
+-	if (nsec3_rr &&
+-	      (ldns_rr_get_type(nsec3_rr) == LDNS_RR_TYPE_NSEC3 ||
+-	       ldns_rr_get_type(nsec3_rr) == LDNS_RR_TYPE_NSEC3PARAM)
+-	    && (ldns_rr_rdf(nsec3_rr, 2) != NULL)
+-	    && ldns_rdf_size(ldns_rr_rdf(nsec3_rr, 2)) > 0) {
+-		return ldns_rdf2native_int16(ldns_rr_rdf(nsec3_rr, 2));
+-	}
+-	return 0;
+-	
+-}
+-
+-ldns_rdf *
+-ldns_nsec3_salt(const ldns_rr *nsec3_rr)
+-{
+-	if (nsec3_rr && 
+-	      (ldns_rr_get_type(nsec3_rr) == LDNS_RR_TYPE_NSEC3 ||
+-	       ldns_rr_get_type(nsec3_rr) == LDNS_RR_TYPE_NSEC3PARAM)
+-	    ) {
+-		return ldns_rr_rdf(nsec3_rr, 3);
+-	}
+-	return NULL;
+-}
+-
+-uint8_t
+-ldns_nsec3_salt_length(const ldns_rr *nsec3_rr)
+-{
+-	ldns_rdf *salt_rdf = ldns_nsec3_salt(nsec3_rr);
+-	if (salt_rdf && ldns_rdf_size(salt_rdf) > 0) {
+-		return (uint8_t) ldns_rdf_data(salt_rdf)[0];
+-	}
+-	return 0;
+-}
+-
+-/* allocs data, free with LDNS_FREE() */
+-uint8_t *
+-ldns_nsec3_salt_data(const ldns_rr *nsec3_rr)
+-{
+-	uint8_t salt_length;
+-	uint8_t *salt;
+-
+-	ldns_rdf *salt_rdf = ldns_nsec3_salt(nsec3_rr);
+-	if (salt_rdf && ldns_rdf_size(salt_rdf) > 0) {
+-	    	salt_length = ldns_rdf_data(salt_rdf)[0];
+-		salt = LDNS_XMALLOC(uint8_t, salt_length);
+-                if(!salt) return NULL;
+-		memcpy(salt, &ldns_rdf_data(salt_rdf)[1], salt_length);
+-		return salt;
+-	}
+-	return NULL;
+-}
+-
+-ldns_rdf *
+-ldns_nsec3_next_owner(const ldns_rr *nsec3_rr)
+-{
+-	if (!nsec3_rr || ldns_rr_get_type(nsec3_rr) != LDNS_RR_TYPE_NSEC3) {
+-		return NULL;
+-	} else {
+-		return ldns_rr_rdf(nsec3_rr, 4);
+-	}
+-}
+-
+-ldns_rdf *
+-ldns_nsec3_bitmap(const ldns_rr *nsec3_rr)
+-{
+-	if (!nsec3_rr || ldns_rr_get_type(nsec3_rr) != LDNS_RR_TYPE_NSEC3) {
+-		return NULL;
+-	} else {
+-		return ldns_rr_rdf(nsec3_rr, 5);
+-	}
+-}
+-
+-ldns_rdf *
+-ldns_nsec3_hash_name_frm_nsec3(const ldns_rr *nsec, ldns_rdf *name)
+-{
+-	uint8_t algorithm;
+-	uint16_t iterations;
+-	uint8_t salt_length;
+-	uint8_t *salt = 0;
+-
+-	ldns_rdf *hashed_owner;
+-
+-	algorithm = ldns_nsec3_algorithm(nsec);
+-	salt_length = ldns_nsec3_salt_length(nsec);
+-	salt = ldns_nsec3_salt_data(nsec);
+-	iterations = ldns_nsec3_iterations(nsec);
+-
+-	hashed_owner = ldns_nsec3_hash_name(name,
+-								 algorithm,
+-								 iterations,
+-								 salt_length,
+-								 salt);
+-
+-	LDNS_FREE(salt);
+-	return hashed_owner;
+-}
+-
+-bool
+-ldns_nsec_bitmap_covers_type(const  ldns_rdf* bitmap, ldns_rr_type type)
+-{
+-	uint8_t* dptr;
+-	uint8_t* dend;
+-
+-	/* From RFC3845 Section 2.1.2:
+-	 *
+-	 *	"The RR type space is split into 256 window blocks, each re-
+-	 *	 presenting the low-order 8 bits of the 16-bit RR type space."
+-	 */
+-	uint8_t  window = type >> 8;
+-	uint8_t subtype = type & 0xff;
+-
+-	if (! bitmap) {
+-		return false;
+-	}
+-	assert(ldns_rdf_get_type(bitmap) == LDNS_RDF_TYPE_BITMAP);
+-
+-	dptr = ldns_rdf_data(bitmap);
+-	dend = ldns_rdf_data(bitmap) + ldns_rdf_size(bitmap);
+-
+-	/* Type Bitmap = ( Window Block # | Bitmap Length | Bitmap ) +
+-	 *                 dptr[0]          dptr[1]         dptr[2:]
+-	 */
+-	while (dptr < dend && dptr[0] <= window) {
+-
+-		if (dptr[0] == window && subtype / 8 < dptr[1] &&
+-				dptr + dptr[1] + 2 <= dend) {
+-
+-			return dptr[2 + subtype / 8] & (0x80 >> (subtype % 8));
+-		}
+-		dptr += dptr[1] + 2; /* next window */
+-	}
+-	return false;
+-}
+-
+-ldns_status
+-ldns_nsec_bitmap_set_type(ldns_rdf* bitmap, ldns_rr_type type)
+-{
+-	uint8_t* dptr;
+-	uint8_t* dend;
+-
+-	/* From RFC3845 Section 2.1.2:
+-	 *
+-	 *	"The RR type space is split into 256 window blocks, each re-
+-	 *	 presenting the low-order 8 bits of the 16-bit RR type space."
+-	 */
+-	uint8_t  window = type >> 8;
+-	uint8_t subtype = type & 0xff;
+-
+-	if (! bitmap) {
+-		return false;
+-	}
+-	assert(ldns_rdf_get_type(bitmap) == LDNS_RDF_TYPE_BITMAP);
+-
+-	dptr = ldns_rdf_data(bitmap);
+-	dend = ldns_rdf_data(bitmap) + ldns_rdf_size(bitmap);
+-
+-	/* Type Bitmap = ( Window Block # | Bitmap Length | Bitmap ) +
+-	 *                 dptr[0]          dptr[1]         dptr[2:]
+-	 */
+-	while (dptr < dend && dptr[0] <= window) {
+-
+-		if (dptr[0] == window && subtype / 8 < dptr[1] &&
+-				dptr + dptr[1] + 2 <= dend) {
+-
+-			dptr[2 + subtype / 8] |= (0x80 >> (subtype % 8));
+-			return LDNS_STATUS_OK;
+-		}
+-		dptr += dptr[1] + 2; /* next window */
+-	}
+-	return LDNS_STATUS_TYPE_NOT_IN_BITMAP;
+-}
+-
+-ldns_status
+-ldns_nsec_bitmap_clear_type(ldns_rdf* bitmap, ldns_rr_type type)
+-{
+-	uint8_t* dptr;
+-	uint8_t* dend;
+-
+-	/* From RFC3845 Section 2.1.2:
+-	 *
+-	 *	"The RR type space is split into 256 window blocks, each re-
+-	 *	 presenting the low-order 8 bits of the 16-bit RR type space."
+-	 */
+-	uint8_t  window = type >> 8;
+-	uint8_t subtype = type & 0xff;
+-
+-	if (! bitmap) {
+-		return false;
+-	}
+-
+-	assert(ldns_rdf_get_type(bitmap) == LDNS_RDF_TYPE_BITMAP);
+-
+-	dptr = ldns_rdf_data(bitmap);
+-	dend = ldns_rdf_data(bitmap) + ldns_rdf_size(bitmap);
+-
+-	/* Type Bitmap = ( Window Block # | Bitmap Length | Bitmap ) +
+-	 *                 dptr[0]          dptr[1]         dptr[2:]
+-	 */
+-	while (dptr < dend && dptr[0] <= window) {
+-
+-		if (dptr[0] == window && subtype / 8 < dptr[1] &&
+-				dptr + dptr[1] + 2 <= dend) {
+-
+-			dptr[2 + subtype / 8] &= ~(0x80 >> (subtype % 8));
+-			return LDNS_STATUS_OK;
+-		}
+-		dptr += dptr[1] + 2; /* next window */
+-	}
+-	return LDNS_STATUS_TYPE_NOT_IN_BITMAP;
+-}
+-
+-
+-bool
+-ldns_nsec_covers_name(const ldns_rr *nsec, const ldns_rdf *name)
+-{
+-	ldns_rdf *nsec_owner = ldns_rr_owner(nsec);
+-	ldns_rdf *hash_next;
+-	char *next_hash_str;
+-	ldns_rdf *nsec_next = NULL;
+-	ldns_status status;
+-	ldns_rdf *chopped_dname;
+-	bool result;
+-
+-	if (ldns_rr_get_type(nsec) == LDNS_RR_TYPE_NSEC) {
+-		if (ldns_rr_rdf(nsec, 0) != NULL) {
+-			nsec_next = ldns_rdf_clone(ldns_rr_rdf(nsec, 0));
+-		} else {
+-			return false;
+-		}
+-	} else if (ldns_rr_get_type(nsec) == LDNS_RR_TYPE_NSEC3) {
+-		hash_next = ldns_nsec3_next_owner(nsec);
+-		next_hash_str = ldns_rdf2str(hash_next);
+-		nsec_next = ldns_dname_new_frm_str(next_hash_str);
+-		LDNS_FREE(next_hash_str);
+-		chopped_dname = ldns_dname_left_chop(nsec_owner);
+-		status = ldns_dname_cat(nsec_next, chopped_dname);
+-		ldns_rdf_deep_free(chopped_dname);
+-		if (status != LDNS_STATUS_OK) {
+-			printf("error catting: %s\n", ldns_get_errorstr_by_id(status));
+-		}
+-	} else {
+-		ldns_rdf_deep_free(nsec_next);
+-		return false;
+-	}
+-
+-	/* in the case of the last nsec */
+-	if(ldns_dname_compare(nsec_owner, nsec_next) > 0) {
+-		result = (ldns_dname_compare(nsec_owner, name) <= 0 ||
+-				ldns_dname_compare(name, nsec_next) < 0);
+-	} else if(ldns_dname_compare(nsec_owner, nsec_next) < 0) {
+-		result = (ldns_dname_compare(nsec_owner, name) <= 0 &&
+-		          ldns_dname_compare(name, nsec_next) < 0);
+-	} else {
+-		result = true;
+-	}
+-
+-	ldns_rdf_deep_free(nsec_next);
+-	return result;
+-}
+-
+-#ifdef HAVE_SSL
+-/* sig may be null - if so look in the packet */
+-
+-ldns_status
+-ldns_pkt_verify_time(ldns_pkt *p, ldns_rr_type t, ldns_rdf *o, 
+-		ldns_rr_list *k, ldns_rr_list *s, 
+-		time_t check_time, ldns_rr_list *good_keys)
+-{
+-	ldns_rr_list *rrset;
+-	ldns_rr_list *sigs;
+-	ldns_rr_list *sigs_covered;
+-	ldns_rdf *rdf_t;
+-	ldns_rr_type t_netorder;
+-
+-	if (!k) {
+-		return LDNS_STATUS_ERR;
+-		/* return LDNS_STATUS_CRYPTO_NO_DNSKEY; */
+-	}
+-
+-	if (t == LDNS_RR_TYPE_RRSIG) {
+-		/* we don't have RRSIG(RRSIG) (yet? ;-) ) */
+-		return LDNS_STATUS_ERR;
+-	}
+-
+-	if (s) {
+-		/* if s is not NULL, the sigs are given to use */
+-		sigs = s;
+-	} else {
+-		/* otherwise get them from the packet */
+-		sigs = ldns_pkt_rr_list_by_name_and_type(p, o,
+-				LDNS_RR_TYPE_RRSIG,
+-				LDNS_SECTION_ANY_NOQUESTION);
+-		if (!sigs) {
+-			/* no sigs */
+-			return LDNS_STATUS_ERR;
+-			/* return LDNS_STATUS_CRYPTO_NO_RRSIG; */
+-		}
+-	}
+-
+-	/* rrsig are subtyped, so now we need to find the correct
+-	 * sigs for the type t
+-	 */
+-	t_netorder = htons(t); /* rdf are in network order! */
+-	/* a type identifier is a 16-bit number, so the size is 2 bytes */
+-	rdf_t = ldns_rdf_new(LDNS_RDF_TYPE_TYPE, 2, &t_netorder);
+-
+-	sigs_covered = ldns_rr_list_subtype_by_rdf(sigs, rdf_t, 0);
+-	ldns_rdf_free(rdf_t);
+-	if (! sigs_covered) {
+-		if (! s) {
+-			ldns_rr_list_deep_free(sigs);
+-		}
+-		return LDNS_STATUS_ERR;
+-	}
+-	ldns_rr_list_deep_free(sigs_covered);
+-
+-	rrset = ldns_pkt_rr_list_by_name_and_type(p, o, t,
+-			LDNS_SECTION_ANY_NOQUESTION);
+-	if (!rrset) {
+-		if (! s) {
+-			ldns_rr_list_deep_free(sigs);
+-		}
+-		return LDNS_STATUS_ERR;
+-	}
+-	return ldns_verify_time(rrset, sigs, k, check_time, good_keys);
+-}
+-
+-ldns_status
+-ldns_pkt_verify(ldns_pkt *p, ldns_rr_type t, ldns_rdf *o, 
+-		ldns_rr_list *k, ldns_rr_list *s, ldns_rr_list *good_keys)
+-{
+-	return ldns_pkt_verify_time(p, t, o, k, s, ldns_time(NULL), good_keys);
+-}
+-#endif /* HAVE_SSL */
+-
+-ldns_status
+-ldns_dnssec_chain_nsec3_list(ldns_rr_list *nsec3_rrs)
+-{
+-	size_t i;
+-	char *next_nsec_owner_str;
+-	ldns_rdf *next_nsec_owner_label;
+-	ldns_rdf *next_nsec_rdf;
+-	ldns_status status = LDNS_STATUS_OK;
+-
+-	for (i = 0; i < ldns_rr_list_rr_count(nsec3_rrs); i++) {
+-		if (i == ldns_rr_list_rr_count(nsec3_rrs) - 1) {
+-			next_nsec_owner_label =
+-				ldns_dname_label(ldns_rr_owner(ldns_rr_list_rr(nsec3_rrs,
+-													  0)), 0);
+-			next_nsec_owner_str = ldns_rdf2str(next_nsec_owner_label);
+-			if (next_nsec_owner_str[strlen(next_nsec_owner_str) - 1]
+-			    == '.') {
+-				next_nsec_owner_str[strlen(next_nsec_owner_str) - 1]
+-					= '\0';
+-			}
+-			status = ldns_str2rdf_b32_ext(&next_nsec_rdf,
+-									next_nsec_owner_str);
+-			if (!ldns_rr_set_rdf(ldns_rr_list_rr(nsec3_rrs, i),
+-							 next_nsec_rdf, 4)) {
+-				/* todo: error */
+-			}
+-
+-			ldns_rdf_deep_free(next_nsec_owner_label);
+-			LDNS_FREE(next_nsec_owner_str);
+-		} else {
+-			next_nsec_owner_label =
+-				ldns_dname_label(ldns_rr_owner(ldns_rr_list_rr(nsec3_rrs,
+-													  i + 1)),
+-							  0);
+-			next_nsec_owner_str = ldns_rdf2str(next_nsec_owner_label);
+-			if (next_nsec_owner_str[strlen(next_nsec_owner_str) - 1]
+-			    == '.') {
+-				next_nsec_owner_str[strlen(next_nsec_owner_str) - 1]
+-					= '\0';
+-			}
+-			status = ldns_str2rdf_b32_ext(&next_nsec_rdf,
+-									next_nsec_owner_str);
+-			ldns_rdf_deep_free(next_nsec_owner_label);
+-			LDNS_FREE(next_nsec_owner_str);
+-			if (!ldns_rr_set_rdf(ldns_rr_list_rr(nsec3_rrs, i),
+-							 next_nsec_rdf, 4)) {
+-				/* todo: error */
+-			}
+-		}
+-	}
+-	return status;
+-}
+-
+-int
+-qsort_rr_compare_nsec3(const void *a, const void *b)
+-{
+-	const ldns_rr *rr1 = * (const ldns_rr **) a;
+-	const ldns_rr *rr2 = * (const ldns_rr **) b;
+-	if (rr1 == NULL && rr2 == NULL) {
+-		return 0;
+-	}
+-	if (rr1 == NULL) {
+-		return -1;
+-	}
+-	if (rr2 == NULL) {
+-		return 1;
+-	}
+-	return ldns_rdf_compare(ldns_rr_owner(rr1), ldns_rr_owner(rr2));
+-}
+-
+-void
+-ldns_rr_list_sort_nsec3(ldns_rr_list *unsorted)
+-{
+-	qsort(unsorted->_rrs,
+-	      ldns_rr_list_rr_count(unsorted),
+-	      sizeof(ldns_rr *),
+-	      qsort_rr_compare_nsec3);
+-}
+-
+-int
+-ldns_dnssec_default_add_to_signatures( ATTR_UNUSED(ldns_rr *sig)
+-				     , ATTR_UNUSED(void *n)
+-				     )
+-{
+-	return LDNS_SIGNATURE_LEAVE_ADD_NEW;
+-}
+-
+-int
+-ldns_dnssec_default_leave_signatures( ATTR_UNUSED(ldns_rr *sig)
+-				    , ATTR_UNUSED(void *n)
+-				    )
+-{
+-	return LDNS_SIGNATURE_LEAVE_NO_ADD;
+-}
+-
+-int
+-ldns_dnssec_default_delete_signatures( ATTR_UNUSED(ldns_rr *sig)
+-				     , ATTR_UNUSED(void *n)
+-				     )
+-{
+-	return LDNS_SIGNATURE_REMOVE_NO_ADD;
+-}
+-
+-int
+-ldns_dnssec_default_replace_signatures( ATTR_UNUSED(ldns_rr *sig)
+-				      , ATTR_UNUSED(void *n)
+-				      )
+-{
+-	return LDNS_SIGNATURE_REMOVE_ADD_NEW;
+-}
+-
+-#ifdef HAVE_SSL
+-ldns_rdf *
+-ldns_convert_dsa_rrsig_asn12rdf(const ldns_buffer *sig,
+-						  const long sig_len)
+-{
+-	ldns_rdf *sigdata_rdf;
+-	DSA_SIG *dsasig;
+-	unsigned char *dsasig_data = (unsigned char*)ldns_buffer_begin(sig);
+-	size_t byte_offset;
+-
+-	dsasig = d2i_DSA_SIG(NULL,
+-					 (const unsigned char **)&dsasig_data,
+-					 sig_len);
+-	if (!dsasig) {
+-                DSA_SIG_free(dsasig);
+-		return NULL;
+-	}
+-
+-	dsasig_data = LDNS_XMALLOC(unsigned char, 41);
+-        if(!dsasig_data) {
+-                DSA_SIG_free(dsasig);
+-                return NULL;
+-        }
+-	dsasig_data[0] = 0;
+-	byte_offset = (size_t) (20 - BN_num_bytes(dsasig->r));
+-	if (byte_offset > 20) {
+-                DSA_SIG_free(dsasig);
+-                LDNS_FREE(dsasig_data);
+-		return NULL;
+-	}
+-	memset(&dsasig_data[1], 0, byte_offset);
+-	BN_bn2bin(dsasig->r, &dsasig_data[1 + byte_offset]);
+-	byte_offset = (size_t) (20 - BN_num_bytes(dsasig->s));
+-	if (byte_offset > 20) {
+-                DSA_SIG_free(dsasig);
+-                LDNS_FREE(dsasig_data);
+-		return NULL;
+-	}
+-	memset(&dsasig_data[21], 0, byte_offset);
+-	BN_bn2bin(dsasig->s, &dsasig_data[21 + byte_offset]);
+-
+-	sigdata_rdf = ldns_rdf_new(LDNS_RDF_TYPE_B64, 41, dsasig_data);
+-        if(!sigdata_rdf) {
+-                LDNS_FREE(dsasig_data);
+-        }
+-	DSA_SIG_free(dsasig);
+-
+-	return sigdata_rdf;
+-}
+-
+-ldns_status
+-ldns_convert_dsa_rrsig_rdf2asn1(ldns_buffer *target_buffer,
+-						  const ldns_rdf *sig_rdf)
+-{
+-	/* the EVP api wants the DER encoding of the signature... */
+-	BIGNUM *R, *S;
+-	DSA_SIG *dsasig;
+-	unsigned char *raw_sig = NULL;
+-	int raw_sig_len;
+-
+-        if(ldns_rdf_size(sig_rdf) < 1 + 2*SHA_DIGEST_LENGTH)
+-                return LDNS_STATUS_SYNTAX_RDATA_ERR;
+-	/* extract the R and S field from the sig buffer */
+-	R = BN_new();
+-	if(!R) return LDNS_STATUS_MEM_ERR;
+-	(void) BN_bin2bn((unsigned char *) ldns_rdf_data(sig_rdf) + 1,
+-	                 SHA_DIGEST_LENGTH, R);
+-	S = BN_new();
+-	if(!S) {
+-		BN_free(R);
+-		return LDNS_STATUS_MEM_ERR;
+-	}
+-	(void) BN_bin2bn((unsigned char *) ldns_rdf_data(sig_rdf) + 21,
+-	                 SHA_DIGEST_LENGTH, S);
+-
+-	dsasig = DSA_SIG_new();
+-	if (!dsasig) {
+-		BN_free(R);
+-		BN_free(S);
+-		return LDNS_STATUS_MEM_ERR;
+-	}
+-
+-	dsasig->r = R;
+-	dsasig->s = S;
+-
+-	raw_sig_len = i2d_DSA_SIG(dsasig, &raw_sig);
+-	if (raw_sig_len < 0) {
+-		DSA_SIG_free(dsasig);
+-		free(raw_sig);
+-		return LDNS_STATUS_SSL_ERR;
+-	}
+-	if (ldns_buffer_reserve(target_buffer, (size_t) raw_sig_len)) {
+-		ldns_buffer_write(target_buffer, raw_sig, (size_t)raw_sig_len);
+-	}
+-
+-	DSA_SIG_free(dsasig);
+-	free(raw_sig);
+-
+-	return ldns_buffer_status(target_buffer);
+-}
+-
+-#ifdef USE_ECDSA
+-#ifndef S_SPLINT_S
+-ldns_rdf *
+-ldns_convert_ecdsa_rrsig_asn12rdf(const ldns_buffer *sig, const long sig_len)
+-{
+-        ECDSA_SIG* ecdsa_sig;
+-	unsigned char *data = (unsigned char*)ldns_buffer_begin(sig);
+-        ldns_rdf* rdf;
+-	ecdsa_sig = d2i_ECDSA_SIG(NULL, (const unsigned char **)&data, sig_len);
+-        if(!ecdsa_sig) return NULL;
+-
+-        /* "r | s". */
+-        data = LDNS_XMALLOC(unsigned char,
+-                BN_num_bytes(ecdsa_sig->r) + BN_num_bytes(ecdsa_sig->s));
+-        if(!data) {
+-                ECDSA_SIG_free(ecdsa_sig);
+-                return NULL;
+-        }
+-        BN_bn2bin(ecdsa_sig->r, data);
+-        BN_bn2bin(ecdsa_sig->s, data+BN_num_bytes(ecdsa_sig->r));
+-	rdf = ldns_rdf_new(LDNS_RDF_TYPE_B64, (size_t)(
+-		BN_num_bytes(ecdsa_sig->r) + BN_num_bytes(ecdsa_sig->s)), data);
+-        ECDSA_SIG_free(ecdsa_sig);
+-        return rdf;
+-}
+-
+-ldns_status
+-ldns_convert_ecdsa_rrsig_rdf2asn1(ldns_buffer *target_buffer,
+-        const ldns_rdf *sig_rdf)
+-{
+-        ECDSA_SIG* sig;
+-	int raw_sig_len;
+-        long bnsize = (long)ldns_rdf_size(sig_rdf) / 2;
+-        /* if too short, or not even length, do not bother */
+-        if(bnsize < 16 || (size_t)bnsize*2 != ldns_rdf_size(sig_rdf))
+-                return LDNS_STATUS_ERR;
+-        
+-        /* use the raw data to parse two evenly long BIGNUMs, "r | s". */
+-        sig = ECDSA_SIG_new();
+-        if(!sig) return LDNS_STATUS_MEM_ERR;
+-        sig->r = BN_bin2bn((const unsigned char*)ldns_rdf_data(sig_rdf),
+-                bnsize, sig->r);
+-        sig->s = BN_bin2bn((const unsigned char*)ldns_rdf_data(sig_rdf)+bnsize,
+-                bnsize, sig->s);
+-        if(!sig->r || !sig->s) {
+-                ECDSA_SIG_free(sig);
+-                return LDNS_STATUS_MEM_ERR;
+-        }
+-
+-	raw_sig_len = i2d_ECDSA_SIG(sig, NULL);
+-	if (ldns_buffer_reserve(target_buffer, (size_t) raw_sig_len)) {
+-                unsigned char* pp = (unsigned char*)
+-			ldns_buffer_current(target_buffer);
+-	        raw_sig_len = i2d_ECDSA_SIG(sig, &pp);
+-                ldns_buffer_skip(target_buffer, (ssize_t) raw_sig_len);
+-	}
+-        ECDSA_SIG_free(sig);
+-
+-	return ldns_buffer_status(target_buffer);
+-}
+-
+-#endif /* S_SPLINT_S */
+-#endif /* USE_ECDSA */
+-#endif /* HAVE_SSL */
+diff --git a/src/ldns/dnssec_sign.c b/src/ldns/dnssec_sign.c
+deleted file mode 100644
+index 4af882a..0000000
+--- a/src/ldns/dnssec_sign.c
++++ /dev/null
+@@ -1,1456 +0,0 @@
+-#include <ldns/config.h>
+-
+-#include <ldns/ldns.h>
+-
+-#include <ldns/dnssec.h>
+-#include <ldns/dnssec_sign.h>
+-
+-#include <strings.h>
+-#include <time.h>
+-
+-#ifdef HAVE_SSL
+-/* this entire file is rather useless when you don't have
+- * crypto...
+- */
+-#include <openssl/ssl.h>
+-#include <openssl/evp.h>
+-#include <openssl/rand.h>
+-#include <openssl/err.h>
+-#include <openssl/md5.h>
+-#endif /* HAVE_SSL */
+-
+-ldns_rr *
+-ldns_create_empty_rrsig(ldns_rr_list *rrset,
+-                        ldns_key *current_key)
+-{
+-	uint32_t orig_ttl;
+-	ldns_rr_class orig_class;
+-	time_t now;
+-	ldns_rr *current_sig;
+-	uint8_t label_count;
+-	ldns_rdf *signame;
+-
+-	label_count = ldns_dname_label_count(ldns_rr_owner(ldns_rr_list_rr(rrset,
+-	                                                   0)));
+-        /* RFC4035 2.2: not counting the leftmost label if it is a wildcard */
+-        if(ldns_dname_is_wildcard(ldns_rr_owner(ldns_rr_list_rr(rrset, 0))))
+-                label_count --;
+-
+-	current_sig = ldns_rr_new_frm_type(LDNS_RR_TYPE_RRSIG);
+-
+-	/* set the type on the new signature */
+-	orig_ttl = ldns_rr_ttl(ldns_rr_list_rr(rrset, 0));
+-	orig_class = ldns_rr_get_class(ldns_rr_list_rr(rrset, 0));
+-
+-	ldns_rr_set_ttl(current_sig, orig_ttl);
+-	ldns_rr_set_class(current_sig, orig_class);
+-	ldns_rr_set_owner(current_sig,
+-			  ldns_rdf_clone(
+-			       ldns_rr_owner(
+-				    ldns_rr_list_rr(rrset,
+-						    0))));
+-
+-	/* fill in what we know of the signature */
+-
+-	/* set the orig_ttl */
+-	(void)ldns_rr_rrsig_set_origttl(
+-		   current_sig,
+-		   ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32,
+-					 orig_ttl));
+-	/* the signers name */
+-	signame = ldns_rdf_clone(ldns_key_pubkey_owner(current_key));
+-	ldns_dname2canonical(signame);
+-	(void)ldns_rr_rrsig_set_signame(
+-			current_sig,
+-			signame);
+-	/* label count - get it from the first rr in the rr_list */
+-	(void)ldns_rr_rrsig_set_labels(
+-			current_sig,
+-			ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8,
+-			                     label_count));
+-	/* inception, expiration */
+-	now = time(NULL);
+-	if (ldns_key_inception(current_key) != 0) {
+-		(void)ldns_rr_rrsig_set_inception(
+-				current_sig,
+-				ldns_native2rdf_int32(
+-				    LDNS_RDF_TYPE_TIME,
+-				    ldns_key_inception(current_key)));
+-	} else {
+-		(void)ldns_rr_rrsig_set_inception(
+-				current_sig,
+-				ldns_native2rdf_int32(LDNS_RDF_TYPE_TIME, now));
+-	}
+-	if (ldns_key_expiration(current_key) != 0) {
+-		(void)ldns_rr_rrsig_set_expiration(
+-				current_sig,
+-				ldns_native2rdf_int32(
+-				    LDNS_RDF_TYPE_TIME,
+-				    ldns_key_expiration(current_key)));
+-	} else {
+-		(void)ldns_rr_rrsig_set_expiration(
+-			     current_sig,
+-				ldns_native2rdf_int32(
+-				    LDNS_RDF_TYPE_TIME,
+-				    now + LDNS_DEFAULT_EXP_TIME));
+-	}
+-
+-	(void)ldns_rr_rrsig_set_keytag(
+-		   current_sig,
+-		   ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16,
+-		                         ldns_key_keytag(current_key)));
+-
+-	(void)ldns_rr_rrsig_set_algorithm(
+-			current_sig,
+-			ldns_native2rdf_int8(
+-			    LDNS_RDF_TYPE_ALG,
+-			    ldns_key_algorithm(current_key)));
+-
+-	(void)ldns_rr_rrsig_set_typecovered(
+-			current_sig,
+-			ldns_native2rdf_int16(
+-			    LDNS_RDF_TYPE_TYPE,
+-			    ldns_rr_get_type(ldns_rr_list_rr(rrset,
+-			                                     0))));
+-	return current_sig;
+-}
+-
+-#ifdef HAVE_SSL
+-ldns_rdf *
+-ldns_sign_public_buffer(ldns_buffer *sign_buf, ldns_key *current_key)
+-{
+-	ldns_rdf *b64rdf = NULL;
+-
+-	switch(ldns_key_algorithm(current_key)) {
+-	case LDNS_SIGN_DSA:
+-	case LDNS_SIGN_DSA_NSEC3:
+-		b64rdf = ldns_sign_public_evp(
+-				   sign_buf,
+-				   ldns_key_evp_key(current_key),
+-				   EVP_dss1());
+-		break;
+-	case LDNS_SIGN_RSASHA1:
+-	case LDNS_SIGN_RSASHA1_NSEC3:
+-		b64rdf = ldns_sign_public_evp(
+-				   sign_buf,
+-				   ldns_key_evp_key(current_key),
+-				   EVP_sha1());
+-		break;
+-#ifdef USE_SHA2
+-	case LDNS_SIGN_RSASHA256:
+-		b64rdf = ldns_sign_public_evp(
+-				   sign_buf,
+-				   ldns_key_evp_key(current_key),
+-				   EVP_sha256());
+-		break;
+-	case LDNS_SIGN_RSASHA512:
+-		b64rdf = ldns_sign_public_evp(
+-				   sign_buf,
+-				   ldns_key_evp_key(current_key),
+-				   EVP_sha512());
+-		break;
+-#endif /* USE_SHA2 */
+-#ifdef USE_GOST
+-	case LDNS_SIGN_ECC_GOST:
+-		b64rdf = ldns_sign_public_evp(
+-				   sign_buf,
+-				   ldns_key_evp_key(current_key),
+-				   EVP_get_digestbyname("md_gost94"));
+-		break;
+-#endif /* USE_GOST */
+-#ifdef USE_ECDSA
+-        case LDNS_SIGN_ECDSAP256SHA256:
+-       		b64rdf = ldns_sign_public_evp(
+-				   sign_buf,
+-				   ldns_key_evp_key(current_key),
+-				   EVP_sha256());
+-                break;
+-        case LDNS_SIGN_ECDSAP384SHA384:
+-       		b64rdf = ldns_sign_public_evp(
+-				   sign_buf,
+-				   ldns_key_evp_key(current_key),
+-				   EVP_sha384());
+-                break;
+-#endif
+-	case LDNS_SIGN_RSAMD5:
+-		b64rdf = ldns_sign_public_evp(
+-				   sign_buf,
+-				   ldns_key_evp_key(current_key),
+-				   EVP_md5());
+-		break;
+-	default:
+-		/* do _you_ know this alg? */
+-		printf("unknown algorithm, ");
+-		printf("is the one used available on this system?\n");
+-		break;
+-	}
+-
+-	return b64rdf;
+-}
+-
+-/**
+- * use this function to sign with a public/private key alg
+- * return the created signatures
+- */
+-ldns_rr_list *
+-ldns_sign_public(ldns_rr_list *rrset, ldns_key_list *keys)
+-{
+-	ldns_rr_list *signatures;
+-	ldns_rr_list *rrset_clone;
+-	ldns_rr *current_sig;
+-	ldns_rdf *b64rdf;
+-	ldns_key *current_key;
+-	size_t key_count;
+-	uint16_t i;
+-	ldns_buffer *sign_buf;
+-	ldns_rdf *new_owner;
+-
+-	if (!rrset || ldns_rr_list_rr_count(rrset) < 1 || !keys) {
+-		return NULL;
+-	}
+-
+-	new_owner = NULL;
+-
+-	signatures = ldns_rr_list_new();
+-
+-	/* prepare a signature and add all the know data
+-	 * prepare the rrset. Sign this together.  */
+-	rrset_clone = ldns_rr_list_clone(rrset);
+-	if (!rrset_clone) {
+-		return NULL;
+-	}
+-
+-	/* make it canonical */
+-	for(i = 0; i < ldns_rr_list_rr_count(rrset_clone); i++) {
+-		ldns_rr_set_ttl(ldns_rr_list_rr(rrset_clone, i), 
+-			ldns_rr_ttl(ldns_rr_list_rr(rrset, 0)));
+-		ldns_rr2canonical(ldns_rr_list_rr(rrset_clone, i));
+-	}
+-	/* sort */
+-	ldns_rr_list_sort(rrset_clone);
+-
+-	for (key_count = 0;
+-		key_count < ldns_key_list_key_count(keys);
+-		key_count++) {
+-		if (!ldns_key_use(ldns_key_list_key(keys, key_count))) {
+-			continue;
+-		}
+-		sign_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN);
+-		if (!sign_buf) {
+-			ldns_rr_list_free(rrset_clone);
+-			ldns_rr_list_free(signatures);
+-			ldns_rdf_free(new_owner);
+-			return NULL;
+-		}
+-		b64rdf = NULL;
+-
+-		current_key = ldns_key_list_key(keys, key_count);
+-		/* sign all RRs with keys that have ZSKbit, !SEPbit.
+-		   sign DNSKEY RRs with keys that have ZSKbit&SEPbit */
+-		if (ldns_key_flags(current_key) & LDNS_KEY_ZONE_KEY) {
+-			current_sig = ldns_create_empty_rrsig(rrset_clone,
+-			                                      current_key);
+-
+-			/* right now, we have: a key, a semi-sig and an rrset. For
+-			 * which we can create the sig and base64 encode that and
+-			 * add that to the signature */
+-
+-			if (ldns_rrsig2buffer_wire(sign_buf, current_sig)
+-			    != LDNS_STATUS_OK) {
+-				ldns_buffer_free(sign_buf);
+-				/* ERROR */
+-				ldns_rr_list_deep_free(rrset_clone);
+-				ldns_rr_free(current_sig);
+-				ldns_rr_list_deep_free(signatures);
+-				return NULL;
+-			}
+-
+-			/* add the rrset in sign_buf */
+-			if (ldns_rr_list2buffer_wire(sign_buf, rrset_clone)
+-			    != LDNS_STATUS_OK) {
+-				ldns_buffer_free(sign_buf);
+-				ldns_rr_list_deep_free(rrset_clone);
+-				ldns_rr_free(current_sig);
+-				ldns_rr_list_deep_free(signatures);
+-				return NULL;
+-			}
+-
+-			b64rdf = ldns_sign_public_buffer(sign_buf, current_key);
+-
+-			if (!b64rdf) {
+-				/* signing went wrong */
+-				ldns_rr_list_deep_free(rrset_clone);
+-				ldns_rr_free(current_sig);
+-				ldns_rr_list_deep_free(signatures);
+-				return NULL;
+-			}
+-
+-			ldns_rr_rrsig_set_sig(current_sig, b64rdf);
+-
+-			/* push the signature to the signatures list */
+-			ldns_rr_list_push_rr(signatures, current_sig);
+-		}
+-		ldns_buffer_free(sign_buf); /* restart for the next key */
+-	}
+-	ldns_rr_list_deep_free(rrset_clone);
+-
+-	return signatures;
+-}
+-
+-/**
+- * Sign data with DSA
+- *
+- * \param[in] to_sign The ldns_buffer containing raw data that is
+- *                    to be signed
+- * \param[in] key The DSA key structure to sign with
+- * \return ldns_rdf for the RRSIG ldns_rr
+- */
+-ldns_rdf *
+-ldns_sign_public_dsa(ldns_buffer *to_sign, DSA *key)
+-{
+-	unsigned char *sha1_hash;
+-	ldns_rdf *sigdata_rdf;
+-	ldns_buffer *b64sig;
+-
+-	DSA_SIG *sig;
+-	uint8_t *data;
+-	size_t pad;
+-
+-	b64sig = ldns_buffer_new(LDNS_MAX_PACKETLEN);
+-	if (!b64sig) {
+-		return NULL;
+-	}
+-
+-	sha1_hash = SHA1((unsigned char*)ldns_buffer_begin(to_sign),
+-				  ldns_buffer_position(to_sign), NULL);
+-	if (!sha1_hash) {
+-		ldns_buffer_free(b64sig);
+-		return NULL;
+-	}
+-
+-	sig = DSA_do_sign(sha1_hash, SHA_DIGEST_LENGTH, key);
+-        if(!sig) {
+-		ldns_buffer_free(b64sig);
+-		return NULL;
+-        }
+-
+-	data = LDNS_XMALLOC(uint8_t, 1 + 2 * SHA_DIGEST_LENGTH);
+-        if(!data) {
+-		ldns_buffer_free(b64sig);
+-                DSA_SIG_free(sig);
+-		return NULL;
+-        }
+-
+-	data[0] = 1;
+-	pad = 20 - (size_t) BN_num_bytes(sig->r);
+-	if (pad > 0) {
+-		memset(data + 1, 0, pad);
+-	}
+-	BN_bn2bin(sig->r, (unsigned char *) (data + 1) + pad);
+-
+-	pad = 20 - (size_t) BN_num_bytes(sig->s);
+-	if (pad > 0) {
+-		memset(data + 1 + SHA_DIGEST_LENGTH, 0, pad);
+-	}
+-	BN_bn2bin(sig->s, (unsigned char *) (data + 1 + SHA_DIGEST_LENGTH + pad));
+-
+-	sigdata_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64,
+-								 1 + 2 * SHA_DIGEST_LENGTH,
+-								 data);
+-
+-	ldns_buffer_free(b64sig);
+-	LDNS_FREE(data);
+-        DSA_SIG_free(sig);
+-
+-	return sigdata_rdf;
+-}
+-
+-#ifdef USE_ECDSA
+-#ifndef S_SPLINT_S
+-static int
+-ldns_pkey_is_ecdsa(EVP_PKEY* pkey)
+-{
+-        EC_KEY* ec;
+-        const EC_GROUP* g;
+-        if(EVP_PKEY_type(pkey->type) != EVP_PKEY_EC)
+-                return 0;
+-        ec = EVP_PKEY_get1_EC_KEY(pkey);
+-        g = EC_KEY_get0_group(ec);
+-        if(!g) {
+-                EC_KEY_free(ec);
+-                return 0;
+-        }
+-        if(EC_GROUP_get_curve_name(g) == NID_secp224r1 ||
+-                EC_GROUP_get_curve_name(g) == NID_X9_62_prime256v1 ||
+-                EC_GROUP_get_curve_name(g) == NID_secp384r1) {
+-                EC_KEY_free(ec);
+-                return 1;
+-        }
+-        /* downref the eckey, the original is still inside the pkey */
+-        EC_KEY_free(ec);
+-        return 0;
+-}
+-#endif /* splint */
+-#endif /* USE_ECDSA */
+-
+-ldns_rdf *
+-ldns_sign_public_evp(ldns_buffer *to_sign,
+-				 EVP_PKEY *key,
+-				 const EVP_MD *digest_type)
+-{
+-	unsigned int siglen;
+-	ldns_rdf *sigdata_rdf;
+-	ldns_buffer *b64sig;
+-	EVP_MD_CTX ctx;
+-	const EVP_MD *md_type;
+-	int r;
+-
+-	siglen = 0;
+-	b64sig = ldns_buffer_new(LDNS_MAX_PACKETLEN);
+-	if (!b64sig) {
+-		return NULL;
+-	}
+-
+-	/* initializes a signing context */
+-	md_type = digest_type;
+-	if(!md_type) {
+-		/* unknown message difest */
+-		ldns_buffer_free(b64sig);
+-		return NULL;
+-	}
+-
+-	EVP_MD_CTX_init(&ctx);
+-	r = EVP_SignInit(&ctx, md_type);
+-	if(r == 1) {
+-		r = EVP_SignUpdate(&ctx, (unsigned char*)
+-					    ldns_buffer_begin(to_sign),
+-					    ldns_buffer_position(to_sign));
+-	} else {
+-		ldns_buffer_free(b64sig);
+-		return NULL;
+-	}
+-	if(r == 1) {
+-		r = EVP_SignFinal(&ctx, (unsigned char*)
+-					   ldns_buffer_begin(b64sig), &siglen, key);
+-	} else {
+-		ldns_buffer_free(b64sig);
+-		return NULL;
+-	}
+-	if(r != 1) {
+-		ldns_buffer_free(b64sig);
+-		return NULL;
+-	}
+-
+-	/* unfortunately, OpenSSL output is differenct from DNS DSA format */
+-#ifndef S_SPLINT_S
+-	if (EVP_PKEY_type(key->type) == EVP_PKEY_DSA) {
+-		sigdata_rdf = ldns_convert_dsa_rrsig_asn12rdf(b64sig, siglen);
+-#ifdef USE_ECDSA
+-        } else if(EVP_PKEY_type(key->type) == EVP_PKEY_EC &&
+-                ldns_pkey_is_ecdsa(key)) {
+-                sigdata_rdf = ldns_convert_ecdsa_rrsig_asn12rdf(b64sig, siglen);
+-#endif
+-	} else {
+-		/* ok output for other types is the same */
+-		sigdata_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, siglen,
+-									 ldns_buffer_begin(b64sig));
+-	}
+-#endif /* splint */
+-	ldns_buffer_free(b64sig);
+-	EVP_MD_CTX_cleanup(&ctx);
+-	return sigdata_rdf;
+-}
+-
+-ldns_rdf *
+-ldns_sign_public_rsasha1(ldns_buffer *to_sign, RSA *key)
+-{
+-	unsigned char *sha1_hash;
+-	unsigned int siglen;
+-	ldns_rdf *sigdata_rdf;
+-	ldns_buffer *b64sig;
+-	int result;
+-
+-	siglen = 0;
+-	b64sig = ldns_buffer_new(LDNS_MAX_PACKETLEN);
+-	if (!b64sig) {
+-		return NULL;
+-	}
+-
+-	sha1_hash = SHA1((unsigned char*)ldns_buffer_begin(to_sign),
+-				  ldns_buffer_position(to_sign), NULL);
+-	if (!sha1_hash) {
+-		ldns_buffer_free(b64sig);
+-		return NULL;
+-	}
+-
+-	result = RSA_sign(NID_sha1, sha1_hash, SHA_DIGEST_LENGTH,
+-				   (unsigned char*)ldns_buffer_begin(b64sig),
+-				   &siglen, key);
+-	if (result != 1) {
+-		ldns_buffer_free(b64sig);
+-		return NULL;
+-	}
+-
+-	sigdata_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, siglen, 
+-								 ldns_buffer_begin(b64sig));
+-	ldns_buffer_free(b64sig); /* can't free this buffer ?? */
+-	return sigdata_rdf;
+-}
+-
+-ldns_rdf *
+-ldns_sign_public_rsamd5(ldns_buffer *to_sign, RSA *key)
+-{
+-	unsigned char *md5_hash;
+-	unsigned int siglen;
+-	ldns_rdf *sigdata_rdf;
+-	ldns_buffer *b64sig;
+-
+-	b64sig = ldns_buffer_new(LDNS_MAX_PACKETLEN);
+-	if (!b64sig) {
+-		return NULL;
+-	}
+-
+-	md5_hash = MD5((unsigned char*)ldns_buffer_begin(to_sign),
+-				ldns_buffer_position(to_sign), NULL);
+-	if (!md5_hash) {
+-		ldns_buffer_free(b64sig);
+-		return NULL;
+-	}
+-
+-	RSA_sign(NID_md5, md5_hash, MD5_DIGEST_LENGTH,
+-		    (unsigned char*)ldns_buffer_begin(b64sig),
+-		    &siglen, key);
+-
+-	sigdata_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, siglen,
+-								 ldns_buffer_begin(b64sig));
+-	ldns_buffer_free(b64sig);
+-	return sigdata_rdf;
+-}
+-#endif /* HAVE_SSL */
+-
+-/**
+- * Pushes all rrs from the rrsets of type A and AAAA on gluelist.
+- */
+-static ldns_status
+-ldns_dnssec_addresses_on_glue_list(
+-		ldns_dnssec_rrsets *cur_rrset,
+-		ldns_rr_list *glue_list)
+-{
+-	ldns_dnssec_rrs *cur_rrs;
+-	while (cur_rrset) {
+-		if (cur_rrset->type == LDNS_RR_TYPE_A 
+-				|| cur_rrset->type == LDNS_RR_TYPE_AAAA) {
+-			for (cur_rrs = cur_rrset->rrs; 
+-					cur_rrs; 
+-					cur_rrs = cur_rrs->next) {
+-				if (cur_rrs->rr) {
+-					if (!ldns_rr_list_push_rr(glue_list, 
+-							cur_rrs->rr)) {
+-						return LDNS_STATUS_MEM_ERR; 
+-						/* ldns_rr_list_push_rr()
+-						 * returns false when unable
+-						 * to increase the capacity
+-						 * of the ldsn_rr_list
+-						 */
+-					}
+-				}
+-			}
+-		}
+-		cur_rrset = cur_rrset->next;
+-	}
+-	return LDNS_STATUS_OK;
+-}
+-
+-/**
+- * Marks the names in the zone that are occluded. Those names will be skipped
+- * when walking the tree with the ldns_dnssec_name_node_next_nonglue()
+- * function. But watch out! Names that are partially occluded (like glue with
+- * the same name as the delegation) will not be marked and should specifically 
+- * be taken into account separately.
+- *
+- * When glue_list is given (not NULL), in the process of marking the names, all
+- * glue resource records will be pushed to that list, even glue at delegation names.
+- *
+- * \param[in] zone the zone in which to mark the names
+- * \param[in] glue_list the list to which to push the glue rrs
+- * \return LDNS_STATUS_OK on success, an error code otherwise
+- */
+-ldns_status
+-ldns_dnssec_zone_mark_and_get_glue(ldns_dnssec_zone *zone, 
+-	ldns_rr_list *glue_list)
+-{
+-	ldns_rbnode_t    *node;
+-	ldns_dnssec_name *name;
+-	ldns_rdf         *owner;
+-	ldns_rdf         *cut = NULL; /* keeps track of zone cuts */
+-	/* When the cut is caused by a delegation, below_delegation will be 1.
+-	 * When caused by a DNAME, below_delegation will be 0.
+-	 */
+-	int below_delegation = -1; /* init suppresses comiler warning */
+-	ldns_status s;
+-
+-	if (!zone || !zone->names) {
+-		return LDNS_STATUS_NULL;
+-	}
+-	for (node = ldns_rbtree_first(zone->names); 
+-			node != LDNS_RBTREE_NULL; 
+-			node = ldns_rbtree_next(node)) {
+-		name = (ldns_dnssec_name *) node->data;
+-		owner = ldns_dnssec_name_name(name);
+-
+-		if (cut) { 
+-			/* The previous node was a zone cut, or a subdomain
+-			 * below a zone cut. Is this node (still) a subdomain
+-			 * below the cut? Then the name is occluded. Unless
+-			 * the name contains a SOA, after which we are 
+-			 * authoritative again.
+-			 *
+-			 * FIXME! If there are labels in between the SOA and
+-			 * the cut, going from the authoritative space (below
+-			 * the SOA) up into occluded space again, will not be
+-			 * detected with the contruct below!
+-			 */
+-			if (ldns_dname_is_subdomain(owner, cut) &&
+-					!ldns_dnssec_rrsets_contains_type(
+-					name->rrsets, LDNS_RR_TYPE_SOA)) {
+-
+-				if (below_delegation && glue_list) {
+-					s = ldns_dnssec_addresses_on_glue_list(
+-						name->rrsets, glue_list);
+-					if (s != LDNS_STATUS_OK) {
+-						return s;
+-					}
+-				}
+-				name->is_glue = true; /* Mark occluded name! */
+-				continue;
+-			} else {
+-				cut = NULL;
+-			}
+-		}
+-
+-		/* The node is not below a zone cut. Is it a zone cut itself?
+-		 * Everything below a SOA is authoritative of course; Except
+-		 * when the name also contains a DNAME :).
+-		 */
+-		if (ldns_dnssec_rrsets_contains_type(
+-				name->rrsets, LDNS_RR_TYPE_NS)
+-			    && !ldns_dnssec_rrsets_contains_type(
+-				name->rrsets, LDNS_RR_TYPE_SOA)) {
+-			cut = owner;
+-			below_delegation = 1;
+-			if (glue_list) { /* record glue on the zone cut */
+-				s = ldns_dnssec_addresses_on_glue_list(
+-					name->rrsets, glue_list);
+-				if (s != LDNS_STATUS_OK) {
+-					return s;
+-				}
+-			}
+-		} else if (ldns_dnssec_rrsets_contains_type(
+-				name->rrsets, LDNS_RR_TYPE_DNAME)) {
+-			cut = owner;
+-			below_delegation = 0;
+-		}
+-	}
+-	return LDNS_STATUS_OK;
+-}
+-
+-/**
+- * Marks the names in the zone that are occluded. Those names will be skipped
+- * when walking the tree with the ldns_dnssec_name_node_next_nonglue()
+- * function. But watch out! Names that are partially occluded (like glue with
+- * the same name as the delegation) will not be marked and should specifically 
+- * be taken into account separately.
+- *
+- * \param[in] zone the zone in which to mark the names
+- * \return LDNS_STATUS_OK on success, an error code otherwise
+- */
+-ldns_status
+-ldns_dnssec_zone_mark_glue(ldns_dnssec_zone *zone)
+-{
+-	return ldns_dnssec_zone_mark_and_get_glue(zone, NULL);
+-}
+-
+-ldns_rbnode_t *
+-ldns_dnssec_name_node_next_nonglue(ldns_rbnode_t *node)
+-{
+-	ldns_rbnode_t *next_node = NULL;
+-	ldns_dnssec_name *next_name = NULL;
+-	bool done = false;
+-
+-	if (node == LDNS_RBTREE_NULL) {
+-		return NULL;
+-	}
+-	next_node = node;
+-	while (!done) {
+-		if (next_node == LDNS_RBTREE_NULL) {
+-			return NULL;
+-		} else {
+-			next_name = (ldns_dnssec_name *)next_node->data;
+-			if (!next_name->is_glue) {
+-				done = true;
+-			} else {
+-				next_node = ldns_rbtree_next(next_node);
+-			}
+-		}
+-	}
+-	return next_node;
+-}
+-
+-ldns_status
+-ldns_dnssec_zone_create_nsecs(ldns_dnssec_zone *zone,
+-                              ldns_rr_list *new_rrs)
+-{
+-
+-	ldns_rbnode_t *first_node, *cur_node, *next_node;
+-	ldns_dnssec_name *cur_name, *next_name;
+-	ldns_rr *nsec_rr;
+-	uint32_t nsec_ttl;
+-	ldns_dnssec_rrsets *soa;
+-
+-	/* the TTL of NSEC rrs should be set to the minimum TTL of
+-	 * the zone SOA (RFC4035 Section 2.3)
+-	 */
+-	soa = ldns_dnssec_name_find_rrset(zone->soa, LDNS_RR_TYPE_SOA);
+-
+-	/* did the caller actually set it? if not,
+-	 * fall back to default ttl
+-	 */
+-	if (soa && soa->rrs && soa->rrs->rr
+-			&& (ldns_rr_rdf(soa->rrs->rr, 6) != NULL)) {
+-		nsec_ttl = ldns_rdf2native_int32(ldns_rr_rdf(soa->rrs->rr, 6));
+-	} else {
+-		nsec_ttl = LDNS_DEFAULT_TTL;
+-	}
+-
+-	first_node = ldns_dnssec_name_node_next_nonglue(
+-			       ldns_rbtree_first(zone->names));
+-	cur_node = first_node;
+-	if (cur_node) {
+-		next_node = ldns_dnssec_name_node_next_nonglue(
+-			           ldns_rbtree_next(cur_node));
+-	} else {
+-		next_node = NULL;
+-	}
+-
+-	while (cur_node && next_node) {
+-		cur_name = (ldns_dnssec_name *)cur_node->data;
+-		next_name = (ldns_dnssec_name *)next_node->data;
+-		nsec_rr = ldns_dnssec_create_nsec(cur_name,
+-		                                  next_name,
+-		                                  LDNS_RR_TYPE_NSEC);
+-		ldns_rr_set_ttl(nsec_rr, nsec_ttl);
+-		if(ldns_dnssec_name_add_rr(cur_name, nsec_rr)!=LDNS_STATUS_OK){
+-			ldns_rr_free(nsec_rr);
+-			return LDNS_STATUS_ERR;
+-		}
+-		ldns_rr_list_push_rr(new_rrs, nsec_rr);
+-		cur_node = next_node;
+-		if (cur_node) {
+-			next_node = ldns_dnssec_name_node_next_nonglue(
+-                               ldns_rbtree_next(cur_node));
+-		}
+-	}
+-
+-	if (cur_node && !next_node) {
+-		cur_name = (ldns_dnssec_name *)cur_node->data;
+-		next_name = (ldns_dnssec_name *)first_node->data;
+-		nsec_rr = ldns_dnssec_create_nsec(cur_name,
+-		                                  next_name,
+-		                                  LDNS_RR_TYPE_NSEC);
+-		ldns_rr_set_ttl(nsec_rr, nsec_ttl);
+-		if(ldns_dnssec_name_add_rr(cur_name, nsec_rr)!=LDNS_STATUS_OK){
+-			ldns_rr_free(nsec_rr);
+-			return LDNS_STATUS_ERR;
+-		}
+-		ldns_rr_list_push_rr(new_rrs, nsec_rr);
+-	} else {
+-		printf("error\n");
+-	}
+-
+-	return LDNS_STATUS_OK;
+-}
+-
+-#ifdef HAVE_SSL
+-static void
+-ldns_hashed_names_node_free(ldns_rbnode_t *node, void *arg) {
+-	(void) arg;
+-	LDNS_FREE(node);
+-}
+-
+-static ldns_status
+-ldns_dnssec_zone_create_nsec3s_mkmap(ldns_dnssec_zone *zone,
+-		ldns_rr_list *new_rrs,
+-		uint8_t algorithm,
+-		uint8_t flags,
+-		uint16_t iterations,
+-		uint8_t salt_length,
+-		uint8_t *salt,
+-		ldns_rbtree_t **map)
+-{
+-	ldns_rbnode_t *first_name_node;
+-	ldns_rbnode_t *current_name_node;
+-	ldns_dnssec_name *current_name;
+-	ldns_status result = LDNS_STATUS_OK;
+-	ldns_rr *nsec_rr;
+-	ldns_rr_list *nsec3_list;
+-	uint32_t nsec_ttl;
+-	ldns_dnssec_rrsets *soa;
+-	ldns_rbnode_t *hashmap_node;
+-
+-	if (!zone || !new_rrs || !zone->names) {
+-		return LDNS_STATUS_ERR;
+-	}
+-
+-	/* the TTL of NSEC rrs should be set to the minimum TTL of
+-	 * the zone SOA (RFC4035 Section 2.3)
+-	 */
+-	soa = ldns_dnssec_name_find_rrset(zone->soa, LDNS_RR_TYPE_SOA);
+-
+-	/* did the caller actually set it? if not,
+-	 * fall back to default ttl
+-	 */
+-	if (soa && soa->rrs && soa->rrs->rr
+-			&& ldns_rr_rdf(soa->rrs->rr, 6) != NULL) {
+-		nsec_ttl = ldns_rdf2native_int32(ldns_rr_rdf(soa->rrs->rr, 6));
+-	} else {
+-		nsec_ttl = LDNS_DEFAULT_TTL;
+-	}
+-
+-	if (zone->hashed_names) {
+-		ldns_traverse_postorder(zone->hashed_names,
+-				ldns_hashed_names_node_free, NULL);
+-		LDNS_FREE(zone->hashed_names);
+-	}
+-	zone->hashed_names = ldns_rbtree_create(ldns_dname_compare_v);
+-	if (zone->hashed_names && map) {
+-		*map = zone->hashed_names;
+-	}
+-
+-	first_name_node = ldns_dnssec_name_node_next_nonglue(
+-					  ldns_rbtree_first(zone->names));
+-
+-	current_name_node = first_name_node;
+-
+-	while (current_name_node && current_name_node != LDNS_RBTREE_NULL &&
+-			result == LDNS_STATUS_OK) {
+-
+-		current_name = (ldns_dnssec_name *) current_name_node->data;
+-		nsec_rr = ldns_dnssec_create_nsec3(current_name,
+-		                                   NULL,
+-		                                   zone->soa->name,
+-		                                   algorithm,
+-		                                   flags,
+-		                                   iterations,
+-		                                   salt_length,
+-		                                   salt);
+-		/* by default, our nsec based generator adds rrsigs
+-		 * remove the bitmap for empty nonterminals */
+-		if (!current_name->rrsets) {
+-			ldns_rdf_deep_free(ldns_rr_pop_rdf(nsec_rr));
+-		}
+-		ldns_rr_set_ttl(nsec_rr, nsec_ttl);
+-		result = ldns_dnssec_name_add_rr(current_name, nsec_rr);
+-		ldns_rr_list_push_rr(new_rrs, nsec_rr);
+-		if (ldns_rr_owner(nsec_rr)) {
+-			hashmap_node = LDNS_MALLOC(ldns_rbnode_t);
+-			if (hashmap_node == NULL) {
+-				return LDNS_STATUS_MEM_ERR;
+-			}
+-			current_name->hashed_name = 
+-				ldns_dname_label(ldns_rr_owner(nsec_rr), 0);
+-
+-			if (current_name->hashed_name == NULL) {
+-				LDNS_FREE(hashmap_node);
+-				return LDNS_STATUS_MEM_ERR;
+-			}
+-			hashmap_node->key  = current_name->hashed_name;
+-			hashmap_node->data = current_name;
+-
+-			if (! ldns_rbtree_insert(zone->hashed_names
+-						, hashmap_node)) {
+-				LDNS_FREE(hashmap_node);
+-			}
+-		}
+-		current_name_node = ldns_dnssec_name_node_next_nonglue(
+-		                   ldns_rbtree_next(current_name_node));
+-	}
+-	if (result != LDNS_STATUS_OK) {
+-		return result;
+-	}
+-
+-	/* Make sorted list of nsec3s (via zone->hashed_names)
+-	 */
+-	nsec3_list = ldns_rr_list_new();
+-	if (nsec3_list == NULL) {
+-		return LDNS_STATUS_MEM_ERR;
+-	}
+-	for ( hashmap_node  = ldns_rbtree_first(zone->hashed_names)
+-	    ; hashmap_node != LDNS_RBTREE_NULL
+-	    ; hashmap_node  = ldns_rbtree_next(hashmap_node)
+-	    ) {
+-		current_name = (ldns_dnssec_name *) hashmap_node->data;
+-		nsec_rr = ((ldns_dnssec_name *) hashmap_node->data)->nsec;
+-		if (nsec_rr) {
+-			ldns_rr_list_push_rr(nsec3_list, nsec_rr);
+-		}
+-	}
+-	result = ldns_dnssec_chain_nsec3_list(nsec3_list);
+-	ldns_rr_list_free(nsec3_list);
+-
+-	return result;
+-}
+-
+-ldns_status
+-ldns_dnssec_zone_create_nsec3s(ldns_dnssec_zone *zone,
+-		ldns_rr_list *new_rrs,
+-		uint8_t algorithm,
+-		uint8_t flags,
+-		uint16_t iterations,
+-		uint8_t salt_length,
+-		uint8_t *salt)
+-{
+-	return ldns_dnssec_zone_create_nsec3s_mkmap(zone, new_rrs, algorithm,
+-		       	flags, iterations, salt_length, salt, NULL);
+-
+-}
+-#endif /* HAVE_SSL */
+-
+-ldns_dnssec_rrs *
+-ldns_dnssec_remove_signatures( ldns_dnssec_rrs *signatures
+-			     , ATTR_UNUSED(ldns_key_list *key_list)
+-			     , int (*func)(ldns_rr *, void *)
+-			     , void *arg
+-			     )
+-{
+-	ldns_dnssec_rrs *base_rrs = signatures;
+-	ldns_dnssec_rrs *cur_rr = base_rrs;
+-	ldns_dnssec_rrs *prev_rr = NULL;
+-	ldns_dnssec_rrs *next_rr;
+-
+-	uint16_t keytag;
+-	size_t i;
+-
+-	if (!cur_rr) {
+-		switch(func(NULL, arg)) {
+-		case LDNS_SIGNATURE_LEAVE_ADD_NEW:
+-		case LDNS_SIGNATURE_REMOVE_ADD_NEW:
+-		break;
+-		case LDNS_SIGNATURE_LEAVE_NO_ADD:
+-		case LDNS_SIGNATURE_REMOVE_NO_ADD:
+-		ldns_key_list_set_use(key_list, false);
+-		break;
+-		default:
+-#ifdef STDERR_MSGS
+-			fprintf(stderr, "[XX] unknown return value from callback\n");
+-#endif
+-			break;
+-		}
+-		return NULL;
+-	}
+-	(void)func(cur_rr->rr, arg);
+-
+-	while (cur_rr) {
+-		next_rr = cur_rr->next;
+-
+-		switch (func(cur_rr->rr, arg)) {
+-		case  LDNS_SIGNATURE_LEAVE_ADD_NEW:
+-			prev_rr = cur_rr;
+-			break;
+-		case LDNS_SIGNATURE_LEAVE_NO_ADD:
+-			keytag = ldns_rdf2native_int16(
+-					   ldns_rr_rrsig_keytag(cur_rr->rr));
+-			for (i = 0; i < ldns_key_list_key_count(key_list); i++) {
+-				if (ldns_key_keytag(ldns_key_list_key(key_list, i)) ==
+-				    keytag) {
+-					ldns_key_set_use(ldns_key_list_key(key_list, i),
+-								  false);
+-				}
+-			}
+-			prev_rr = cur_rr;
+-			break;
+-		case LDNS_SIGNATURE_REMOVE_NO_ADD:
+-			keytag = ldns_rdf2native_int16(
+-					   ldns_rr_rrsig_keytag(cur_rr->rr));
+-			for (i = 0; i < ldns_key_list_key_count(key_list); i++) {
+-				if (ldns_key_keytag(ldns_key_list_key(key_list, i))
+-				    == keytag) {
+-					ldns_key_set_use(ldns_key_list_key(key_list, i),
+-								  false);
+-				}
+-			}
+-			if (prev_rr) {
+-				prev_rr->next = next_rr;
+-			} else {
+-				base_rrs = next_rr;
+-			}
+-			LDNS_FREE(cur_rr);
+-			break;
+-		case LDNS_SIGNATURE_REMOVE_ADD_NEW:
+-			if (prev_rr) {
+-				prev_rr->next = next_rr;
+-			} else {
+-				base_rrs = next_rr;
+-			}
+-			LDNS_FREE(cur_rr);
+-			break;
+-		default:
+-#ifdef STDERR_MSGS
+-			fprintf(stderr, "[XX] unknown return value from callback\n");
+-#endif
+-			break;
+-		}
+-		cur_rr = next_rr;
+-	}
+-
+-	return base_rrs;
+-}
+-
+-#ifdef HAVE_SSL
+-ldns_status
+-ldns_dnssec_zone_create_rrsigs(ldns_dnssec_zone *zone,
+-                               ldns_rr_list *new_rrs,
+-                               ldns_key_list *key_list,
+-                               int (*func)(ldns_rr *, void*),
+-                               void *arg)
+-{
+-	return ldns_dnssec_zone_create_rrsigs_flg(zone, new_rrs, key_list,
+-		func, arg, 0);
+-}
+-
+-/** If there are KSKs use only them and mark ZSKs unused */
+-static void
+-ldns_key_list_filter_for_dnskey(ldns_key_list *key_list)
+-{
+-	int saw_ksk = 0;
+-	size_t i;
+-	for(i=0; i<ldns_key_list_key_count(key_list); i++)
+-		if((ldns_key_flags(ldns_key_list_key(key_list, i))&LDNS_KEY_SEP_KEY)) {
+-			saw_ksk = 1;
+-			break;
+-		}
+-	if(!saw_ksk)
+-		return;
+-	for(i=0; i<ldns_key_list_key_count(key_list); i++)
+-		if(!(ldns_key_flags(ldns_key_list_key(key_list, i))&LDNS_KEY_SEP_KEY))
+-			ldns_key_set_use(ldns_key_list_key(key_list, i), 0);
+-}
+-
+-/** If there are no ZSKs use KSK as ZSK */
+-static void
+-ldns_key_list_filter_for_non_dnskey(ldns_key_list *key_list)
+-{
+-	int saw_zsk = 0;
+-	size_t i;
+-	for(i=0; i<ldns_key_list_key_count(key_list); i++)
+-		if(!(ldns_key_flags(ldns_key_list_key(key_list, i))&LDNS_KEY_SEP_KEY)) {
+-			saw_zsk = 1;
+-			break;
+-		}
+-	if(!saw_zsk)
+-		return;
+-	/* else filter all KSKs */
+-	for(i=0; i<ldns_key_list_key_count(key_list); i++)
+-		if((ldns_key_flags(ldns_key_list_key(key_list, i))&LDNS_KEY_SEP_KEY))
+-			ldns_key_set_use(ldns_key_list_key(key_list, i), 0);
+-}
+-
+-ldns_status
+-ldns_dnssec_zone_create_rrsigs_flg( ldns_dnssec_zone *zone
+-				  , ldns_rr_list *new_rrs
+-				  , ldns_key_list *key_list
+-				  , int (*func)(ldns_rr *, void*)
+-				  , void *arg
+-				  , int flags
+-				  )
+-{
+-	ldns_status result = LDNS_STATUS_OK;
+-
+-	ldns_rbnode_t *cur_node;
+-	ldns_rr_list *rr_list;
+-
+-	ldns_dnssec_name *cur_name;
+-	ldns_dnssec_rrsets *cur_rrset;
+-	ldns_dnssec_rrs *cur_rr;
+-
+-	ldns_rr_list *siglist;
+-
+-	size_t i;
+-
+-	int on_delegation_point = 0; /* handle partially occluded names */
+-
+-	ldns_rr_list *pubkey_list = ldns_rr_list_new();
+-	for (i = 0; i<ldns_key_list_key_count(key_list); i++) {
+-		ldns_rr_list_push_rr( pubkey_list
+-				    , ldns_key2rr(ldns_key_list_key(
+-							key_list, i))
+-				    );
+-	}
+-	/* TODO: callback to see is list should be signed */
+-	/* TODO: remove 'old' signatures from signature list */
+-	cur_node = ldns_rbtree_first(zone->names);
+-	while (cur_node != LDNS_RBTREE_NULL) {
+-		cur_name = (ldns_dnssec_name *) cur_node->data;
+-
+-		if (!cur_name->is_glue) {
+-			on_delegation_point = ldns_dnssec_rrsets_contains_type(
+-					cur_name->rrsets, LDNS_RR_TYPE_NS)
+-				&& !ldns_dnssec_rrsets_contains_type(
+-					cur_name->rrsets, LDNS_RR_TYPE_SOA);
+-			cur_rrset = cur_name->rrsets;
+-			while (cur_rrset) {
+-				/* reset keys to use */
+-				ldns_key_list_set_use(key_list, true);
+-
+-				/* walk through old sigs, remove the old,
+-				   and mark which keys (not) to use) */
+-				cur_rrset->signatures =
+-					ldns_dnssec_remove_signatures(cur_rrset->signatures,
+-											key_list,
+-											func,
+-											arg);
+-				if(!(flags&LDNS_SIGN_DNSKEY_WITH_ZSK) &&
+-					cur_rrset->type == LDNS_RR_TYPE_DNSKEY)
+-					ldns_key_list_filter_for_dnskey(key_list);
+-
+-				if(cur_rrset->type != LDNS_RR_TYPE_DNSKEY)
+-					ldns_key_list_filter_for_non_dnskey(key_list);
+-
+-				/* TODO: just set count to zero? */
+-				rr_list = ldns_rr_list_new();
+-
+-				cur_rr = cur_rrset->rrs;
+-				while (cur_rr) {
+-					ldns_rr_list_push_rr(rr_list, cur_rr->rr);
+-					cur_rr = cur_rr->next;
+-				}
+-
+-				/* only sign non-delegation RRsets */
+-				/* (glue should have been marked earlier, 
+-				 *  except on the delegation points itself) */
+-				if (!on_delegation_point ||
+-						ldns_rr_list_type(rr_list) 
+-							== LDNS_RR_TYPE_DS ||
+-						ldns_rr_list_type(rr_list) 
+-							== LDNS_RR_TYPE_NSEC ||
+-						ldns_rr_list_type(rr_list) 
+-							== LDNS_RR_TYPE_NSEC3) {
+-					siglist = ldns_sign_public(rr_list, key_list);
+-					for (i = 0; i < ldns_rr_list_rr_count(siglist); i++) {
+-						if (cur_rrset->signatures) {
+-							result = ldns_dnssec_rrs_add_rr(cur_rrset->signatures,
+-											   ldns_rr_list_rr(siglist,
+-														    i));
+-						} else {
+-							cur_rrset->signatures = ldns_dnssec_rrs_new();
+-							cur_rrset->signatures->rr =
+-								ldns_rr_list_rr(siglist, i);
+-						}
+-						if (new_rrs) {
+-							ldns_rr_list_push_rr(new_rrs,
+-												 ldns_rr_list_rr(siglist,
+-															  i));
+-						}
+-					}
+-					ldns_rr_list_free(siglist);
+-				}
+-
+-				ldns_rr_list_free(rr_list);
+-
+-				cur_rrset = cur_rrset->next;
+-			}
+-
+-			/* sign the nsec */
+-			ldns_key_list_set_use(key_list, true);
+-			cur_name->nsec_signatures =
+-				ldns_dnssec_remove_signatures(cur_name->nsec_signatures,
+-										key_list,
+-										func,
+-										arg);
+-			ldns_key_list_filter_for_non_dnskey(key_list);
+-
+-			rr_list = ldns_rr_list_new();
+-			ldns_rr_list_push_rr(rr_list, cur_name->nsec);
+-			siglist = ldns_sign_public(rr_list, key_list);
+-
+-			for (i = 0; i < ldns_rr_list_rr_count(siglist); i++) {
+-				if (cur_name->nsec_signatures) {
+-					result = ldns_dnssec_rrs_add_rr(cur_name->nsec_signatures,
+-									   ldns_rr_list_rr(siglist, i));
+-				} else {
+-					cur_name->nsec_signatures = ldns_dnssec_rrs_new();
+-					cur_name->nsec_signatures->rr =
+-						ldns_rr_list_rr(siglist, i);
+-				}
+-				if (new_rrs) {
+-					ldns_rr_list_push_rr(new_rrs,
+-								 ldns_rr_list_rr(siglist, i));
+-				}
+-			}
+-
+-			ldns_rr_list_free(siglist);
+-			ldns_rr_list_free(rr_list);
+-		}
+-		cur_node = ldns_rbtree_next(cur_node);
+-	}
+-
+-	ldns_rr_list_deep_free(pubkey_list);
+-	return result;
+-}
+-
+-ldns_status
+-ldns_dnssec_zone_sign(ldns_dnssec_zone *zone,
+-				  ldns_rr_list *new_rrs,
+-				  ldns_key_list *key_list,
+-				  int (*func)(ldns_rr *, void *),
+-				  void *arg)
+-{
+-	return ldns_dnssec_zone_sign_flg(zone, new_rrs, key_list, func, arg, 0);
+-}
+-
+-ldns_status
+-ldns_dnssec_zone_sign_flg(ldns_dnssec_zone *zone,
+-				  ldns_rr_list *new_rrs,
+-				  ldns_key_list *key_list,
+-				  int (*func)(ldns_rr *, void *),
+-				  void *arg,
+-				  int flags)
+-{
+-	ldns_status result = LDNS_STATUS_OK;
+-
+-	if (!zone || !new_rrs || !key_list) {
+-		return LDNS_STATUS_ERR;
+-	}
+-
+-	/* zone is already sorted */
+-	result = ldns_dnssec_zone_mark_glue(zone);
+-	if (result != LDNS_STATUS_OK) {
+-		return result;
+-	}
+-
+-	/* check whether we need to add nsecs */
+-	if (zone->names && !((ldns_dnssec_name *)zone->names->root->data)->nsec) {
+-		result = ldns_dnssec_zone_create_nsecs(zone, new_rrs);
+-		if (result != LDNS_STATUS_OK) {
+-			return result;
+-		}
+-	}
+-
+-	result = ldns_dnssec_zone_create_rrsigs_flg(zone,
+-					new_rrs,
+-					key_list,
+-					func,
+-					arg,
+-					flags);
+-
+-	return result;
+-}
+-
+-ldns_status
+-ldns_dnssec_zone_sign_nsec3(ldns_dnssec_zone *zone,
+-					   ldns_rr_list *new_rrs,
+-					   ldns_key_list *key_list,
+-					   int (*func)(ldns_rr *, void *),
+-					   void *arg,
+-					   uint8_t algorithm,
+-					   uint8_t flags,
+-					   uint16_t iterations,
+-					   uint8_t salt_length,
+-					   uint8_t *salt)
+-{
+-	return ldns_dnssec_zone_sign_nsec3_flg_mkmap(zone, new_rrs, key_list,
+-		func, arg, algorithm, flags, iterations, salt_length, salt, 0,
+-	       	NULL);
+-}
+-
+-ldns_status
+-ldns_dnssec_zone_sign_nsec3_flg_mkmap(ldns_dnssec_zone *zone,
+-		ldns_rr_list *new_rrs,
+-		ldns_key_list *key_list,
+-		int (*func)(ldns_rr *, void *),
+-		void *arg,
+-		uint8_t algorithm,
+-		uint8_t flags,
+-		uint16_t iterations,
+-		uint8_t salt_length,
+-		uint8_t *salt,
+-		int signflags,
+-		ldns_rbtree_t **map)
+-{
+-	ldns_rr *nsec3, *nsec3param;
+-	ldns_status result = LDNS_STATUS_OK;
+-
+-	/* zone is already sorted */
+-	result = ldns_dnssec_zone_mark_glue(zone);
+-	if (result != LDNS_STATUS_OK) {
+-		return result;
+-	}
+-
+-	/* TODO if there are already nsec3s presents and their
+-	 * parameters are the same as these, we don't have to recreate
+-	 */
+-	if (zone->names) {
+-		/* add empty nonterminals */
+-		result = ldns_dnssec_zone_add_empty_nonterminals(zone);
+-		if (result != LDNS_STATUS_OK) {
+-			return result;
+-		}
+-
+-		nsec3 = ((ldns_dnssec_name *)zone->names->root->data)->nsec;
+-		if (nsec3 && ldns_rr_get_type(nsec3) == LDNS_RR_TYPE_NSEC3) {
+-			/* no need to recreate */
+-		} else {
+-			if (!ldns_dnssec_zone_find_rrset(zone,
+-									   zone->soa->name,
+-									   LDNS_RR_TYPE_NSEC3PARAM)) {
+-				/* create and add the nsec3param rr */
+-				nsec3param =
+-					ldns_rr_new_frm_type(LDNS_RR_TYPE_NSEC3PARAM);
+-				ldns_rr_set_owner(nsec3param,
+-							   ldns_rdf_clone(zone->soa->name));
+-				ldns_nsec3_add_param_rdfs(nsec3param,
+-									 algorithm,
+-									 flags,
+-									 iterations,
+-									 salt_length,
+-									 salt);
+-				/* always set bit 7 of the flags to zero, according to
+-				 * rfc5155 section 11. The bits are counted from right to left,
+-				 * so bit 7 in rfc5155 is bit 0 in ldns */
+-				ldns_set_bit(ldns_rdf_data(ldns_rr_rdf(nsec3param, 1)), 0, 0);
+-				result = ldns_dnssec_zone_add_rr(zone, nsec3param);
+-				if (result != LDNS_STATUS_OK) {
+-					return result;
+-				}
+-				ldns_rr_list_push_rr(new_rrs, nsec3param);
+-			}
+-			result = ldns_dnssec_zone_create_nsec3s_mkmap(zone,
+-											new_rrs,
+-											algorithm,
+-											flags,
+-											iterations,
+-											salt_length,
+-											salt,
+-											map);
+-			if (result != LDNS_STATUS_OK) {
+-				return result;
+-			}
+-		}
+-
+-		result = ldns_dnssec_zone_create_rrsigs_flg(zone,
+-						new_rrs,
+-						key_list,
+-						func,
+-						arg,
+-						signflags);
+-	}
+-
+-	return result;
+-}
+-
+-ldns_status
+-ldns_dnssec_zone_sign_nsec3_flg(ldns_dnssec_zone *zone,
+-		ldns_rr_list *new_rrs,
+-		ldns_key_list *key_list,
+-		int (*func)(ldns_rr *, void *),
+-		void *arg,
+-		uint8_t algorithm,
+-		uint8_t flags,
+-		uint16_t iterations,
+-		uint8_t salt_length,
+-		uint8_t *salt,
+-		int signflags)
+-{
+-	return ldns_dnssec_zone_sign_nsec3_flg_mkmap(zone, new_rrs, key_list,
+-		func, arg, algorithm, flags, iterations, salt_length, salt,
+-		signflags, NULL);
+-}
+-
+-ldns_zone *
+-ldns_zone_sign(const ldns_zone *zone, ldns_key_list *key_list)
+-{
+-	ldns_dnssec_zone *dnssec_zone;
+-	ldns_zone *signed_zone;
+-	ldns_rr_list *new_rrs;
+-	size_t i;
+-
+-	signed_zone = ldns_zone_new();
+-	dnssec_zone = ldns_dnssec_zone_new();
+-
+-	(void) ldns_dnssec_zone_add_rr(dnssec_zone, ldns_zone_soa(zone));
+-	ldns_zone_set_soa(signed_zone, ldns_rr_clone(ldns_zone_soa(zone)));
+-
+-	for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(zone)); i++) {
+-		(void) ldns_dnssec_zone_add_rr(dnssec_zone,
+-								 ldns_rr_list_rr(ldns_zone_rrs(zone),
+-											  i));
+-		ldns_zone_push_rr(signed_zone,
+-					   ldns_rr_clone(ldns_rr_list_rr(ldns_zone_rrs(zone),
+-											   i)));
+-	}
+-
+-	new_rrs = ldns_rr_list_new();
+-	(void) ldns_dnssec_zone_sign(dnssec_zone,
+-						    new_rrs,
+-						    key_list,
+-						    ldns_dnssec_default_replace_signatures,
+-						    NULL);
+-
+-    	for (i = 0; i < ldns_rr_list_rr_count(new_rrs); i++) {
+-		ldns_rr_list_push_rr(ldns_zone_rrs(signed_zone),
+-						 ldns_rr_clone(ldns_rr_list_rr(new_rrs, i)));
+-	}
+-
+-	ldns_rr_list_deep_free(new_rrs);
+-	ldns_dnssec_zone_free(dnssec_zone);
+-
+-	return signed_zone;
+-}
+-
+-ldns_zone *
+-ldns_zone_sign_nsec3(ldns_zone *zone, ldns_key_list *key_list, uint8_t algorithm, uint8_t flags, uint16_t iterations, uint8_t salt_length, uint8_t *salt)
+-{
+-	ldns_dnssec_zone *dnssec_zone;
+-	ldns_zone *signed_zone;
+-	ldns_rr_list *new_rrs;
+-	size_t i;
+-
+-	signed_zone = ldns_zone_new();
+-	dnssec_zone = ldns_dnssec_zone_new();
+-
+-	(void) ldns_dnssec_zone_add_rr(dnssec_zone, ldns_zone_soa(zone));
+-	ldns_zone_set_soa(signed_zone, ldns_rr_clone(ldns_zone_soa(zone)));
+-
+-	for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(zone)); i++) {
+-		(void) ldns_dnssec_zone_add_rr(dnssec_zone,
+-								 ldns_rr_list_rr(ldns_zone_rrs(zone),
+-											  i));
+-		ldns_zone_push_rr(signed_zone, 
+-					   ldns_rr_clone(ldns_rr_list_rr(ldns_zone_rrs(zone),
+-											   i)));
+-	}
+-
+-	new_rrs = ldns_rr_list_new();
+-	(void) ldns_dnssec_zone_sign_nsec3(dnssec_zone,
+-								new_rrs,
+-								key_list,
+-								ldns_dnssec_default_replace_signatures,
+-								NULL,
+-								algorithm,
+-								flags,
+-								iterations,
+-								salt_length,
+-								salt);
+-
+-    	for (i = 0; i < ldns_rr_list_rr_count(new_rrs); i++) {
+-		ldns_rr_list_push_rr(ldns_zone_rrs(signed_zone),
+-						 ldns_rr_clone(ldns_rr_list_rr(new_rrs, i)));
+-	}
+-
+-	ldns_rr_list_deep_free(new_rrs);
+-	ldns_dnssec_zone_free(dnssec_zone);
+-
+-	return signed_zone;
+-}
+-#endif /* HAVE_SSL */
+-
+-
+diff --git a/src/ldns/dnssec_verify.c b/src/ldns/dnssec_verify.c
+deleted file mode 100644
+index 1af6635..0000000
+--- a/src/ldns/dnssec_verify.c
++++ /dev/null
+@@ -1,2684 +0,0 @@
+-#include <ldns/config.h>
+-
+-#include <ldns/ldns.h>
+-
+-#include <strings.h>
+-#include <time.h>
+-
+-#ifdef HAVE_SSL
+-/* this entire file is rather useless when you don't have
+- * crypto...
+- */
+-#include <openssl/ssl.h>
+-#include <openssl/evp.h>
+-#include <openssl/rand.h>
+-#include <openssl/err.h>
+-#include <openssl/md5.h>
+-
+-ldns_dnssec_data_chain *
+-ldns_dnssec_data_chain_new(void)
+-{
+-	ldns_dnssec_data_chain *nc = LDNS_CALLOC(ldns_dnssec_data_chain, 1);
+-        if(!nc) return NULL;
+-	/* 
+-	 * not needed anymore because CALLOC initalizes everything to zero.
+-
+-	nc->rrset = NULL;
+-	nc->parent_type = 0;
+-	nc->parent = NULL;
+-	nc->signatures = NULL;
+-	nc->packet_rcode = 0;
+-	nc->packet_qtype = 0;
+-	nc->packet_nodata = false;
+-
+-	 */
+-	return nc;
+-}
+-
+-void
+-ldns_dnssec_data_chain_free(ldns_dnssec_data_chain *chain)
+-{
+-	LDNS_FREE(chain);
+-}
+-
+-void
+-ldns_dnssec_data_chain_deep_free(ldns_dnssec_data_chain *chain)
+-{
+-	ldns_rr_list_deep_free(chain->rrset);
+-	ldns_rr_list_deep_free(chain->signatures);
+-	if (chain->parent) {
+-		ldns_dnssec_data_chain_deep_free(chain->parent);
+-	}
+-	LDNS_FREE(chain);
+-}
+-
+-void
+-ldns_dnssec_data_chain_print_fmt(FILE *out, const ldns_output_format *fmt,
+-		const ldns_dnssec_data_chain *chain)
+-{
+-	ldns_lookup_table *rcode;
+-	const ldns_rr_descriptor *rr_descriptor;
+-	if (chain) {
+-		ldns_dnssec_data_chain_print_fmt(out, fmt, chain->parent);
+-		if (ldns_rr_list_rr_count(chain->rrset) > 0) {
+-			rcode = ldns_lookup_by_id(ldns_rcodes,
+-								 (int) chain->packet_rcode);
+-			if (rcode) {
+-				fprintf(out, ";; rcode: %s\n", rcode->name);
+-			}
+-
+-			rr_descriptor = ldns_rr_descript(chain->packet_qtype);
+-			if (rr_descriptor && rr_descriptor->_name) {
+-				fprintf(out, ";; qtype: %s\n", rr_descriptor->_name);
+-			} else if (chain->packet_qtype != 0) {
+-				fprintf(out, "TYPE%u", 
+-					   chain->packet_qtype);
+-			}
+-			if (chain->packet_nodata) {
+-				fprintf(out, ";; NODATA response\n");
+-			}
+-			fprintf(out, "rrset:\n");
+-			ldns_rr_list_print_fmt(out, fmt, chain->rrset);
+-			fprintf(out, "sigs:\n");
+-			ldns_rr_list_print_fmt(out, fmt, chain->signatures);
+-			fprintf(out, "---\n");
+-		} else {
+-			fprintf(out, "<no data>\n");
+-		}
+-	}
+-}
+-void
+-ldns_dnssec_data_chain_print(FILE *out, const ldns_dnssec_data_chain *chain)
+-{
+-	ldns_dnssec_data_chain_print_fmt(
+-			out, ldns_output_format_default, chain);
+-}
+-
+-
+-static void
+-ldns_dnssec_build_data_chain_dnskey(ldns_resolver *res,
+-					    uint16_t qflags,
+-					    const ldns_pkt *pkt,
+-					    ldns_rr_list *signatures,
+-						ldns_dnssec_data_chain *new_chain,
+-						ldns_rdf *key_name,
+-						ldns_rr_class c) {
+-	ldns_rr_list *keys;
+-	ldns_pkt *my_pkt;
+-	if (signatures && ldns_rr_list_rr_count(signatures) > 0) {
+-		new_chain->signatures = ldns_rr_list_clone(signatures);
+-		new_chain->parent_type = 0;
+-
+-		keys = ldns_pkt_rr_list_by_name_and_type(
+-				  pkt,
+-				 key_name,
+-				 LDNS_RR_TYPE_DNSKEY,
+-				 LDNS_SECTION_ANY_NOQUESTION
+-			  );
+-		if (!keys) {
+-			my_pkt = ldns_resolver_query(res,
+-									key_name,
+-									LDNS_RR_TYPE_DNSKEY,
+-									c,
+-									qflags);
+-			if (my_pkt) {
+-			keys = ldns_pkt_rr_list_by_name_and_type(
+-					  my_pkt,
+-					 key_name,
+-					 LDNS_RR_TYPE_DNSKEY,
+-					 LDNS_SECTION_ANY_NOQUESTION
+-				  );
+-			new_chain->parent = ldns_dnssec_build_data_chain(res,
+-													qflags,
+-													keys,
+-													my_pkt,
+-													NULL);
+-			new_chain->parent->packet_qtype = LDNS_RR_TYPE_DNSKEY;
+-			ldns_pkt_free(my_pkt);
+-			}
+-		} else {
+-			new_chain->parent = ldns_dnssec_build_data_chain(res,
+-													qflags,
+-													keys,
+-													pkt,
+-													NULL);
+-			new_chain->parent->packet_qtype = LDNS_RR_TYPE_DNSKEY;
+-		}
+-		ldns_rr_list_deep_free(keys);
+-	}
+-}
+-
+-static void
+-ldns_dnssec_build_data_chain_other(ldns_resolver *res,
+-					    uint16_t qflags,
+-						ldns_dnssec_data_chain *new_chain,
+-						ldns_rdf *key_name,
+-						ldns_rr_class c,
+-						ldns_rr_list *dss)
+-{
+-	/* 'self-signed', parent is a DS */
+-	
+-	/* okay, either we have other keys signing the current one,
+-	 * or the current
+-	 * one should have a DS record in the parent zone.
+-	 * How do we find this out? Try both?
+-	 *
+-	 * request DNSKEYS for current zone,
+-	 * add all signatures to current level
+-	 */
+-	ldns_pkt *my_pkt;
+-	ldns_rr_list *signatures2;
+-	
+-	new_chain->parent_type = 1;
+-
+-	my_pkt = ldns_resolver_query(res,
+-							key_name,
+-							LDNS_RR_TYPE_DS,
+-							c,
+-							qflags);
+-	if (my_pkt) {
+-	dss = ldns_pkt_rr_list_by_name_and_type(my_pkt,
+-									key_name,
+-									LDNS_RR_TYPE_DS,
+-									LDNS_SECTION_ANY_NOQUESTION
+-									);
+-	if (dss) {
+-		new_chain->parent = ldns_dnssec_build_data_chain(res,
+-												qflags,
+-												dss,
+-												my_pkt,
+-												NULL);
+-		new_chain->parent->packet_qtype = LDNS_RR_TYPE_DS;
+-		ldns_rr_list_deep_free(dss);
+-	}
+-	ldns_pkt_free(my_pkt);
+-	}
+-
+-	my_pkt = ldns_resolver_query(res,
+-							key_name,
+-							LDNS_RR_TYPE_DNSKEY,
+-							c,
+-							qflags);
+-	if (my_pkt) {
+-	signatures2 = ldns_pkt_rr_list_by_name_and_type(my_pkt,
+-										   key_name,
+-										   LDNS_RR_TYPE_RRSIG,
+-										   LDNS_SECTION_ANSWER);
+-	if (signatures2) {
+-		if (new_chain->signatures) {
+-			printf("There were already sigs!\n");
+-			ldns_rr_list_deep_free(new_chain->signatures);
+-			printf("replacing the old sigs\n");
+-		}
+-		new_chain->signatures = signatures2;
+-	}
+-	ldns_pkt_free(my_pkt);
+-	}
+-}
+-
+-static ldns_dnssec_data_chain *
+-ldns_dnssec_build_data_chain_nokeyname(ldns_resolver *res,
+-                                       uint16_t qflags,
+-                                       ldns_rr *orig_rr,
+-                                       const ldns_rr_list *rrset,
+-                                       ldns_dnssec_data_chain *new_chain)
+-{
+-	ldns_rdf *possible_parent_name;
+-	ldns_pkt *my_pkt;
+-	/* apparently we were not able to find a signing key, so
+-	   we assume the chain ends here
+-	*/
+-	/* try parents for auth denial of DS */
+-	if (orig_rr) {
+-		possible_parent_name = ldns_rr_owner(orig_rr);
+-	} else if (rrset && ldns_rr_list_rr_count(rrset) > 0) {
+-		possible_parent_name = ldns_rr_owner(ldns_rr_list_rr(rrset, 0));
+-	} else {
+-		/* no information to go on, give up */
+-		return new_chain;
+-	}
+-
+-	my_pkt = ldns_resolver_query(res,
+-	              possible_parent_name,
+-	              LDNS_RR_TYPE_DS,
+-	              LDNS_RR_CLASS_IN,
+-	              qflags);
+-	if (!my_pkt) {
+-		return new_chain;
+-	}
+-
+-	if (ldns_pkt_ancount(my_pkt) > 0) {
+-		/* add error, no sigs but DS in parent */
+-		/*ldns_pkt_print(stdout, my_pkt);*/
+-		ldns_pkt_free(my_pkt);
+-	} else {
+-		/* are there signatures? */
+-		new_chain->parent =  ldns_dnssec_build_data_chain(res, 
+-		                          qflags, 
+-		                          NULL,
+-		                          my_pkt,
+-		                          NULL);
+-
+-		new_chain->parent->packet_qtype = LDNS_RR_TYPE_DS;
+-		
+-	}
+-	return new_chain;
+-}
+-
+-
+-ldns_dnssec_data_chain *
+-ldns_dnssec_build_data_chain(ldns_resolver *res,
+-					    uint16_t qflags,
+-					    const ldns_rr_list *rrset,
+-					    const ldns_pkt *pkt,
+-					    ldns_rr *orig_rr)
+-{
+-	ldns_rr_list *signatures = NULL;
+-	ldns_rr_list *dss = NULL;
+-	
+-	ldns_rr_list *my_rrset;
+-
+-	ldns_pkt *my_pkt;
+-
+-	ldns_rdf *name = NULL, *key_name = NULL;
+-	ldns_rr_type type = 0;
+-	ldns_rr_class c = 0;
+-
+-	bool other_rrset = false;
+-
+-	ldns_dnssec_data_chain *new_chain = ldns_dnssec_data_chain_new();
+-
+-	assert(pkt != NULL);
+-
+-	if (!ldns_dnssec_pkt_has_rrsigs(pkt)) {
+-		/* hmm. no dnssec data in the packet. go up to try and deny
+-		 * DS? */
+-		return new_chain;
+-	}
+-
+-	if (orig_rr) {
+-		new_chain->rrset = ldns_rr_list_new();
+-		ldns_rr_list_push_rr(new_chain->rrset, orig_rr);
+-		new_chain->parent = ldns_dnssec_build_data_chain(res,
+-											    qflags,
+-											    rrset,
+-											    pkt,
+-											    NULL);
+-		new_chain->packet_rcode = ldns_pkt_get_rcode(pkt);
+-		new_chain->packet_qtype = ldns_rr_get_type(orig_rr);
+-		if (ldns_pkt_ancount(pkt) == 0) {
+-			new_chain->packet_nodata = true;
+-		}
+-		return new_chain;
+-	}
+-	
+-	if (!rrset || ldns_rr_list_rr_count(rrset) < 1) {
+-		/* hmm, no data, do we have denial? only works if pkt was given,
+-		   otherwise caller has to do the check himself */
+-		new_chain->packet_nodata = true;
+-		if (pkt) {
+-			my_rrset = ldns_pkt_rr_list_by_type(pkt,
+-										 LDNS_RR_TYPE_NSEC,
+-										 LDNS_SECTION_ANY_NOQUESTION
+-										 );
+-			if (my_rrset) {
+-				if (ldns_rr_list_rr_count(my_rrset) > 0) {
+-					type = LDNS_RR_TYPE_NSEC;
+-					other_rrset = true;
+-				} else {
+-					ldns_rr_list_deep_free(my_rrset);
+-					my_rrset = NULL;
+-				}
+-			} else {
+-				/* nothing, try nsec3 */
+-				my_rrset = ldns_pkt_rr_list_by_type(pkt,
+-						     LDNS_RR_TYPE_NSEC3,
+-							LDNS_SECTION_ANY_NOQUESTION);
+-				if (my_rrset) {
+-					if (ldns_rr_list_rr_count(my_rrset) > 0) {
+-						type = LDNS_RR_TYPE_NSEC3;
+-						other_rrset = true;
+-					} else {
+-						ldns_rr_list_deep_free(my_rrset);
+-						my_rrset = NULL;
+-					}
+-				} else {
+-					/* nothing, stop */
+-					/* try parent zone? for denied insecure? */
+-					return new_chain;
+-				}
+-			}
+-		} else {
+-			return new_chain;
+-		}
+-	} else {
+-		my_rrset = (ldns_rr_list *) rrset;
+-	}
+-	
+-	if (my_rrset && ldns_rr_list_rr_count(my_rrset) > 0) {
+-		new_chain->rrset = ldns_rr_list_clone(my_rrset);
+-		name = ldns_rr_owner(ldns_rr_list_rr(my_rrset, 0));
+-		type = ldns_rr_get_type(ldns_rr_list_rr(my_rrset, 0));
+-		c = ldns_rr_get_class(ldns_rr_list_rr(my_rrset, 0));
+-	}
+-	
+-	if (other_rrset) {
+-		ldns_rr_list_deep_free(my_rrset);
+-	}
+-	
+-	/* normally there will only be 1 signature 'set'
+-	   but there can be more than 1 denial (wildcards)
+-	   so check for NSEC
+-	*/
+-	if (type == LDNS_RR_TYPE_NSEC || type == LDNS_RR_TYPE_NSEC3) {
+-		/* just throw in all signatures, the tree builder must sort
+-		   this out */
+-		if (pkt) {
+-			signatures = ldns_dnssec_pkt_get_rrsigs_for_type(pkt, type);
+-		} else {
+-			my_pkt = ldns_resolver_query(res, name, type, c, qflags);
+-			if (my_pkt) {
+-			signatures = ldns_dnssec_pkt_get_rrsigs_for_type(pkt, type);
+-			ldns_pkt_free(my_pkt);
+-			}
+-		}
+-	} else {
+-		if (pkt) {
+-			signatures =
+-				ldns_dnssec_pkt_get_rrsigs_for_name_and_type(pkt,
+-													name,
+-													type);
+-		}
+-		if (!signatures) {
+-			my_pkt = ldns_resolver_query(res, name, type, c, qflags);
+-			if (my_pkt) {
+-			signatures =
+-				ldns_dnssec_pkt_get_rrsigs_for_name_and_type(my_pkt,
+-													name,
+-													type);
+-			ldns_pkt_free(my_pkt);
+-			}
+-		}
+-	}
+-
+-	if (signatures && ldns_rr_list_rr_count(signatures) > 0) {
+-		key_name = ldns_rr_rdf(ldns_rr_list_rr(signatures, 0), 7);
+-	}
+-	if (!key_name) {
+-		if (signatures) {
+-			ldns_rr_list_deep_free(signatures);
+-		}
+-		return ldns_dnssec_build_data_chain_nokeyname(res,
+-		                                              qflags,
+-		                                              orig_rr,
+-		                                              rrset,
+-		                                              new_chain);
+-	}
+-	if (type != LDNS_RR_TYPE_DNSKEY) {
+-		ldns_dnssec_build_data_chain_dnskey(res,
+-		                                    qflags,
+-		                                    pkt,
+-		                                    signatures,
+-		                                    new_chain,
+-		                                    key_name,
+-		                                    c
+-		                                   );
+-	} else {
+-		ldns_dnssec_build_data_chain_other(res,
+-		                                   qflags,
+-		                                   new_chain,
+-		                                   key_name,
+-		                                   c,
+-		                                   dss
+-		                                  );
+-	}
+-	if (signatures) {
+-		ldns_rr_list_deep_free(signatures);
+-	}
+-	return new_chain;
+-}
+-
+-ldns_dnssec_trust_tree *
+-ldns_dnssec_trust_tree_new(void)
+-{
+-	ldns_dnssec_trust_tree *new_tree = LDNS_XMALLOC(ldns_dnssec_trust_tree,
+-										   1);
+-        if(!new_tree) return NULL;
+-	new_tree->rr = NULL;
+-	new_tree->rrset = NULL;
+-	new_tree->parent_count = 0;
+-
+-	return new_tree;
+-}
+-
+-void
+-ldns_dnssec_trust_tree_free(ldns_dnssec_trust_tree *tree)
+-{
+-	size_t i;
+-	if (tree) {
+-		for (i = 0; i < tree->parent_count; i++) {
+-			ldns_dnssec_trust_tree_free(tree->parents[i]);
+-		}
+-	}
+-	LDNS_FREE(tree);
+-}
+-
+-size_t
+-ldns_dnssec_trust_tree_depth(ldns_dnssec_trust_tree *tree)
+-{
+-	size_t result = 0;
+-	size_t parent = 0;
+-	size_t i;
+-	
+-	for (i = 0; i < tree->parent_count; i++) {
+-		parent = ldns_dnssec_trust_tree_depth(tree->parents[i]);
+-		if (parent > result) {
+-			result = parent;
+-		}
+-	}
+-	return 1 + result;
+-}
+-
+-/* TODO ldns_ */
+-static void
+-print_tabs(FILE *out, size_t nr, uint8_t *map, size_t treedepth)
+-{
+-	size_t i;
+-	for (i = 0; i < nr; i++) {
+-		if (i == nr - 1) {
+-			fprintf(out, "|---");
+-		} else if (map && i < treedepth && map[i] == 1) {
+-			fprintf(out, "|   ");
+-		} else {
+-			fprintf(out, "    ");
+-		}
+-	}
+-}
+-
+-static void
+-ldns_dnssec_trust_tree_print_sm_fmt(FILE *out, 
+-		const ldns_output_format *fmt,
+-		ldns_dnssec_trust_tree *tree,
+-		size_t tabs,
+-		bool extended,
+-		uint8_t *sibmap,
+-		size_t treedepth)
+-{
+-	size_t i;
+-	const ldns_rr_descriptor *descriptor;
+-	bool mapset = false;
+-	
+-	if (!sibmap) {
+-		treedepth = ldns_dnssec_trust_tree_depth(tree);
+-		sibmap = LDNS_XMALLOC(uint8_t, treedepth);
+-                if(!sibmap)
+-                        return; /* mem err */
+-		memset(sibmap, 0, treedepth);
+-		mapset = true;
+-	}
+-	
+-	if (tree) {
+-		if (tree->rr) {
+-			print_tabs(out, tabs, sibmap, treedepth);
+-			ldns_rdf_print(out, ldns_rr_owner(tree->rr));
+-			descriptor = ldns_rr_descript(ldns_rr_get_type(tree->rr));
+-
+-			if (descriptor->_name) {
+-				fprintf(out, " (%s", descriptor->_name);
+-			} else {
+-				fprintf(out, " (TYPE%d", 
+-					   ldns_rr_get_type(tree->rr));
+-			}
+-			if (tabs > 0) {
+-				if (ldns_rr_get_type(tree->rr) == LDNS_RR_TYPE_DNSKEY) {
+-					fprintf(out, " keytag: %u",
+-					        (unsigned int) ldns_calc_keytag(tree->rr));
+-					fprintf(out, " alg: ");
+-					ldns_rdf_print(out, ldns_rr_rdf(tree->rr, 2));
+-					fprintf(out, " flags: ");
+-					ldns_rdf_print(out, ldns_rr_rdf(tree->rr, 0));
+-				} else if (ldns_rr_get_type(tree->rr) == LDNS_RR_TYPE_DS) {
+-					fprintf(out, " keytag: ");
+-					ldns_rdf_print(out, ldns_rr_rdf(tree->rr, 0));
+-					fprintf(out, " digest type: ");
+-					ldns_rdf_print(out, ldns_rr_rdf(tree->rr, 2));
+-				}
+-				if (ldns_rr_get_type(tree->rr) == LDNS_RR_TYPE_NSEC) {
+-					fprintf(out, " ");
+-					ldns_rdf_print(out, ldns_rr_rdf(tree->rr, 0));
+-					fprintf(out, " ");
+-					ldns_rdf_print(out, ldns_rr_rdf(tree->rr, 1));
+-				}
+-			}
+-			
+-			fprintf(out, ")\n");
+-			for (i = 0; i < tree->parent_count; i++) {
+-				if (tree->parent_count > 1 && i < tree->parent_count - 1) {
+-					sibmap[tabs] = 1;
+-				} else {
+-					sibmap[tabs] = 0;
+-				}
+-				/* only print errors */
+-				if (ldns_rr_get_type(tree->parents[i]->rr) == 
+-				    LDNS_RR_TYPE_NSEC ||
+-				    ldns_rr_get_type(tree->parents[i]->rr) ==
+-				    LDNS_RR_TYPE_NSEC3) {
+-					if (tree->parent_status[i] == LDNS_STATUS_OK) {
+-						print_tabs(out, tabs + 1, sibmap, treedepth);
+-						if (tabs == 0 &&
+-						    ldns_rr_get_type(tree->rr) == LDNS_RR_TYPE_NS &&
+-							ldns_rr_rd_count(tree->rr) > 0) {
+-							fprintf(out, "Existence of DS is denied by:\n");
+-						} else {
+-							fprintf(out, "Existence is denied by:\n");
+-						}
+-					} else {
+-						/* NS records aren't signed */
+-						if (ldns_rr_get_type(tree->rr) == LDNS_RR_TYPE_NS) {
+-							fprintf(out, "Existence of DS is denied by:\n");
+-						} else {
+-							print_tabs(out, tabs + 1, sibmap, treedepth);
+-							fprintf(out,
+-								   "Error in denial of existence: %s\n",
+-								   ldns_get_errorstr_by_id(
+-									   tree->parent_status[i]));
+-						}
+-					}
+-				} else
+-					if (tree->parent_status[i] != LDNS_STATUS_OK) {
+-						print_tabs(out, tabs + 1, sibmap, treedepth);
+-						fprintf(out,
+-							   "%s:\n",
+-							   ldns_get_errorstr_by_id(
+-							       tree->parent_status[i]));
+-						if (tree->parent_status[i]
+-						    == LDNS_STATUS_SSL_ERR) {
+-							printf("; SSL Error: ");
+-							ERR_load_crypto_strings();
+-							ERR_print_errors_fp(stdout);
+-							printf("\n");
+-						}
+-						ldns_rr_print_fmt(out, fmt, 
+-							tree->
+-							parent_signature[i]);
+-						printf("For RRset:\n");
+-						ldns_rr_list_print_fmt(out, fmt,
+-								tree->rrset);
+-						printf("With key:\n");
+-						ldns_rr_print_fmt(out, fmt,
+-							tree->parents[i]->rr);
+-					}
+-				ldns_dnssec_trust_tree_print_sm_fmt(out, fmt,
+-						tree->parents[i],
+-						tabs+1,
+-						extended,
+-						sibmap,
+-						treedepth);
+-			}
+-		} else {
+-			print_tabs(out, tabs, sibmap, treedepth);
+-			fprintf(out, "<no data>\n");
+-		}
+-	} else {
+-		fprintf(out, "<null pointer>\n");
+-	}
+-	
+-	if (mapset) {
+-		LDNS_FREE(sibmap);
+-	}
+-}
+-
+-void
+-ldns_dnssec_trust_tree_print_fmt(FILE *out, const ldns_output_format *fmt,
+-		ldns_dnssec_trust_tree *tree,
+-		size_t tabs,
+-		bool extended)
+-{
+-	ldns_dnssec_trust_tree_print_sm_fmt(out, fmt, 
+-			tree, tabs, extended, NULL, 0);
+-}
+-
+-void
+-ldns_dnssec_trust_tree_print(FILE *out,
+-		ldns_dnssec_trust_tree *tree,
+-		size_t tabs,
+-		bool extended)
+-{
+-	ldns_dnssec_trust_tree_print_fmt(out, ldns_output_format_default, 
+-			tree, tabs, extended);
+-}
+-
+-
+-ldns_status
+-ldns_dnssec_trust_tree_add_parent(ldns_dnssec_trust_tree *tree,
+-                                  const ldns_dnssec_trust_tree *parent,
+-                                  const ldns_rr *signature,
+-                                  const ldns_status parent_status)
+-{
+-	if (tree
+-	    && parent
+-	    && tree->parent_count < LDNS_DNSSEC_TRUST_TREE_MAX_PARENTS) {
+-		/*
+-		  printf("Add parent for: ");
+-		  ldns_rr_print(stdout, tree->rr);
+-		  printf("parent: ");
+-		  ldns_rr_print(stdout, parent->rr);
+-		*/
+-		tree->parents[tree->parent_count] =
+-			(ldns_dnssec_trust_tree *) parent;
+-		tree->parent_status[tree->parent_count] = parent_status;
+-		tree->parent_signature[tree->parent_count] = (ldns_rr *) signature;
+-		tree->parent_count++;
+-		return LDNS_STATUS_OK;
+-	} else {
+-		return LDNS_STATUS_ERR;
+-	}
+-}
+-
+-/* if rr is null, take the first from the rrset */
+-ldns_dnssec_trust_tree *
+-ldns_dnssec_derive_trust_tree_time(
+-		ldns_dnssec_data_chain *data_chain, 
+-		ldns_rr *rr, 
+-		time_t check_time
+-		)
+-{
+-	ldns_rr_list *cur_rrset;
+-	ldns_rr_list *cur_sigs;
+-	ldns_rr *cur_rr = NULL;
+-	ldns_rr *cur_sig_rr;
+-	size_t i, j;
+-
+-	ldns_dnssec_trust_tree *new_tree = ldns_dnssec_trust_tree_new();
+-        if(!new_tree)
+-                return NULL;
+-	
+-	if (data_chain && data_chain->rrset) {
+-		cur_rrset = data_chain->rrset;
+-	
+-		cur_sigs = data_chain->signatures;
+-
+-		if (rr) {
+-			cur_rr = rr;
+-		}
+-
+-		if (!cur_rr && ldns_rr_list_rr_count(cur_rrset) > 0) {
+-			cur_rr = ldns_rr_list_rr(cur_rrset, 0);
+-		}
+-
+-		if (cur_rr) {
+-			new_tree->rr = cur_rr;
+-			new_tree->rrset = cur_rrset;
+-			/* there are three possibilities:
+-			   1 - 'normal' rrset, signed by a key
+-			   2 - dnskey signed by other dnskey
+-			   3 - dnskey proven by higher level DS
+-			   (data denied by nsec is a special case that can
+-			   occur in multiple places)
+-				   
+-			*/
+-			if (cur_sigs) {
+-				for (i = 0; i < ldns_rr_list_rr_count(cur_sigs); i++) {
+-					/* find the appropriate key in the parent list */
+-					cur_sig_rr = ldns_rr_list_rr(cur_sigs, i);
+-
+-					if (ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_NSEC) {
+-						if (ldns_dname_compare(ldns_rr_owner(cur_sig_rr),
+-										   ldns_rr_owner(cur_rr)))
+-							{
+-								/* find first that does match */
+-
+-								for (j = 0;
+-								     j < ldns_rr_list_rr_count(cur_rrset) && 
+-										ldns_dname_compare(ldns_rr_owner(cur_sig_rr),ldns_rr_owner(cur_rr)) != 0;
+-								     j++) {
+-									cur_rr = ldns_rr_list_rr(cur_rrset, j);
+-									
+-								}
+-								if (ldns_dname_compare(ldns_rr_owner(cur_sig_rr), 
+-												   ldns_rr_owner(cur_rr)))
+-									{
+-										break;
+-									}
+-							}
+-							
+-					}
+-					/* option 1 */
+-					if (data_chain->parent) {
+-						ldns_dnssec_derive_trust_tree_normal_rrset_time(
+-						    new_tree,
+-						    data_chain,
+-						    cur_sig_rr,
+-						    check_time);
+-					}
+-
+-					/* option 2 */
+-					ldns_dnssec_derive_trust_tree_dnskey_rrset_time(
+-					    new_tree,
+-					    data_chain,
+-					    cur_rr,
+-					    cur_sig_rr,
+-					    check_time);
+-				}
+-					
+-				ldns_dnssec_derive_trust_tree_ds_rrset_time(
+-						new_tree, data_chain, 
+-						cur_rr, check_time);
+-			} else {
+-				/* no signatures? maybe it's nsec data */
+-					
+-				/* just add every rr from parent as new parent */
+-				ldns_dnssec_derive_trust_tree_no_sig_time(
+-					new_tree, data_chain, check_time);
+-			}
+-		}
+-	}
+-
+-	return new_tree;
+-}
+-
+-ldns_dnssec_trust_tree *
+-ldns_dnssec_derive_trust_tree(ldns_dnssec_data_chain *data_chain, ldns_rr *rr)
+-{
+-	return ldns_dnssec_derive_trust_tree_time(data_chain, rr, ldns_time(NULL));
+-}
+-
+-void
+-ldns_dnssec_derive_trust_tree_normal_rrset_time(
+-		ldns_dnssec_trust_tree *new_tree, 
+-		ldns_dnssec_data_chain *data_chain, 
+-		ldns_rr *cur_sig_rr,
+-		time_t check_time)
+-{
+-	size_t i, j;
+-	ldns_rr_list *cur_rrset = ldns_rr_list_clone(data_chain->rrset); 
+-	ldns_dnssec_trust_tree *cur_parent_tree;
+-	ldns_rr *cur_parent_rr;
+-	uint16_t cur_keytag;
+-	ldns_rr_list *tmp_rrset = NULL;
+-	ldns_status cur_status;
+-
+-	cur_keytag = ldns_rdf2native_int16(ldns_rr_rrsig_keytag(cur_sig_rr));
+-	
+-	for (j = 0; j < ldns_rr_list_rr_count(data_chain->parent->rrset); j++) {
+-		cur_parent_rr = ldns_rr_list_rr(data_chain->parent->rrset, j);
+-		if (ldns_rr_get_type(cur_parent_rr) == LDNS_RR_TYPE_DNSKEY) {
+-			if (ldns_calc_keytag(cur_parent_rr) == cur_keytag) {
+-
+-				/* TODO: check wildcard nsec too */
+-				if (cur_rrset && ldns_rr_list_rr_count(cur_rrset) > 0) {
+-					tmp_rrset = cur_rrset;
+-					if (ldns_rr_get_type(ldns_rr_list_rr(cur_rrset, 0))
+-					    == LDNS_RR_TYPE_NSEC ||
+-					    ldns_rr_get_type(ldns_rr_list_rr(cur_rrset, 0))
+-					    == LDNS_RR_TYPE_NSEC3) {
+-						/* might contain different names! 
+-						   sort and split */
+-						ldns_rr_list_sort(cur_rrset);
+-						assert(tmp_rrset == cur_rrset);
+-						tmp_rrset = ldns_rr_list_pop_rrset(cur_rrset);
+-						
+-						/* with nsecs, this might be the wrong one */
+-						while (tmp_rrset &&
+-						       ldns_rr_list_rr_count(cur_rrset) > 0 &&
+-						       ldns_dname_compare(
+-								ldns_rr_owner(ldns_rr_list_rr(
+-										        tmp_rrset, 0)),
+-								ldns_rr_owner(cur_sig_rr)) != 0) {
+-							ldns_rr_list_deep_free(tmp_rrset);
+-							tmp_rrset =
+-								ldns_rr_list_pop_rrset(cur_rrset);
+-						}
+-					}
+-					cur_status = ldns_verify_rrsig_time(
+-							tmp_rrset, 
+-							cur_sig_rr, 
+-							cur_parent_rr,
+-							check_time);
+-					if (tmp_rrset && tmp_rrset != cur_rrset
+-							) {
+-						ldns_rr_list_deep_free(
+-								tmp_rrset);
+-						tmp_rrset = NULL;
+-					}
+-					/* avoid dupes */
+-					for (i = 0; i < new_tree->parent_count; i++) {
+-						if (cur_parent_rr == new_tree->parents[i]->rr) {
+-							goto done;
+-						}
+-					}
+-
+-					cur_parent_tree =
+-						ldns_dnssec_derive_trust_tree_time(
+-								data_chain->parent,
+-						                cur_parent_rr,
+-								check_time);
+-					(void)ldns_dnssec_trust_tree_add_parent(new_tree,
+-					           cur_parent_tree,
+-					           cur_sig_rr,
+-					           cur_status);
+-				}
+-			}
+-		}
+-	}
+- done:
+-	ldns_rr_list_deep_free(cur_rrset);
+-}
+-
+-void
+-ldns_dnssec_derive_trust_tree_normal_rrset(ldns_dnssec_trust_tree *new_tree,
+-                                           ldns_dnssec_data_chain *data_chain,
+-                                           ldns_rr *cur_sig_rr)
+-{
+-	ldns_dnssec_derive_trust_tree_normal_rrset_time(
+-			new_tree, data_chain, cur_sig_rr, ldns_time(NULL));
+-}
+-
+-void
+-ldns_dnssec_derive_trust_tree_dnskey_rrset_time(
+-		ldns_dnssec_trust_tree *new_tree, 
+-		ldns_dnssec_data_chain *data_chain, 
+-		ldns_rr *cur_rr, 
+-		ldns_rr *cur_sig_rr,
+-		time_t check_time)
+-{
+-	size_t j;
+-	ldns_rr_list *cur_rrset = data_chain->rrset;
+-	ldns_dnssec_trust_tree *cur_parent_tree;
+-	ldns_rr *cur_parent_rr;
+-	uint16_t cur_keytag;
+-	ldns_status cur_status;
+-
+-	cur_keytag = ldns_rdf2native_int16(ldns_rr_rrsig_keytag(cur_sig_rr));
+-
+-	for (j = 0; j < ldns_rr_list_rr_count(cur_rrset); j++) {
+-		cur_parent_rr = ldns_rr_list_rr(cur_rrset, j);
+-		if (cur_parent_rr != cur_rr &&
+-		    ldns_rr_get_type(cur_parent_rr) == LDNS_RR_TYPE_DNSKEY) {
+-			if (ldns_calc_keytag(cur_parent_rr) == cur_keytag
+-			    ) {
+-				cur_parent_tree = ldns_dnssec_trust_tree_new();
+-				cur_parent_tree->rr = cur_parent_rr;
+-				cur_parent_tree->rrset = cur_rrset;
+-				cur_status = ldns_verify_rrsig_time(
+-						cur_rrset, cur_sig_rr, 
+-						cur_parent_rr, check_time);
+-				(void) ldns_dnssec_trust_tree_add_parent(new_tree,
+-				            cur_parent_tree, cur_sig_rr, cur_status);
+-			}
+-		}
+-	}
+-}
+-
+-void
+-ldns_dnssec_derive_trust_tree_dnskey_rrset(ldns_dnssec_trust_tree *new_tree,
+-                                           ldns_dnssec_data_chain *data_chain,
+-                                           ldns_rr *cur_rr,
+-                                           ldns_rr *cur_sig_rr)
+-{
+-	ldns_dnssec_derive_trust_tree_dnskey_rrset_time(
+-			new_tree, data_chain, cur_rr, cur_sig_rr, ldns_time(NULL));
+-}
+-
+-void
+-ldns_dnssec_derive_trust_tree_ds_rrset_time(
+-		ldns_dnssec_trust_tree *new_tree,
+-		ldns_dnssec_data_chain *data_chain, 
+-		ldns_rr *cur_rr,
+-		time_t check_time)
+-{
+-	size_t j, h;
+-	ldns_rr_list *cur_rrset = data_chain->rrset;
+-	ldns_dnssec_trust_tree *cur_parent_tree;
+-	ldns_rr *cur_parent_rr;
+-
+-	/* try the parent to see whether there are DSs there */
+-	if (ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_DNSKEY &&
+-	    data_chain->parent &&
+-	    data_chain->parent->rrset
+-	    ) {
+-		for (j = 0;
+-			j < ldns_rr_list_rr_count(data_chain->parent->rrset);
+-			j++) {
+-			cur_parent_rr = ldns_rr_list_rr(data_chain->parent->rrset, j);
+-			if (ldns_rr_get_type(cur_parent_rr) == LDNS_RR_TYPE_DS) {
+-				for (h = 0; h < ldns_rr_list_rr_count(cur_rrset); h++) {
+-					cur_rr = ldns_rr_list_rr(cur_rrset, h);
+-					if (ldns_rr_compare_ds(cur_rr, cur_parent_rr)) {
+-						cur_parent_tree =
+-							ldns_dnssec_derive_trust_tree_time(
+-							    data_chain->parent, 
+-							    cur_parent_rr,
+-							    check_time);
+-						(void) ldns_dnssec_trust_tree_add_parent(
+-						            new_tree,
+-						            cur_parent_tree,
+-						            NULL,
+-						            LDNS_STATUS_OK);
+-					} else {
+-						/*ldns_rr_print(stdout, cur_parent_rr);*/
+-					}
+-				}
+-			}
+-		}
+-	}
+-}
+-
+-void
+-ldns_dnssec_derive_trust_tree_ds_rrset(ldns_dnssec_trust_tree *new_tree,
+-                                       ldns_dnssec_data_chain *data_chain,
+-                                       ldns_rr *cur_rr)
+-{
+-	ldns_dnssec_derive_trust_tree_ds_rrset_time(
+-			new_tree, data_chain, cur_rr, ldns_time(NULL));
+-}
+-
+-void
+-ldns_dnssec_derive_trust_tree_no_sig_time(
+-		ldns_dnssec_trust_tree *new_tree, 
+-		ldns_dnssec_data_chain *data_chain,
+-		time_t check_time)
+-{
+-	size_t i;
+-	ldns_rr_list *cur_rrset;
+-	ldns_rr *cur_parent_rr;
+-	ldns_dnssec_trust_tree *cur_parent_tree;
+-	ldns_status result;
+-	
+-	if (data_chain->parent && data_chain->parent->rrset) {
+-		cur_rrset = data_chain->parent->rrset;
+-		/* nsec? */
+-		if (cur_rrset && ldns_rr_list_rr_count(cur_rrset) > 0) {
+-			if (ldns_rr_get_type(ldns_rr_list_rr(cur_rrset, 0)) ==
+-			    LDNS_RR_TYPE_NSEC3) {
+-				result = ldns_dnssec_verify_denial_nsec3(
+-					        new_tree->rr,
+-						   cur_rrset,
+-						   data_chain->parent->signatures,
+-						   data_chain->packet_rcode,
+-						   data_chain->packet_qtype,
+-						   data_chain->packet_nodata);
+-			} else if (ldns_rr_get_type(ldns_rr_list_rr(cur_rrset, 0)) ==
+-					 LDNS_RR_TYPE_NSEC) {
+-				result = ldns_dnssec_verify_denial(
+-					        new_tree->rr,
+-						   cur_rrset,
+-						   data_chain->parent->signatures);
+-			} else {
+-				/* unsigned zone, unsigned parent */
+-				result = LDNS_STATUS_OK;
+-			}
+-		} else {
+-			result = LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED;
+-		}
+-		for (i = 0; i < ldns_rr_list_rr_count(cur_rrset); i++) {
+-			cur_parent_rr = ldns_rr_list_rr(cur_rrset, i);
+-			cur_parent_tree = 
+-				ldns_dnssec_derive_trust_tree_time(
+-						data_chain->parent, 
+-						cur_parent_rr,
+-						check_time);
+-			(void) ldns_dnssec_trust_tree_add_parent(new_tree,
+-			            cur_parent_tree, NULL, result);
+-		}
+-	}
+-}
+-
+-void
+-ldns_dnssec_derive_trust_tree_no_sig(ldns_dnssec_trust_tree *new_tree,
+-                                     ldns_dnssec_data_chain *data_chain)
+-{
+-	ldns_dnssec_derive_trust_tree_no_sig_time(
+-			new_tree, data_chain, ldns_time(NULL));
+-}
+-
+-/*
+- * returns OK if there is a path from tree to key with only OK
+- * the (first) error in between otherwise
+- * or NOT_FOUND if the key wasn't present at all
+- */
+-ldns_status
+-ldns_dnssec_trust_tree_contains_keys(ldns_dnssec_trust_tree *tree,
+-							  ldns_rr_list *trusted_keys)
+-{
+-	size_t i;
+-	ldns_status result = LDNS_STATUS_CRYPTO_NO_DNSKEY;
+-	bool equal;
+-	ldns_status parent_result;
+-	
+-	if (tree && trusted_keys && ldns_rr_list_rr_count(trusted_keys) > 0)
+-		{ if (tree->rr) {
+-				for (i = 0; i < ldns_rr_list_rr_count(trusted_keys); i++) {
+-					equal = ldns_rr_compare_ds(
+-							  tree->rr,
+-							  ldns_rr_list_rr(trusted_keys, i));
+-					if (equal) {
+-						result = LDNS_STATUS_OK;
+-						return result;
+-					}
+-				}
+-			}
+-			for (i = 0; i < tree->parent_count; i++) {
+-				parent_result =
+-					ldns_dnssec_trust_tree_contains_keys(tree->parents[i],
+-												  trusted_keys);
+-				if (parent_result != LDNS_STATUS_CRYPTO_NO_DNSKEY) {
+-					if (tree->parent_status[i] != LDNS_STATUS_OK) {
+-						result = tree->parent_status[i];
+-					} else {
+-						if (tree->rr &&
+-						    ldns_rr_get_type(tree->rr)
+-						    == LDNS_RR_TYPE_NSEC &&
+-						    parent_result == LDNS_STATUS_OK
+-						    ) {
+-							result =
+-								LDNS_STATUS_DNSSEC_EXISTENCE_DENIED;
+-						} else {
+-							result = parent_result;
+-						}
+-					}
+-				}
+-			}
+-		} else {
+-		result = LDNS_STATUS_ERR;
+-	}
+-	
+-	return result;
+-}
+-
+-ldns_status
+-ldns_verify_time(
+-		ldns_rr_list *rrset,
+-		ldns_rr_list *rrsig, 
+-		const ldns_rr_list *keys, 
+-		time_t check_time,
+-		ldns_rr_list *good_keys
+-		)
+-{
+-	uint16_t i;
+-	ldns_status verify_result = LDNS_STATUS_ERR;
+-
+-	if (!rrset || !rrsig || !keys) {
+-		return LDNS_STATUS_ERR;
+-	}
+-
+-	if (ldns_rr_list_rr_count(rrset) < 1) {
+-		return LDNS_STATUS_ERR;
+-	}
+-
+-	if (ldns_rr_list_rr_count(rrsig) < 1) {
+-		return LDNS_STATUS_CRYPTO_NO_RRSIG;
+-	}
+-	
+-	if (ldns_rr_list_rr_count(keys) < 1) {
+-		verify_result = LDNS_STATUS_CRYPTO_NO_TRUSTED_DNSKEY;
+-	} else {
+-		for (i = 0; i < ldns_rr_list_rr_count(rrsig); i++) {
+-			ldns_status s = ldns_verify_rrsig_keylist_time(
+-					rrset, ldns_rr_list_rr(rrsig, i), 
+-					keys, check_time, good_keys);
+-			/* try a little to get more descriptive error */
+-			if(s == LDNS_STATUS_OK) {
+-				verify_result = LDNS_STATUS_OK;
+-			} else if(verify_result == LDNS_STATUS_ERR)
+-				verify_result = s;
+-			else if(s !=  LDNS_STATUS_ERR && verify_result ==
+-				LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY)
+-				verify_result = s;
+-		}
+-	}
+-	return verify_result;
+-}
+-
+-ldns_status
+-ldns_verify(ldns_rr_list *rrset, ldns_rr_list *rrsig, const ldns_rr_list *keys, 
+-		  ldns_rr_list *good_keys)
+-{
+-	return ldns_verify_time(rrset, rrsig, keys, ldns_time(NULL), good_keys);
+-}
+-
+-ldns_status
+-ldns_verify_notime(ldns_rr_list *rrset, ldns_rr_list *rrsig,
+-	const ldns_rr_list *keys, ldns_rr_list *good_keys)
+-{
+-	uint16_t i;
+-	ldns_status verify_result = LDNS_STATUS_ERR;
+-
+-	if (!rrset || !rrsig || !keys) {
+-		return LDNS_STATUS_ERR;
+-	}
+-
+-	if (ldns_rr_list_rr_count(rrset) < 1) {
+-		return LDNS_STATUS_ERR;
+-	}
+-
+-	if (ldns_rr_list_rr_count(rrsig) < 1) {
+-		return LDNS_STATUS_CRYPTO_NO_RRSIG;
+-	}
+-
+-	if (ldns_rr_list_rr_count(keys) < 1) {
+-		verify_result = LDNS_STATUS_CRYPTO_NO_TRUSTED_DNSKEY;
+-	} else {
+-		for (i = 0; i < ldns_rr_list_rr_count(rrsig); i++) {
+-			ldns_status s = ldns_verify_rrsig_keylist_notime(rrset,
+-				ldns_rr_list_rr(rrsig, i), keys, good_keys);
+-
+-			/* try a little to get more descriptive error */
+-			if (s == LDNS_STATUS_OK) {
+-				verify_result = LDNS_STATUS_OK;
+-			} else if (verify_result == LDNS_STATUS_ERR) {
+-				verify_result = s;
+-			} else if (s !=  LDNS_STATUS_ERR && verify_result ==
+-				LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY) {
+-				verify_result = s;
+-			}
+-		}
+-	}
+-	return verify_result;
+-}
+-
+-ldns_rr_list *
+-ldns_fetch_valid_domain_keys_time(const ldns_resolver *res,
+-                             const ldns_rdf *domain,
+-                             const ldns_rr_list *keys,
+-			     time_t check_time,
+-                             ldns_status *status)
+-{
+-	ldns_rr_list * trusted_keys = NULL;
+-	ldns_rr_list * ds_keys = NULL;
+-	ldns_rdf * prev_parent_domain;
+-	ldns_rdf *      parent_domain;
+-	ldns_rr_list * parent_keys = NULL;
+-
+-	if (res && domain && keys) {
+-
+-		if ((trusted_keys = ldns_validate_domain_dnskey_time(res,
+-                                         domain, keys, check_time))) {
+-			*status = LDNS_STATUS_OK;
+-		} else {
+-			/* No trusted keys in this domain, we'll have to find some in the parent domain */
+-			*status = LDNS_STATUS_CRYPTO_NO_TRUSTED_DNSKEY;
+-
+-			parent_domain = ldns_dname_left_chop(domain);
+-			while (parent_domain && /* Fail if we are at the root*/
+-					ldns_rdf_size(parent_domain) > 0) {
+-	
+-				if ((parent_keys = 
+-					ldns_fetch_valid_domain_keys_time(res,
+-					     parent_domain,
+-					     keys,
+-					     check_time,
+-					     status))) {
+-					/* Check DS records */
+-					if ((ds_keys =
+-						ldns_validate_domain_ds_time(res,
+-						     domain,
+-						     parent_keys,
+-						     check_time))) {
+-						trusted_keys =
+-						ldns_fetch_valid_domain_keys_time(
+-								res, 
+-								domain, 
+-								ds_keys, 
+-								check_time,
+-								status);
+-						ldns_rr_list_deep_free(ds_keys);
+-					} else {
+-						/* No valid DS at the parent -- fail */
+-						*status = LDNS_STATUS_CRYPTO_NO_TRUSTED_DS ;
+-					}
+-					ldns_rr_list_deep_free(parent_keys);
+-					break;
+-				} else {
+-					parent_domain = ldns_dname_left_chop((
+-						prev_parent_domain 
+-							= parent_domain
+-						));
+-					ldns_rdf_deep_free(prev_parent_domain);
+-				}
+-			}
+-			if (parent_domain) {
+-				ldns_rdf_deep_free(parent_domain);
+-			}
+-		}
+-	}
+-	return trusted_keys;
+-}
+-
+-ldns_rr_list *
+-ldns_fetch_valid_domain_keys(const ldns_resolver *res,
+-                             const ldns_rdf *domain,
+-                             const ldns_rr_list *keys,
+-                             ldns_status *status)
+-{
+-	return ldns_fetch_valid_domain_keys_time(
+-			res, domain, keys, ldns_time(NULL), status);
+-}
+-
+-ldns_rr_list *
+-ldns_validate_domain_dnskey_time(
+-		const ldns_resolver * res,
+-		const ldns_rdf * domain,
+-		const ldns_rr_list * keys,
+-		time_t check_time
+-		)
+-{
+-	ldns_pkt * keypkt;
+-	ldns_rr * cur_key;
+-	uint16_t key_i; uint16_t key_j; uint16_t key_k;
+-	uint16_t sig_i; ldns_rr * cur_sig;
+-
+-	ldns_rr_list * domain_keys = NULL;
+-	ldns_rr_list * domain_sigs = NULL;
+-	ldns_rr_list * trusted_keys = NULL;
+-
+-	/* Fetch keys for the domain */
+-	keypkt = ldns_resolver_query(res, domain,
+-		LDNS_RR_TYPE_DNSKEY, LDNS_RR_CLASS_IN, LDNS_RD);
+-	if (keypkt) {
+-		domain_keys = ldns_pkt_rr_list_by_type(keypkt,
+-									    LDNS_RR_TYPE_DNSKEY,
+-									    LDNS_SECTION_ANSWER);
+-		domain_sigs = ldns_pkt_rr_list_by_type(keypkt,
+-									    LDNS_RR_TYPE_RRSIG,
+-									    LDNS_SECTION_ANSWER);
+-
+-		/* Try to validate the record using our keys */
+-		for (key_i=0; key_i< ldns_rr_list_rr_count(domain_keys); key_i++) {
+-      
+-			cur_key = ldns_rr_list_rr(domain_keys, key_i);
+-			for (key_j=0; key_j<ldns_rr_list_rr_count(keys); key_j++) {
+-				if (ldns_rr_compare_ds(ldns_rr_list_rr(keys, key_j),
+-								   cur_key)) {
+-          
+-					/* Current key is trusted -- validate */
+-					trusted_keys = ldns_rr_list_new();
+-          
+-					for (sig_i=0;
+-						sig_i<ldns_rr_list_rr_count(domain_sigs);
+-						sig_i++) {
+-						cur_sig = ldns_rr_list_rr(domain_sigs, sig_i);
+-						/* Avoid non-matching sigs */
+-						if (ldns_rdf2native_int16(
+-							   ldns_rr_rrsig_keytag(cur_sig))
+-						    == ldns_calc_keytag(cur_key)) {
+-							if (ldns_verify_rrsig_time(
+-									domain_keys,
+-									cur_sig,
+-									cur_key,
+-									check_time)
+-							    == LDNS_STATUS_OK) {
+-                
+-								/* Push the whole rrset 
+-								   -- we can't do much more */
+-								for (key_k=0;
+-									key_k<ldns_rr_list_rr_count(
+-											domain_keys);
+-									key_k++) {
+-									ldns_rr_list_push_rr(
+-									    trusted_keys,
+-									    ldns_rr_clone(
+-										   ldns_rr_list_rr(
+-											  domain_keys,
+-											  key_k)));
+-								}
+-                
+-								ldns_rr_list_deep_free(domain_keys);
+-								ldns_rr_list_deep_free(domain_sigs);
+-								ldns_pkt_free(keypkt);
+-								return trusted_keys;
+-							}
+-						}
+-					}
+-	  
+-					/* Only push our trusted key */
+-					ldns_rr_list_push_rr(trusted_keys,
+-									 ldns_rr_clone(cur_key));
+-				}
+-			}
+-		}
+-
+-		ldns_rr_list_deep_free(domain_keys);
+-		ldns_rr_list_deep_free(domain_sigs);
+-		ldns_pkt_free(keypkt);
+-
+-	} else {
+-		/* LDNS_STATUS_CRYPTO_NO_DNSKEY */
+-	}
+-    
+-	return trusted_keys;
+-}
+-
+-ldns_rr_list *
+-ldns_validate_domain_dnskey(const ldns_resolver * res,
+-					   const ldns_rdf * domain,
+-					   const ldns_rr_list * keys)
+-{
+-	return ldns_validate_domain_dnskey_time(
+-			res, domain, keys, ldns_time(NULL));
+-}
+-
+-ldns_rr_list *
+-ldns_validate_domain_ds_time(
+-		const ldns_resolver *res, 
+-		const ldns_rdf * domain,
+-		const ldns_rr_list * keys,
+-		time_t check_time)
+-{
+-	ldns_pkt * dspkt;
+-	uint16_t key_i;
+-	ldns_rr_list * rrset = NULL;
+-	ldns_rr_list * sigs = NULL;
+-	ldns_rr_list * trusted_keys = NULL;
+-
+-	/* Fetch DS for the domain */
+-	dspkt = ldns_resolver_query(res, domain,
+-		LDNS_RR_TYPE_DS, LDNS_RR_CLASS_IN, LDNS_RD);
+-	if (dspkt) {
+-		rrset = ldns_pkt_rr_list_by_type(dspkt,
+-								   LDNS_RR_TYPE_DS,
+-								   LDNS_SECTION_ANSWER);
+-		sigs = ldns_pkt_rr_list_by_type(dspkt,
+-								  LDNS_RR_TYPE_RRSIG,
+-								  LDNS_SECTION_ANSWER);
+-
+-		/* Validate sigs */
+-		if (ldns_verify_time(rrset, sigs, keys, check_time, NULL)
+-			       	== LDNS_STATUS_OK) {
+-			trusted_keys = ldns_rr_list_new();
+-			for (key_i=0; key_i<ldns_rr_list_rr_count(rrset); key_i++) {
+-				ldns_rr_list_push_rr(trusted_keys,
+-								 ldns_rr_clone(ldns_rr_list_rr(rrset,
+-														 key_i)
+-											)
+-								 );
+-			}
+-		}
+-
+-		ldns_rr_list_deep_free(rrset);
+-		ldns_rr_list_deep_free(sigs);
+-		ldns_pkt_free(dspkt);
+-
+-	} else {
+-		/* LDNS_STATUS_CRYPTO_NO_DS */
+-	}
+-
+-	return trusted_keys;
+-}
+-
+-ldns_rr_list *
+-ldns_validate_domain_ds(const ldns_resolver *res,
+-				    const ldns_rdf * domain,
+-				    const ldns_rr_list * keys)
+-{
+-	return ldns_validate_domain_ds_time(res, domain, keys, ldns_time(NULL));
+-}
+-
+-ldns_status
+-ldns_verify_trusted_time(
+-		ldns_resolver *res, 
+-		ldns_rr_list *rrset, 
+-		ldns_rr_list * rrsigs, 
+-		time_t check_time,
+-		ldns_rr_list * validating_keys
+-		)
+-{
+-	uint16_t sig_i; uint16_t key_i;
+-	ldns_rr * cur_sig; ldns_rr * cur_key;
+-	ldns_rr_list * trusted_keys = NULL;
+-	ldns_status result = LDNS_STATUS_ERR;
+-
+-	if (!res || !rrset || !rrsigs) {
+-		return LDNS_STATUS_ERR;
+-	}
+-
+-	if (ldns_rr_list_rr_count(rrset) < 1) {
+-		return LDNS_STATUS_ERR;
+-	}
+-
+-	if (ldns_rr_list_rr_count(rrsigs) < 1) {
+-		return LDNS_STATUS_CRYPTO_NO_RRSIG;
+-	}
+-  
+-	/* Look at each sig */
+-	for (sig_i=0; sig_i < ldns_rr_list_rr_count(rrsigs); sig_i++) {
+-
+-		cur_sig = ldns_rr_list_rr(rrsigs, sig_i);
+-		/* Get a valid signer key and validate the sig */
+-		if ((trusted_keys = ldns_fetch_valid_domain_keys_time(
+-					res, 
+-					ldns_rr_rrsig_signame(cur_sig), 
+-					ldns_resolver_dnssec_anchors(res), 
+-					check_time,
+-					&result))) {
+-
+-			for (key_i = 0;
+-				key_i < ldns_rr_list_rr_count(trusted_keys);
+-				key_i++) {
+-				cur_key = ldns_rr_list_rr(trusted_keys, key_i);
+-
+-				if ((result = ldns_verify_rrsig_time(rrset,
+-								cur_sig, 
+-								cur_key,
+-								check_time))
+-				    == LDNS_STATUS_OK) {
+-					if (validating_keys) {
+-						ldns_rr_list_push_rr(validating_keys,
+-										 ldns_rr_clone(cur_key));
+-					}
+-					ldns_rr_list_deep_free(trusted_keys);
+-					return LDNS_STATUS_OK;
+-				} 
+-			}
+-		}
+-	}
+-
+-	ldns_rr_list_deep_free(trusted_keys);
+-	return result;
+-}
+-
+-ldns_status
+-ldns_verify_trusted(
+-		ldns_resolver *res,
+-		ldns_rr_list *rrset, 
+-		ldns_rr_list * rrsigs, 
+-		ldns_rr_list * validating_keys)
+-{
+-	return ldns_verify_trusted_time(
+-			res, rrset, rrsigs, ldns_time(NULL), validating_keys);
+-}
+-
+-
+-ldns_status
+-ldns_dnssec_verify_denial(ldns_rr *rr,
+-                          ldns_rr_list *nsecs,
+-                          ldns_rr_list *rrsigs)
+-{
+-	ldns_rdf *rr_name;
+-	ldns_rdf *wildcard_name;
+-	ldns_rdf *chopped_dname;
+-	ldns_rr *cur_nsec;
+-	size_t i;
+-	ldns_status result;
+-	/* needed for wildcard check on exact match */
+-	ldns_rr *rrsig;
+-	bool name_covered = false;
+-	bool type_covered = false;
+-	bool wildcard_covered = false;
+-	bool wildcard_type_covered = false;
+-
+-	wildcard_name = ldns_dname_new_frm_str("*");
+-	rr_name = ldns_rr_owner(rr);
+-	chopped_dname = ldns_dname_left_chop(rr_name);
+-	result = ldns_dname_cat(wildcard_name, chopped_dname);
+-	ldns_rdf_deep_free(chopped_dname);
+-	if (result != LDNS_STATUS_OK) {
+-		return result;
+-	}
+-	
+-	for  (i = 0; i < ldns_rr_list_rr_count(nsecs); i++) {
+-		cur_nsec = ldns_rr_list_rr(nsecs, i);
+-		if (ldns_dname_compare(rr_name, ldns_rr_owner(cur_nsec)) == 0) {
+-			/* see section 5.4 of RFC4035, if the label count of the NSEC's
+-			   RRSIG is equal, then it is proven that wildcard expansion 
+-			   could not have been used to match the request */
+-			rrsig = ldns_dnssec_get_rrsig_for_name_and_type(
+-					  ldns_rr_owner(cur_nsec),
+-					  ldns_rr_get_type(cur_nsec),
+-					  rrsigs);
+-			if (rrsig && ldns_rdf2native_int8(ldns_rr_rrsig_labels(rrsig))
+-			    == ldns_dname_label_count(rr_name)) {
+-				wildcard_covered = true;
+-			}
+-			
+-			if (ldns_nsec_bitmap_covers_type(ldns_nsec_get_bitmap(cur_nsec),
+-									   ldns_rr_get_type(rr))) {
+-				type_covered = true;
+-			}
+-		}
+-		if (ldns_nsec_covers_name(cur_nsec, rr_name)) {
+-			name_covered = true;
+-		}
+-		
+-		if (ldns_dname_compare(wildcard_name,
+-						   ldns_rr_owner(cur_nsec)) == 0) {
+-			if (ldns_nsec_bitmap_covers_type(ldns_nsec_get_bitmap(cur_nsec),
+-									   ldns_rr_get_type(rr))) {
+-				wildcard_type_covered = true;
+-			}
+-		}
+-		
+-		if (ldns_nsec_covers_name(cur_nsec, wildcard_name)) {
+-			wildcard_covered = true;
+-		}
+-		
+-	}
+-	
+-	ldns_rdf_deep_free(wildcard_name);
+-	
+-	if (type_covered || !name_covered) {
+-		return LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED;
+-	}
+-	
+-	if (wildcard_type_covered || !wildcard_covered) {
+-		return LDNS_STATUS_DNSSEC_NSEC_WILDCARD_NOT_COVERED;
+-	}
+-
+-	return LDNS_STATUS_OK;
+-}
+-
+-ldns_status
+-ldns_dnssec_verify_denial_nsec3_match( ldns_rr *rr
+-				     , ldns_rr_list *nsecs
+-				     , ATTR_UNUSED(ldns_rr_list *rrsigs)
+-				     , ldns_pkt_rcode packet_rcode
+-				     , ldns_rr_type packet_qtype
+-				     , bool packet_nodata
+-				     , ldns_rr **match
+-				     )
+-{
+-	ldns_rdf *closest_encloser;
+-	ldns_rdf *wildcard;
+-	ldns_rdf *hashed_wildcard_name;
+-	bool wildcard_covered = false;
+-	ldns_rdf *zone_name;
+-	ldns_rdf *hashed_name;
+-	/* self assignment to suppress uninitialized warning */
+-	ldns_rdf *next_closer = next_closer;
+-	ldns_rdf *hashed_next_closer;
+-	size_t i;
+-	ldns_status result = LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED;
+-
+-	if (match) {
+-		*match = NULL;
+-	}
+-
+-	zone_name = ldns_dname_left_chop(ldns_rr_owner(ldns_rr_list_rr(nsecs,0)));
+-
+-	/* section 8.4 */
+-	if (packet_rcode == LDNS_RCODE_NXDOMAIN) {
+-		closest_encloser = ldns_dnssec_nsec3_closest_encloser(
+-						   ldns_rr_owner(rr),
+-						   ldns_rr_get_type(rr),
+-						   nsecs);
+-                if(!closest_encloser) {
+-                        result = LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED;
+-                        goto done;
+-                }
+-
+-		wildcard = ldns_dname_new_frm_str("*");
+-		(void) ldns_dname_cat(wildcard, closest_encloser);
+-
+-		for (i = 0; i < ldns_rr_list_rr_count(nsecs); i++) {
+-			hashed_wildcard_name =
+-				ldns_nsec3_hash_name_frm_nsec3(ldns_rr_list_rr(nsecs, 0),
+-										 wildcard
+-										 );
+-			(void) ldns_dname_cat(hashed_wildcard_name, zone_name);
+-
+-			if (ldns_nsec_covers_name(ldns_rr_list_rr(nsecs, i),
+-								 hashed_wildcard_name)) {
+-				wildcard_covered = true;
+-				if (match) {
+-					*match = ldns_rr_list_rr(nsecs, i);
+-				}
+-			}
+-			ldns_rdf_deep_free(hashed_wildcard_name);
+-		}
+-
+-		if (! wildcard_covered) {
+-			result = LDNS_STATUS_DNSSEC_NSEC_WILDCARD_NOT_COVERED;
+-		} else {
+-			result = LDNS_STATUS_OK;
+-		}
+-		ldns_rdf_deep_free(closest_encloser);
+-		ldns_rdf_deep_free(wildcard);
+-
+-	} else if (packet_nodata && packet_qtype != LDNS_RR_TYPE_DS) {
+-		/* section 8.5 */
+-		hashed_name = ldns_nsec3_hash_name_frm_nsec3(
+-		                   ldns_rr_list_rr(nsecs, 0),
+-		                   ldns_rr_owner(rr));
+-		(void) ldns_dname_cat(hashed_name, zone_name);
+-		for (i = 0; i < ldns_rr_list_rr_count(nsecs); i++) {
+-			if (ldns_dname_compare(hashed_name,
+-			         ldns_rr_owner(ldns_rr_list_rr(nsecs, i)))
+-			    == 0) {
+-				if (!ldns_nsec_bitmap_covers_type(
+-					    ldns_nsec3_bitmap(ldns_rr_list_rr(nsecs, i)),
+-					    packet_qtype)
+-				    &&
+-				    !ldns_nsec_bitmap_covers_type(
+-					    ldns_nsec3_bitmap(ldns_rr_list_rr(nsecs, i)),
+-					    LDNS_RR_TYPE_CNAME)) {
+-					result = LDNS_STATUS_OK;
+-					if (match) {
+-						*match = ldns_rr_list_rr(nsecs, i);
+-					}
+-					goto done;
+-				}
+-			}
+-		}
+-		result = LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED;
+-		/* wildcard no data? section 8.7 */
+-		closest_encloser = ldns_dnssec_nsec3_closest_encloser(
+-				   ldns_rr_owner(rr),
+-				   ldns_rr_get_type(rr),
+-				   nsecs);
+-		if(!closest_encloser) {
+-			result = LDNS_STATUS_NSEC3_ERR;
+-			goto done;
+-		}
+-		wildcard = ldns_dname_new_frm_str("*");
+-		(void) ldns_dname_cat(wildcard, closest_encloser);
+-		for (i = 0; i < ldns_rr_list_rr_count(nsecs); i++) {
+-			hashed_wildcard_name =
+-				ldns_nsec3_hash_name_frm_nsec3(ldns_rr_list_rr(nsecs, 0),
+-					 wildcard);
+-			(void) ldns_dname_cat(hashed_wildcard_name, zone_name);
+-
+-			if (ldns_dname_compare(hashed_wildcard_name,
+-			         ldns_rr_owner(ldns_rr_list_rr(nsecs, i)))
+-			    == 0) {
+-				if (!ldns_nsec_bitmap_covers_type(
+-					    ldns_nsec3_bitmap(ldns_rr_list_rr(nsecs, i)),
+-					    packet_qtype)
+-				    &&
+-				    !ldns_nsec_bitmap_covers_type(
+-					    ldns_nsec3_bitmap(ldns_rr_list_rr(nsecs, i)),
+-					    LDNS_RR_TYPE_CNAME)) {
+-					result = LDNS_STATUS_OK;
+-					if (match) {
+-						*match = ldns_rr_list_rr(nsecs, i);
+-					}
+-				}
+-			}
+-			ldns_rdf_deep_free(hashed_wildcard_name);
+-			if (result == LDNS_STATUS_OK) {
+-				break;
+-			}
+-		}
+-		ldns_rdf_deep_free(closest_encloser);
+-		ldns_rdf_deep_free(wildcard);
+-	} else if (packet_nodata && packet_qtype == LDNS_RR_TYPE_DS) {
+-		/* section 8.6 */
+-		/* note: up to XXX this is the same as for 8.5 */
+-		hashed_name = ldns_nsec3_hash_name_frm_nsec3(ldns_rr_list_rr(nsecs,
+-														 0),
+-											ldns_rr_owner(rr)
+-											);
+-		(void) ldns_dname_cat(hashed_name, zone_name);
+-		for (i = 0; i < ldns_rr_list_rr_count(nsecs); i++) {
+-			if (ldns_dname_compare(hashed_name,
+-							   ldns_rr_owner(ldns_rr_list_rr(nsecs,
+-													   i)))
+-			    == 0) {
+-				if (!ldns_nsec_bitmap_covers_type(
+-					    ldns_nsec3_bitmap(ldns_rr_list_rr(nsecs, i)),
+-					    LDNS_RR_TYPE_DS)
+-				    && 
+-				    !ldns_nsec_bitmap_covers_type(
+-					    ldns_nsec3_bitmap(ldns_rr_list_rr(nsecs, i)),
+-					    LDNS_RR_TYPE_CNAME)) {
+-					result = LDNS_STATUS_OK;
+-					if (match) {
+-						*match = ldns_rr_list_rr(nsecs, i);
+-					}
+-					goto done;
+-				}
+-			}
+-		}
+-
+-		/* XXX see note above */
+-		result = LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED;
+-
+-		closest_encloser = ldns_dnssec_nsec3_closest_encloser(
+-				   ldns_rr_owner(rr),
+-				   ldns_rr_get_type(rr),
+-				   nsecs);
+-		if(!closest_encloser) {
+-			result = LDNS_STATUS_NSEC3_ERR;
+-			goto done;
+-		}
+-		/* Now check if we have a Opt-Out NSEC3 that covers the "next closer"*/
+-
+-		if (ldns_dname_label_count(closest_encloser) + 1
+-		    >= ldns_dname_label_count(ldns_rr_owner(rr))) {
+-			
+-			/* Query name *is* the "next closer". */
+-			hashed_next_closer = hashed_name;
+-		} else {
+-
+-			/* "next closer" has less labels than the query name.
+-			 * Create the name and hash it.
+-			 */
+-			next_closer = ldns_dname_clone_from(
+-					ldns_rr_owner(rr),
+-					ldns_dname_label_count(ldns_rr_owner(rr))
+-					- (ldns_dname_label_count(closest_encloser) + 1)
+-					);
+-			hashed_next_closer = ldns_nsec3_hash_name_frm_nsec3(
+-					ldns_rr_list_rr(nsecs, 0),
+-					next_closer
+-					);
+-			(void) ldns_dname_cat(hashed_next_closer, zone_name);
+-		}
+-		/* Find the NSEC3 that covers the "next closer" */
+-		for (i = 0; i < ldns_rr_list_rr_count(nsecs); i++) {
+-			if (ldns_nsec_covers_name(ldns_rr_list_rr(nsecs, i),
+-			                          hashed_next_closer) && 
+-				ldns_nsec3_optout(ldns_rr_list_rr(nsecs, i))) {
+-
+-				result = LDNS_STATUS_OK;
+-				if (match) {
+-					*match = ldns_rr_list_rr(nsecs, i);
+-				}
+-				break;
+-			}
+-		}
+-		if (ldns_dname_label_count(closest_encloser) + 1
+-		    < ldns_dname_label_count(ldns_rr_owner(rr))) {
+-
+-			/* "next closer" has less labels than the query name.
+-			 * Dispose of the temporary variables that held that name.
+-			 */
+-			ldns_rdf_deep_free(hashed_next_closer);
+-			ldns_rdf_deep_free(next_closer);
+-		}
+-		ldns_rdf_deep_free(closest_encloser);
+-	}
+-
+- done:
+-	ldns_rdf_deep_free(zone_name);
+-	return result;
+-}
+-
+-ldns_status
+-ldns_dnssec_verify_denial_nsec3(ldns_rr *rr,
+-						  ldns_rr_list *nsecs,
+-						  ldns_rr_list *rrsigs,
+-						  ldns_pkt_rcode packet_rcode,
+-						  ldns_rr_type packet_qtype,
+-						  bool packet_nodata)
+-{
+-	return ldns_dnssec_verify_denial_nsec3_match(
+-				rr, nsecs, rrsigs, packet_rcode,
+-				packet_qtype, packet_nodata, NULL
+-	       );
+-}
+-
+-#ifdef USE_GOST
+-EVP_PKEY*
+-ldns_gost2pkey_raw(unsigned char* key, size_t keylen)
+-{
+-	/* prefix header for X509 encoding */
+-	uint8_t asn[37] = { 0x30, 0x63, 0x30, 0x1c, 0x06, 0x06, 0x2a, 0x85, 
+-		0x03, 0x02, 0x02, 0x13, 0x30, 0x12, 0x06, 0x07, 0x2a, 0x85, 
+-		0x03, 0x02, 0x02, 0x23, 0x01, 0x06, 0x07, 0x2a, 0x85, 0x03, 
+-		0x02, 0x02, 0x1e, 0x01, 0x03, 0x43, 0x00, 0x04, 0x40};
+-	unsigned char encoded[37+64];
+-	const unsigned char* pp;
+-	if(keylen != 64) {
+-		/* key wrong size */
+-		return NULL;
+-	}
+-
+-	/* create evp_key */
+-	memmove(encoded, asn, 37);
+-	memmove(encoded+37, key, 64);
+-	pp = (unsigned char*)&encoded[0];
+-
+-	return d2i_PUBKEY(NULL, &pp, (int)sizeof(encoded));
+-}
+-
+-static ldns_status
+-ldns_verify_rrsig_gost_raw(unsigned char* sig, size_t siglen, 
+-	ldns_buffer* rrset, unsigned char* key, size_t keylen)
+-{
+-	EVP_PKEY *evp_key;
+-	ldns_status result;
+-
+-	(void) ldns_key_EVP_load_gost_id();
+-	evp_key = ldns_gost2pkey_raw(key, keylen);
+-	if(!evp_key) {
+-		/* could not convert key */
+-		return LDNS_STATUS_CRYPTO_BOGUS;
+-	}
+-
+-	/* verify signature */
+-	result = ldns_verify_rrsig_evp_raw(sig, siglen, rrset, 
+-		evp_key, EVP_get_digestbyname("md_gost94"));
+-	EVP_PKEY_free(evp_key);
+-
+-	return result;
+-}
+-#endif
+-
+-#ifdef USE_ECDSA
+-EVP_PKEY*
+-ldns_ecdsa2pkey_raw(unsigned char* key, size_t keylen, uint8_t algo)
+-{
+-	unsigned char buf[256+2]; /* sufficient for 2*384/8+1 */
+-        const unsigned char* pp = buf;
+-        EVP_PKEY *evp_key;
+-        EC_KEY *ec;
+-	/* check length, which uncompressed must be 2 bignums */
+-        if(algo == LDNS_ECDSAP256SHA256) {
+-		if(keylen != 2*256/8) return NULL;
+-                ec = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
+-        } else if(algo == LDNS_ECDSAP384SHA384) {
+-		if(keylen != 2*384/8) return NULL;
+-                ec = EC_KEY_new_by_curve_name(NID_secp384r1);
+-        } else    ec = NULL;
+-        if(!ec) return NULL;
+-	if(keylen+1 > sizeof(buf))
+-		return NULL; /* sanity check */
+-	/* prepend the 0x02 (from docs) (or actually 0x04 from implementation
+-	 * of openssl) for uncompressed data */
+-	buf[0] = POINT_CONVERSION_UNCOMPRESSED;
+-	memmove(buf+1, key, keylen);
+-        if(!o2i_ECPublicKey(&ec, &pp, (int)keylen+1)) {
+-                EC_KEY_free(ec);
+-                return NULL;
+-        }
+-        evp_key = EVP_PKEY_new();
+-        if(!evp_key) {
+-                EC_KEY_free(ec);
+-                return NULL;
+-        }
+-        if (!EVP_PKEY_assign_EC_KEY(evp_key, ec)) {
+-		EVP_PKEY_free(evp_key);
+-		EC_KEY_free(ec);
+-		return NULL;
+-	}
+-        return evp_key;
+-}
+-
+-static ldns_status
+-ldns_verify_rrsig_ecdsa_raw(unsigned char* sig, size_t siglen, 
+-	ldns_buffer* rrset, unsigned char* key, size_t keylen, uint8_t algo)
+-{
+-        EVP_PKEY *evp_key;
+-        ldns_status result;
+-        const EVP_MD *d;
+-
+-        evp_key = ldns_ecdsa2pkey_raw(key, keylen, algo);
+-        if(!evp_key) {
+-		/* could not convert key */
+-		return LDNS_STATUS_CRYPTO_BOGUS;
+-        }
+-        if(algo == LDNS_ECDSAP256SHA256)
+-                d = EVP_sha256();
+-        else    d = EVP_sha384(); /* LDNS_ECDSAP384SHA384 */
+-	result = ldns_verify_rrsig_evp_raw(sig, siglen, rrset, evp_key, d);
+-	EVP_PKEY_free(evp_key);
+-	return result;
+-}
+-#endif
+-
+-ldns_status
+-ldns_verify_rrsig_buffers(ldns_buffer *rawsig_buf, ldns_buffer *verify_buf, 
+-					 ldns_buffer *key_buf, uint8_t algo)
+-{
+-	return ldns_verify_rrsig_buffers_raw(
+-			 (unsigned char*)ldns_buffer_begin(rawsig_buf),
+-			 ldns_buffer_position(rawsig_buf),
+-			 verify_buf,
+-			 (unsigned char*)ldns_buffer_begin(key_buf), 
+-			 ldns_buffer_position(key_buf), algo);
+-}
+-
+-ldns_status
+-ldns_verify_rrsig_buffers_raw(unsigned char* sig, size_t siglen,
+-						ldns_buffer *verify_buf, unsigned char* key, size_t keylen, 
+-						uint8_t algo)
+-{
+-	/* check for right key */
+-	switch(algo) {
+-	case LDNS_DSA:
+-	case LDNS_DSA_NSEC3:
+-		return ldns_verify_rrsig_dsa_raw(sig,
+-								   siglen,
+-								   verify_buf,
+-								   key,
+-								   keylen);
+-		break;
+-	case LDNS_RSASHA1:
+-	case LDNS_RSASHA1_NSEC3:
+-		return ldns_verify_rrsig_rsasha1_raw(sig,
+-									  siglen,
+-									  verify_buf,
+-									  key,
+-									  keylen);
+-		break;
+-#ifdef USE_SHA2
+-	case LDNS_RSASHA256:
+-		return ldns_verify_rrsig_rsasha256_raw(sig,
+-									    siglen,
+-									    verify_buf,
+-									    key,
+-									    keylen);
+-		break;
+-	case LDNS_RSASHA512:
+-		return ldns_verify_rrsig_rsasha512_raw(sig,
+-									    siglen,
+-									    verify_buf,
+-									    key,
+-									    keylen);
+-		break;
+-#endif
+-#ifdef USE_GOST
+-	case LDNS_ECC_GOST:
+-		return ldns_verify_rrsig_gost_raw(sig, siglen, verify_buf,
+-			key, keylen);
+-		break;
+-#endif
+-#ifdef USE_ECDSA
+-        case LDNS_ECDSAP256SHA256:
+-        case LDNS_ECDSAP384SHA384:
+-		return ldns_verify_rrsig_ecdsa_raw(sig, siglen, verify_buf,
+-			key, keylen, algo);
+-		break;
+-#endif
+-	case LDNS_RSAMD5:
+-		return ldns_verify_rrsig_rsamd5_raw(sig,
+-									 siglen,
+-									 verify_buf,
+-									 key,
+-									 keylen);
+-		break;
+-	default:
+-		/* do you know this alg?! */
+-		return LDNS_STATUS_CRYPTO_UNKNOWN_ALGO;
+-	}
+-}
+-
+-
+-/**
+- * Reset the ttl in the rrset with the orig_ttl from the sig 
+- * and update owner name if it was wildcard 
+- * Also canonicalizes the rrset.
+- * @param rrset: rrset to modify
+- * @param sig: signature to take TTL and wildcard values from
+- */
+-static void
+-ldns_rrset_use_signature_ttl(ldns_rr_list* rrset_clone, ldns_rr* rrsig)
+-{
+-	uint32_t orig_ttl;
+-	uint16_t i;
+-	uint8_t label_count;
+-	ldns_rdf *wildcard_name;
+-	ldns_rdf *wildcard_chopped;
+-	ldns_rdf *wildcard_chopped_tmp;
+-	
+-	if ((rrsig == NULL) || ldns_rr_rd_count(rrsig) < 4) {
+-		return;
+-	}
+-
+-	orig_ttl = ldns_rdf2native_int32( ldns_rr_rdf(rrsig, 3));
+-	label_count = ldns_rdf2native_int8(ldns_rr_rdf(rrsig, 2));
+-
+-	for(i = 0; i < ldns_rr_list_rr_count(rrset_clone); i++) {
+-		if (label_count < 
+-		    ldns_dname_label_count(
+-			   ldns_rr_owner(ldns_rr_list_rr(rrset_clone, i)))) {
+-			(void) ldns_str2rdf_dname(&wildcard_name, "*");
+-			wildcard_chopped = ldns_rdf_clone(ldns_rr_owner(
+-				ldns_rr_list_rr(rrset_clone, i)));
+-			while (label_count < ldns_dname_label_count(wildcard_chopped)) {
+-				wildcard_chopped_tmp = ldns_dname_left_chop(
+-					wildcard_chopped);
+-				ldns_rdf_deep_free(wildcard_chopped);
+-				wildcard_chopped = wildcard_chopped_tmp;
+-			}
+-			(void) ldns_dname_cat(wildcard_name, wildcard_chopped);
+-			ldns_rdf_deep_free(wildcard_chopped);
+-			ldns_rdf_deep_free(ldns_rr_owner(ldns_rr_list_rr(
+-				rrset_clone, i)));
+-			ldns_rr_set_owner(ldns_rr_list_rr(rrset_clone, i), 
+-				wildcard_name);
+-		}
+-		ldns_rr_set_ttl(ldns_rr_list_rr(rrset_clone, i), orig_ttl);
+-		/* convert to lowercase */
+-		ldns_rr2canonical(ldns_rr_list_rr(rrset_clone, i));
+-	}
+-}
+-
+-/**
+- * Make raw signature buffer out of rrsig
+- * @param rawsig_buf: raw signature buffer for result
+- * @param rrsig: signature to convert
+- * @return OK or more specific error.
+- */
+-static ldns_status
+-ldns_rrsig2rawsig_buffer(ldns_buffer* rawsig_buf, ldns_rr* rrsig)
+-{
+-	uint8_t sig_algo;
+-       
+-	if (rrsig == NULL) {
+-		return LDNS_STATUS_CRYPTO_NO_RRSIG;
+-	}
+-	if (ldns_rr_rdf(rrsig, 1) == NULL) {
+-		return LDNS_STATUS_MISSING_RDATA_FIELDS_RRSIG;
+-	}
+-	sig_algo = ldns_rdf2native_int8(ldns_rr_rdf(rrsig, 1));
+-	/* check for known and implemented algo's now (otherwise 
+-	 * the function could return a wrong error
+-	 */
+-	/* create a buffer with signature rdata */
+-	/* for some algorithms we need other data than for others... */
+-	/* (the DSA API wants DER encoding for instance) */
+-
+-	switch(sig_algo) {
+-	case LDNS_RSAMD5:
+-	case LDNS_RSASHA1:
+-	case LDNS_RSASHA1_NSEC3:
+-#ifdef USE_SHA2
+-	case LDNS_RSASHA256:
+-	case LDNS_RSASHA512:
+-#endif
+-#ifdef USE_GOST
+-	case LDNS_ECC_GOST:
+-#endif
+-		if (ldns_rr_rdf(rrsig, 8) == NULL) {
+-			return LDNS_STATUS_MISSING_RDATA_FIELDS_RRSIG;
+-		}
+-		if (ldns_rdf2buffer_wire(rawsig_buf, ldns_rr_rdf(rrsig, 8))
+-			       	!= LDNS_STATUS_OK) {
+-			return LDNS_STATUS_MEM_ERR;
+-		}
+-		break;
+-	case LDNS_DSA:
+-	case LDNS_DSA_NSEC3:
+-		/* EVP takes rfc2459 format, which is a tad longer than dns format */
+-		if (ldns_rr_rdf(rrsig, 8) == NULL) {
+-			return LDNS_STATUS_MISSING_RDATA_FIELDS_RRSIG;
+-		}
+-		if (ldns_convert_dsa_rrsig_rdf2asn1(
+-					rawsig_buf, ldns_rr_rdf(rrsig, 8)) 
+-				!= LDNS_STATUS_OK) {
+-			/*
+-			  if (ldns_rdf2buffer_wire(rawsig_buf,
+-			  ldns_rr_rdf(rrsig, 8)) != LDNS_STATUS_OK) {
+-			*/
+-			return LDNS_STATUS_MEM_ERR;
+-		}
+-		break;
+-#ifdef USE_ECDSA
+-        case LDNS_ECDSAP256SHA256:
+-        case LDNS_ECDSAP384SHA384:
+-                /* EVP produces an ASN prefix on the signature, which is
+-                 * not used in the DNS */
+-		if (ldns_rr_rdf(rrsig, 8) == NULL) {
+-			return LDNS_STATUS_MISSING_RDATA_FIELDS_RRSIG;
+-		}
+-		if (ldns_convert_ecdsa_rrsig_rdf2asn1(
+-					rawsig_buf, ldns_rr_rdf(rrsig, 8))
+-				!= LDNS_STATUS_OK) {
+-			return LDNS_STATUS_MEM_ERR;
+-                }
+-                break;
+-#endif
+-	case LDNS_DH:
+-	case LDNS_ECC:
+-	case LDNS_INDIRECT:
+-		return LDNS_STATUS_CRYPTO_ALGO_NOT_IMPL;
+-	default:
+-		return LDNS_STATUS_CRYPTO_UNKNOWN_ALGO;
+-	}
+-	return LDNS_STATUS_OK;
+-}
+-
+-/**
+- * Check RRSIG timestamps against the given 'now' time.
+- * @param rrsig: signature to check.
+- * @param now: the current time in seconds epoch.
+- * @return status code LDNS_STATUS_OK if all is fine.
+- */
+-static ldns_status
+-ldns_rrsig_check_timestamps(ldns_rr* rrsig, time_t now)
+-{
+-	int32_t inception, expiration;
+-	
+-	/* check the signature time stamps */
+-	inception = (int32_t)ldns_rdf2native_time_t(
+-		ldns_rr_rrsig_inception(rrsig));
+-	expiration = (int32_t)ldns_rdf2native_time_t(
+-		ldns_rr_rrsig_expiration(rrsig));
+-
+-	if (expiration - inception < 0) {
+-		/* bad sig, expiration before inception?? Tsssg */
+-		return LDNS_STATUS_CRYPTO_EXPIRATION_BEFORE_INCEPTION;
+-	}
+-	if (((int32_t) now) - inception < 0) {
+-		/* bad sig, inception date has not yet come to pass */
+-		return LDNS_STATUS_CRYPTO_SIG_NOT_INCEPTED;
+-	}
+-	if (expiration - ((int32_t) now) < 0) {
+-		/* bad sig, expiration date has passed */
+-		return LDNS_STATUS_CRYPTO_SIG_EXPIRED;
+-	}
+-	return LDNS_STATUS_OK;
+-}
+-
+-/**
+- * Prepare for verification.
+- * @param rawsig_buf: raw signature buffer made ready.
+- * @param verify_buf: data for verification buffer made ready.
+- * @param rrset_clone: made ready.
+- * @param rrsig: signature to prepare for.
+- * @return LDNS_STATUS_OK is all went well. Otherwise specific error.
+- */
+-static ldns_status
+-ldns_prepare_for_verify(ldns_buffer* rawsig_buf, ldns_buffer* verify_buf, 
+-	ldns_rr_list* rrset_clone, ldns_rr* rrsig)
+-{
+-	ldns_status result;
+-
+-	/* canonicalize the sig */
+-	ldns_dname2canonical(ldns_rr_owner(rrsig));
+-	
+-	/* check if the typecovered is equal to the type checked */
+-	if (ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rrsig)) !=
+-	    ldns_rr_get_type(ldns_rr_list_rr(rrset_clone, 0)))
+-		return LDNS_STATUS_CRYPTO_TYPE_COVERED_ERR;
+-	
+-	/* create a buffer with b64 signature rdata */
+-	result = ldns_rrsig2rawsig_buffer(rawsig_buf, rrsig);
+-	if(result != LDNS_STATUS_OK)
+-		return result;
+-
+-	/* use TTL from signature. Use wildcard names for wildcards */
+-	/* also canonicalizes rrset_clone */
+-	ldns_rrset_use_signature_ttl(rrset_clone, rrsig);
+-
+-	/* sort the rrset in canonical order  */
+-	ldns_rr_list_sort(rrset_clone);
+-
+-	/* put the signature rr (without the b64) to the verify_buf */
+-	if (ldns_rrsig2buffer_wire(verify_buf, rrsig) != LDNS_STATUS_OK)
+-		return LDNS_STATUS_MEM_ERR;
+-
+-	/* add the rrset in verify_buf */
+-	if(ldns_rr_list2buffer_wire(verify_buf, rrset_clone) 
+-		!= LDNS_STATUS_OK)
+-		return LDNS_STATUS_MEM_ERR;
+-
+-	return LDNS_STATUS_OK;
+-}
+-
+-/**
+- * Check if a key matches a signature.
+- * Checks keytag, sigalgo and signature.
+- * @param rawsig_buf: raw signature buffer for verify
+- * @param verify_buf: raw data buffer for verify
+- * @param rrsig: the rrsig
+- * @param key: key to attempt.
+- * @return LDNS_STATUS_OK if OK, else some specific error.
+- */
+-static ldns_status
+-ldns_verify_test_sig_key(ldns_buffer* rawsig_buf, ldns_buffer* verify_buf, 
+-	ldns_rr* rrsig, ldns_rr* key)
+-{
+-	uint8_t sig_algo;
+-       
+-	if (rrsig == NULL) {
+-		return LDNS_STATUS_CRYPTO_NO_RRSIG;
+-	}
+-	if (ldns_rr_rdf(rrsig, 1) == NULL) {
+-		return LDNS_STATUS_MISSING_RDATA_FIELDS_RRSIG;
+-	}
+-	sig_algo = ldns_rdf2native_int8(ldns_rr_rdf(rrsig, 1));
+-
+-	/* before anything, check if the keytags match */
+-	if (ldns_calc_keytag(key)
+-	    ==
+-	    ldns_rdf2native_int16(ldns_rr_rrsig_keytag(rrsig))
+-	    ) {
+-		ldns_buffer* key_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN);
+-		ldns_status result = LDNS_STATUS_ERR;
+-
+-		/* put the key-data in a buffer, that's the third rdf, with
+-		 * the base64 encoded key data */
+-		if (ldns_rr_rdf(key, 3) == NULL) {
+-			ldns_buffer_free(key_buf);
+-			return LDNS_STATUS_MISSING_RDATA_FIELDS_KEY;
+-		}
+-		if (ldns_rdf2buffer_wire(key_buf, ldns_rr_rdf(key, 3))
+-			       	!= LDNS_STATUS_OK) {
+-			ldns_buffer_free(key_buf); 
+-			/* returning is bad might screw up
+-			   good keys later in the list
+-			   what to do? */
+-			return LDNS_STATUS_ERR;
+-		}
+-
+-		if (ldns_rr_rdf(key, 2) == NULL) {
+-			result = LDNS_STATUS_MISSING_RDATA_FIELDS_KEY;
+-		}
+-		else if (sig_algo == ldns_rdf2native_int8(
+-					ldns_rr_rdf(key, 2))) {
+-			result = ldns_verify_rrsig_buffers(rawsig_buf, 
+-				verify_buf, key_buf, sig_algo);
+-		} else {
+-			/* No keys with the corresponding algorithm are found */
+-			result = LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY;
+-		}
+-
+-		ldns_buffer_free(key_buf); 
+-		return result;
+-	}
+-	else {
+-		/* No keys with the corresponding keytag are found */
+-		return LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY;
+-	}
+-}
+-
+-/* 
+- * to verify:
+- * - create the wire fmt of the b64 key rdata
+- * - create the wire fmt of the sorted rrset
+- * - create the wire fmt of the b64 sig rdata
+- * - create the wire fmt of the sig without the b64 rdata
+- * - cat the sig data (without b64 rdata) to the rrset
+- * - verify the rrset+sig, with the b64 data and the b64 key data
+- */
+-ldns_status
+-ldns_verify_rrsig_keylist_time(
+-		ldns_rr_list *rrset,
+-		ldns_rr *rrsig,
+-		const ldns_rr_list *keys, 
+-		time_t check_time,
+-		ldns_rr_list *good_keys)
+-{
+-	ldns_status result;
+-	ldns_rr_list *valid = ldns_rr_list_new();
+-	if (!valid)
+-		return LDNS_STATUS_MEM_ERR;
+-
+-	result = ldns_verify_rrsig_keylist_notime(rrset, rrsig, keys, valid);
+-	if(result != LDNS_STATUS_OK) {
+-		ldns_rr_list_free(valid); 
+-		return result;
+-	}
+-
+-	/* check timestamps last; its OK except time */
+-	result = ldns_rrsig_check_timestamps(rrsig, check_time);
+-	if(result != LDNS_STATUS_OK) {
+-		ldns_rr_list_free(valid); 
+-		return result;
+-	}
+-
+-	ldns_rr_list_cat(good_keys, valid);
+-	ldns_rr_list_free(valid);
+-	return LDNS_STATUS_OK;
+-}
+-
+-/* 
+- * to verify:
+- * - create the wire fmt of the b64 key rdata
+- * - create the wire fmt of the sorted rrset
+- * - create the wire fmt of the b64 sig rdata
+- * - create the wire fmt of the sig without the b64 rdata
+- * - cat the sig data (without b64 rdata) to the rrset
+- * - verify the rrset+sig, with the b64 data and the b64 key data
+- */
+-ldns_status
+-ldns_verify_rrsig_keylist(ldns_rr_list *rrset,
+-					 ldns_rr *rrsig,
+-					 const ldns_rr_list *keys, 
+-					 ldns_rr_list *good_keys)
+-{
+-	return ldns_verify_rrsig_keylist_time(
+-			rrset, rrsig, keys, ldns_time(NULL), good_keys);
+-}
+-
+-ldns_status
+-ldns_verify_rrsig_keylist_notime(ldns_rr_list *rrset,
+-					 ldns_rr *rrsig,
+-					 const ldns_rr_list *keys, 
+-					 ldns_rr_list *good_keys)
+-{
+-	ldns_buffer *rawsig_buf;
+-	ldns_buffer *verify_buf;
+-	uint16_t i;
+-	ldns_status result, status;
+-	ldns_rr_list *rrset_clone;
+-	ldns_rr_list *validkeys;
+-
+-	if (!rrset) {
+-		return LDNS_STATUS_ERR;
+-	}
+-
+-	validkeys = ldns_rr_list_new();
+-	if (!validkeys) {
+-		return LDNS_STATUS_MEM_ERR;
+-	}
+-	
+-	/* clone the rrset so that we can fiddle with it */
+-	rrset_clone = ldns_rr_list_clone(rrset);
+-
+-	/* create the buffers which will certainly hold the raw data */
+-	rawsig_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN);
+-	verify_buf  = ldns_buffer_new(LDNS_MAX_PACKETLEN);
+-
+-	result = ldns_prepare_for_verify(rawsig_buf, verify_buf, 
+-		rrset_clone, rrsig);
+-	if(result != LDNS_STATUS_OK) {
+-		ldns_buffer_free(verify_buf);
+-		ldns_buffer_free(rawsig_buf);
+-		ldns_rr_list_deep_free(rrset_clone);
+-		ldns_rr_list_free(validkeys);
+-		return result;
+-	}
+-
+-	result = LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY;
+-	for(i = 0; i < ldns_rr_list_rr_count(keys); i++) {
+-		status = ldns_verify_test_sig_key(rawsig_buf, verify_buf, 
+-			rrsig, ldns_rr_list_rr(keys, i));
+-		if (status == LDNS_STATUS_OK) {
+-			/* one of the keys has matched, don't break
+-			 * here, instead put the 'winning' key in
+-			 * the validkey list and return the list 
+-			 * later */
+-			if (!ldns_rr_list_push_rr(validkeys, 
+-				ldns_rr_list_rr(keys,i))) {
+-				/* couldn't push the key?? */
+-				ldns_buffer_free(rawsig_buf);
+-				ldns_buffer_free(verify_buf);
+-				ldns_rr_list_deep_free(rrset_clone);
+-				ldns_rr_list_free(validkeys);
+-				return LDNS_STATUS_MEM_ERR;
+-			}
+-
+-			result = status;
+-		}
+-
+-		if (result == LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY) {
+-			result = status;
+-		}
+-	}
+-
+-	/* no longer needed */
+-	ldns_rr_list_deep_free(rrset_clone);
+-	ldns_buffer_free(rawsig_buf);
+-	ldns_buffer_free(verify_buf);
+-
+-	if (ldns_rr_list_rr_count(validkeys) == 0) {
+-		/* no keys were added, return last error */
+-		ldns_rr_list_free(validkeys); 
+-		return result;
+-	}
+-
+-	/* do not check timestamps */
+-
+-	ldns_rr_list_cat(good_keys, validkeys);
+-	ldns_rr_list_free(validkeys);
+-	return LDNS_STATUS_OK;
+-}
+-
+-ldns_status
+-ldns_verify_rrsig_time(
+-		ldns_rr_list *rrset, 
+-		ldns_rr *rrsig, 
+-		ldns_rr *key, 
+-		time_t check_time)
+-{
+-	ldns_buffer *rawsig_buf;
+-	ldns_buffer *verify_buf;
+-	ldns_status result;
+-	ldns_rr_list *rrset_clone;
+-
+-	if (!rrset) {
+-		return LDNS_STATUS_NO_DATA;
+-	}
+-	/* clone the rrset so that we can fiddle with it */
+-	rrset_clone = ldns_rr_list_clone(rrset);
+-	/* create the buffers which will certainly hold the raw data */
+-	rawsig_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN);
+-	verify_buf  = ldns_buffer_new(LDNS_MAX_PACKETLEN);
+-
+-	result = ldns_prepare_for_verify(rawsig_buf, verify_buf, 
+-		rrset_clone, rrsig);
+-	if(result != LDNS_STATUS_OK) {
+-		ldns_rr_list_deep_free(rrset_clone);
+-		ldns_buffer_free(rawsig_buf);
+-		ldns_buffer_free(verify_buf);
+-		return result;
+-	}
+-	result = ldns_verify_test_sig_key(rawsig_buf, verify_buf, 
+-		rrsig, key);
+-	/* no longer needed */
+-	ldns_rr_list_deep_free(rrset_clone);
+-	ldns_buffer_free(rawsig_buf);
+-	ldns_buffer_free(verify_buf);
+-
+-	/* check timestamp last, apart from time its OK */
+-	if(result == LDNS_STATUS_OK)
+-		result = ldns_rrsig_check_timestamps(rrsig, check_time);
+-
+-	return result;
+-}
+-
+-ldns_status
+-ldns_verify_rrsig(ldns_rr_list *rrset, ldns_rr *rrsig, ldns_rr *key)
+-{
+-	return ldns_verify_rrsig_time(rrset, rrsig, key, ldns_time(NULL));
+-}
+-
+-
+-ldns_status
+-ldns_verify_rrsig_evp(ldns_buffer *sig,
+-				  ldns_buffer *rrset,
+-				  EVP_PKEY *key,
+-				  const EVP_MD *digest_type)
+-{
+-	return ldns_verify_rrsig_evp_raw(
+-			 (unsigned char*)ldns_buffer_begin(sig),
+-			 ldns_buffer_position(sig),
+-			 rrset,
+-			 key,
+-			 digest_type);
+-}
+-
+-ldns_status
+-ldns_verify_rrsig_evp_raw(unsigned char *sig, size_t siglen, 
+-					 ldns_buffer *rrset, EVP_PKEY *key, const EVP_MD *digest_type)
+-{
+-	EVP_MD_CTX ctx;
+-	int res;
+-
+-	EVP_MD_CTX_init(&ctx);
+-	
+-	EVP_VerifyInit(&ctx, digest_type);
+-	EVP_VerifyUpdate(&ctx,
+-				  ldns_buffer_begin(rrset),
+-				  ldns_buffer_position(rrset));
+-	res = EVP_VerifyFinal(&ctx, sig, (unsigned int) siglen, key);
+-	
+-	EVP_MD_CTX_cleanup(&ctx);
+-	
+-	if (res == 1) {
+-		return LDNS_STATUS_OK;
+-	} else if (res == 0) {
+-		return LDNS_STATUS_CRYPTO_BOGUS;
+-	}
+-	/* TODO how to communicate internal SSL error?
+-	   let caller use ssl's get_error() */
+-	return LDNS_STATUS_SSL_ERR;
+-}
+-
+-ldns_status
+-ldns_verify_rrsig_dsa(ldns_buffer *sig, ldns_buffer *rrset, ldns_buffer *key)
+-{
+-	return ldns_verify_rrsig_dsa_raw(
+-			 (unsigned char*) ldns_buffer_begin(sig),
+-			 ldns_buffer_position(sig),
+-			 rrset,
+-			 (unsigned char*) ldns_buffer_begin(key),
+-			 ldns_buffer_position(key));
+-}
+-
+-ldns_status
+-ldns_verify_rrsig_rsasha1(ldns_buffer *sig, ldns_buffer *rrset, ldns_buffer *key)
+-{
+-	return ldns_verify_rrsig_rsasha1_raw(
+-			 (unsigned char*)ldns_buffer_begin(sig),
+-			 ldns_buffer_position(sig),
+-			 rrset,
+-			 (unsigned char*) ldns_buffer_begin(key),
+-			 ldns_buffer_position(key));
+-}
+-
+-ldns_status
+-ldns_verify_rrsig_rsamd5(ldns_buffer *sig, ldns_buffer *rrset, ldns_buffer *key)
+-{
+-	return ldns_verify_rrsig_rsamd5_raw(
+-			 (unsigned char*)ldns_buffer_begin(sig),
+-			 ldns_buffer_position(sig),
+-			 rrset,
+-			 (unsigned char*) ldns_buffer_begin(key),
+-			 ldns_buffer_position(key));
+-}
+-
+-ldns_status
+-ldns_verify_rrsig_dsa_raw(unsigned char* sig, size_t siglen,
+-					 ldns_buffer* rrset, unsigned char* key, size_t keylen)
+-{
+-	EVP_PKEY *evp_key;
+-	ldns_status result;
+-
+-	evp_key = EVP_PKEY_new();
+-	if (EVP_PKEY_assign_DSA(evp_key, ldns_key_buf2dsa_raw(key, keylen))) {
+-		result = ldns_verify_rrsig_evp_raw(sig,
+-								siglen,
+-								rrset,
+-								evp_key,
+-								EVP_dss1());
+-	} else {
+-		result = LDNS_STATUS_SSL_ERR;
+-	}
+-	EVP_PKEY_free(evp_key);
+-	return result;
+-
+-}
+-
+-ldns_status
+-ldns_verify_rrsig_rsasha1_raw(unsigned char* sig, size_t siglen,
+-						ldns_buffer* rrset, unsigned char* key, size_t keylen)
+-{
+-	EVP_PKEY *evp_key;
+-	ldns_status result;
+-
+-	evp_key = EVP_PKEY_new();
+-	if (EVP_PKEY_assign_RSA(evp_key, ldns_key_buf2rsa_raw(key, keylen))) {
+-		result = ldns_verify_rrsig_evp_raw(sig,
+-								siglen,
+-								rrset,
+-								evp_key,
+-								EVP_sha1());
+-	} else {
+-		result = LDNS_STATUS_SSL_ERR;
+-	}
+-	EVP_PKEY_free(evp_key);
+-
+-	return result;
+-}
+-
+-ldns_status
+-ldns_verify_rrsig_rsasha256_raw(unsigned char* sig,
+-						  size_t siglen,
+-						  ldns_buffer* rrset,
+-						  unsigned char* key,
+-						  size_t keylen)
+-{
+-#ifdef USE_SHA2
+-	EVP_PKEY *evp_key;
+-	ldns_status result;
+-
+-	evp_key = EVP_PKEY_new();
+-	if (EVP_PKEY_assign_RSA(evp_key, ldns_key_buf2rsa_raw(key, keylen))) {
+-		result = ldns_verify_rrsig_evp_raw(sig,
+-								siglen,
+-								rrset,
+-								evp_key,
+-								EVP_sha256());
+-	} else {
+-		result = LDNS_STATUS_SSL_ERR;
+-	}
+-	EVP_PKEY_free(evp_key);
+-
+-	return result;
+-#else
+-	/* touch these to prevent compiler warnings */
+-	(void) sig;
+-	(void) siglen;
+-	(void) rrset;
+-	(void) key;
+-	(void) keylen;
+-	return LDNS_STATUS_CRYPTO_UNKNOWN_ALGO;
+-#endif
+-}
+-
+-ldns_status
+-ldns_verify_rrsig_rsasha512_raw(unsigned char* sig,
+-						  size_t siglen,
+-						  ldns_buffer* rrset,
+-						  unsigned char* key,
+-						  size_t keylen)
+-{
+-#ifdef USE_SHA2
+-	EVP_PKEY *evp_key;
+-	ldns_status result;
+-
+-	evp_key = EVP_PKEY_new();
+-	if (EVP_PKEY_assign_RSA(evp_key, ldns_key_buf2rsa_raw(key, keylen))) {
+-		result = ldns_verify_rrsig_evp_raw(sig,
+-								siglen,
+-								rrset,
+-								evp_key,
+-								EVP_sha512());
+-	} else {
+-		result = LDNS_STATUS_SSL_ERR;
+-	}
+-	EVP_PKEY_free(evp_key);
+-
+-	return result;
+-#else
+-	/* touch these to prevent compiler warnings */
+-	(void) sig;
+-	(void) siglen;
+-	(void) rrset;
+-	(void) key;
+-	(void) keylen;
+-	return LDNS_STATUS_CRYPTO_UNKNOWN_ALGO;
+-#endif
+-}
+-
+-
+-ldns_status
+-ldns_verify_rrsig_rsamd5_raw(unsigned char* sig,
+-					    size_t siglen,
+-					    ldns_buffer* rrset,
+-					    unsigned char* key,
+-					    size_t keylen)
+-{
+-	EVP_PKEY *evp_key;
+-	ldns_status result;
+-
+-	evp_key = EVP_PKEY_new();
+-	if (EVP_PKEY_assign_RSA(evp_key, ldns_key_buf2rsa_raw(key, keylen))) {
+-		result = ldns_verify_rrsig_evp_raw(sig,
+-								siglen,
+-								rrset,
+-								evp_key,
+-								EVP_md5());
+-	} else {
+-		result = LDNS_STATUS_SSL_ERR;
+-	}
+-	EVP_PKEY_free(evp_key);
+-
+-	return result;
+-}
+-
+-#endif
+diff --git a/src/ldns/dnssec_zone.c b/src/ldns/dnssec_zone.c
+deleted file mode 100644
+index 0fec48c..0000000
+--- a/src/ldns/dnssec_zone.c
++++ /dev/null
+@@ -1,1192 +0,0 @@
+-/*
+- * special zone file structures and functions for better dnssec handling
+- */
+-
+-#include <ldns/config.h>
+-
+-#include <ldns/ldns.h>
+-
+-ldns_dnssec_rrs *
+-ldns_dnssec_rrs_new(void)
+-{
+-	ldns_dnssec_rrs *new_rrs;
+-	new_rrs = LDNS_MALLOC(ldns_dnssec_rrs);
+-        if(!new_rrs) return NULL;
+-	new_rrs->rr = NULL;
+-	new_rrs->next = NULL;
+-	return new_rrs;
+-}
+-
+-INLINE void
+-ldns_dnssec_rrs_free_internal(ldns_dnssec_rrs *rrs, int deep)
+-{
+-	ldns_dnssec_rrs *next;
+-	while (rrs) {
+-		next = rrs->next;
+-		if (deep) {
+-			ldns_rr_free(rrs->rr);
+-		}
+-		LDNS_FREE(rrs);
+-		rrs = next;
+-	}
+-}
+-
+-void
+-ldns_dnssec_rrs_free(ldns_dnssec_rrs *rrs)
+-{
+-	ldns_dnssec_rrs_free_internal(rrs, 0);
+-}
+-
+-void
+-ldns_dnssec_rrs_deep_free(ldns_dnssec_rrs *rrs)
+-{
+-	ldns_dnssec_rrs_free_internal(rrs, 1);
+-}
+-
+-ldns_status
+-ldns_dnssec_rrs_add_rr(ldns_dnssec_rrs *rrs, ldns_rr *rr)
+-{
+-	int cmp;
+-	ldns_dnssec_rrs *new_rrs;
+-	if (!rrs || !rr) {
+-		return LDNS_STATUS_ERR;
+-	}
+-
+-	/* this could be done more efficiently; name and type should already
+-	   be equal */
+-	cmp = ldns_rr_compare(rrs->rr, rr);
+-	if (cmp < 0) {
+-		if (rrs->next) {
+-			return ldns_dnssec_rrs_add_rr(rrs->next, rr);
+-		} else {
+-			new_rrs = ldns_dnssec_rrs_new();
+-			new_rrs->rr = rr;
+-			rrs->next = new_rrs;
+-		}
+-	} else if (cmp > 0) {
+-		/* put the current old rr in the new next, put the new
+-		   rr in the current container */
+-		new_rrs = ldns_dnssec_rrs_new();
+-		new_rrs->rr = rrs->rr;
+-		new_rrs->next = rrs->next;
+-		rrs->rr = rr;
+-		rrs->next = new_rrs;
+-	}
+-	/* Silently ignore equal rr's */
+-	return LDNS_STATUS_OK;
+-}
+-
+-void
+-ldns_dnssec_rrs_print_fmt(FILE *out, const ldns_output_format *fmt,
+-	       ldns_dnssec_rrs *rrs)
+-{
+-	if (!rrs) {
+-		if ((fmt->flags & LDNS_COMMENT_LAYOUT))
+-			fprintf(out, "; <void>");
+-	} else {
+-		if (rrs->rr) {
+-			ldns_rr_print_fmt(out, fmt, rrs->rr);
+-		}
+-		if (rrs->next) {
+-			ldns_dnssec_rrs_print_fmt(out, fmt, rrs->next);
+-		}
+-	}
+-}
+-
+-void
+-ldns_dnssec_rrs_print(FILE *out, ldns_dnssec_rrs *rrs)
+-{
+-	ldns_dnssec_rrs_print_fmt(out, ldns_output_format_default, rrs);
+-}
+-
+-
+-ldns_dnssec_rrsets *
+-ldns_dnssec_rrsets_new(void)
+-{
+-	ldns_dnssec_rrsets *new_rrsets;
+-	new_rrsets = LDNS_MALLOC(ldns_dnssec_rrsets);
+-        if(!new_rrsets) return NULL;
+-	new_rrsets->rrs = NULL;
+-	new_rrsets->type = 0;
+-	new_rrsets->signatures = NULL;
+-	new_rrsets->next = NULL;
+-	return new_rrsets;
+-}
+-
+-INLINE void
+-ldns_dnssec_rrsets_free_internal(ldns_dnssec_rrsets *rrsets, int deep)
+-{
+-	if (rrsets) {
+-		if (rrsets->rrs) {
+-			ldns_dnssec_rrs_free_internal(rrsets->rrs, deep);
+-		}
+-		if (rrsets->next) {
+-			ldns_dnssec_rrsets_free_internal(rrsets->next, deep);
+-		}
+-		if (rrsets->signatures) {
+-			ldns_dnssec_rrs_free_internal(rrsets->signatures, deep);
+-		}
+-		LDNS_FREE(rrsets);
+-	}
+-}
+-
+-void
+-ldns_dnssec_rrsets_free(ldns_dnssec_rrsets *rrsets)
+-{
+-	ldns_dnssec_rrsets_free_internal(rrsets, 0);
+-}
+-
+-void
+-ldns_dnssec_rrsets_deep_free(ldns_dnssec_rrsets *rrsets)
+-{
+-	ldns_dnssec_rrsets_free_internal(rrsets, 1);
+-}
+-
+-ldns_rr_type
+-ldns_dnssec_rrsets_type(ldns_dnssec_rrsets *rrsets)
+-{
+-	if (rrsets) {
+-		return rrsets->type;
+-	} else {
+-		return 0;
+-	}
+-}
+-
+-ldns_status
+-ldns_dnssec_rrsets_set_type(ldns_dnssec_rrsets *rrsets,
+-					   ldns_rr_type type)
+-{
+-	if (rrsets) {
+-		rrsets->type = type;
+-		return LDNS_STATUS_OK;
+-	}
+-	return LDNS_STATUS_ERR;
+-}
+-
+-static ldns_dnssec_rrsets *
+-ldns_dnssec_rrsets_new_frm_rr(ldns_rr *rr)
+-{
+-	ldns_dnssec_rrsets *new_rrsets;
+-	ldns_rr_type rr_type;
+-	bool rrsig;
+-
+-	new_rrsets = ldns_dnssec_rrsets_new();
+-	rr_type = ldns_rr_get_type(rr);
+-	if (rr_type == LDNS_RR_TYPE_RRSIG) {
+-		rrsig = true;
+-		rr_type = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
+-	} else {
+-		rrsig = false;
+-	}
+-	if (!rrsig) {
+-		new_rrsets->rrs = ldns_dnssec_rrs_new();
+-		new_rrsets->rrs->rr = rr;
+-	} else {
+-		new_rrsets->signatures = ldns_dnssec_rrs_new();
+-		new_rrsets->signatures->rr = rr;
+-	}
+-	new_rrsets->type = rr_type;
+-	return new_rrsets;
+-}
+-
+-ldns_status
+-ldns_dnssec_rrsets_add_rr(ldns_dnssec_rrsets *rrsets, ldns_rr *rr)
+-{
+-	ldns_dnssec_rrsets *new_rrsets;
+-	ldns_rr_type rr_type;
+-	bool rrsig = false;
+-	ldns_status result = LDNS_STATUS_OK;
+-
+-	if (!rrsets || !rr) {
+-		return LDNS_STATUS_ERR;
+-	}
+-
+-	rr_type = ldns_rr_get_type(rr);
+-
+-	if (rr_type == LDNS_RR_TYPE_RRSIG) {
+-		rrsig = true;
+-		rr_type = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
+-	}
+-
+-	if (!rrsets->rrs && rrsets->type == 0 && !rrsets->signatures) {
+-		if (!rrsig) {
+-			rrsets->rrs = ldns_dnssec_rrs_new();
+-			rrsets->rrs->rr = rr;
+-			rrsets->type = rr_type;
+-		} else {
+-			rrsets->signatures = ldns_dnssec_rrs_new();
+-			rrsets->signatures->rr = rr;
+-			rrsets->type = rr_type;
+-		}
+-		return LDNS_STATUS_OK;
+-	}
+-
+-	if (rr_type > ldns_dnssec_rrsets_type(rrsets)) {
+-		if (rrsets->next) {
+-			result = ldns_dnssec_rrsets_add_rr(rrsets->next, rr);
+-		} else {
+-			new_rrsets = ldns_dnssec_rrsets_new_frm_rr(rr);
+-			rrsets->next = new_rrsets;
+-		}
+-	} else if (rr_type < ldns_dnssec_rrsets_type(rrsets)) {
+-		/* move the current one into the new next, 
+-		   replace field of current with data from new rr */
+-		new_rrsets = ldns_dnssec_rrsets_new();
+-		new_rrsets->rrs = rrsets->rrs;
+-		new_rrsets->type = rrsets->type;
+-		new_rrsets->signatures = rrsets->signatures;
+-		new_rrsets->next = rrsets->next;
+-		if (!rrsig) {
+-			rrsets->rrs = ldns_dnssec_rrs_new();
+-			rrsets->rrs->rr = rr;
+-			rrsets->signatures = NULL;
+-		} else {
+-			rrsets->rrs = NULL;
+-			rrsets->signatures = ldns_dnssec_rrs_new();
+-			rrsets->signatures->rr = rr;
+-		}
+-		rrsets->type = rr_type;
+-		rrsets->next = new_rrsets;
+-	} else {
+-		/* equal, add to current rrsets */
+-		if (rrsig) {
+-			if (rrsets->signatures) {
+-				result = ldns_dnssec_rrs_add_rr(rrsets->signatures, rr);
+-			} else {
+-				rrsets->signatures = ldns_dnssec_rrs_new();
+-				rrsets->signatures->rr = rr;
+-			}
+-		} else {
+-			if (rrsets->rrs) {
+-				result = ldns_dnssec_rrs_add_rr(rrsets->rrs, rr);
+-			} else {
+-				rrsets->rrs = ldns_dnssec_rrs_new();
+-				rrsets->rrs->rr = rr;
+-			}
+-		}
+-	}
+-
+-	return result;
+-}
+-
+-static void
+-ldns_dnssec_rrsets_print_soa_fmt(FILE *out, const ldns_output_format *fmt,
+-		ldns_dnssec_rrsets *rrsets,
+-		bool follow,
+-		bool show_soa)
+-{
+-	if (!rrsets) {
+-		if ((fmt->flags & LDNS_COMMENT_LAYOUT))
+-			fprintf(out, "; <void>\n");
+-	} else {
+-		if (rrsets->rrs &&
+-		    (show_soa ||
+-			ldns_rr_get_type(rrsets->rrs->rr) != LDNS_RR_TYPE_SOA
+-		    )
+-		   ) {
+-			ldns_dnssec_rrs_print_fmt(out, fmt, rrsets->rrs);
+-			if (rrsets->signatures) {
+-				ldns_dnssec_rrs_print_fmt(out, fmt, 
+-						rrsets->signatures);
+-			}
+-		}
+-		if (follow && rrsets->next) {
+-			ldns_dnssec_rrsets_print_soa_fmt(out, fmt, 
+-					rrsets->next, follow, show_soa);
+-		}
+-	}
+-}
+-
+-
+-void
+-ldns_dnssec_rrsets_print_fmt(FILE *out, const ldns_output_format *fmt,
+-		ldns_dnssec_rrsets *rrsets, 
+-		bool follow)
+-{
+-	ldns_dnssec_rrsets_print_soa_fmt(out, fmt, rrsets, follow, true);
+-}
+-
+-void
+-ldns_dnssec_rrsets_print(FILE *out, ldns_dnssec_rrsets *rrsets, bool follow)
+-{
+-	ldns_dnssec_rrsets_print_fmt(out, ldns_output_format_default, 
+-			rrsets, follow);
+-}
+-
+-ldns_dnssec_name *
+-ldns_dnssec_name_new(void)
+-{
+-	ldns_dnssec_name *new_name;
+-
+-	new_name = LDNS_CALLOC(ldns_dnssec_name, 1);
+-	if (!new_name) {
+-		return NULL;
+-	}
+-	/*
+-	 * not needed anymore because CALLOC initalizes everything to zero.
+-
+-	new_name->name = NULL;
+-	new_name->rrsets = NULL;
+-	new_name->name_alloced = false;
+-	new_name->nsec = NULL;
+-	new_name->nsec_signatures = NULL;
+-
+-	new_name->is_glue = false;
+-	new_name->hashed_name = NULL;
+-
+-	 */
+-	return new_name;
+-}
+-
+-ldns_dnssec_name *
+-ldns_dnssec_name_new_frm_rr(ldns_rr *rr)
+-{
+-	ldns_dnssec_name *new_name = ldns_dnssec_name_new();
+-
+-	new_name->name = ldns_rr_owner(rr);
+-	if(ldns_dnssec_name_add_rr(new_name, rr) != LDNS_STATUS_OK) {
+-		ldns_dnssec_name_free(new_name);
+-		return NULL;
+-	}
+-
+-	return new_name;
+-}
+-
+-INLINE void
+-ldns_dnssec_name_free_internal(ldns_dnssec_name *name,
+-                               int deep)
+-{
+-	if (name) {
+-		if (name->name_alloced) {
+-			ldns_rdf_deep_free(name->name);
+-		}
+-		if (name->rrsets) {
+-			ldns_dnssec_rrsets_free_internal(name->rrsets, deep);
+-		}
+-		if (name->nsec && deep) {
+-			ldns_rr_free(name->nsec);
+-		}
+-		if (name->nsec_signatures) {
+-			ldns_dnssec_rrs_free_internal(name->nsec_signatures, deep);
+-		}
+-		if (name->hashed_name) {
+-			if (deep) {
+-				ldns_rdf_deep_free(name->hashed_name);
+-			}
+-		}
+-		LDNS_FREE(name);
+-	}
+-}
+-
+-void
+-ldns_dnssec_name_free(ldns_dnssec_name *name)
+-{
+-  ldns_dnssec_name_free_internal(name, 0);
+-}
+-
+-void
+-ldns_dnssec_name_deep_free(ldns_dnssec_name *name)
+-{
+-  ldns_dnssec_name_free_internal(name, 1);
+-}
+-
+-ldns_rdf *
+-ldns_dnssec_name_name(ldns_dnssec_name *name)
+-{
+-	if (name) {
+-		return name->name;
+-	}
+-	return NULL;
+-}
+-
+-bool
+-ldns_dnssec_name_is_glue(ldns_dnssec_name *name)
+-{
+-	if (name) {
+-		return name->is_glue;
+-	}
+-	return false;
+-}
+-
+-void
+-ldns_dnssec_name_set_name(ldns_dnssec_name *rrset,
+-					 ldns_rdf *dname)
+-{
+-	if (rrset && dname) {
+-		rrset->name = dname;
+-	}
+-}
+-
+-
+-void
+-ldns_dnssec_name_set_nsec(ldns_dnssec_name *rrset, ldns_rr *nsec)
+-{
+-	if (rrset && nsec) {
+-		rrset->nsec = nsec;
+-	}
+-}
+-
+-int
+-ldns_dnssec_name_cmp(const void *a, const void *b)
+-{
+-	ldns_dnssec_name *na = (ldns_dnssec_name *) a;
+-	ldns_dnssec_name *nb = (ldns_dnssec_name *) b;
+-
+-	if (na && nb) {
+-		return ldns_dname_compare(ldns_dnssec_name_name(na),
+-							 ldns_dnssec_name_name(nb));
+-	} else if (na) {
+-		return 1;
+-	} else if (nb) {
+-		return -1;
+-	} else {
+-		return 0;
+-	}
+-}
+-
+-ldns_status
+-ldns_dnssec_name_add_rr(ldns_dnssec_name *name,
+-				    ldns_rr *rr)
+-{
+-	ldns_status result = LDNS_STATUS_OK;
+-	ldns_rr_type rr_type;
+-	ldns_rr_type typecovered = 0;
+-
+-	/* special handling for NSEC3 and NSECX covering RRSIGS */
+-
+-	if (!name || !rr) {
+-		return LDNS_STATUS_ERR;
+-	}
+-
+-	rr_type = ldns_rr_get_type(rr);
+-
+-	if (rr_type == LDNS_RR_TYPE_RRSIG) {
+-		typecovered = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
+-	}
+-
+-	if (rr_type == LDNS_RR_TYPE_NSEC ||
+-	    rr_type == LDNS_RR_TYPE_NSEC3) {
+-		/* XX check if is already set (and error?) */
+-		name->nsec = rr;
+-	} else if (typecovered == LDNS_RR_TYPE_NSEC ||
+-			 typecovered == LDNS_RR_TYPE_NSEC3) {
+-		if (name->nsec_signatures) {
+-			result = ldns_dnssec_rrs_add_rr(name->nsec_signatures, rr);
+-		} else {
+-			name->nsec_signatures = ldns_dnssec_rrs_new();
+-			name->nsec_signatures->rr = rr;
+-		}
+-	} else {
+-		/* it's a 'normal' RR, add it to the right rrset */
+-		if (name->rrsets) {
+-			result = ldns_dnssec_rrsets_add_rr(name->rrsets, rr);
+-		} else {
+-			name->rrsets = ldns_dnssec_rrsets_new();
+-			result = ldns_dnssec_rrsets_add_rr(name->rrsets, rr);
+-		}
+-	}
+-	return result;
+-}
+-
+-ldns_dnssec_rrsets *
+-ldns_dnssec_name_find_rrset(ldns_dnssec_name *name,
+-					   ldns_rr_type type) {
+-	ldns_dnssec_rrsets *result;
+-
+-	result = name->rrsets;
+-	while (result) {
+-		if (result->type == type) {
+-			return result;
+-		} else {
+-			result = result->next;
+-		}
+-	}
+-	return NULL;
+-}
+-
+-ldns_dnssec_rrsets *
+-ldns_dnssec_zone_find_rrset(ldns_dnssec_zone *zone,
+-					   ldns_rdf *dname,
+-					   ldns_rr_type type)
+-{
+-	ldns_rbnode_t *node;
+-
+-	if (!zone || !dname || !zone->names) {
+-		return NULL;
+-	}
+-
+-	node = ldns_rbtree_search(zone->names, dname);
+-	if (node) {
+-		return ldns_dnssec_name_find_rrset((ldns_dnssec_name *)node->data,
+-									type);
+-	} else {
+-		return NULL;
+-	}
+-}
+-
+-static void
+-ldns_dnssec_name_print_soa_fmt(FILE *out, const ldns_output_format *fmt,
+-		ldns_dnssec_name *name, 
+-		bool show_soa)
+-{
+-	if (name) {
+-		if(name->rrsets) {
+-			ldns_dnssec_rrsets_print_soa_fmt(out, fmt, 
+-					name->rrsets, true, show_soa);
+-		} else if ((fmt->flags & LDNS_COMMENT_LAYOUT)) {
+-			fprintf(out, ";; Empty nonterminal: ");
+-			ldns_rdf_print(out, name->name);
+-			fprintf(out, "\n");
+-		}
+-		if(name->nsec) {
+-			ldns_rr_print_fmt(out, fmt, name->nsec);
+-		}
+-		if (name->nsec_signatures) {
+-			ldns_dnssec_rrs_print_fmt(out, fmt, 
+-					name->nsec_signatures);
+-		}
+-	} else if ((fmt->flags & LDNS_COMMENT_LAYOUT)) {
+-		fprintf(out, "; <void>\n");
+-	}
+-}
+-
+-
+-void
+-ldns_dnssec_name_print_fmt(FILE *out, const ldns_output_format *fmt,
+-		ldns_dnssec_name *name)
+-{
+-	ldns_dnssec_name_print_soa_fmt(out, fmt, name, true);
+-}
+-
+-void
+-ldns_dnssec_name_print(FILE *out, ldns_dnssec_name *name)
+-{
+-	ldns_dnssec_name_print_fmt(out, ldns_output_format_default, name);
+-}
+-
+-
+-ldns_dnssec_zone *
+-ldns_dnssec_zone_new(void)
+-{
+-	ldns_dnssec_zone *zone = LDNS_MALLOC(ldns_dnssec_zone);
+-        if(!zone) return NULL;
+-	zone->soa = NULL;
+-	zone->names = NULL;
+-	zone->hashed_names = NULL;
+-	zone->_nsec3params = NULL;
+-
+-	return 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;
+-}
+-
+-/* When the zone is first read into an list and then inserted into an
+- * ldns_dnssec_zone (rbtree) the nodes of the rbtree are allocated close (next)
+- * to each other. Because ldns-verify-zone (the only program that uses this
+- * function) uses the rbtree mostly for sequentual walking, this results
+- * in a speed increase (of 15% on linux) because we have less CPU-cache misses.
+- */
+-#define FASTER_DNSSEC_ZONE_NEW_FRM_FP 1 /* Because of L2 cache efficiency */
+-
+-static ldns_status
+-ldns_dnssec_zone_add_empty_nonterminals_nsec3(
+-		ldns_dnssec_zone *zone, ldns_rbtree_t *nsec3s);
+-
+-static void
+-ldns_todo_nsec3_ents_node_free(ldns_rbnode_t *node, void *arg) {
+-	(void) arg;
+-	ldns_rdf_deep_free((ldns_rdf *)node->key);
+-	LDNS_FREE(node);
+-}
+-
+-ldns_status
+-ldns_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_rdf *my_origin = NULL;
+-	ldns_rdf *my_prev = NULL;
+-
+-	ldns_dnssec_zone *newzone = ldns_dnssec_zone_new();
+-	/* NSEC3s may occur before the names they refer to. We must remember
+-	   them and add them to the name later on, after the name is read.
+-	   We track not yet  matching NSEC3s*n the todo_nsec3s list */
+-	ldns_rr_list* todo_nsec3s = ldns_rr_list_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.
+-
+-	   nsec3_ents (where ent is e.n.t.; i.e. empty non terminal) will
+-	   hold the NSEC3s that still didn't have a matching name in the
+-	   zone tree, even after all names were read.  They can only match
+-	   after the zone is equiped with all the empty non terminals. */
+-	ldns_rbtree_t todo_nsec3_ents;
+-	ldns_rbnode_t *new_node;
+-	ldns_rr_list* todo_nsec3_rrsigs = ldns_rr_list_new();
+-
+-	ldns_status status;
+-
+-#ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
+-	ldns_zone* zone = NULL;
+-#else
+-	uint32_t  my_ttl = ttl;
+-#endif
+-
+-	ldns_rbtree_init(&todo_nsec3_ents, ldns_dname_compare_v);
+-
+-#ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
+-	status = ldns_zone_new_frm_fp_l(&zone, fp, origin,ttl, c, line_nr);
+-	if (status != LDNS_STATUS_OK)
+-		goto error;
+-#endif
+-	if (!newzone || !todo_nsec3s || !todo_nsec3_rrsigs ) {
+-		status = LDNS_STATUS_MEM_ERR;
+-		goto error;
+-	}
+-	if (origin) {
+-		if (!(my_origin = ldns_rdf_clone(origin))) {
+-			status = LDNS_STATUS_MEM_ERR;
+-			goto error;
+-		}
+-		if (!(my_prev   = ldns_rdf_clone(origin))) {
+-			status = LDNS_STATUS_MEM_ERR;
+-			goto error;
+-		}
+-	}
+-
+-#ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
+-	if (ldns_zone_soa(zone)) {
+-		status = ldns_dnssec_zone_add_rr(newzone, ldns_zone_soa(zone));
+-		if (status != LDNS_STATUS_OK)
+-			goto error;
+-	}
+-	for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(zone)); i++) {
+-		cur_rr = ldns_rr_list_rr(ldns_zone_rrs(zone), i);
+-		status = LDNS_STATUS_OK;
+-#else
+-	while (!feof(fp)) {
+-		status = ldns_rr_new_frm_fp_l(&cur_rr, fp, &my_ttl, &my_origin,
+-				&my_prev, line_nr);
+-
+-#endif
+-		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(todo_nsec3s,
+-						       	cur_rr);
+-				}
+-				status = LDNS_STATUS_OK;
+-
+-			} else if (status != LDNS_STATUS_OK)
+-				goto error;
+-
+-			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*/
+-			status = LDNS_STATUS_OK;
+-			break;
+-
+-		case LDNS_STATUS_SYNTAX_INCLUDE:/* $include not implemented */
+-			status =  LDNS_STATUS_SYNTAX_INCLUDE_ERR_NOTIMPL;
+-			break;
+-
+-		default:
+-			goto error;
+-		}
+-	}
+-
+-	for (i = 0; status == LDNS_STATUS_OK &&
+-			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);
+-		if (status == LDNS_STATUS_DNSSEC_NSEC3_ORIGINAL_NOT_FOUND) {
+-			if (!(new_node = LDNS_MALLOC(ldns_rbnode_t))) {
+-				status = LDNS_STATUS_MEM_ERR;
+-				break;
+-			}
+-			new_node->key  = ldns_dname_label(ldns_rr_owner(cur_rr), 0);
+-			new_node->data = cur_rr;
+-			if (!ldns_rbtree_insert(&todo_nsec3_ents, new_node)) {
+-				LDNS_FREE(new_node);
+-				status = LDNS_STATUS_MEM_ERR;
+-				break;
+-			}
+-			status = LDNS_STATUS_OK;
+-		}
+-	}
+-	if (todo_nsec3_ents.count > 0)
+-		(void) ldns_dnssec_zone_add_empty_nonterminals_nsec3(
+-				newzone, &todo_nsec3_ents);
+-	for (i = 0; status == LDNS_STATUS_OK &&
+-			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);
+-	}
+-	if (z) {
+-		*z = newzone;
+-		newzone = NULL;
+-	} else {
+-		ldns_dnssec_zone_free(newzone);
+-	}
+-
+-error:
+-#ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
+-	if (zone) {
+-		ldns_zone_free(zone);
+-	}
+-#endif
+-	ldns_rr_list_free(todo_nsec3_rrsigs);
+-	ldns_traverse_postorder(&todo_nsec3_ents,
+-			ldns_todo_nsec3_ents_node_free, NULL);
+-	ldns_rr_list_free(todo_nsec3s);
+-
+-	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;
+-}
+-
+-ldns_status
+-ldns_dnssec_zone_new_frm_fp(ldns_dnssec_zone** z, FILE* fp, ldns_rdf* origin,
+-		uint32_t ttl, ldns_rr_class ATTR_UNUSED(c))
+-{
+-	return ldns_dnssec_zone_new_frm_fp_l(z, fp, origin, ttl, c, NULL);
+-}
+-
+-static void
+-ldns_dnssec_name_node_free(ldns_rbnode_t *node, void *arg) {
+-	(void) arg;
+-	ldns_dnssec_name_free((ldns_dnssec_name *)node->data);
+-	LDNS_FREE(node);
+-}
+-
+-static void
+-ldns_dnssec_name_node_deep_free(ldns_rbnode_t *node, void *arg) {
+-	(void) arg;
+-	ldns_dnssec_name_deep_free((ldns_dnssec_name *)node->data);
+-	LDNS_FREE(node);
+-}
+-
+-void
+-ldns_dnssec_zone_free(ldns_dnssec_zone *zone)
+-{
+-	if (zone) {
+-		if (zone->names) {
+-			/* destroy all name structures within the tree */
+-			ldns_traverse_postorder(zone->names,
+-						    ldns_dnssec_name_node_free,
+-						    NULL);
+-			LDNS_FREE(zone->names);
+-		}
+-		LDNS_FREE(zone);
+-	}
+-}
+-
+-void
+-ldns_dnssec_zone_deep_free(ldns_dnssec_zone *zone)
+-{
+-	if (zone) {
+-		if (zone->names) {
+-			/* destroy all name structures within the tree */
+-			ldns_traverse_postorder(zone->names,
+-						    ldns_dnssec_name_node_deep_free,
+-						    NULL);
+-			LDNS_FREE(zone->names);
+-		}
+-		LDNS_FREE(zone);
+-	}
+-}
+-
+-/* use for dname comparison in tree */
+-int
+-ldns_dname_compare_v(const void *a, const void *b) {
+-	return ldns_dname_compare((ldns_rdf *)a, (ldns_rdf *)b);
+-}
+-
+-static void
+-ldns_dnssec_name_make_hashed_name(ldns_dnssec_zone *zone,
+-		ldns_dnssec_name* name, ldns_rr* nsec3rr);
+-
+-static void
+-ldns_hashed_names_node_free(ldns_rbnode_t *node, void *arg) {
+-	(void) arg;
+-	LDNS_FREE(node);
+-}
+-
+-static void
+-ldns_dnssec_zone_hashed_names_from_nsec3(
+-		ldns_dnssec_zone* zone, ldns_rr* nsec3rr)
+-{
+-	ldns_rbnode_t* current_node;
+-	ldns_dnssec_name* current_name;
+-
+-	assert(zone != NULL);
+-	assert(nsec3rr != NULL);
+-
+-	if (zone->hashed_names) {
+-		ldns_traverse_postorder(zone->hashed_names,
+-				ldns_hashed_names_node_free, NULL);
+-		LDNS_FREE(zone->hashed_names);
+-	}
+-	zone->_nsec3params = nsec3rr;
+-
+-	/* So this is a NSEC3 zone.
+-	* Calculate hashes for all names already in the zone
+-	*/
+-	zone->hashed_names = ldns_rbtree_create(ldns_dname_compare_v);
+-	if (zone->hashed_names == NULL) {
+-		return;
+-	}
+-	for ( current_node  = ldns_rbtree_first(zone->names)
+-	    ; current_node != LDNS_RBTREE_NULL
+-	    ; current_node  = ldns_rbtree_next(current_node)
+-	    ) {
+-		current_name = (ldns_dnssec_name *) current_node->data;
+-		ldns_dnssec_name_make_hashed_name(zone, current_name, nsec3rr);
+-
+-	}
+-}
+-
+-static void
+-ldns_dnssec_name_make_hashed_name(ldns_dnssec_zone *zone,
+-		ldns_dnssec_name* name, ldns_rr* nsec3rr)
+-{
+-	ldns_rbnode_t* new_node;
+-
+-	assert(name != NULL);
+-	if (! zone->_nsec3params) {
+-		if (! nsec3rr) {
+-			return;
+-		}
+-		ldns_dnssec_zone_hashed_names_from_nsec3(zone, nsec3rr);
+-
+-	} else if (! nsec3rr) {
+-		nsec3rr = zone->_nsec3params;
+-	}
+-	name->hashed_name = ldns_nsec3_hash_name_frm_nsec3(nsec3rr, name->name);
+-
+-	/* Also store in zone->hashed_names */
+-	if ((new_node = LDNS_MALLOC(ldns_rbnode_t))) {
+-
+-		new_node->key  = name->hashed_name;
+-		new_node->data = name;
+-
+-		if (ldns_rbtree_insert(zone->hashed_names, new_node) == NULL) {
+-
+-				LDNS_FREE(new_node);
+-		}
+-	}
+-}
+-
+-
+-static ldns_rbnode_t *
+-ldns_dnssec_zone_find_nsec3_original(ldns_dnssec_zone *zone, ldns_rr *rr) {
+-	ldns_rdf *hashed_name;
+-
+-	hashed_name = ldns_dname_label(ldns_rr_owner(rr), 0);
+-	if (hashed_name == NULL) {
+-		return NULL;
+-	}
+-	if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_NSEC3 && ! zone->_nsec3params){
+-
+-		ldns_dnssec_zone_hashed_names_from_nsec3(zone, rr);
+-	}
+-	if (zone->hashed_names == NULL) {
+-		ldns_rdf_deep_free(hashed_name);
+-		return NULL;
+-	}
+-	return  ldns_rbtree_search(zone->hashed_names, hashed_name);
+-}
+-
+-ldns_status
+-ldns_dnssec_zone_add_rr(ldns_dnssec_zone *zone, ldns_rr *rr)
+-{
+-	ldns_status result = LDNS_STATUS_OK;
+-	ldns_dnssec_name *cur_name;
+-	ldns_rbnode_t *cur_node;
+-	ldns_rr_type type_covered = 0;
+-
+-	if (!zone || !rr) {
+-		return LDNS_STATUS_ERR;
+-	}
+-
+-	if (!zone->names) {
+-		zone->names = ldns_rbtree_create(ldns_dname_compare_v);
+-                if(!zone->names) return LDNS_STATUS_MEM_ERR;
+-	}
+-
+-	/* we need the original of the hashed name if this is
+-	   an NSEC3, or an RRSIG that covers an NSEC3 */
+-	if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_RRSIG) {
+-		type_covered = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
+-	}
+-	if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_NSEC3 ||
+-	    type_covered == LDNS_RR_TYPE_NSEC3) {
+-		cur_node = ldns_dnssec_zone_find_nsec3_original(zone, rr);
+-		if (!cur_node) {
+-			return LDNS_STATUS_DNSSEC_NSEC3_ORIGINAL_NOT_FOUND;
+-		}
+-	} else {
+-		cur_node = ldns_rbtree_search(zone->names, ldns_rr_owner(rr));
+-	}
+-	if (!cur_node) {
+-		/* add */
+-		cur_name = ldns_dnssec_name_new_frm_rr(rr);
+-                if(!cur_name) return LDNS_STATUS_MEM_ERR;
+-		cur_node = LDNS_MALLOC(ldns_rbnode_t);
+-                if(!cur_node) {
+-                        ldns_dnssec_name_free(cur_name);
+-                        return LDNS_STATUS_MEM_ERR;
+-                }
+-		cur_node->key = ldns_rr_owner(rr);
+-		cur_node->data = cur_name;
+-		(void)ldns_rbtree_insert(zone->names, cur_node);
+-		ldns_dnssec_name_make_hashed_name(zone, cur_name, NULL);
+-	} else {
+-		cur_name = (ldns_dnssec_name *) cur_node->data;
+-		result = ldns_dnssec_name_add_rr(cur_name, rr);
+-	}
+-	if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_SOA) {
+-		zone->soa = cur_name;
+-	}
+-	return result;
+-}
+-
+-void
+-ldns_dnssec_zone_names_print_fmt(FILE *out, const ldns_output_format *fmt,
+-		ldns_rbtree_t *tree, 
+-		bool print_soa)
+-{
+-	ldns_rbnode_t *node;
+-	ldns_dnssec_name *name;
+-
+-	node = ldns_rbtree_first(tree);
+-	while (node != LDNS_RBTREE_NULL) {
+-		name = (ldns_dnssec_name *) node->data;
+-		ldns_dnssec_name_print_soa_fmt(out, fmt, name, print_soa);
+-		if ((fmt->flags & LDNS_COMMENT_LAYOUT))
+-			fprintf(out, ";\n");
+-		node = ldns_rbtree_next(node);
+-	}
+-}
+-
+-void
+-ldns_dnssec_zone_names_print(FILE *out, ldns_rbtree_t *tree, bool print_soa)
+-{
+-	ldns_dnssec_zone_names_print_fmt(out, ldns_output_format_default,
+-		       tree, print_soa);
+-}
+-
+-void
+-ldns_dnssec_zone_print_fmt(FILE *out, const ldns_output_format *fmt,
+-	       ldns_dnssec_zone *zone)
+-{
+-	if (zone) {
+-		if (zone->soa) {
+-			if ((fmt->flags & LDNS_COMMENT_LAYOUT)) {
+-				fprintf(out, ";; Zone: ");
+-				ldns_rdf_print(out, ldns_dnssec_name_name(
+-							zone->soa));
+-				fprintf(out, "\n;\n");
+-			}
+-			ldns_dnssec_rrsets_print_fmt(out, fmt,
+-					ldns_dnssec_name_find_rrset(
+-						zone->soa, 
+-						LDNS_RR_TYPE_SOA), 
+-					false);
+-			if ((fmt->flags & LDNS_COMMENT_LAYOUT))
+-				fprintf(out, ";\n");
+-		}
+-
+-		if (zone->names) {
+-			ldns_dnssec_zone_names_print_fmt(out, fmt, 
+-					zone->names, false);
+-		}
+-	}
+-}
+-
+-void
+-ldns_dnssec_zone_print(FILE *out, ldns_dnssec_zone *zone)
+-{
+-	ldns_dnssec_zone_print_fmt(out, ldns_output_format_default, zone);
+-}
+-
+-static ldns_status
+-ldns_dnssec_zone_add_empty_nonterminals_nsec3(
+-		ldns_dnssec_zone *zone, ldns_rbtree_t *nsec3s)
+-{
+-	ldns_dnssec_name *new_name;
+-	ldns_rdf *cur_name;
+-	ldns_rdf *next_name;
+-	ldns_rbnode_t *cur_node, *next_node, *new_node;
+-
+-	/* for the detection */
+-	uint16_t i, cur_label_count, next_label_count;
+-	uint16_t soa_label_count = 0;
+-	ldns_rdf *l1, *l2;
+-	int lpos;
+-
+-	if (!zone) {
+-		return LDNS_STATUS_ERR;
+-	}
+-	if (zone->soa && zone->soa->name) {
+-		soa_label_count = ldns_dname_label_count(zone->soa->name);
+-	}
+-	
+-	cur_node = ldns_rbtree_first(zone->names);
+-	while (cur_node != LDNS_RBTREE_NULL) {
+-		next_node = ldns_rbtree_next(cur_node);
+-		
+-		/* skip glue */
+-		while (next_node != LDNS_RBTREE_NULL && 
+-		       next_node->data &&
+-		       ((ldns_dnssec_name *)next_node->data)->is_glue
+-		) {
+-			next_node = ldns_rbtree_next(next_node);
+-		}
+-
+-		if (next_node == LDNS_RBTREE_NULL) {
+-			next_node = ldns_rbtree_first(zone->names);
+-		}
+-		if (! cur_node->data || ! next_node->data) {
+-			return LDNS_STATUS_ERR;
+-		}
+-		cur_name = ((ldns_dnssec_name *)cur_node->data)->name;
+-		next_name = ((ldns_dnssec_name *)next_node->data)->name;
+-		cur_label_count = ldns_dname_label_count(cur_name);
+-		next_label_count = ldns_dname_label_count(next_name);
+-
+-		/* Since the names are in canonical order, we can
+-		 * recognize empty non-terminals by their labels;
+-		 * every label after the first one on the next owner
+-		 * name is a non-terminal if it either does not exist
+-		 * in the current name or is different from the same
+-		 * label in the current name (counting from the end)
+-		 */
+-		for (i = 1; i < next_label_count - soa_label_count; i++) {
+-			lpos = (int)cur_label_count - (int)next_label_count + (int)i;
+-			if (lpos >= 0) {
+-				l1 = ldns_dname_clone_from(cur_name, (uint8_t)lpos);
+-			} else {
+-				l1 = NULL;
+-			}
+-			l2 = ldns_dname_clone_from(next_name, i);
+-
+-			if (!l1 || ldns_dname_compare(l1, l2) != 0) {
+-				/* We have an empty nonterminal, add it to the
+-				 * tree
+-				 */
+-				ldns_rbnode_t *node = NULL;
+-				ldns_rdf *ent_name;
+-
+-				if (!(ent_name = ldns_dname_clone_from(
+-						next_name, i)))
+-					return LDNS_STATUS_MEM_ERR;
+-
+-				if (nsec3s && zone->_nsec3params) {
+-					ldns_rdf *ent_hashed_name;
+-
+-					if (!(ent_hashed_name =
+-					    ldns_nsec3_hash_name_frm_nsec3(
+-							zone->_nsec3params,
+-							ent_name)))
+-						return LDNS_STATUS_MEM_ERR;
+-					node = ldns_rbtree_search(nsec3s, 
+-							ent_hashed_name);
+-					if (!node) {
+-						ldns_rdf_deep_free(l1);
+-						ldns_rdf_deep_free(l2);
+-						continue;
+-					}
+-				}
+-				new_name = ldns_dnssec_name_new();
+-				if (!new_name) {
+-					return LDNS_STATUS_MEM_ERR;
+-				}
+-				new_name->name = ent_name;
+-				if (!new_name->name) {
+-					ldns_dnssec_name_free(new_name);
+-					return LDNS_STATUS_MEM_ERR;
+-				}
+-				new_name->name_alloced = true;
+-				new_node = LDNS_MALLOC(ldns_rbnode_t);
+-				if (!new_node) {
+-					ldns_dnssec_name_free(new_name);
+-					return LDNS_STATUS_MEM_ERR;
+-				}
+-				new_node->key = new_name->name;
+-				new_node->data = new_name;
+-				(void)ldns_rbtree_insert(zone->names, new_node);
+-				ldns_dnssec_name_make_hashed_name(
+-						zone, new_name, NULL);
+-				if (node)
+-					(void) ldns_dnssec_zone_add_rr(zone,
+-							(ldns_rr *)node->data);
+-			}
+-			ldns_rdf_deep_free(l1);
+-			ldns_rdf_deep_free(l2);
+-		}
+-		
+-		/* we might have inserted a new node after
+-		 * the current one so we can't just use next()
+-		 */
+-		if (next_node != ldns_rbtree_first(zone->names)) {
+-			cur_node = next_node;
+-		} else {
+-			cur_node = LDNS_RBTREE_NULL;
+-		}
+-	}
+-	return LDNS_STATUS_OK;
+-}
+-
+-ldns_status
+-ldns_dnssec_zone_add_empty_nonterminals(ldns_dnssec_zone *zone)
+-{
+-	return ldns_dnssec_zone_add_empty_nonterminals_nsec3(zone, NULL);
+-}
+-
+-bool
+-ldns_dnssec_zone_is_nsec3_optout(ldns_dnssec_zone* zone)
+-{
+-	ldns_rr* nsec3;
+-	ldns_rbnode_t* node;
+-
+-	if (ldns_dnssec_name_find_rrset(zone->soa, LDNS_RR_TYPE_NSEC3PARAM)) {
+-		node = ldns_rbtree_first(zone->names);
+-		while (node != LDNS_RBTREE_NULL) {
+-			nsec3 = ((ldns_dnssec_name*)node->data)->nsec;
+-			if (nsec3 &&ldns_rr_get_type(nsec3) 
+-					== LDNS_RR_TYPE_NSEC3 &&
+-					ldns_nsec3_optout(nsec3)) {
+-				return true;
+-			}
+-			node = ldns_rbtree_next(node);
+-		}
+-	}
+-	return false;
+-}
+diff --git a/src/ldns/duration.c b/src/ldns/duration.c
+deleted file mode 100644
+index 6d0a388..0000000
+--- a/src/ldns/duration.c
++++ /dev/null
+@@ -1,354 +0,0 @@
+-/*
+- * $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/config.h>
+-#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 (int) (d1->years - d2->years);
+-    }
+-    if (d1->months != d2->months) {
+-        return (int) (d1->months - d2->months);
+-    }
+-    if (d1->weeks != d2->weeks) {
+-        return (int) (d1->weeks - d2->weeks);
+-    }
+-    if (d1->days != d2->days) {
+-        return (int) (d1->days - d2->days);
+-    }
+-    if (d1->hours != d2->hours) {
+-        return (int) (d1->hours - d2->hours);
+-    }
+-    if (d1->minutes != d2->minutes) {
+-        return (int) (d1->minutes - d2->minutes);
+-    }
+-    if (d1->seconds != d2->seconds) {
+-        return (int) (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 = (time_t) 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 = (time_t) atoi(str+1);
+-        str = X;
+-        not_weeks = 1;
+-    }
+-    X = strchr(str, 'D');
+-    if (X) {
+-        duration->days = (time_t) atoi(str+1);
+-        str = X;
+-        not_weeks = 1;
+-    }
+-    if (T) {
+-        str = T;
+-        not_weeks = 1;
+-    }
+-    X = strchr(str, 'H');
+-    if (X && T) {
+-        duration->hours = (time_t) 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 = (time_t) atoi(str+1);
+-        str = X;
+-        not_weeks = 1;
+-    }
+-    X = strchr(str, 'S');
+-    if (X && T) {
+-        duration->seconds = (time_t) 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 = (time_t) 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", (unsigned int) 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", (unsigned int) 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", (unsigned int) 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", (unsigned int) 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", (unsigned int) 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", (unsigned int) 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", (unsigned int) 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;
+-
+-    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;
+-}
+-
+-
+-/**
+- * Clean up duration.
+- *
+- */
+-void
+-ldns_duration_cleanup(ldns_duration_type* duration)
+-{
+-    if (!duration) {
+-        return;
+-    }
+-    free(duration);
+-    return;
+-}
+diff --git a/src/ldns/error.c b/src/ldns/error.c
+deleted file mode 100644
+index 82ea61a..0000000
+--- a/src/ldns/error.c
++++ /dev/null
+@@ -1,160 +0,0 @@
+-/*
+- * a error2str function to make sense of all the
+- * error codes we have laying ardoun
+- *
+- * a Net::DNS like library for C
+- * LibDNS Team @ NLnet Labs
+- * (c) NLnet Labs, 2005-2006
+- * See the file LICENSE for the license
+- */
+-
+-#include <ldns/config.h>
+-
+-#include <ldns/ldns.h>
+-
+-ldns_lookup_table ldns_error_str[] = {
+-	{ LDNS_STATUS_OK, "All OK" },
+-	{ LDNS_STATUS_EMPTY_LABEL, "Empty label" },
+-        { LDNS_STATUS_LABEL_OVERFLOW, "Label length overflow" },
+-        { LDNS_STATUS_DOMAINNAME_OVERFLOW, "Domainname length overflow" },
+-        { LDNS_STATUS_DOMAINNAME_UNDERFLOW, "Domainname length underflow (zero length)" },
+-        { LDNS_STATUS_DDD_OVERFLOW, "\\DDD sequence overflow (>255)" },
+-        { LDNS_STATUS_PACKET_OVERFLOW, "Packet size overflow" },
+-        { LDNS_STATUS_INVALID_POINTER, "Invalid compression pointer" },
+-        { LDNS_STATUS_MEM_ERR, "General memory error" },
+-        { LDNS_STATUS_INTERNAL_ERR, "Internal error, this should not happen" },
+-        { LDNS_STATUS_SSL_ERR, "Error in SSL library" },
+-        { LDNS_STATUS_ERR, "General LDNS error" },
+-        { LDNS_STATUS_INVALID_INT, "Conversion error, integer expected" },
+-        { LDNS_STATUS_INVALID_IP4, "Conversion error, ip4 addr expected" },
+-        { LDNS_STATUS_INVALID_IP6, "Conversion error, ip6 addr expected" },
+-        { LDNS_STATUS_INVALID_STR, "Conversion error, string expected" },
+-	{ LDNS_STATUS_INVALID_B32_EXT, "Conversion error, b32 ext encoding expected" },
+-        { LDNS_STATUS_INVALID_B64, "Conversion error, b64 encoding expected" },
+-        { LDNS_STATUS_INVALID_HEX, "Conversion error, hex encoding expected" },
+-        { LDNS_STATUS_INVALID_TIME, "Conversion error, time encoding expected" },
+-        { LDNS_STATUS_NETWORK_ERR, "Could not send or receive, because of network error" },
+-        { LDNS_STATUS_ADDRESS_ERR, "Could not start AXFR, because of address error" },
+-        { LDNS_STATUS_FILE_ERR, "Could not open the files" },
+-        { LDNS_STATUS_UNKNOWN_INET, "Uknown address family" },
+-        { LDNS_STATUS_NOT_IMPL, "This function is not implemented (yet), please notify the developers - or not..." },
+-	{ LDNS_STATUS_NULL, "Supplied value pointer null" },
+-        { LDNS_STATUS_CRYPTO_UNKNOWN_ALGO, "Unknown cryptographic algorithm" },
+-        { LDNS_STATUS_CRYPTO_ALGO_NOT_IMPL, "Cryptographic algorithm not implemented" },
+-        { LDNS_STATUS_CRYPTO_NO_RRSIG, "No DNSSEC signature(s)" },
+-        { LDNS_STATUS_CRYPTO_NO_DNSKEY, "No DNSSEC public key(s)" },
+-        { LDNS_STATUS_CRYPTO_TYPE_COVERED_ERR, "The signature does not cover this RRset" },
+-        { LDNS_STATUS_CRYPTO_NO_TRUSTED_DNSKEY, "No signatures found for trusted DNSSEC public key(s)" },
+-        { LDNS_STATUS_CRYPTO_NO_DS, "No DS record(s)" },
+-        { LDNS_STATUS_CRYPTO_NO_TRUSTED_DS, "Could not validate DS record(s)" },
+-        { LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY, "No keys with the keytag and algorithm from the RRSIG found" },
+-        { LDNS_STATUS_CRYPTO_VALIDATED, "Valid DNSSEC signature" },
+-        { LDNS_STATUS_CRYPTO_BOGUS, "Bogus DNSSEC signature" },
+-        { LDNS_STATUS_CRYPTO_SIG_EXPIRED, "DNSSEC signature has expired" },
+-        { LDNS_STATUS_CRYPTO_SIG_NOT_INCEPTED, "DNSSEC signature not incepted yet" },
+-	{ LDNS_STATUS_CRYPTO_TSIG_BOGUS, "Bogus TSIG signature" },
+-	{ LDNS_STATUS_CRYPTO_TSIG_ERR, "Could not create TSIG signature" },
+-        { LDNS_STATUS_CRYPTO_EXPIRATION_BEFORE_INCEPTION, "DNSSEC signature has expiration date earlier than inception date" },
+-	{ LDNS_STATUS_ENGINE_KEY_NOT_LOADED, "Unable to load private key from engine" },
+-        { LDNS_STATUS_NSEC3_ERR, "Error in NSEC3 denial of existence proof" },
+-	{ LDNS_STATUS_RES_NO_NS, "No (valid) nameservers defined in the resolver" },
+-	{ LDNS_STATUS_RES_QUERY, "No correct query given to resolver" },
+-	{ LDNS_STATUS_WIRE_INCOMPLETE_HEADER, "header section incomplete" },
+-	{ LDNS_STATUS_WIRE_INCOMPLETE_QUESTION, "question section incomplete" },
+-	{ LDNS_STATUS_WIRE_INCOMPLETE_ANSWER, "answer section incomplete" },
+-	{ LDNS_STATUS_WIRE_INCOMPLETE_AUTHORITY, "authority section incomplete" },
+-	{ LDNS_STATUS_WIRE_INCOMPLETE_ADDITIONAL, "additional section incomplete" },
+-	{ LDNS_STATUS_NO_DATA, "No data" },
+-	{ LDNS_STATUS_EXISTS_ERR, "Element already exists" },
+-	{ LDNS_STATUS_CERT_BAD_ALGORITHM, "Bad algorithm type for CERT record" },
+-	{ LDNS_STATUS_SYNTAX_TYPE_ERR, "Syntax error, could not parse the RR's type" },
+-	{ LDNS_STATUS_SYNTAX_CLASS_ERR, "Syntax error, could not parse the RR's class" },
+-	{ LDNS_STATUS_SYNTAX_TTL_ERR, "Syntax error, could not parse the RR's TTL" },
+-	{ LDNS_STATUS_SYNTAX_INCLUDE_ERR_NOTIMPL, "Syntax error, $INCLUDE not implemented" },
+-	{ LDNS_STATUS_SYNTAX_RDATA_ERR, "Syntax error, could not parse the RR's rdata" },
+-	{ LDNS_STATUS_SYNTAX_DNAME_ERR, "Syntax error, could not parse the RR's dname(s)" },
+-	{ LDNS_STATUS_SYNTAX_VERSION_ERR, "Syntax error, version mismatch" },
+-	{ LDNS_STATUS_SYNTAX_ALG_ERR, "Syntax error, algorithm unknown or non parseable" },
+-	{ LDNS_STATUS_SYNTAX_KEYWORD_ERR, "Syntax error, unknown keyword in input" },
+-	{ LDNS_STATUS_SYNTAX_ERR, "Syntax error, could not parse the RR" },
+-	{ LDNS_STATUS_SYNTAX_EMPTY, "Empty line was returned" },
+-	{ LDNS_STATUS_SYNTAX_TTL, "$TTL directive was seen in the zone" },
+-	{ LDNS_STATUS_SYNTAX_ORIGIN, "$ORIGIN directive was seen in the zone" },
+-	{ LDNS_STATUS_SYNTAX_INCLUDE, "$INCLUDE directive was seen in the zone" },
+-	{ LDNS_STATUS_SYNTAX_ITERATIONS_OVERFLOW, "Iterations count for NSEC3 record higher than maximum" },
+-	{ LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR, "Syntax error, value expected" },
+-	{ LDNS_STATUS_SYNTAX_INTEGER_OVERFLOW, "Syntax error, integer value too large" },
+-	{ LDNS_STATUS_SYNTAX_BAD_ESCAPE, "Syntax error, bad escape sequence" },
+-	{ LDNS_STATUS_SOCKET_ERROR, "Error creating socket" },
+-	{ LDNS_STATUS_DNSSEC_EXISTENCE_DENIED, "Existence denied by NSEC" },
+-	{ LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED, "RR not covered by the given NSEC RRs" },
+-	{ LDNS_STATUS_DNSSEC_NSEC_WILDCARD_NOT_COVERED, "wildcard not covered by the given NSEC RRs" },
+-	{ LDNS_STATUS_DNSSEC_NSEC3_ORIGINAL_NOT_FOUND, "original of NSEC3 hashed name could not be found" },
+-	{ LDNS_STATUS_MISSING_RDATA_FIELDS_RRSIG, "The RRSIG has to few rdata fields" },
+-	{ LDNS_STATUS_MISSING_RDATA_FIELDS_KEY, "The DNSKEY has to few rdata fields" },
+-	{ LDNS_STATUS_CRYPTO_SIG_EXPIRED_WITHIN_MARGIN, 
+-		"DNSSEC signature will expire too soon" },
+-	{ LDNS_STATUS_CRYPTO_SIG_NOT_INCEPTED_WITHIN_MARGIN,
+-		"DNSSEC signature not incepted long enough" },
+-	{ LDNS_STATUS_DANE_UNKNOWN_CERTIFICATE_USAGE,
+-		"Unknown TLSA Certificate Usage" },
+-	{ LDNS_STATUS_DANE_UNKNOWN_SELECTOR, "Unknown TLSA Selector" },
+-	{ LDNS_STATUS_DANE_UNKNOWN_MATCHING_TYPE,
+-		"Unknown TLSA Matching Type" },
+-	{ LDNS_STATUS_DANE_UNKNOWN_PROTOCOL,
+-		"Unknown protocol. Only IPv4 and IPv6 are understood" },
+-	{ LDNS_STATUS_DANE_UNKNOWN_TRANSPORT,
+-		"Unknown transport. Should be one of {tcp, udp, sctp}" },
+-	{ LDNS_STATUS_DANE_MISSING_EXTRA_CERTS,  /* Trust anchor assertion */
+-		"More than one certificate should be provided" },
+-	{ LDNS_STATUS_DANE_EXTRA_CERTS_NOT_USED, /* Trust anchor assertion */
+-		"Non of the extra certificates is used to sign the first" },
+-	{ LDNS_STATUS_DANE_OFFSET_OUT_OF_RANGE,   /* Trust anchor assertion */
+-		"The offset was out of range" },
+-	{ LDNS_STATUS_DANE_INSECURE,             /* Unused by library */
+-		"The queried resource records were insecure" },
+-	{ LDNS_STATUS_DANE_BOGUS,             /* Unused by library */
+-		"The queried resource records were bogus" },
+-	{ LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH,
+-		"The TLSA record(s) "
+-		"did not match with the server certificate (chain)" },
+-	{ LDNS_STATUS_DANE_NON_CA_CERTIFICATE,
+-		"The certificate was not a CA certificate" },
+-	{ LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE,
+-		"Could not PKIX validate" },
+-	{ LDNS_STATUS_DANE_PKIX_NO_SELF_SIGNED_TRUST_ANCHOR,
+-		"The validation path "
+-		"did not end in a self-signed certificate" },
+-        { LDNS_STATUS_INVALID_ILNP64, 
+-		"Conversion error, 4 colon separated hex numbers expected" },
+-        { LDNS_STATUS_INVALID_EUI48, 
+-		"Conversion error, 6 two character hex numbers "
+-		"separated by dashes expected (i.e. xx-xx-xx-xx-xx-xx" },
+-        { LDNS_STATUS_INVALID_EUI64, 
+-		"Conversion error, 8 two character hex numbers "
+-		"separated by dashes expected (i.e. xx-xx-xx-xx-xx-xx-xx-xx" },
+-	{ LDNS_STATUS_WIRE_RDATA_ERR, "invalid rdata in wire format" },
+-        { LDNS_STATUS_INVALID_TAG, 
+-		"Conversion error, a non-zero sequence of US-ASCII letters "
+-		"and numbers in lower case expected" },
+-        { LDNS_STATUS_TYPE_NOT_IN_BITMAP, 
+-		"The RR type bitmap rdata field did not have "
+-		"a bit reserved for the specific RR type" },
+-        { LDNS_STATUS_INVALID_RDF_TYPE, 
+-		"The rdata field was not of the expected type" },
+-        { LDNS_STATUS_RDATA_OVERFLOW, "Rdata size overflow" },
+-	{ 0, NULL }
+-};
+-
+-const char *
+-ldns_get_errorstr_by_id(ldns_status err)
+-{
+-        ldns_lookup_table *lt;
+-
+-        lt = ldns_lookup_by_id(ldns_error_str, err);
+-
+-        if (lt) {
+-                return lt->name;
+-        }
+-        return NULL;
+-}
+diff --git a/src/ldns/higher.c b/src/ldns/higher.c
+deleted file mode 100644
+index 8ce86a4..0000000
+--- a/src/ldns/higher.c
++++ /dev/null
+@@ -1,344 +0,0 @@
+-/*
+- * higher.c
+- *
+- * Specify some higher level functions that would
+- * be usefull to would be developers
+- *
+- * a Net::DNS like library for C
+- *
+- * (c) NLnet Labs, 2004-2006
+- *
+- * See the file LICENSE for the license
+- */
+-
+-#include <ldns/config.h>
+-
+-#include <ldns/ldns.h>
+-
+-#ifdef HAVE_SSL
+-#include <openssl/ssl.h>
+-#include <openssl/sha.h>
+-#endif /* HAVE_SSL */
+-
+-ldns_rr_list *
+-ldns_get_rr_list_addr_by_name(ldns_resolver *res, ldns_rdf *name, ldns_rr_class c, 
+-		uint16_t flags)
+-{
+-	ldns_pkt *pkt;
+-	ldns_rr_list *aaaa;
+-	ldns_rr_list *a;
+-	ldns_rr_list *result = NULL;
+-	ldns_rr_list *hostsfilenames;
+-	size_t i;
+-	uint8_t ip6;
+-
+-	a = NULL; 
+-	aaaa = NULL; 
+-	result = NULL;
+-
+-	if (!res) {
+-		return NULL;
+-	}
+-	if (ldns_rdf_get_type(name) != LDNS_RDF_TYPE_DNAME) {
+-		return NULL;
+-	}
+-
+-	ip6 = ldns_resolver_ip6(res); /* we use INET_ANY here, save
+-					 what was there */
+-
+-	ldns_resolver_set_ip6(res, LDNS_RESOLV_INETANY);
+-	
+-	hostsfilenames = ldns_get_rr_list_hosts_frm_file(NULL);
+-	for (i = 0; i < ldns_rr_list_rr_count(hostsfilenames); i++) {
+-		if (ldns_rdf_compare(name, 
+-					ldns_rr_owner(ldns_rr_list_rr(hostsfilenames, 
+-							i))) == 0) {
+-			if (!result) {
+-				result = ldns_rr_list_new();
+-			}
+-			ldns_rr_list_push_rr(result, 
+-					ldns_rr_clone(ldns_rr_list_rr(hostsfilenames, i)));
+-		}
+-	}
+-	ldns_rr_list_deep_free(hostsfilenames);
+-
+-	if (result) {
+-		return result;
+-	}
+-
+-	/* add the RD flags, because we want an answer */
+-	pkt = ldns_resolver_query(res, name, LDNS_RR_TYPE_AAAA, c, flags | LDNS_RD);
+-	if (pkt) {
+-		/* extract the data we need */
+-		aaaa = ldns_pkt_rr_list_by_type(pkt, LDNS_RR_TYPE_AAAA, 
+-			LDNS_SECTION_ANSWER);
+-		ldns_pkt_free(pkt);
+-	} 
+-
+-	pkt = ldns_resolver_query(res, name, LDNS_RR_TYPE_A, c, flags | LDNS_RD);
+-	if (pkt) {
+-		/* extract the data we need */
+-		a = ldns_pkt_rr_list_by_type(pkt, LDNS_RR_TYPE_A, LDNS_SECTION_ANSWER);
+-		ldns_pkt_free(pkt);
+-	} 
+-	ldns_resolver_set_ip6(res, ip6);
+-
+-	if (aaaa && a) {
+-		result = ldns_rr_list_cat_clone(aaaa, a);
+-		ldns_rr_list_deep_free(aaaa);
+-		ldns_rr_list_deep_free(a);
+-		return result;
+-	}
+-	
+-	if (aaaa) {
+-		result = ldns_rr_list_clone(aaaa);
+-	}
+-	
+-	if (a) {
+-		result = ldns_rr_list_clone(a);
+-	}
+-
+-	ldns_rr_list_deep_free(aaaa);
+-	ldns_rr_list_deep_free(a);
+-	return result;
+-}
+-
+-ldns_rr_list *
+-ldns_get_rr_list_name_by_addr(ldns_resolver *res, ldns_rdf *addr, ldns_rr_class c, 
+-		uint16_t flags)
+-{
+-	ldns_pkt *pkt;
+-	ldns_rr_list *names;
+-	ldns_rdf *name;
+-
+-	names = NULL;
+-
+-	if (!res || !addr) {
+-		return NULL;
+-	}
+-
+-	if (ldns_rdf_get_type(addr) != LDNS_RDF_TYPE_A &&
+-			ldns_rdf_get_type(addr) != LDNS_RDF_TYPE_AAAA) {
+-		return NULL;
+-	}
+-
+-	name = ldns_rdf_address_reverse(addr);
+-	
+-	/* add the RD flags, because we want an answer */
+-	pkt = ldns_resolver_query(res, name, LDNS_RR_TYPE_PTR, c, flags | LDNS_RD);
+-	ldns_rdf_deep_free(name);
+-	if (pkt) {
+-		/* extract the data we need */
+-		names = ldns_pkt_rr_list_by_type(pkt, 
+-				LDNS_RR_TYPE_PTR, LDNS_SECTION_ANSWER);
+-		ldns_pkt_free(pkt);
+-	}
+-	return names;
+-}
+-
+-/* read a line, put it in a buffer, parse the buffer */
+-ldns_rr_list *
+-ldns_get_rr_list_hosts_frm_fp(FILE *fp)
+-{
+-	return ldns_get_rr_list_hosts_frm_fp_l(fp, NULL);
+-}
+-
+-ldns_rr_list *
+-ldns_get_rr_list_hosts_frm_fp_l(FILE *fp, int *line_nr)
+-{
+-	ssize_t i, j;
+-	size_t cnt;
+-	char *line;
+-	char *word;
+-	char *addr;
+-	char *rr_str;
+-	ldns_buffer *linebuf;
+-	ldns_rr *rr;
+-	ldns_rr_list *list;
+-	ldns_rdf *tmp;
+-	bool ip6;
+-	ldns_status parse_result;
+-
+-	line = LDNS_XMALLOC(char, LDNS_MAX_LINELEN + 1);
+-	word = LDNS_XMALLOC(char, LDNS_MAX_LINELEN + 1);
+-	addr = LDNS_XMALLOC(char, LDNS_MAX_LINELEN + 1);
+-	rr_str = LDNS_XMALLOC(char, LDNS_MAX_LINELEN + 1);
+-	ip6 = false;
+-	list = ldns_rr_list_new();
+-	rr = NULL;
+-	if(!line || !word || !addr || !rr_str || !list) {
+-		LDNS_FREE(line);
+-		LDNS_FREE(word);
+-		LDNS_FREE(addr);
+-		LDNS_FREE(rr_str);
+-		ldns_rr_list_free(list);
+-		return NULL;
+-	}
+-
+-	for(i = ldns_fget_token_l(fp, line, "\n", LDNS_MAX_LINELEN, line_nr);
+-			i > 0; i = ldns_fget_token_l(fp, line, "\n", LDNS_MAX_LINELEN, line_nr)) {
+-		/* # is comment */
+-		if (line[0] == '#') {
+-			continue;
+-		}
+-		/* put it in a buffer for further processing */
+-		linebuf = LDNS_MALLOC(ldns_buffer);
+-		if(!linebuf) {
+-			LDNS_FREE(line);
+-			LDNS_FREE(word);
+-			LDNS_FREE(addr);
+-			LDNS_FREE(rr_str);
+-			ldns_rr_list_deep_free(list);
+-			return NULL;
+-		}
+-
+-		ldns_buffer_new_frm_data(linebuf, line, (size_t) i);
+-		for(cnt = 0, j = ldns_bget_token(linebuf, word, LDNS_PARSE_NO_NL, LDNS_MAX_LINELEN);
+-				j > 0;
+-				j = ldns_bget_token(linebuf, word, LDNS_PARSE_NO_NL, LDNS_MAX_LINELEN), cnt++) {
+-			if (cnt == 0) {
+-				/* the address */
+-				if ((tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_AAAA, 
+-								word))) {
+-					/* ip6 */
+-					ldns_rdf_deep_free(tmp);
+-					ip6 = true;
+-				} else {
+-					if ((tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_A, 
+-									word))) {
+-						/* ip4 */
+-						ldns_rdf_deep_free(tmp);
+-						ip6 = false;
+-					} else {
+-						/* kaput */
+-						break;
+-					}
+-				}
+-				(void)strlcpy(addr, word, LDNS_MAX_LINELEN+1);
+-			} else {
+-				/* la al la la */
+-				if (ip6) {
+-					snprintf(rr_str, LDNS_MAX_LINELEN, 
+-						"%s IN AAAA %s", word, addr);
+-				} else {
+-					snprintf(rr_str, LDNS_MAX_LINELEN, 
+-						"%s IN A %s", word, addr);
+-				}
+-				parse_result = ldns_rr_new_frm_str(&rr, rr_str, 0, NULL, NULL);
+-				if (parse_result == LDNS_STATUS_OK && ldns_rr_owner(rr) && ldns_rr_rd_count(rr) > 0) {
+-					ldns_rr_list_push_rr(list, ldns_rr_clone(rr));
+-				}
+-				ldns_rr_free(rr);
+-			}
+-		}
+-		ldns_buffer_free(linebuf);
+-	}
+-	LDNS_FREE(line);
+-	LDNS_FREE(word);
+-	LDNS_FREE(addr);
+-	LDNS_FREE(rr_str);
+-	return list;
+-}
+-
+-ldns_rr_list *
+-ldns_get_rr_list_hosts_frm_file(char *filename)
+-{
+-	ldns_rr_list *names;
+-	FILE *fp;
+-
+-	if (!filename) {
+-                fp = fopen(LDNS_RESOLV_HOSTS, "r");
+-        
+-        } else {
+-                fp = fopen(filename, "r");
+-        }
+-        if (!fp) {
+-                return NULL;
+-        }
+-
+-	names = ldns_get_rr_list_hosts_frm_fp(fp);
+-	fclose(fp);
+-	return names;
+-}
+-
+-uint16_t
+-ldns_getaddrinfo(ldns_resolver *res, ldns_rdf *node, ldns_rr_class c, 
+-		ldns_rr_list **ret)
+-{
+-	ldns_rdf_type t;
+-	uint16_t names_found;
+-	ldns_resolver *r;
+-	ldns_status s;
+-
+-	t = ldns_rdf_get_type(node);
+-	names_found = 0;
+-	r = res;
+-
+-	if (res == NULL) {
+-		/* prepare a new resolver, using /etc/resolv.conf as a guide  */
+-		s = ldns_resolver_new_frm_file(&r, NULL);
+-		if (s != LDNS_STATUS_OK) {
+-			return 0;
+-		} 
+-	}
+-
+-	if (t == LDNS_RDF_TYPE_DNAME) {
+-		/* we're asked to query for a name */
+-		*ret = ldns_get_rr_list_addr_by_name(r, node, c, 0);
+-		names_found = ldns_rr_list_rr_count(*ret);
+-	}
+-
+-	if (t == LDNS_RDF_TYPE_A || t == LDNS_RDF_TYPE_AAAA) {
+-		/* an address */
+-		*ret = ldns_get_rr_list_name_by_addr(r, node, c, 0);
+-		names_found = ldns_rr_list_rr_count(*ret);
+-	}
+-
+-	if (res == NULL) {
+-		ldns_resolver_deep_free(r);
+-	}
+-	
+-	return names_found;
+-}
+-
+-bool
+-ldns_nsec_type_check(ldns_rr *nsec, ldns_rr_type t)
+-{
+-	switch (ldns_rr_get_type(nsec)) {
+-	case LDNS_RR_TYPE_NSEC	: if (ldns_rr_rd_count(nsec) < 2) {
+-					  return false;
+-				  }
+-				  return ldns_nsec_bitmap_covers_type(
+-						  ldns_rr_rdf(nsec, 1), t);
+-
+-	case LDNS_RR_TYPE_NSEC3	: if (ldns_rr_rd_count(nsec) < 6) {
+-					  return false;
+-				  }
+-				  return ldns_nsec_bitmap_covers_type(
+-						  ldns_rr_rdf(nsec, 5), t);
+-
+-	default			: return false;
+-	}
+-}
+-
+-void
+-ldns_print_rr_rdf(FILE *fp, ldns_rr *r, int rdfnum, ...)
+-{
+-	int16_t rdf;
+-	ldns_rdf *rd;
+-	va_list va_rdf;
+-	va_start(va_rdf, rdfnum);
+-
+-	for (rdf = (int16_t)rdfnum; rdf != -1; rdf = (int16_t)va_arg(va_rdf, int)) 
+-	{
+-		rd = ldns_rr_rdf(r, rdf);
+-		if (!rd) {
+-			continue;
+-		} else {
+-			ldns_rdf_print(fp, rd);
+-			fprintf(fp, " "); /* not sure if we want to do this */
+-		}
+-	}
+-	va_end(va_rdf);
+-}
+-
+diff --git a/src/ldns/host2str.c b/src/ldns/host2str.c
+deleted file mode 100644
+index 3445254..0000000
+--- a/src/ldns/host2str.c
++++ /dev/null
+@@ -1,2635 +0,0 @@
+-/*
+- * host2str.c
+- *
+- * conversion routines from the host format
+- * to the presentation format (strings)
+- *
+- * a Net::DNS like library for C
+- *
+- * (c) NLnet Labs, 2004-2006
+- *
+- * See the file LICENSE for the license
+- */
+-#include <ldns/config.h>
+-
+-#include <ldns/ldns.h>
+-
+-#include <limits.h>
+-
+-#ifdef HAVE_SYS_SOCKET_H
+-#include <sys/socket.h>
+-#endif
+-#ifdef HAVE_ARPA_INET_H
+-#include <arpa/inet.h>
+-#endif
+-#ifdef HAVE_NETDB_H
+-#include <netdb.h>
+-#endif
+-#include <time.h>
+-#include <sys/time.h>
+-
+-#ifndef INET_ADDRSTRLEN
+-#define INET_ADDRSTRLEN 16
+-#endif
+-#ifndef INET6_ADDRSTRLEN
+-#define INET6_ADDRSTRLEN 46
+-#endif
+-
+-/* lookup tables for standard DNS stuff  */
+-
+-/* Taken from RFC 2535, section 7.  */
+-ldns_lookup_table ldns_algorithms[] = {
+-        { LDNS_RSAMD5, "RSAMD5" },
+-        { LDNS_DH, "DH" },
+-        { LDNS_DSA, "DSA" },
+-        { LDNS_ECC, "ECC" },
+-        { LDNS_RSASHA1, "RSASHA1" },
+-        { LDNS_DSA_NSEC3, "DSA-NSEC3-SHA1" },
+-        { LDNS_RSASHA1_NSEC3, "RSASHA1-NSEC3-SHA1" },
+-#ifdef USE_SHA2
+-	{ LDNS_RSASHA256, "RSASHA256"},
+-	{ LDNS_RSASHA512, "RSASHA512"},
+-#endif
+-#ifdef USE_GOST
+-	{ LDNS_ECC_GOST, "ECC-GOST"},
+-#endif
+-#ifdef USE_ECDSA
+-        { LDNS_ECDSAP256SHA256, "ECDSAP256SHA256"},
+-        { LDNS_ECDSAP384SHA384, "ECDSAP384SHA384"},
+-#endif
+-        { LDNS_INDIRECT, "INDIRECT" },
+-        { LDNS_PRIVATEDNS, "PRIVATEDNS" },
+-        { LDNS_PRIVATEOID, "PRIVATEOID" },
+-        { 0, NULL }
+-};
+-
+-/* Taken from RFC 4398  */
+-ldns_lookup_table ldns_cert_algorithms[] = {
+-        { LDNS_CERT_PKIX, "PKIX" },
+-        { LDNS_CERT_SPKI, "SPKI" },
+-        { LDNS_CERT_PGP, "PGP" },
+-        { LDNS_CERT_IPKIX, "IPKIX" },
+-        { LDNS_CERT_ISPKI, "ISPKI" },
+-        { LDNS_CERT_IPGP, "IPGP" },
+-        { LDNS_CERT_ACPKIX, "ACPKIX" },
+-        { LDNS_CERT_IACPKIX, "IACPKIX" },
+-        { LDNS_CERT_URI, "URI" },
+-        { LDNS_CERT_OID, "OID" },
+-        { 0, NULL }
+-};
+-
+-/* classes  */
+-ldns_lookup_table ldns_rr_classes[] = {
+-        { LDNS_RR_CLASS_IN, "IN" },
+-        { LDNS_RR_CLASS_CH, "CH" },
+-        { LDNS_RR_CLASS_HS, "HS" },
+-        { LDNS_RR_CLASS_NONE, "NONE" },
+-        { LDNS_RR_CLASS_ANY, "ANY" },
+-        { 0, NULL }
+-};
+-
+-/* if these are used elsewhere */
+-ldns_lookup_table ldns_rcodes[] = {
+-        { LDNS_RCODE_NOERROR, "NOERROR" },
+-        { LDNS_RCODE_FORMERR, "FORMERR" },
+-        { LDNS_RCODE_SERVFAIL, "SERVFAIL" },
+-        { LDNS_RCODE_NXDOMAIN, "NXDOMAIN" },
+-        { LDNS_RCODE_NOTIMPL, "NOTIMPL" },
+-        { LDNS_RCODE_REFUSED, "REFUSED" },
+-        { LDNS_RCODE_YXDOMAIN, "YXDOMAIN" },
+-        { LDNS_RCODE_YXRRSET, "YXRRSET" },
+-        { LDNS_RCODE_NXRRSET, "NXRRSET" },
+-        { LDNS_RCODE_NOTAUTH, "NOTAUTH" },
+-        { LDNS_RCODE_NOTZONE, "NOTZONE" },
+-        { 0, NULL }
+-};
+-
+-ldns_lookup_table ldns_opcodes[] = {
+-        { LDNS_PACKET_QUERY, "QUERY" },
+-        { LDNS_PACKET_IQUERY, "IQUERY" },
+-        { LDNS_PACKET_STATUS, "STATUS" },
+-	{ LDNS_PACKET_NOTIFY, "NOTIFY" },
+-	{ LDNS_PACKET_UPDATE, "UPDATE" },
+-        { 0, NULL }
+-};
+-
+-const ldns_output_format   ldns_output_format_nocomments_record = { 0, NULL };
+-const ldns_output_format  *ldns_output_format_nocomments 
+-			= &ldns_output_format_nocomments_record;
+-const ldns_output_format   ldns_output_format_onlykeyids_record = {
+-	LDNS_COMMENT_KEY, NULL
+-};
+-const ldns_output_format  *ldns_output_format_onlykeyids
+-			= &ldns_output_format_onlykeyids_record;
+-const ldns_output_format  *ldns_output_format_default
+-			= &ldns_output_format_onlykeyids_record;
+-
+-const ldns_output_format   ldns_output_format_bubblebabble_record = { 
+-	LDNS_COMMENT_KEY | LDNS_COMMENT_BUBBLEBABBLE | LDNS_COMMENT_FLAGS, NULL
+-};
+-const ldns_output_format  *ldns_output_format_bubblebabble 
+-			= &ldns_output_format_bubblebabble_record;
+-
+-static bool
+-ldns_output_format_covers_type(const ldns_output_format* fmt, ldns_rr_type t)
+-{
+-	return fmt && (fmt->flags & LDNS_FMT_RFC3597) &&
+-		((ldns_output_format_storage*)fmt)->bitmap &&
+-		ldns_nsec_bitmap_covers_type(
+-				((ldns_output_format_storage*)fmt)->bitmap, t);
+-}
+-
+-ldns_status
+-ldns_output_format_set_type(ldns_output_format* fmt, ldns_rr_type t)
+-{
+-	ldns_output_format_storage* fmt_st = (ldns_output_format_storage*)fmt;
+-	ldns_status s;
+-	
+-	assert(fmt != NULL);
+-	
+-	if (!(fmt_st->flags & LDNS_FMT_RFC3597)) {
+-		ldns_output_format_set(fmt, LDNS_FMT_RFC3597);
+-	}
+-	if (! fmt_st->bitmap) {
+-		s = ldns_rdf_bitmap_known_rr_types_space(&fmt_st->bitmap);
+-		if (s != LDNS_STATUS_OK) {
+-			return s;
+-		}
+-	}
+-	return ldns_nsec_bitmap_set_type(fmt_st->bitmap, t);
+-}
+-
+-ldns_status
+-ldns_output_format_clear_type(ldns_output_format* fmt, ldns_rr_type t)
+-{
+-	ldns_output_format_storage* fmt_st = (ldns_output_format_storage*)fmt;
+-	ldns_status s;
+-	
+-	assert(fmt != NULL);
+-
+-	if (!(fmt_st->flags & LDNS_FMT_RFC3597)) {
+-		ldns_output_format_set(fmt, LDNS_FMT_RFC3597);
+-	}
+-	if (! fmt_st->bitmap) {
+-		s = ldns_rdf_bitmap_known_rr_types(&fmt_st->bitmap);
+-		if (s != LDNS_STATUS_OK) {
+-			return s;
+-		}
+-	}
+-	return ldns_nsec_bitmap_clear_type(fmt_st->bitmap, t);
+-}
+-
+-ldns_status
+-ldns_pkt_opcode2buffer_str(ldns_buffer *output, ldns_pkt_opcode opcode)
+-{
+-	ldns_lookup_table *lt = ldns_lookup_by_id(ldns_opcodes, opcode);
+-	if (lt && lt->name) {
+-		ldns_buffer_printf(output, "%s", lt->name);
+-	} else {
+-		ldns_buffer_printf(output, "OPCODE%u", opcode);
+-	}
+-	return ldns_buffer_status(output);
+-}
+-
+-ldns_status
+-ldns_pkt_rcode2buffer_str(ldns_buffer *output, ldns_pkt_rcode rcode)
+-{
+-	ldns_lookup_table *lt = ldns_lookup_by_id(ldns_rcodes, rcode);
+-	if (lt && lt->name) {
+-		ldns_buffer_printf(output, "%s", lt->name);
+-	} else {
+-		ldns_buffer_printf(output, "RCODE%u", rcode);
+-	}
+-	return ldns_buffer_status(output);
+-}
+-
+-ldns_status
+-ldns_algorithm2buffer_str(ldns_buffer *output,
+-                          ldns_algorithm algorithm)
+-{
+-	ldns_lookup_table *lt = ldns_lookup_by_id(ldns_algorithms,
+-	                                          algorithm);
+-	if (lt && lt->name) {
+-		ldns_buffer_printf(output, "%s", lt->name);
+-	} else {
+-		ldns_buffer_printf(output, "ALG%u", algorithm);
+-	}
+-	return ldns_buffer_status(output);
+-}
+-
+-ldns_status
+-ldns_cert_algorithm2buffer_str(ldns_buffer *output,
+-                               ldns_cert_algorithm cert_algorithm)
+-{
+-	ldns_lookup_table *lt = ldns_lookup_by_id(ldns_cert_algorithms,
+-	                                          cert_algorithm);
+-	if (lt && lt->name) {
+-		ldns_buffer_printf(output, "%s", lt->name);
+-	} else {
+-		ldns_buffer_printf(output, "CERT_ALG%u",
+-		                   cert_algorithm);
+-	}
+-	return ldns_buffer_status(output);
+-}
+-
+-char *
+-ldns_pkt_opcode2str(ldns_pkt_opcode opcode)
+-{
+-	char *str;
+-	ldns_buffer *buf;
+-
+-	buf = ldns_buffer_new(12);
+-	if (!buf) {
+-		return NULL;
+-	}
+-
+-	str = NULL;
+-	if (ldns_pkt_opcode2buffer_str(buf, opcode) == LDNS_STATUS_OK) {
+-		str = ldns_buffer_export2str(buf);
+-	}
+-
+-	ldns_buffer_free(buf);
+-	return str;
+-}
+-
+-char *
+-ldns_pkt_rcode2str(ldns_pkt_rcode rcode)
+-{
+-	char *str;
+-	ldns_buffer *buf;
+-
+-	buf = ldns_buffer_new(10);
+-	if (!buf) {
+-		return NULL;
+-	}
+-
+-	str = NULL;
+-	if (ldns_pkt_rcode2buffer_str(buf, rcode) == LDNS_STATUS_OK) {
+-		str = ldns_buffer_export2str(buf);
+-	}
+-
+-	ldns_buffer_free(buf);
+-	return str;
+-}
+-
+-char *
+-ldns_pkt_algorithm2str(ldns_algorithm algorithm)
+-{
+-	char *str;
+-	ldns_buffer *buf;
+-
+-	buf = ldns_buffer_new(10);
+-	if (!buf) {
+-		return NULL;
+-	}
+-
+-	str = NULL;
+-	if (ldns_algorithm2buffer_str(buf, algorithm)
+-	    == LDNS_STATUS_OK) {
+-		str = ldns_buffer_export2str(buf);
+-	}
+-
+-	ldns_buffer_free(buf);
+-	return str;
+-}
+-
+-char *
+-ldns_pkt_cert_algorithm2str(ldns_cert_algorithm cert_algorithm)
+-{
+-	char *str;
+-	ldns_buffer *buf;
+-
+-	buf = ldns_buffer_new(10);
+-	if (!buf) {
+-		return NULL;
+-	}
+-
+-	str = NULL;
+-	if (ldns_cert_algorithm2buffer_str(buf, cert_algorithm)
+-	    == LDNS_STATUS_OK) {
+-		str = ldns_buffer_export2str(buf);
+-	}
+-
+-	ldns_buffer_free(buf);
+-	return str;
+-}
+-
+-
+-/* do NOT pass compressed data here :p */
+-ldns_status
+-ldns_rdf2buffer_str_dname(ldns_buffer *output, const ldns_rdf *dname)
+-{
+-	/* can we do with 1 pos var? or without at all? */
+-	uint8_t src_pos = 0;
+-	uint8_t len;
+-	uint8_t *data;
+-	uint8_t i;
+-	unsigned char c;
+-
+-	data = (uint8_t*)ldns_rdf_data(dname);
+-	len = data[src_pos];
+-
+-	if (ldns_rdf_size(dname) > LDNS_MAX_DOMAINLEN) {
+-		/* too large, return */
+-		return LDNS_STATUS_DOMAINNAME_OVERFLOW;
+-	}
+-
+-	/* special case: root label */
+-	if (1 == ldns_rdf_size(dname)) {
+-		ldns_buffer_printf(output, ".");
+-	} else {
+-		while ((len > 0) && src_pos < ldns_rdf_size(dname)) {
+-			src_pos++;
+-			for(i = 0; i < len; i++) {
+-				/* paranoia check for various 'strange'
+-				   characters in dnames
+-				*/
+-				c = (unsigned char) data[src_pos];
+-				if(c == '.' || c == ';' ||
+-				   c == '(' || c == ')' ||
+-				   c == '\\') {
+-					ldns_buffer_printf(output, "\\%c",
+-							data[src_pos]);
+-				} else if (!(isascii(c) && isgraph(c))) {
+-					ldns_buffer_printf(output, "\\%03u",
+-						        data[src_pos]);
+-				} else {
+-					ldns_buffer_printf(output, "%c", data[src_pos]);
+-				}
+-				src_pos++;
+-			}
+-
+-			if (src_pos < ldns_rdf_size(dname)) {
+-				ldns_buffer_printf(output, ".");
+-			}
+-			len = data[src_pos];
+-		}
+-	}
+-	return ldns_buffer_status(output);
+-}
+-
+-ldns_status
+-ldns_rdf2buffer_str_int8(ldns_buffer *output, const ldns_rdf *rdf)
+-{
+-	uint8_t data = ldns_rdf_data(rdf)[0];
+-	ldns_buffer_printf(output, "%lu", (unsigned long) data);
+-	return ldns_buffer_status(output);
+-}
+-
+-ldns_status
+-ldns_rdf2buffer_str_int16(ldns_buffer *output, const ldns_rdf *rdf)
+-{
+-	uint16_t data = ldns_read_uint16(ldns_rdf_data(rdf));
+-	ldns_buffer_printf(output, "%lu", (unsigned long) data);
+-	return ldns_buffer_status(output);
+-}
+-
+-ldns_status
+-ldns_rdf2buffer_str_int32(ldns_buffer *output, const ldns_rdf *rdf)
+-{
+-	uint32_t data = ldns_read_uint32(ldns_rdf_data(rdf));
+-	ldns_buffer_printf(output, "%lu", (unsigned long) data);
+-	return ldns_buffer_status(output);
+-}
+-
+-ldns_status
+-ldns_rdf2buffer_str_time(ldns_buffer *output, const ldns_rdf *rdf)
+-{
+-	/* create a YYYYMMDDHHMMSS string if possible */
+-	struct tm tm;
+-	char date_buf[16];
+-
+-	memset(&tm, 0, sizeof(tm));
+-	if (ldns_serial_arithmitics_gmtime_r(ldns_rdf2native_int32(rdf), time(NULL), &tm)
+-	    && strftime(date_buf, 15, "%Y%m%d%H%M%S", &tm)) {
+-		ldns_buffer_printf(output, "%s", date_buf);
+-	}
+-	return ldns_buffer_status(output);
+-}
+-
+-ldns_status
+-ldns_rdf2buffer_str_a(ldns_buffer *output, const ldns_rdf *rdf)
+-{
+-	char str[INET_ADDRSTRLEN];
+-
+-	if (inet_ntop(AF_INET, ldns_rdf_data(rdf), str, INET_ADDRSTRLEN)) {
+-		ldns_buffer_printf(output, "%s", str);
+-	}
+-	return ldns_buffer_status(output);
+-}
+-
+-ldns_status
+-ldns_rdf2buffer_str_aaaa(ldns_buffer *output, const ldns_rdf *rdf)
+-{
+-	char str[INET6_ADDRSTRLEN];
+-
+-	if (inet_ntop(AF_INET6, ldns_rdf_data(rdf), str, INET6_ADDRSTRLEN)) {
+-		ldns_buffer_printf(output, "%s", str);
+-	}
+-
+-	return ldns_buffer_status(output);
+-}
+-
+-static void 
+-ldns_characters2buffer_str(ldns_buffer* output,
+-		size_t amount, const uint8_t* characters)
+-{
+-	uint8_t ch;
+-	while (amount > 0) {
+-		ch = *characters++;
+-		if (isprint((int)ch) || ch == '\t') {
+-			if (ch == '\"' || ch == '\\')
+-				ldns_buffer_printf(output, "\\%c", ch);
+-			else
+-				ldns_buffer_printf(output, "%c", ch);
+-		} else {
+-			ldns_buffer_printf(output, "\\%03u",
+-                                (unsigned)(uint8_t) ch);
+-		}
+-		amount--;
+-	}
+-}
+-
+-ldns_status
+-ldns_rdf2buffer_str_str(ldns_buffer *output, const ldns_rdf *rdf)
+-{
+-        if(ldns_rdf_size(rdf) < 1) {
+-                return LDNS_STATUS_WIRE_RDATA_ERR;
+-        }
+-        if((int)ldns_rdf_size(rdf) < (int)ldns_rdf_data(rdf)[0] + 1) {
+-                return LDNS_STATUS_WIRE_RDATA_ERR;
+-        }
+-	ldns_buffer_printf(output, "\"");
+-	ldns_characters2buffer_str(output, 
+-			ldns_rdf_data(rdf)[0], ldns_rdf_data(rdf) + 1);
+-	ldns_buffer_printf(output, "\"");
+-	return ldns_buffer_status(output);
+-}
+-
+-ldns_status
+-ldns_rdf2buffer_str_b64(ldns_buffer *output, const ldns_rdf *rdf)
+-{
+-	size_t size = ldns_b64_ntop_calculate_size(ldns_rdf_size(rdf));
+-	char *b64 = LDNS_XMALLOC(char, size);
+-	if(!b64) return LDNS_STATUS_MEM_ERR;
+-	if (ldns_b64_ntop(ldns_rdf_data(rdf), ldns_rdf_size(rdf), b64, size)) {
+-		ldns_buffer_printf(output, "%s", b64);
+-	}
+-	LDNS_FREE(b64);
+-	return ldns_buffer_status(output);
+-}
+-
+-ldns_status
+-ldns_rdf2buffer_str_b32_ext(ldns_buffer *output, const ldns_rdf *rdf)
+-{
+-	size_t size;
+-	char *b32;
+-	if(ldns_rdf_size(rdf) == 0)
+-		return LDNS_STATUS_OK;
+-        /* remove -1 for the b32-hash-len octet */
+-	size = ldns_b32_ntop_calculate_size(ldns_rdf_size(rdf) - 1);
+-        /* add one for the end nul for the string */
+-	b32 = LDNS_XMALLOC(char, size + 1);
+-	if(!b32) return LDNS_STATUS_MEM_ERR;
+-	size = (size_t) ldns_b32_ntop_extended_hex(ldns_rdf_data(rdf) + 1,
+-		ldns_rdf_size(rdf) - 1, b32, size+1);
+-	if (size > 0) {
+-		ldns_buffer_printf(output, "%s", b32);
+-	}
+-	LDNS_FREE(b32);
+-	return ldns_buffer_status(output);
+-}
+-
+-ldns_status
+-ldns_rdf2buffer_str_hex(ldns_buffer *output, const ldns_rdf *rdf)
+-{
+-	size_t i;
+-	for (i = 0; i < ldns_rdf_size(rdf); i++) {
+-		ldns_buffer_printf(output, "%02x", ldns_rdf_data(rdf)[i]);
+-	}
+-
+-	return ldns_buffer_status(output);
+-}
+-
+-static ldns_status
+-ldns_rdf2buffer_str_type_fmt(ldns_buffer *output,
+-		const ldns_output_format* fmt, const ldns_rdf *rdf)
+-{
+-        uint16_t data = ldns_read_uint16(ldns_rdf_data(rdf));
+-
+-	if (! ldns_output_format_covers_type(fmt, data) &&
+-			ldns_rr_descript(data) &&
+-			ldns_rr_descript(data)->_name) {
+-
+-		ldns_buffer_printf(output, "%s",ldns_rr_descript(data)->_name);
+-	} else {
+-		ldns_buffer_printf(output, "TYPE%u", data);
+-	}
+-	return  ldns_buffer_status(output);
+-}
+-
+-ldns_status
+-ldns_rdf2buffer_str_type(ldns_buffer *output, const ldns_rdf *rdf)
+-{
+-	return ldns_rdf2buffer_str_type_fmt(output,
+-			ldns_output_format_default, rdf);
+-}
+-
+-ldns_status
+-ldns_rdf2buffer_str_class(ldns_buffer *output, const ldns_rdf *rdf)
+-{
+-	uint16_t data = ldns_read_uint16(ldns_rdf_data(rdf));
+-	ldns_lookup_table *lt;
+-
+- 	lt = ldns_lookup_by_id(ldns_rr_classes, (int) data);
+-	if (lt) {
+-		ldns_buffer_printf(output, "\t%s", lt->name);
+-	} else {
+-		ldns_buffer_printf(output, "\tCLASS%d", data);
+-	}
+-	return ldns_buffer_status(output);
+-}
+-
+-ldns_status
+-ldns_rdf2buffer_str_cert_alg(ldns_buffer *output, const ldns_rdf *rdf)
+-{
+-        uint16_t data = ldns_read_uint16(ldns_rdf_data(rdf));
+-	ldns_lookup_table *lt;
+- 	lt = ldns_lookup_by_id(ldns_cert_algorithms, (int) data);
+-	if (lt) {
+-		ldns_buffer_printf(output, "%s", lt->name);
+-	} else {
+-		ldns_buffer_printf(output, "%d", data);
+-	}
+-	return ldns_buffer_status(output);
+-}
+-
+-ldns_status
+-ldns_rdf2buffer_str_alg(ldns_buffer *output, const ldns_rdf *rdf)
+-{
+-	return ldns_rdf2buffer_str_int8(output, rdf);
+-}
+-
+-static void
+-loc_cm_print(ldns_buffer *output, uint8_t mantissa, uint8_t exponent)
+-{
+-	uint8_t i;
+-	/* is it 0.<two digits> ? */
+-	if(exponent < 2) {
+-		if(exponent == 1)
+-			mantissa *= 10;
+-		ldns_buffer_printf(output, "0.%02ld", (long)mantissa);
+-		return;
+-	}
+-	/* always <digit><string of zeros> */
+-	ldns_buffer_printf(output, "%d", (int)mantissa);
+-	for(i=0; i<exponent-2; i++)
+-		ldns_buffer_printf(output, "0");
+-}
+-
+-ldns_status
+-ldns_rr_type2buffer_str(ldns_buffer *output, const ldns_rr_type type)
+-{
+-	const ldns_rr_descriptor *descriptor;
+-
+-	descriptor = ldns_rr_descript(type);
+-
+-	switch (type) {
+-		case LDNS_RR_TYPE_IXFR:
+-			ldns_buffer_printf(output, "IXFR");
+-			break;
+-		case LDNS_RR_TYPE_AXFR:
+-			ldns_buffer_printf(output, "AXFR");
+-			break;
+-		case LDNS_RR_TYPE_MAILA:
+-			ldns_buffer_printf(output, "MAILA");
+-			break;
+-		case LDNS_RR_TYPE_MAILB:
+-			ldns_buffer_printf(output, "MAILB");
+-			break;
+-		case LDNS_RR_TYPE_ANY:
+-			ldns_buffer_printf(output, "ANY");
+-			break;
+-		default:
+-			if (descriptor && descriptor->_name) {
+-				ldns_buffer_printf(output, "%s", descriptor->_name);
+-			} else {
+-				ldns_buffer_printf(output, "TYPE%u", type);
+-			}
+-	}
+-	return ldns_buffer_status(output);
+-}
+-
+-char *
+-ldns_rr_type2str(const ldns_rr_type type)
+-{
+-	char *str;
+-	ldns_buffer *buf;
+-
+-	buf = ldns_buffer_new(10);
+-	if (!buf) {
+-		return NULL;
+-	}
+-
+-	str = NULL;
+-	if (ldns_rr_type2buffer_str(buf, type) == LDNS_STATUS_OK) {
+-		str = ldns_buffer_export2str(buf);
+-	}
+-
+-	ldns_buffer_free(buf);
+-	return str;
+-}
+-
+-
+-ldns_status
+-ldns_rr_class2buffer_str(ldns_buffer *output,
+-                         const ldns_rr_class klass)
+-{
+-	ldns_lookup_table *lt;
+-
+-	lt = ldns_lookup_by_id(ldns_rr_classes, klass);
+-	if (lt) {
+-		ldns_buffer_printf(output, "%s", lt->name);
+-	} else {
+-		ldns_buffer_printf(output, "CLASS%d", klass);
+-	}
+-	return ldns_buffer_status(output);
+-}
+-
+-char *
+-ldns_rr_class2str(const ldns_rr_class klass)
+-{
+-	ldns_buffer *buf;
+-	char *str;
+-
+-	buf = ldns_buffer_new(10);
+-	if (!buf) {
+-		return NULL;
+-	}
+-
+-	str = NULL;
+-	if (ldns_rr_class2buffer_str(buf, klass) == LDNS_STATUS_OK) {
+-		str = ldns_buffer_export2str(buf);
+-	}
+-	ldns_buffer_free(buf);
+-	return str;
+-}
+-
+-ldns_status
+-ldns_rdf2buffer_str_loc(ldns_buffer *output, const ldns_rdf *rdf)
+-{
+-	/* we could do checking (ie degrees < 90 etc)? */
+-	uint8_t version;
+-	uint8_t size;
+-	uint8_t horizontal_precision;
+-	uint8_t vertical_precision;
+-	uint32_t longitude;
+-	uint32_t latitude;
+-	uint32_t altitude;
+-	char northerness;
+-	char easterness;
+-	uint32_t h;
+-	uint32_t m;
+-	double s;
+-
+-	uint32_t equator = (uint32_t) ldns_power(2, 31);
+-
+-        if(ldns_rdf_size(rdf) < 1) {
+-                return LDNS_STATUS_WIRE_RDATA_ERR;
+-        }
+-       	version = ldns_rdf_data(rdf)[0];
+-	if (version == 0) {
+-		if(ldns_rdf_size(rdf) < 16) {
+-			return LDNS_STATUS_WIRE_RDATA_ERR;
+-		}
+-		size = ldns_rdf_data(rdf)[1];
+-		horizontal_precision = ldns_rdf_data(rdf)[2];
+-		vertical_precision = ldns_rdf_data(rdf)[3];
+-
+-		latitude = ldns_read_uint32(&ldns_rdf_data(rdf)[4]);
+-		longitude = ldns_read_uint32(&ldns_rdf_data(rdf)[8]);
+-		altitude = ldns_read_uint32(&ldns_rdf_data(rdf)[12]);
+-
+-		if (latitude > equator) {
+-			northerness = 'N';
+-			latitude = latitude - equator;
+-		} else {
+-			northerness = 'S';
+-			latitude = equator - latitude;
+-		}
+-		h = latitude / (1000 * 60 * 60);
+-		latitude = latitude % (1000 * 60 * 60);
+-		m = latitude / (1000 * 60);
+-		latitude = latitude % (1000 * 60);
+-		s = (double) latitude / 1000.0;
+-		ldns_buffer_printf(output, "%02u %02u %0.3f %c ",
+-			h, m, s, northerness);
+-
+-		if (longitude > equator) {
+-			easterness = 'E';
+-			longitude = longitude - equator;
+-		} else {
+-			easterness = 'W';
+-			longitude = equator - longitude;
+-		}
+-		h = longitude / (1000 * 60 * 60);
+-		longitude = longitude % (1000 * 60 * 60);
+-		m = longitude / (1000 * 60);
+-		longitude = longitude % (1000 * 60);
+-		s = (double) longitude / (1000.0);
+-		ldns_buffer_printf(output, "%02u %02u %0.3f %c ",
+-			h, m, s, easterness);
+-
+-
+-		s = ((double) altitude) / 100;
+-		s -= 100000;
+-
+-		if(altitude%100 != 0)
+-			ldns_buffer_printf(output, "%.2f", s);
+-		else
+-			ldns_buffer_printf(output, "%.0f", s);
+-
+-		ldns_buffer_printf(output, "m ");
+-
+-		loc_cm_print(output, (size & 0xf0) >> 4, size & 0x0f);
+-		ldns_buffer_printf(output, "m ");
+-
+-		loc_cm_print(output, (horizontal_precision & 0xf0) >> 4,
+-			horizontal_precision & 0x0f);
+-		ldns_buffer_printf(output, "m ");
+-
+-		loc_cm_print(output, (vertical_precision & 0xf0) >> 4,
+-			vertical_precision & 0x0f);
+-		ldns_buffer_printf(output, "m");
+-
+-		return ldns_buffer_status(output);
+-	} else {
+-		return ldns_rdf2buffer_str_hex(output, rdf);
+-	}
+-}
+-
+-ldns_status
+-ldns_rdf2buffer_str_unknown(ldns_buffer *output, const ldns_rdf *rdf)
+-{
+-	ldns_buffer_printf(output, "\\# %u ", ldns_rdf_size(rdf));
+-	return ldns_rdf2buffer_str_hex(output, rdf);
+-}
+-
+-ldns_status
+-ldns_rdf2buffer_str_nsap(ldns_buffer *output, const ldns_rdf *rdf)
+-{
+-	ldns_buffer_printf(output, "0x");
+-	return ldns_rdf2buffer_str_hex(output, rdf);
+-}
+-
+-ldns_status
+-ldns_rdf2buffer_str_atma(ldns_buffer *output, const ldns_rdf *rdf)
+-{
+-	return ldns_rdf2buffer_str_hex(output, rdf);
+-}
+-
+-ldns_status
+-ldns_rdf2buffer_str_wks(ldns_buffer *output, const ldns_rdf *rdf)
+-{
+-	/* protocol, followed by bitmap of services */
+-	struct protoent *protocol;
+-	char *proto_name = NULL;
+-	uint8_t protocol_nr;
+-	struct servent *service;
+-	uint16_t current_service;
+-
+-        if(ldns_rdf_size(rdf) < 1) {
+-                return LDNS_STATUS_WIRE_RDATA_ERR;
+-        }
+-	protocol_nr = ldns_rdf_data(rdf)[0];
+-	protocol = getprotobynumber((int) protocol_nr);
+-	if (protocol && (protocol->p_name != NULL)) {
+-		proto_name = protocol->p_name;
+-		ldns_buffer_printf(output, "%s ", protocol->p_name);
+-	} else {
+-		ldns_buffer_printf(output, "%u ", protocol_nr);
+-	}
+-
+-#ifdef HAVE_ENDPROTOENT
+-	endprotoent();
+-#endif
+-
+-	for (current_service = 0;
+-	     current_service < (ldns_rdf_size(rdf)-1)*8; current_service++) {
+-		if (ldns_get_bit(&(ldns_rdf_data(rdf)[1]), current_service)) {
+-			service = getservbyport((int) htons(current_service),
+-			                        proto_name);
+-			if (service && service->s_name) {
+-				ldns_buffer_printf(output, "%s ", service->s_name);
+-			} else {
+-				ldns_buffer_printf(output, "%u ", current_service);
+-			}
+-#ifdef HAVE_ENDSERVENT
+-			endservent();
+-#endif
+-		}
+-	}
+-	return ldns_buffer_status(output);
+-}
+-
+-static ldns_status
+-ldns_rdf2buffer_str_nsec_fmt(ldns_buffer *output,
+-		const ldns_output_format* fmt, const ldns_rdf *rdf)
+-{
+-	/* Note: this code is duplicated in higher.c in
+-	 * ldns_nsec_type_check() function
+-	 */
+-	uint8_t window_block_nr;
+-	uint8_t bitmap_length;
+-	uint16_t type;
+-	uint16_t pos = 0;
+-	uint16_t bit_pos;
+-	uint8_t *data = ldns_rdf_data(rdf);
+-
+-	while((size_t)(pos + 2) < ldns_rdf_size(rdf)) {
+-		window_block_nr = data[pos];
+-		bitmap_length = data[pos + 1];
+-		pos += 2;
+-		if (ldns_rdf_size(rdf) < pos + bitmap_length) {
+-			return LDNS_STATUS_WIRE_RDATA_ERR;
+-		}
+-		for (bit_pos = 0; bit_pos < (bitmap_length) * 8; bit_pos++) {
+-			if (! ldns_get_bit(&data[pos], bit_pos)) {
+-				continue;
+-			}
+-			type = 256 * (uint16_t) window_block_nr + bit_pos;
+-
+-			if (! ldns_output_format_covers_type(fmt, type) &&
+-					ldns_rr_descript(type) &&
+-					ldns_rr_descript(type)->_name){
+-
+-				ldns_buffer_printf(output, "%s ",
+-						ldns_rr_descript(type)->_name);
+-			} else {
+-				ldns_buffer_printf(output, "TYPE%u ", type);
+-			}
+-		}
+-		pos += (uint16_t) bitmap_length;
+-	}
+-	return ldns_buffer_status(output);
+-}
+-
+-ldns_status
+-ldns_rdf2buffer_str_nsec(ldns_buffer *output, const ldns_rdf *rdf)
+-{
+-	return ldns_rdf2buffer_str_nsec_fmt(output,
+-			ldns_output_format_default, rdf);
+-}
+-
+-ldns_status
+-ldns_rdf2buffer_str_nsec3_salt(ldns_buffer *output, const ldns_rdf *rdf)
+-{
+-	uint8_t salt_length;
+-	uint8_t salt_pos;
+-
+-	uint8_t *data = ldns_rdf_data(rdf);
+-
+-        if(ldns_rdf_size(rdf) < 1) {
+-                return LDNS_STATUS_WIRE_RDATA_ERR;
+-        }
+-	salt_length = data[0];
+-	/* from now there are variable length entries so remember pos */
+-	if (salt_length == 0 || ((size_t)salt_length)+1 > ldns_rdf_size(rdf)) {
+-		ldns_buffer_printf(output, "- ");
+-	} else {
+-		for (salt_pos = 0; salt_pos < salt_length; salt_pos++) {
+-			ldns_buffer_printf(output, "%02x", data[1 + salt_pos]);
+-		}
+-		ldns_buffer_printf(output, " ");
+-	}
+-
+-	return ldns_buffer_status(output);
+-}
+-
+-ldns_status
+-ldns_rdf2buffer_str_period(ldns_buffer *output, const ldns_rdf *rdf)
+-{
+-	/* period is the number of seconds */
+-	if (ldns_rdf_size(rdf) != 4) {
+-		return LDNS_STATUS_WIRE_RDATA_ERR;
+-	}
+-	ldns_buffer_printf(output, "%u", ldns_read_uint32(ldns_rdf_data(rdf)));
+-	return ldns_buffer_status(output);
+-}
+-
+-ldns_status
+-ldns_rdf2buffer_str_tsigtime(ldns_buffer *output,const  ldns_rdf *rdf)
+-{
+-	/* tsigtime is 48 bits network order unsigned integer */
+-	uint64_t tsigtime = 0;
+-	uint8_t *data = ldns_rdf_data(rdf);
+-	uint64_t d0, d1, d2, d3, d4, d5;
+-
+-	if (ldns_rdf_size(rdf) < 6) {
+-		return LDNS_STATUS_WIRE_RDATA_ERR;
+-	}
+-	d0 = data[0]; /* cast to uint64 for shift operations */
+-	d1 = data[1];
+-	d2 = data[2];
+-	d3 = data[3];
+-	d4 = data[4];
+-	d5 = data[5];
+-	tsigtime = (d0<<40) | (d1<<32) | (d2<<24) | (d3<<16) | (d4<<8) | d5;
+-
+-	ldns_buffer_printf(output, "%llu ", (long long)tsigtime);
+-
+-	return ldns_buffer_status(output);
+-}
+-
+-ldns_status
+-ldns_rdf2buffer_str_apl(ldns_buffer *output, const ldns_rdf *rdf)
+-{
+-	uint8_t *data = ldns_rdf_data(rdf);
+-	uint16_t address_family;
+-	uint8_t prefix;
+-	bool negation;
+-	uint8_t adf_length;
+-	size_t i;
+-	size_t pos = 0;
+-
+-	while (pos < (unsigned int) ldns_rdf_size(rdf)) {
+-                if(pos + 3 >= (unsigned)ldns_rdf_size(rdf))
+-                        return LDNS_STATUS_WIRE_RDATA_ERR;
+-		address_family = ldns_read_uint16(&data[pos]);
+-		prefix = data[pos + 2];
+-		negation = data[pos + 3] & LDNS_APL_NEGATION;
+-		adf_length = data[pos + 3] & LDNS_APL_MASK;
+-		if (address_family == LDNS_APL_IP4) {
+-			/* check if prefix < 32? */
+-			if (negation) {
+-				ldns_buffer_printf(output, "!");
+-			}
+-			ldns_buffer_printf(output, "%u:", address_family);
+-			/* address is variable length 0 - 4 */
+-			for (i = 0; i < 4; i++) {
+-				if (i > 0) {
+-					ldns_buffer_printf(output, ".");
+-				}
+-				if (i < (unsigned short) adf_length) {
+-                                        if(pos+i+4 >= ldns_rdf_size(rdf))
+-					    return LDNS_STATUS_WIRE_RDATA_ERR;
+-					ldns_buffer_printf(output, "%d",
+-					                   data[pos + i + 4]);
+-				} else {
+-					ldns_buffer_printf(output, "0");
+-				}
+-			}
+-			ldns_buffer_printf(output, "/%u ", prefix);
+-		} else if (address_family == LDNS_APL_IP6) {
+-			/* check if prefix < 128? */
+-			if (negation) {
+-				ldns_buffer_printf(output, "!");
+-			}
+-			ldns_buffer_printf(output, "%u:", address_family);
+-			/* address is variable length 0 - 16 */
+-			for (i = 0; i < 16; i++) {
+-				if (i % 2 == 0 && i > 0) {
+-					ldns_buffer_printf(output, ":");
+-				}
+-				if (i < (unsigned short) adf_length) {
+-                                        if(pos+i+4 >= ldns_rdf_size(rdf))
+-					    return LDNS_STATUS_WIRE_RDATA_ERR;
+-					ldns_buffer_printf(output, "%02x",
+-					                   data[pos + i + 4]);
+-				} else {
+-					ldns_buffer_printf(output, "00");
+-				}
+-			}
+-			ldns_buffer_printf(output, "/%u ", prefix);
+-
+-		} else {
+-			/* unknown address family */
+-			ldns_buffer_printf(output,
+-					"Unknown address family: %u data: ",
+-					address_family);
+-			for (i = 1; i < (unsigned short) (4 + adf_length); i++) {
+-                                if(pos+i >= ldns_rdf_size(rdf))
+-                                        return LDNS_STATUS_WIRE_RDATA_ERR;
+-				ldns_buffer_printf(output, "%02x", data[i]);
+-			}
+-		}
+-		pos += 4 + adf_length;
+-	}
+-	return ldns_buffer_status(output);
+-}
+-
+-ldns_status
+-ldns_rdf2buffer_str_int16_data(ldns_buffer *output, const ldns_rdf *rdf)
+-{
+-	size_t size;
+-	char *b64;
+-	if (ldns_rdf_size(rdf) < 2) {
+-		return LDNS_STATUS_WIRE_RDATA_ERR;
+-	}
+-	/* Subtract the size (2) of the number that specifies the length */
+-	size = ldns_b64_ntop_calculate_size(ldns_rdf_size(rdf) - 2);
+-	ldns_buffer_printf(output, "%u ", ldns_rdf_size(rdf) - 2);
+-	if (ldns_rdf_size(rdf) > 2) {
+-		b64 = LDNS_XMALLOC(char, size);
+-		if(!b64)
+-			return LDNS_STATUS_MEM_ERR;
+-
+-		if (ldns_rdf_size(rdf) > 2 &&
+-		ldns_b64_ntop(ldns_rdf_data(rdf) + 2,
+-					ldns_rdf_size(rdf) - 2,
+-					b64, size)) {
+-			ldns_buffer_printf(output, "%s", b64);
+-		}
+-		LDNS_FREE(b64);
+-	}
+-	return ldns_buffer_status(output);
+-}
+-
+-ldns_status
+-ldns_rdf2buffer_str_ipseckey(ldns_buffer *output, const ldns_rdf *rdf)
+-{
+-	/* wire format from
+-	   http://www.ietf.org/internet-drafts/draft-ietf-ipseckey-rr-12.txt
+-	*/
+-	uint8_t *data = ldns_rdf_data(rdf);
+-	uint8_t precedence;
+-	uint8_t gateway_type;
+-	uint8_t algorithm;
+-
+-	ldns_rdf *gateway = NULL;
+-	uint8_t *gateway_data;
+-
+-	size_t public_key_size;
+-	uint8_t *public_key_data;
+-	ldns_rdf *public_key;
+-
+-	size_t offset = 0;
+-	ldns_status status;
+-
+-	if (ldns_rdf_size(rdf) < 3) {
+-		return LDNS_STATUS_WIRE_RDATA_ERR;
+-	}
+-	precedence = data[0];
+-	gateway_type = data[1];
+-	algorithm = data[2];
+-	offset = 3;
+-
+-	switch (gateway_type) {
+-		case 0:
+-			/* no gateway */
+-			break;
+-		case 1:
+-			gateway_data = LDNS_XMALLOC(uint8_t, LDNS_IP4ADDRLEN);
+-                        if(!gateway_data)
+-                                return LDNS_STATUS_MEM_ERR;
+-			if (ldns_rdf_size(rdf) < offset + LDNS_IP4ADDRLEN) {
+-				return LDNS_STATUS_ERR;
+-			}
+-			memcpy(gateway_data, &data[offset], LDNS_IP4ADDRLEN);
+-			gateway = ldns_rdf_new(LDNS_RDF_TYPE_A,
+-					LDNS_IP4ADDRLEN , gateway_data);
+-			offset += LDNS_IP4ADDRLEN;
+-                        if(!gateway) {
+-                                LDNS_FREE(gateway_data);
+-                                return LDNS_STATUS_MEM_ERR;
+-                        }
+-			break;
+-		case 2:
+-			gateway_data = LDNS_XMALLOC(uint8_t, LDNS_IP6ADDRLEN);
+-                        if(!gateway_data)
+-                                return LDNS_STATUS_MEM_ERR;
+-			if (ldns_rdf_size(rdf) < offset + LDNS_IP6ADDRLEN) {
+-				return LDNS_STATUS_ERR;
+-			}
+-			memcpy(gateway_data, &data[offset], LDNS_IP6ADDRLEN);
+-			offset += LDNS_IP6ADDRLEN;
+-			gateway =
+-				ldns_rdf_new(LDNS_RDF_TYPE_AAAA,
+-						LDNS_IP6ADDRLEN, gateway_data);
+-                        if(!gateway) {
+-                                LDNS_FREE(gateway_data);
+-                                return LDNS_STATUS_MEM_ERR;
+-                        }
+-			break;
+-		case 3:
+-			status = ldns_wire2dname(&gateway, data,
+-					ldns_rdf_size(rdf), &offset);
+-                        if(status != LDNS_STATUS_OK)
+-                                return status;
+-			break;
+-		default:
+-			/* error? */
+-			break;
+-	}
+-
+-	if (ldns_rdf_size(rdf) <= offset) {
+-		return LDNS_STATUS_ERR;
+-	}
+-	public_key_size = ldns_rdf_size(rdf) - offset;
+-	public_key_data = LDNS_XMALLOC(uint8_t, public_key_size);
+-        if(!public_key_data) {
+-                ldns_rdf_free(gateway);
+-                return LDNS_STATUS_MEM_ERR;
+-        }
+-	memcpy(public_key_data, &data[offset], public_key_size);
+-	public_key = ldns_rdf_new(LDNS_RDF_TYPE_B64,
+-			public_key_size, public_key_data);
+-        if(!public_key) {
+-                LDNS_FREE(public_key_data);
+-                ldns_rdf_free(gateway);
+-                return LDNS_STATUS_MEM_ERR;
+-        }
+-
+-	ldns_buffer_printf(output, "%u %u %u ", precedence, gateway_type, algorithm);
+-	if (gateway)
+-	  	(void) ldns_rdf2buffer_str(output, gateway);
+-	else
+-		ldns_buffer_printf(output, ".");
+-	ldns_buffer_printf(output, " ");
+-	(void) ldns_rdf2buffer_str(output, public_key);
+-
+-	ldns_rdf_free(gateway);
+-	ldns_rdf_free(public_key);
+-
+-	return ldns_buffer_status(output);
+-}
+-
+-ldns_status
+-ldns_rdf2buffer_str_ilnp64(ldns_buffer *output, const ldns_rdf *rdf)
+-{
+-	if (ldns_rdf_size(rdf) != 8) {
+-		return LDNS_STATUS_WIRE_RDATA_ERR;
+-	}
+-	ldns_buffer_printf(output,"%.4x:%.4x:%.4x:%.4x",
+-				ldns_read_uint16(ldns_rdf_data(rdf)),
+-				ldns_read_uint16(ldns_rdf_data(rdf)+2),
+-				ldns_read_uint16(ldns_rdf_data(rdf)+4),
+-				ldns_read_uint16(ldns_rdf_data(rdf)+6));
+-	return ldns_buffer_status(output);
+-}
+-
+-ldns_status
+-ldns_rdf2buffer_str_eui48(ldns_buffer *output, const ldns_rdf *rdf)
+-{
+-	if (ldns_rdf_size(rdf) != 6) {
+-		return LDNS_STATUS_WIRE_RDATA_ERR;
+-	}
+-	ldns_buffer_printf(output,"%.2x-%.2x-%.2x-%.2x-%.2x-%.2x",
+-				ldns_rdf_data(rdf)[0], ldns_rdf_data(rdf)[1],
+-				ldns_rdf_data(rdf)[2], ldns_rdf_data(rdf)[3],
+-				ldns_rdf_data(rdf)[4], ldns_rdf_data(rdf)[5]);
+-	return ldns_buffer_status(output);
+-}
+-
+-ldns_status
+-ldns_rdf2buffer_str_eui64(ldns_buffer *output, const ldns_rdf *rdf)
+-{
+-	if (ldns_rdf_size(rdf) != 8) {
+-		return LDNS_STATUS_WIRE_RDATA_ERR;
+-	}
+-	ldns_buffer_printf(output,"%.2x-%.2x-%.2x-%.2x-%.2x-%.2x-%.2x-%.2x",
+-				ldns_rdf_data(rdf)[0], ldns_rdf_data(rdf)[1],
+-				ldns_rdf_data(rdf)[2], ldns_rdf_data(rdf)[3],
+-				ldns_rdf_data(rdf)[4], ldns_rdf_data(rdf)[5],
+-				ldns_rdf_data(rdf)[6], ldns_rdf_data(rdf)[7]);
+-	return ldns_buffer_status(output);
+-}
+-
+-ldns_status
+-ldns_rdf2buffer_str_tag(ldns_buffer *output, const ldns_rdf *rdf)
+-{
+-	size_t nchars;
+-	const uint8_t* chars;
+-	char ch;
+-	if (ldns_rdf_size(rdf) < 2) {
+-		return LDNS_STATUS_WIRE_RDATA_ERR;
+-	}
+-	nchars = ldns_rdf_data(rdf)[0];
+-	if (nchars >= ldns_rdf_size(rdf) || /* should be rdf_size - 1 */
+-			nchars < 1) {
+-		return LDNS_STATUS_WIRE_RDATA_ERR;
+-	}
+-	chars = ldns_rdf_data(rdf) + 1;
+-	while (nchars > 0) {
+-		ch = (char)*chars++;
+-		if (! isalnum(ch)) {
+-			return LDNS_STATUS_WIRE_RDATA_ERR;
+-		}
+-		ldns_buffer_printf(output, "%c", ch);
+-		nchars--;
+-	}
+-	return ldns_buffer_status(output);
+-}
+-
+-ldns_status
+-ldns_rdf2buffer_str_long_str(ldns_buffer *output, const ldns_rdf *rdf)
+-{
+-
+-	ldns_buffer_printf(output, "\"");
+-	ldns_characters2buffer_str(output,
+-			ldns_rdf_size(rdf), ldns_rdf_data(rdf));
+-	ldns_buffer_printf(output, "\"");
+-	return ldns_buffer_status(output);
+-}
+-
+-ldns_status
+-ldns_rdf2buffer_str_hip(ldns_buffer *output, const ldns_rdf *rdf)
+-{
+-	uint8_t *data = ldns_rdf_data(rdf);
+-	size_t rdf_size = ldns_rdf_size(rdf);
+-	uint8_t hit_size;
+-	uint16_t pk_size;
+-	int written;
+-	
+-	if (rdf_size < 6) {
+-		return LDNS_STATUS_WIRE_RDATA_ERR;
+-	}
+-	if ((hit_size = data[0]) == 0 ||
+-			(pk_size = ldns_read_uint16(data + 2)) == 0 ||
+-			rdf_size < (size_t) hit_size + pk_size + 4) {
+-
+-		return LDNS_STATUS_WIRE_RDATA_ERR;
+-	}
+-
+-	ldns_buffer_printf(output, "%d ", (int) data[1]);
+-
+-	for (data += 4; hit_size > 0; hit_size--, data++) {
+-
+-		ldns_buffer_printf(output, "%02x", (int) *data);
+-	}
+-	ldns_buffer_write_u8(output, (uint8_t) ' ');
+-
+-	if (ldns_buffer_reserve(output,
+-				ldns_b64_ntop_calculate_size(pk_size))) {
+-
+-		written = ldns_b64_ntop(data, pk_size,
+-				(char *) ldns_buffer_current(output),
+-				ldns_buffer_remaining(output));
+-
+-		if (written > 0 &&
+-				written < (int) ldns_buffer_remaining(output)) {
+-
+-			output->_position += written;
+-		}
+-	}
+-	return ldns_buffer_status(output);
+-}
+-
+-static ldns_status
+-ldns_rdf2buffer_str_fmt(ldns_buffer *buffer,
+-		const ldns_output_format* fmt, const ldns_rdf *rdf)
+-{
+-	ldns_status res = LDNS_STATUS_OK;
+-
+-	/*ldns_buffer_printf(buffer, "%u:", ldns_rdf_get_type(rdf));*/
+-	if (rdf) {
+-		switch(ldns_rdf_get_type(rdf)) {
+-		case LDNS_RDF_TYPE_NONE:
+-			break;
+-		case LDNS_RDF_TYPE_DNAME:
+-			res = ldns_rdf2buffer_str_dname(buffer, rdf);
+-			break;
+-		case LDNS_RDF_TYPE_INT8: /* Don't output mnemonics for these */
+-		case LDNS_RDF_TYPE_ALG:
+-		case LDNS_RDF_TYPE_CERTIFICATE_USAGE:
+-		case LDNS_RDF_TYPE_SELECTOR:
+-		case LDNS_RDF_TYPE_MATCHING_TYPE:
+-			res = ldns_rdf2buffer_str_int8(buffer, rdf);
+-			break;
+-		case LDNS_RDF_TYPE_INT16:
+-			res = ldns_rdf2buffer_str_int16(buffer, rdf);
+-			break;
+-		case LDNS_RDF_TYPE_INT32:
+-			res = ldns_rdf2buffer_str_int32(buffer, rdf);
+-			break;
+-		case LDNS_RDF_TYPE_PERIOD:
+-			res = ldns_rdf2buffer_str_period(buffer, rdf);
+-			break;
+-		case LDNS_RDF_TYPE_TSIGTIME:
+-			res = ldns_rdf2buffer_str_tsigtime(buffer, rdf);
+-			break;
+-		case LDNS_RDF_TYPE_A:
+-			res = ldns_rdf2buffer_str_a(buffer, rdf);
+-			break;
+-		case LDNS_RDF_TYPE_AAAA:
+-			res = ldns_rdf2buffer_str_aaaa(buffer, rdf);
+-			break;
+-		case LDNS_RDF_TYPE_STR:
+-			res = ldns_rdf2buffer_str_str(buffer, rdf);
+-			break;
+-		case LDNS_RDF_TYPE_APL:
+-			res = ldns_rdf2buffer_str_apl(buffer, rdf);
+-			break;
+-		case LDNS_RDF_TYPE_B32_EXT:
+-			res = ldns_rdf2buffer_str_b32_ext(buffer, rdf);
+-			break;
+-		case LDNS_RDF_TYPE_B64:
+-			res = ldns_rdf2buffer_str_b64(buffer, rdf);
+-			break;
+-		case LDNS_RDF_TYPE_HEX:
+-			res = ldns_rdf2buffer_str_hex(buffer, rdf);
+-			break;
+-		case LDNS_RDF_TYPE_NSEC:
+-			res = ldns_rdf2buffer_str_nsec_fmt(buffer, fmt, rdf);
+-			break;
+-		case LDNS_RDF_TYPE_NSEC3_SALT:
+-			res = ldns_rdf2buffer_str_nsec3_salt(buffer, rdf);
+-			break;
+-		case LDNS_RDF_TYPE_TYPE:
+-			res = ldns_rdf2buffer_str_type_fmt(buffer, fmt, rdf);
+-			break;
+-		case LDNS_RDF_TYPE_CLASS:
+-			res = ldns_rdf2buffer_str_class(buffer, rdf);
+-			break;
+-		case LDNS_RDF_TYPE_CERT_ALG:
+-			res = ldns_rdf2buffer_str_cert_alg(buffer, rdf);
+-			break;
+-		case LDNS_RDF_TYPE_UNKNOWN:
+-			res = ldns_rdf2buffer_str_unknown(buffer, rdf);
+-			break;
+-		case LDNS_RDF_TYPE_TIME:
+-			res = ldns_rdf2buffer_str_time(buffer, rdf);
+-			break;
+-		case LDNS_RDF_TYPE_HIP:
+-			res = ldns_rdf2buffer_str_hip(buffer, rdf);
+-			break;
+-		case LDNS_RDF_TYPE_LOC:
+-			res = ldns_rdf2buffer_str_loc(buffer, rdf);
+-			break;
+-		case LDNS_RDF_TYPE_WKS:
+-		case LDNS_RDF_TYPE_SERVICE:
+-			res = ldns_rdf2buffer_str_wks(buffer, rdf);
+-			break;
+-		case LDNS_RDF_TYPE_NSAP:
+-			res = ldns_rdf2buffer_str_nsap(buffer, rdf);
+-			break;
+-		case LDNS_RDF_TYPE_ATMA:
+-			res = ldns_rdf2buffer_str_atma(buffer, rdf);
+-			break;
+-		case LDNS_RDF_TYPE_IPSECKEY:
+-			res = ldns_rdf2buffer_str_ipseckey(buffer, rdf);
+-			break;
+-		case LDNS_RDF_TYPE_INT16_DATA:
+-			res = ldns_rdf2buffer_str_int16_data(buffer, rdf);
+-			break;
+-		case LDNS_RDF_TYPE_NSEC3_NEXT_OWNER:
+-			res = ldns_rdf2buffer_str_b32_ext(buffer, rdf);
+-			break;
+-		case LDNS_RDF_TYPE_ILNP64:
+-			res = ldns_rdf2buffer_str_ilnp64(buffer, rdf);
+-			break;
+-		case LDNS_RDF_TYPE_EUI48:
+-			res = ldns_rdf2buffer_str_eui48(buffer, rdf);
+-			break;
+-		case LDNS_RDF_TYPE_EUI64:
+-			res = ldns_rdf2buffer_str_eui64(buffer, rdf);
+-			break;
+-		case LDNS_RDF_TYPE_TAG:
+-			res = ldns_rdf2buffer_str_tag(buffer, rdf);
+-			break;
+-		case LDNS_RDF_TYPE_LONG_STR:
+-			res = ldns_rdf2buffer_str_long_str(buffer, rdf);
+-			break;
+-		}
+-	} else {
+-		/** This will write mangled RRs */
+-		ldns_buffer_printf(buffer, "(null) ");
+-		res = LDNS_STATUS_ERR;
+-	}
+-	return res;
+-}
+-
+-ldns_status
+-ldns_rdf2buffer_str(ldns_buffer *buffer, const ldns_rdf *rdf)
+-{
+-	return ldns_rdf2buffer_str_fmt(buffer,ldns_output_format_default,rdf);
+-}
+-
+-static ldns_rdf *
+-ldns_b32_ext2dname(const ldns_rdf *rdf)
+-{
+-	size_t size;
+-	char *b32;
+-	ldns_rdf *out;
+-	if(ldns_rdf_size(rdf) == 0)
+-		return NULL;
+-        /* remove -1 for the b32-hash-len octet */
+-	size = ldns_b32_ntop_calculate_size(ldns_rdf_size(rdf) - 1);
+-        /* add one for the end nul for the string */
+-	b32 = LDNS_XMALLOC(char, size + 2);
+-	if (b32) {
+-		if (ldns_b32_ntop_extended_hex(ldns_rdf_data(rdf) + 1, 
+-				ldns_rdf_size(rdf) - 1, b32, size+1) > 0) {
+-			b32[size] = '.';
+-			b32[size+1] = '\0';
+-			if (ldns_str2rdf_dname(&out, b32) == LDNS_STATUS_OK) {
+-				LDNS_FREE(b32);
+-				return out;
+-			}
+-		}
+-		LDNS_FREE(b32);
+-	}
+-	return NULL;
+-}
+-
+-static ldns_status
+-ldns_rr2buffer_str_rfc3597(ldns_buffer *output, const ldns_rr *rr)
+-{
+-	size_t total_rdfsize = 0;
+-	size_t i, j;
+-
+-	ldns_buffer_printf(output, "TYPE%u\t", ldns_rr_get_type(rr));
+-	for (i = 0; i < ldns_rr_rd_count(rr); i++) {
+-		total_rdfsize += ldns_rdf_size(ldns_rr_rdf(rr, i));
+-	}
+-	if (total_rdfsize == 0) {
+-		ldns_buffer_printf(output, "\\# 0\n");
+-		return ldns_buffer_status(output);
+-	}
+-	ldns_buffer_printf(output, "\\# %d ", total_rdfsize);
+-	for (i = 0; i < ldns_rr_rd_count(rr); i++) {
+-		for (j = 0; j < ldns_rdf_size(ldns_rr_rdf(rr, i)); j++) {
+-			ldns_buffer_printf(output, "%.2x",
+-					ldns_rdf_data(ldns_rr_rdf(rr, i))[j]);
+-		}
+-	}
+-	ldns_buffer_printf(output, "\n");
+-	return ldns_buffer_status(output);
+-}
+-
+-ldns_status
+-ldns_rr2buffer_str_fmt(ldns_buffer *output, 
+-		const ldns_output_format *fmt, const ldns_rr *rr)
+-{
+-	uint16_t i, flags;
+-	ldns_status status = LDNS_STATUS_OK;
+-	ldns_output_format_storage* fmt_st = (ldns_output_format_storage*)fmt;
+-
+-	if (fmt_st == NULL) {
+-		fmt_st = (ldns_output_format_storage*)
+-			  ldns_output_format_default;
+-	}
+-	if (!rr) {
+-		if (LDNS_COMMENT_NULLS & fmt_st->flags) {
+-			ldns_buffer_printf(output, "; (null)\n");
+-		}
+-		return ldns_buffer_status(output);
+-	}
+-	if (ldns_rr_owner(rr)) {
+-		status = ldns_rdf2buffer_str_dname(output, ldns_rr_owner(rr));
+-	}
+-	if (status != LDNS_STATUS_OK) {
+-		return status;
+-	}
+-
+-	/* TTL should NOT be printed if it is a question */
+-	if (!ldns_rr_is_question(rr)) {
+-		ldns_buffer_printf(output, "\t%d", ldns_rr_ttl(rr));
+-	}
+-
+-	ldns_buffer_printf(output, "\t");
+-	status = ldns_rr_class2buffer_str(output, ldns_rr_get_class(rr));
+-	if (status != LDNS_STATUS_OK) {
+-		return status;
+-	}
+-	ldns_buffer_printf(output, "\t");
+-
+-	if (ldns_output_format_covers_type(fmt, ldns_rr_get_type(rr))) {
+-		return ldns_rr2buffer_str_rfc3597(output, rr);
+-	}
+-	status = ldns_rr_type2buffer_str(output, ldns_rr_get_type(rr));
+-	if (status != LDNS_STATUS_OK) {
+-		return status;
+-	}
+-
+-	if (ldns_rr_rd_count(rr) > 0) {
+-		ldns_buffer_printf(output, "\t");
+-	} else if (!ldns_rr_is_question(rr)) {
+-		ldns_buffer_printf(output, "\t\\# 0");
+-	}
+-
+-	for (i = 0; i < ldns_rr_rd_count(rr); i++) {
+-		/* ldns_rdf2buffer_str handles NULL input fine! */
+-		if ((fmt_st->flags & LDNS_FMT_ZEROIZE_RRSIGS) &&
+-				(ldns_rr_get_type(rr) == LDNS_RR_TYPE_RRSIG) &&
+-				((/* inception  */ i == 4 &&
+-				  ldns_rdf_get_type(ldns_rr_rdf(rr, 4)) == 
+-							LDNS_RDF_TYPE_TIME) ||
+-				  (/* expiration */ i == 5 &&
+-				   ldns_rdf_get_type(ldns_rr_rdf(rr, 5)) ==
+-				   			LDNS_RDF_TYPE_TIME) ||
+-				  (/* signature  */ i == 8 &&
+-				   ldns_rdf_get_type(ldns_rr_rdf(rr, 8)) ==
+-				   			LDNS_RDF_TYPE_B64))) {
+-
+-			ldns_buffer_printf(output, "(null)");
+-			status = ldns_buffer_status(output);
+-		} else if ((fmt_st->flags & LDNS_FMT_PAD_SOA_SERIAL) &&
+-				(ldns_rr_get_type(rr) == LDNS_RR_TYPE_SOA) &&
+-				/* serial */ i == 2 &&
+-			 	ldns_rdf_get_type(ldns_rr_rdf(rr, 2)) ==
+-			 				LDNS_RDF_TYPE_INT32) {
+-			ldns_buffer_printf(output, "%10lu",
+-				(unsigned long) ldns_read_uint32(
+-					ldns_rdf_data(ldns_rr_rdf(rr, 2))));
+-			status = ldns_buffer_status(output);
+-		} else {
+-			status = ldns_rdf2buffer_str_fmt(output,
+-					fmt, ldns_rr_rdf(rr, i));
+-		}
+-		if(status != LDNS_STATUS_OK)
+-			return status;
+-		if (i < ldns_rr_rd_count(rr) - 1) {
+-			ldns_buffer_printf(output, " ");
+-		}
+-	}
+-	/* per RR special comments - handy for DNSSEC types */
+-	/* check to prevent question sec. rr from
+-	 * getting here */
+-	if (ldns_rr_rd_count(rr) > 0) {
+-		switch (ldns_rr_get_type(rr)) {
+-		case LDNS_RR_TYPE_DNSKEY:
+-			/* if ldns_rr_rd_count(rr) > 0
+-				then ldns_rr_rdf(rr, 0) exists! */
+-			if (! (fmt_st->flags & LDNS_COMMENT_KEY)) {
+-				break;
+-			}
+-			flags = ldns_rdf2native_int16(ldns_rr_rdf(rr, 0));
+-			ldns_buffer_printf(output, " ;{");
+-			if (fmt_st->flags & LDNS_COMMENT_KEY_ID) {
+-				ldns_buffer_printf(output, "id = %u",
+-					(unsigned int) ldns_calc_keytag(rr));
+-			}
+-			if ((fmt_st->flags & LDNS_COMMENT_KEY_TYPE) &&
+-					(flags & LDNS_KEY_ZONE_KEY)){
+-
+-				if (flags & LDNS_KEY_SEP_KEY) {
+-					ldns_buffer_printf(output, " (ksk)");
+-				} else {
+-					ldns_buffer_printf(output, " (zsk)");
+-				}
+-				if (fmt_st->flags & LDNS_COMMENT_KEY_SIZE){
+-					ldns_buffer_printf(output, ", ");
+-				}
+-			} else if (fmt_st->flags
+-					& (LDNS_COMMENT_KEY_ID
+-						|LDNS_COMMENT_KEY_SIZE)) {
+-				ldns_buffer_printf( output, ", ");
+-			}
+-			if (fmt_st->flags & LDNS_COMMENT_KEY_SIZE) {
+-				ldns_buffer_printf(output, "size = %db",
+-					ldns_rr_dnskey_key_size(rr));
+-			}
+-			ldns_buffer_printf(output, "}");
+-			break;
+-		case LDNS_RR_TYPE_RRSIG:
+-			if ((fmt_st->flags & LDNS_COMMENT_KEY)
+-					&& (fmt_st->flags& LDNS_COMMENT_RRSIGS)
+-					&& ldns_rr_rdf(rr, 6) != NULL) {
+-				ldns_buffer_printf(output, " ;{id = %d}",
+-						ldns_rdf2native_int16(
+-							ldns_rr_rdf(rr, 6)));
+-			}
+-			break;
+-		case LDNS_RR_TYPE_DS:
+-			if ((fmt_st->flags & LDNS_COMMENT_BUBBLEBABBLE) &&
+-					ldns_rr_rdf(rr, 3) != NULL) {
+-
+-				uint8_t *data = ldns_rdf_data(
+-						ldns_rr_rdf(rr, 3));
+-				size_t len = ldns_rdf_size(ldns_rr_rdf(rr, 3));
+-				char *babble = ldns_bubblebabble(data, len);
+-				if(babble) {
+-					ldns_buffer_printf(output,
+-							" ;{%s}", babble);
+-				}
+-				LDNS_FREE(babble);
+-			}
+-			break;
+-		case LDNS_RR_TYPE_NSEC3:
+-			if (! (fmt_st->flags & LDNS_COMMENT_FLAGS) &&
+-				! (fmt_st->flags & LDNS_COMMENT_NSEC3_CHAIN)) {
+-				break;
+-			}
+-			ldns_buffer_printf(output, " ;{");
+-			if ((fmt_st->flags & LDNS_COMMENT_FLAGS)) {
+-				if (ldns_nsec3_optout(rr)) {
+-					ldns_buffer_printf(output,
+-						" flags: optout");
+-				} else {
+-					ldns_buffer_printf(output," flags: -");
+-				}
+-				if (fmt_st->flags & LDNS_COMMENT_NSEC3_CHAIN &&
+-						fmt_st->hashmap != NULL) {
+-					ldns_buffer_printf(output, ", ");
+-				}
+-			}
+-			if (fmt_st->flags & LDNS_COMMENT_NSEC3_CHAIN &&
+-					fmt_st->hashmap != NULL) {
+-				ldns_rbnode_t *node;
+-				ldns_rdf *key = ldns_dname_label(
+-						ldns_rr_owner(rr), 0);
+-				if (key) {
+-					node = ldns_rbtree_search(
+-						fmt_st->hashmap,
+-						(void *) key);
+-					if (node->data) {
+-						ldns_buffer_printf(output,
+-							"from: ");
+-						(void) ldns_rdf2buffer_str(
+-							output,
+-							ldns_dnssec_name_name(
+-							   (ldns_dnssec_name*)
+-							   node->data
+-							));
+-					}
+-					ldns_rdf_free(key);
+-				}
+-				key = ldns_b32_ext2dname(
+-						ldns_nsec3_next_owner(rr));
+-				if (key) {
+-					node = ldns_rbtree_search(
+-						fmt_st->hashmap,
+-						(void *) key);
+-					if (node->data) {
+-						ldns_buffer_printf(output,
+-							" to: ");
+-						(void) ldns_rdf2buffer_str(
+-							output,
+-							ldns_dnssec_name_name(
+-							   (ldns_dnssec_name*)
+-							   node->data
+-							));
+-					}
+-					ldns_rdf_free(key);
+-				}
+-			}
+-			ldns_buffer_printf(output, "}");
+-			break;
+-		default:
+-			break;
+-
+-		}
+-	}
+-	/* last */
+-	ldns_buffer_printf(output, "\n");
+-	return ldns_buffer_status(output);
+-}
+-
+-ldns_status
+-ldns_rr2buffer_str(ldns_buffer *output, const ldns_rr *rr)
+-{
+-	return ldns_rr2buffer_str_fmt(output, ldns_output_format_default, rr);
+-}
+-
+-ldns_status
+-ldns_rr_list2buffer_str_fmt(ldns_buffer *output, 
+-		const ldns_output_format *fmt, const ldns_rr_list *list)
+-{
+-	uint16_t i;
+-
+-	for(i = 0; i < ldns_rr_list_rr_count(list); i++) {
+-		(void) ldns_rr2buffer_str_fmt(output, fmt, 
+-				ldns_rr_list_rr(list, i));
+-	}
+-	return ldns_buffer_status(output);
+-}
+-
+-ldns_status
+-ldns_rr_list2buffer_str(ldns_buffer *output, const ldns_rr_list *list)
+-{
+-	return ldns_rr_list2buffer_str_fmt(
+-			output, ldns_output_format_default, list);
+-}
+-
+-ldns_status
+-ldns_pktheader2buffer_str(ldns_buffer *output, const ldns_pkt *pkt)
+-{
+-	ldns_lookup_table *opcode = ldns_lookup_by_id(ldns_opcodes,
+-			                    (int) ldns_pkt_get_opcode(pkt));
+-	ldns_lookup_table *rcode = ldns_lookup_by_id(ldns_rcodes,
+-			                    (int) ldns_pkt_get_rcode(pkt));
+-
+-	ldns_buffer_printf(output, ";; ->>HEADER<<- ");
+-	if (opcode) {
+-		ldns_buffer_printf(output, "opcode: %s, ", opcode->name);
+-	} else {
+-		ldns_buffer_printf(output, "opcode: ?? (%u), ",
+-				ldns_pkt_get_opcode(pkt));
+-	}
+-	if (rcode) {
+-		ldns_buffer_printf(output, "rcode: %s, ", rcode->name);
+-	} else {
+-		ldns_buffer_printf(output, "rcode: ?? (%u), ", ldns_pkt_get_rcode(pkt));
+-	}
+-	ldns_buffer_printf(output, "id: %d\n", ldns_pkt_id(pkt));
+-	ldns_buffer_printf(output, ";; flags: ");
+-
+-	if (ldns_pkt_qr(pkt)) {
+-		ldns_buffer_printf(output, "qr ");
+-	}
+-	if (ldns_pkt_aa(pkt)) {
+-		ldns_buffer_printf(output, "aa ");
+-	}
+-	if (ldns_pkt_tc(pkt)) {
+-		ldns_buffer_printf(output, "tc ");
+-	}
+-	if (ldns_pkt_rd(pkt)) {
+-		ldns_buffer_printf(output, "rd ");
+-	}
+-	if (ldns_pkt_cd(pkt)) {
+-		ldns_buffer_printf(output, "cd ");
+-	}
+-	if (ldns_pkt_ra(pkt)) {
+-		ldns_buffer_printf(output, "ra ");
+-	}
+-	if (ldns_pkt_ad(pkt)) {
+-		ldns_buffer_printf(output, "ad ");
+-	}
+-	ldns_buffer_printf(output, "; ");
+-	ldns_buffer_printf(output, "QUERY: %u, ", ldns_pkt_qdcount(pkt));
+-	ldns_buffer_printf(output, "ANSWER: %u, ", ldns_pkt_ancount(pkt));
+-	ldns_buffer_printf(output, "AUTHORITY: %u, ", ldns_pkt_nscount(pkt));
+-	ldns_buffer_printf(output, "ADDITIONAL: %u ", ldns_pkt_arcount(pkt));
+-	return ldns_buffer_status(output);
+-}
+-
+-ldns_status
+-ldns_pkt2buffer_str_fmt(ldns_buffer *output, 
+-		const ldns_output_format *fmt, const ldns_pkt *pkt)
+-{
+-	uint16_t i;
+-	ldns_status status = LDNS_STATUS_OK;
+-	char *tmp;
+-	struct timeval time;
+-	time_t time_tt;
+-
+-	if (!pkt) {
+-		ldns_buffer_printf(output, "null");
+-		return LDNS_STATUS_OK;
+-	}
+-
+-	if (ldns_buffer_status_ok(output)) {
+-		status = ldns_pktheader2buffer_str(output, pkt);
+-		if (status != LDNS_STATUS_OK) {
+-			return status;
+-		}
+-
+-		ldns_buffer_printf(output, "\n");
+-
+-		ldns_buffer_printf(output, ";; QUESTION SECTION:\n;; ");
+-
+-
+-		for (i = 0; i < ldns_pkt_qdcount(pkt); i++) {
+-			status = ldns_rr2buffer_str_fmt(output, fmt,
+-				       ldns_rr_list_rr(
+-					       ldns_pkt_question(pkt), i));
+-			if (status != LDNS_STATUS_OK) {
+-				return status;
+-			}
+-		}
+-		ldns_buffer_printf(output, "\n");
+-
+-		ldns_buffer_printf(output, ";; ANSWER SECTION:\n");
+-		for (i = 0; i < ldns_pkt_ancount(pkt); i++) {
+-			status = ldns_rr2buffer_str_fmt(output, fmt,
+-				       ldns_rr_list_rr(
+-					       ldns_pkt_answer(pkt), i));
+-			if (status != LDNS_STATUS_OK) {
+-				return status;
+-			}
+-
+-		}
+-		ldns_buffer_printf(output, "\n");
+-
+-		ldns_buffer_printf(output, ";; AUTHORITY SECTION:\n");
+-
+-		for (i = 0; i < ldns_pkt_nscount(pkt); i++) {
+-			status = ldns_rr2buffer_str_fmt(output, fmt,
+-				       ldns_rr_list_rr(
+-					       ldns_pkt_authority(pkt), i));
+-			if (status != LDNS_STATUS_OK) {
+-				return status;
+-			}
+-		}
+-		ldns_buffer_printf(output, "\n");
+-
+-		ldns_buffer_printf(output, ";; ADDITIONAL SECTION:\n");
+-		for (i = 0; i < ldns_pkt_arcount(pkt); i++) {
+-			status = ldns_rr2buffer_str_fmt(output, fmt,
+-				       ldns_rr_list_rr(
+-					       ldns_pkt_additional(pkt), i));
+-			if (status != LDNS_STATUS_OK) {
+-				return status;
+-			}
+-
+-		}
+-		ldns_buffer_printf(output, "\n");
+-		/* add some futher fields */
+-		ldns_buffer_printf(output, ";; Query time: %d msec\n",
+-				ldns_pkt_querytime(pkt));
+-		if (ldns_pkt_edns(pkt)) {
+-			ldns_buffer_printf(output,
+-				   ";; EDNS: version %u; flags:",
+-				   ldns_pkt_edns_version(pkt));
+-			if (ldns_pkt_edns_do(pkt)) {
+-				ldns_buffer_printf(output, " do");
+-			}
+-			/* the extended rcode is the value set, shifted four bits,
+-			 * and or'd with the original rcode */
+-			if (ldns_pkt_edns_extended_rcode(pkt)) {
+-				ldns_buffer_printf(output, " ; ext-rcode: %d",
+-					(ldns_pkt_edns_extended_rcode(pkt) << 4 | ldns_pkt_get_rcode(pkt)));
+-			}
+-			ldns_buffer_printf(output, " ; udp: %u\n",
+-					   ldns_pkt_edns_udp_size(pkt));
+-
+-			if (ldns_pkt_edns_data(pkt)) {
+-				ldns_buffer_printf(output, ";; Data: ");
+-				(void)ldns_rdf2buffer_str(output,
+-							  ldns_pkt_edns_data(pkt));
+-				ldns_buffer_printf(output, "\n");
+-			}
+-		}
+-		if (ldns_pkt_tsig(pkt)) {
+-			ldns_buffer_printf(output, ";; TSIG:\n;; ");
+-			(void) ldns_rr2buffer_str_fmt(
+-					output, fmt, ldns_pkt_tsig(pkt));
+-			ldns_buffer_printf(output, "\n");
+-		}
+-		if (ldns_pkt_answerfrom(pkt)) {
+-			tmp = ldns_rdf2str(ldns_pkt_answerfrom(pkt));
+-			ldns_buffer_printf(output, ";; SERVER: %s\n", tmp);
+-			LDNS_FREE(tmp);
+-		}
+-		time = ldns_pkt_timestamp(pkt);
+-		time_tt = (time_t)time.tv_sec;
+-		ldns_buffer_printf(output, ";; WHEN: %s",
+-				(char*)ctime(&time_tt));
+-
+-		ldns_buffer_printf(output, ";; MSG SIZE  rcvd: %d\n",
+-				(int)ldns_pkt_size(pkt));
+-	} else {
+-		return ldns_buffer_status(output);
+-	}
+-	return status;
+-}
+-
+-ldns_status
+-ldns_pkt2buffer_str(ldns_buffer *output, const ldns_pkt *pkt)
+-{
+-	return ldns_pkt2buffer_str_fmt(output, ldns_output_format_default, pkt);
+-}
+-
+-
+-#ifdef HAVE_SSL
+-static ldns_status
+-ldns_hmac_key2buffer_str(ldns_buffer *output, const ldns_key *k)
+-{
+-	ldns_status status;
+-	size_t i;
+-	ldns_rdf *b64_bignum;
+-
+-	ldns_buffer_printf(output, "Key: ");
+-
+- 	i = ldns_key_hmac_size(k);
+-	b64_bignum =  ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, ldns_key_hmac_key(k));
+-	status = ldns_rdf2buffer_str(output, b64_bignum);
+-	ldns_rdf_deep_free(b64_bignum);
+-	ldns_buffer_printf(output, "\n");
+-	return status;
+-}
+-#endif
+-
+-#if defined(HAVE_SSL) && defined(USE_GOST)
+-static ldns_status
+-ldns_gost_key2buffer_str(ldns_buffer *output, EVP_PKEY *p)
+-{
+-	unsigned char* pp = NULL;
+-	int ret;
+-	ldns_rdf *b64_bignum;
+-	ldns_status status;
+-
+-	ldns_buffer_printf(output, "GostAsn1: ");
+-
+-	ret = i2d_PrivateKey(p, &pp);
+-	b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, (size_t)ret, pp);
+-	status = ldns_rdf2buffer_str(output, b64_bignum);
+-
+-	ldns_rdf_deep_free(b64_bignum);
+-	OPENSSL_free(pp);
+-	ldns_buffer_printf(output, "\n");
+-	return status;
+-}
+-#endif
+-
+-ldns_status
+-ldns_key2buffer_str(ldns_buffer *output, const ldns_key *k)
+-{
+-	ldns_status status = LDNS_STATUS_OK;
+-	unsigned char  *bignum;
+-#ifdef HAVE_SSL
+-#  ifndef S_SPLINT_S
+-	uint16_t i;
+-#  endif
+-	/* not used when ssl is not defined */
+-	/*@unused@*/
+-	ldns_rdf *b64_bignum = NULL;
+-
+-	RSA *rsa;
+-	DSA *dsa;
+-#endif /* HAVE_SSL */
+-
+-	if (!k) {
+-		return LDNS_STATUS_ERR;
+-	}
+-
+-	bignum = LDNS_XMALLOC(unsigned char, LDNS_MAX_KEYLEN);
+-	if (!bignum) {
+-		return LDNS_STATUS_ERR;
+-	}
+-
+-	if (ldns_buffer_status_ok(output)) {
+-#ifdef HAVE_SSL
+-		switch(ldns_key_algorithm(k)) {
+-			case LDNS_SIGN_RSASHA1:
+-			case LDNS_SIGN_RSASHA1_NSEC3:
+-			case LDNS_SIGN_RSASHA256:
+-			case LDNS_SIGN_RSASHA512:
+-			case LDNS_SIGN_RSAMD5:
+-				/* copied by looking at dnssec-keygen output */
+-				/* header */
+-				rsa = ldns_key_rsa_key(k);
+-
+-				ldns_buffer_printf(output,"Private-key-format: v1.2\n");
+-				switch(ldns_key_algorithm(k)) {
+-				case LDNS_SIGN_RSAMD5:
+-					ldns_buffer_printf(output,
+-								    "Algorithm: %u (RSA)\n",
+-								    LDNS_RSAMD5);
+-					break;
+-				case LDNS_SIGN_RSASHA1:
+-					ldns_buffer_printf(output,
+-								    "Algorithm: %u (RSASHA1)\n",
+-								    LDNS_RSASHA1);
+-					break;
+-				case LDNS_SIGN_RSASHA1_NSEC3:
+-					ldns_buffer_printf(output,
+-								    "Algorithm: %u (RSASHA1_NSEC3)\n",
+-								    LDNS_RSASHA1_NSEC3);
+-					break;
+-#ifdef USE_SHA2
+-				case LDNS_SIGN_RSASHA256:
+-					ldns_buffer_printf(output,
+-								    "Algorithm: %u (RSASHA256)\n",
+-								    LDNS_RSASHA256);
+-					break;
+-				case LDNS_SIGN_RSASHA512:
+-					ldns_buffer_printf(output,
+-								    "Algorithm: %u (RSASHA512)\n",
+-								    LDNS_RSASHA512);
+-					break;
+-#endif
+-				default:
+-#ifdef STDERR_MSGS
+-					fprintf(stderr, "Warning: unknown signature ");
+-					fprintf(stderr,
+-						   "algorithm type %u\n",
+-						   ldns_key_algorithm(k));
+-#endif
+-					ldns_buffer_printf(output,
+-								    "Algorithm: %u (Unknown)\n",
+-								    ldns_key_algorithm(k));
+-					break;
+-				}
+-
+-				/* print to buf, convert to bin, convert to b64,
+-				 * print to buf */
+-				ldns_buffer_printf(output, "Modulus: ");
+-#ifndef S_SPLINT_S
+-				i = (uint16_t)BN_bn2bin(rsa->n, bignum);
+-				if (i > LDNS_MAX_KEYLEN) {
+-					goto error;
+-				}
+-				b64_bignum =  ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum);
+-				if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) {
+-					ldns_rdf_deep_free(b64_bignum);
+-					goto error;
+-				}
+-				ldns_rdf_deep_free(b64_bignum);
+-				ldns_buffer_printf(output, "\n");
+-				ldns_buffer_printf(output, "PublicExponent: ");
+-				i = (uint16_t)BN_bn2bin(rsa->e, bignum);
+-				if (i > LDNS_MAX_KEYLEN) {
+-					goto error;
+-				}
+-				b64_bignum =  ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum);
+-				if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) {
+-					ldns_rdf_deep_free(b64_bignum);
+-					goto error;
+-				}
+-				ldns_rdf_deep_free(b64_bignum);
+-				ldns_buffer_printf(output, "\n");
+-
+-				ldns_buffer_printf(output, "PrivateExponent: ");
+-				if (rsa->d) {
+-					i = (uint16_t)BN_bn2bin(rsa->d, bignum);
+-					if (i > LDNS_MAX_KEYLEN) {
+-						goto error;
+-					}
+-					b64_bignum =  ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum);
+-					if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) {
+-						ldns_rdf_deep_free(b64_bignum);
+-						goto error;
+-					}
+-					ldns_rdf_deep_free(b64_bignum);
+-					ldns_buffer_printf(output, "\n");
+-				} else {
+-					ldns_buffer_printf(output, "(Not available)\n");
+-				}
+-
+-				ldns_buffer_printf(output, "Prime1: ");
+-				if (rsa->p) {
+-					i = (uint16_t)BN_bn2bin(rsa->p, bignum);
+-					if (i > LDNS_MAX_KEYLEN) {
+-						goto error;
+-					}
+-					b64_bignum =  ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum);
+-					if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) {
+-						ldns_rdf_deep_free(b64_bignum);
+-						goto error;
+-					}
+-					ldns_rdf_deep_free(b64_bignum);
+-					ldns_buffer_printf(output, "\n");
+-				} else {
+-					ldns_buffer_printf(output, "(Not available)\n");
+-				}
+-
+-				ldns_buffer_printf(output, "Prime2: ");
+-				if (rsa->q) {
+-					i = (uint16_t)BN_bn2bin(rsa->q, bignum);
+-					if (i > LDNS_MAX_KEYLEN) {
+-						goto error;
+-					}
+-					b64_bignum =  ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum);
+-					if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) {
+-						ldns_rdf_deep_free(b64_bignum);
+-						goto error;
+-					}
+-					ldns_rdf_deep_free(b64_bignum);
+-					ldns_buffer_printf(output, "\n");
+-				} else {
+-					ldns_buffer_printf(output, "(Not available)\n");
+-				}
+-
+-				ldns_buffer_printf(output, "Exponent1: ");
+-				if (rsa->dmp1) {
+-					i = (uint16_t)BN_bn2bin(rsa->dmp1, bignum);
+-					if (i > LDNS_MAX_KEYLEN) {
+-						goto error;
+-					}
+-					b64_bignum =  ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum);
+-					if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) {
+-						ldns_rdf_deep_free(b64_bignum);
+-						goto error;
+-					}
+-					ldns_rdf_deep_free(b64_bignum);
+-					ldns_buffer_printf(output, "\n");
+-				} else {
+-					ldns_buffer_printf(output, "(Not available)\n");
+-				}
+-
+-				ldns_buffer_printf(output, "Exponent2: ");
+-				if (rsa->dmq1) {
+-					i = (uint16_t)BN_bn2bin(rsa->dmq1, bignum);
+-					if (i > LDNS_MAX_KEYLEN) {
+-						goto error;
+-					}
+-					b64_bignum =  ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum);
+-					if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) {
+-						ldns_rdf_deep_free(b64_bignum);
+-						goto error;
+-					}
+-					ldns_rdf_deep_free(b64_bignum);
+-					ldns_buffer_printf(output, "\n");
+-				} else {
+-					ldns_buffer_printf(output, "(Not available)\n");
+-				}
+-
+-				ldns_buffer_printf(output, "Coefficient: ");
+-				if (rsa->iqmp) {
+-					i = (uint16_t)BN_bn2bin(rsa->iqmp, bignum);
+-					if (i > LDNS_MAX_KEYLEN) {
+-						goto error;
+-					}
+-					b64_bignum =  ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum);
+-					if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) {
+-						ldns_rdf_deep_free(b64_bignum);
+-						goto error;
+-					}
+-					ldns_rdf_deep_free(b64_bignum);
+-					ldns_buffer_printf(output, "\n");
+-				} else {
+-					ldns_buffer_printf(output, "(Not available)\n");
+-				}
+-#endif /* splint */
+-
+-				RSA_free(rsa);
+-				break;
+-			case LDNS_SIGN_DSA:
+-			case LDNS_SIGN_DSA_NSEC3:
+-				dsa = ldns_key_dsa_key(k);
+-
+-				ldns_buffer_printf(output,"Private-key-format: v1.2\n");
+-				if (ldns_key_algorithm(k) == LDNS_SIGN_DSA) {
+-					ldns_buffer_printf(output,"Algorithm: 3 (DSA)\n");
+-				} else if (ldns_key_algorithm(k) == LDNS_SIGN_DSA_NSEC3) {
+-					ldns_buffer_printf(output,"Algorithm: 6 (DSA_NSEC3)\n");
+-				}
+-
+-				/* print to buf, convert to bin, convert to b64,
+-				 * print to buf */
+-				ldns_buffer_printf(output, "Prime(p): ");
+-#ifndef S_SPLINT_S
+-				if (dsa->p) {
+-					i = (uint16_t)BN_bn2bin(dsa->p, bignum);
+-					if (i > LDNS_MAX_KEYLEN) {
+-						goto error;
+-					}
+-					b64_bignum =  ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum);
+-					if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) {
+-						ldns_rdf_deep_free(b64_bignum);
+-						goto error;
+-					}
+-					ldns_rdf_deep_free(b64_bignum);
+-					ldns_buffer_printf(output, "\n");
+-				} else {
+-					printf("(Not available)\n");
+-				}
+-
+-				ldns_buffer_printf(output, "Subprime(q): ");
+-				if (dsa->q) {
+-					i = (uint16_t)BN_bn2bin(dsa->q, bignum);
+-					if (i > LDNS_MAX_KEYLEN) {
+-						goto error;
+-					}
+-					b64_bignum =  ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum);
+-					if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) {
+-						ldns_rdf_deep_free(b64_bignum);
+-						goto error;
+-					}
+-					ldns_rdf_deep_free(b64_bignum);
+-					ldns_buffer_printf(output, "\n");
+-				} else {
+-					printf("(Not available)\n");
+-				}
+-
+-				ldns_buffer_printf(output, "Base(g): ");
+-				if (dsa->g) {
+-					i = (uint16_t)BN_bn2bin(dsa->g, bignum);
+-					if (i > LDNS_MAX_KEYLEN) {
+-						goto error;
+-					}
+-					b64_bignum =  ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum);
+-					if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) {
+-						ldns_rdf_deep_free(b64_bignum);
+-						goto error;
+-					}
+-					ldns_rdf_deep_free(b64_bignum);
+-					ldns_buffer_printf(output, "\n");
+-				} else {
+-					printf("(Not available)\n");
+-				}
+-
+-				ldns_buffer_printf(output, "Private_value(x): ");
+-				if (dsa->priv_key) {
+-					i = (uint16_t)BN_bn2bin(dsa->priv_key, bignum);
+-					if (i > LDNS_MAX_KEYLEN) {
+-						goto error;
+-					}
+-					b64_bignum =  ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum);
+-					if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) {
+-						ldns_rdf_deep_free(b64_bignum);
+-						goto error;
+-					}
+-					ldns_rdf_deep_free(b64_bignum);
+-					ldns_buffer_printf(output, "\n");
+-				} else {
+-					printf("(Not available)\n");
+-				}
+-
+-				ldns_buffer_printf(output, "Public_value(y): ");
+-				if (dsa->pub_key) {
+-					i = (uint16_t)BN_bn2bin(dsa->pub_key, bignum);
+-					if (i > LDNS_MAX_KEYLEN) {
+-						goto error;
+-					}
+-					b64_bignum =  ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum);
+-					if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) {
+-						ldns_rdf_deep_free(b64_bignum);
+-						goto error;
+-					}
+-					ldns_rdf_deep_free(b64_bignum);
+-					ldns_buffer_printf(output, "\n");
+-				} else {
+-					printf("(Not available)\n");
+-				}
+-#endif /* splint */
+-				break;
+-			case LDNS_SIGN_ECC_GOST:
+-				/* no format defined, use blob */
+-#if defined(HAVE_SSL) && defined(USE_GOST)
+-				ldns_buffer_printf(output, "Private-key-format: v1.2\n");
+-				ldns_buffer_printf(output, "Algorithm: %d (ECC-GOST)\n", LDNS_SIGN_ECC_GOST);
+-				status = ldns_gost_key2buffer_str(output, 
+-#ifndef S_SPLINT_S
+-					k->_key.key
+-#else
+-					NULL
+-#endif
+-				);
+-#else
+-				goto error;
+-#endif /* GOST */
+-				break;
+-			case LDNS_SIGN_ECDSAP256SHA256:
+-			case LDNS_SIGN_ECDSAP384SHA384:
+-#ifdef USE_ECDSA
+-                                ldns_buffer_printf(output, "Private-key-format: v1.2\n");
+-				ldns_buffer_printf(output, "Algorithm: %d (", ldns_key_algorithm(k));
+-                                status=ldns_algorithm2buffer_str(output, (ldns_algorithm)ldns_key_algorithm(k));
+-#ifndef S_SPLINT_S
+-				ldns_buffer_printf(output, ")\n");
+-                                if(k->_key.key) {
+-                                        EC_KEY* ec = EVP_PKEY_get1_EC_KEY(k->_key.key);
+-                                        const BIGNUM* b = EC_KEY_get0_private_key(ec);
+-                                        ldns_buffer_printf(output, "PrivateKey: ");
+-                                        i = (uint16_t)BN_bn2bin(b, bignum);
+-                                        if (i > LDNS_MAX_KEYLEN) {
+-                                                goto error;
+-                                        }
+-                                        b64_bignum =  ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum);
+-                                        if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) {
+-						ldns_rdf_deep_free(b64_bignum);
+-                                                goto error;
+-                                        }
+-                                        ldns_rdf_deep_free(b64_bignum);
+-				        ldns_buffer_printf(output, "\n");
+-                                        /* down reference count in EC_KEY
+-                                         * its still assigned to the PKEY */
+-                                        EC_KEY_free(ec);
+-                                }
+-#endif /* splint */
+-#else
+-				goto error;
+-#endif /* ECDSA */
+-                                break;
+-			case LDNS_SIGN_HMACMD5:
+-				/* there's not much of a format defined for TSIG */
+-				/* It's just a binary blob, Same for all algorithms */
+-                ldns_buffer_printf(output, "Private-key-format: v1.2\n");
+-                ldns_buffer_printf(output, "Algorithm: 157 (HMAC_MD5)\n");
+-				status = ldns_hmac_key2buffer_str(output, k);
+-				break;
+-			case LDNS_SIGN_HMACSHA1:
+-		        ldns_buffer_printf(output, "Private-key-format: v1.2\n");
+-		        ldns_buffer_printf(output, "Algorithm: 158 (HMAC_SHA1)\n");
+-				status = ldns_hmac_key2buffer_str(output, k);
+-				break;
+-			case LDNS_SIGN_HMACSHA256:
+-		        ldns_buffer_printf(output, "Private-key-format: v1.2\n");
+-		        ldns_buffer_printf(output, "Algorithm: 159 (HMAC_SHA256)\n");
+-				status = ldns_hmac_key2buffer_str(output, k);
+-				break;
+-		}
+-#endif /* HAVE_SSL */
+-	} else {
+-		LDNS_FREE(bignum);
+-		return ldns_buffer_status(output);
+-	}
+-	LDNS_FREE(bignum);
+-	return status;
+-
+-#ifdef HAVE_SSL
+-	/* compiles warn the label isn't used */
+-error:
+-	LDNS_FREE(bignum);
+-	return LDNS_STATUS_ERR;
+-#endif /* HAVE_SSL */
+-
+-}
+-
+-/*
+- * Zero terminate the buffer and copy data.
+- */
+-char *
+-ldns_buffer2str(ldns_buffer *buffer)
+-{
+-	char *str;
+-
+-	/* check if buffer ends with \0, if not, and
+-	   if there is space, add it */
+-	if (*(ldns_buffer_at(buffer, ldns_buffer_position(buffer))) != 0) {
+-		if (!ldns_buffer_reserve(buffer, 1)) {
+-			return NULL;
+-		}
+-		ldns_buffer_write_u8(buffer, (uint8_t) '\0');
+-		if (!ldns_buffer_set_capacity(buffer, ldns_buffer_position(buffer))) {
+-			return NULL;
+-		}
+-	}
+-
+-	str = strdup((const char *)ldns_buffer_begin(buffer));
+-        if(!str) {
+-                return NULL;
+-        }
+-	return str;
+-}
+-
+-/*
+- * Zero terminate the buffer and export data.
+- */
+-char *
+-ldns_buffer_export2str(ldns_buffer *buffer)
+-{
+-	/* Append '\0' as string terminator */
+-	if (! ldns_buffer_reserve(buffer, 1)) {
+-		return NULL;
+-	}
+-	ldns_buffer_write_u8(buffer, 0);
+-
+-	/* reallocate memory to the size of the string and export */
+-	ldns_buffer_set_capacity(buffer, ldns_buffer_position(buffer));
+-	return ldns_buffer_export(buffer);
+-}
+-
+-char *
+-ldns_rdf2str(const ldns_rdf *rdf)
+-{
+-	char *result = NULL;
+-	ldns_buffer *tmp_buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN);
+-
+-	if (!tmp_buffer) {
+-		return NULL;
+-	}
+-	if (ldns_rdf2buffer_str(tmp_buffer, rdf) == LDNS_STATUS_OK) {
+-		/* export and return string, destroy rest */
+-		result = ldns_buffer_export2str(tmp_buffer);
+-	}
+-	ldns_buffer_free(tmp_buffer);
+-	return result;
+-}
+-
+-char *
+-ldns_rr2str_fmt(const ldns_output_format *fmt, const ldns_rr *rr)
+-{
+-	char *result = NULL;
+-	ldns_buffer *tmp_buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN);
+-
+-	if (!tmp_buffer) {
+-		return NULL;
+-	}
+-	if (ldns_rr2buffer_str_fmt(tmp_buffer, fmt, rr)
+-		       	== LDNS_STATUS_OK) {
+-		/* export and return string, destroy rest */
+-		result = ldns_buffer_export2str(tmp_buffer);
+-	}
+-	ldns_buffer_free(tmp_buffer);
+-	return result;
+-}
+-
+-char *
+-ldns_rr2str(const ldns_rr *rr)
+-{
+-	return ldns_rr2str_fmt(ldns_output_format_default, rr);
+-}
+-
+-char *
+-ldns_pkt2str_fmt(const ldns_output_format *fmt, const ldns_pkt *pkt)
+-{
+-	char *result = NULL;
+-	ldns_buffer *tmp_buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN);
+-
+-	if (!tmp_buffer) {
+-		return NULL;
+-	}
+-	if (ldns_pkt2buffer_str_fmt(tmp_buffer, fmt, pkt)
+-		       	== LDNS_STATUS_OK) {
+-		/* export and return string, destroy rest */
+-		result = ldns_buffer_export2str(tmp_buffer);
+-	}
+-
+-	ldns_buffer_free(tmp_buffer);
+-	return result;
+-}
+-
+-char *
+-ldns_pkt2str(const ldns_pkt *pkt)
+-{
+-	return ldns_pkt2str_fmt(ldns_output_format_default, pkt);
+-}
+-
+-char *
+-ldns_key2str(const ldns_key *k)
+-{
+-	char *result = NULL;
+-	ldns_buffer *tmp_buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN);
+-
+-	if (!tmp_buffer) {
+-		return NULL;
+-	}
+-	if (ldns_key2buffer_str(tmp_buffer, k) == LDNS_STATUS_OK) {
+-		/* export and return string, destroy rest */
+-		result = ldns_buffer_export2str(tmp_buffer);
+-	}
+-	ldns_buffer_free(tmp_buffer);
+-	return result;
+-}
+-
+-char *
+-ldns_rr_list2str_fmt(const ldns_output_format *fmt, const ldns_rr_list *list)
+-{
+-	char *result = NULL;
+-	ldns_buffer *tmp_buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN);
+-
+-	if (!tmp_buffer) {
+-		return NULL;
+-	}
+-	if (list) {
+-		if (ldns_rr_list2buffer_str_fmt(
+-				   tmp_buffer, fmt, list)
+-			       	== LDNS_STATUS_OK) {
+-		}
+-	} else {
+-		if (fmt == NULL) {
+-			fmt = ldns_output_format_default;
+-		}
+-		if (fmt->flags & LDNS_COMMENT_NULLS) {
+-			ldns_buffer_printf(tmp_buffer, "; (null)\n");
+-		}
+-	}
+-
+-	/* export and return string, destroy rest */
+-	result = ldns_buffer_export2str(tmp_buffer);
+-	ldns_buffer_free(tmp_buffer);
+-	return result;
+-}
+-
+-char *
+-ldns_rr_list2str(const ldns_rr_list *list)
+-{
+-	return ldns_rr_list2str_fmt(ldns_output_format_default, list);
+-}
+-
+-void
+-ldns_rdf_print(FILE *output, const ldns_rdf *rdf)
+-{
+-	char *str = ldns_rdf2str(rdf);
+-	if (str) {
+-		fprintf(output, "%s", str);
+-	} else {
+-		fprintf(output, ";Unable to convert rdf to string\n");
+-	}
+-	LDNS_FREE(str);
+-}
+-
+-void
+-ldns_rr_print_fmt(FILE *output,
+-		const ldns_output_format *fmt, const ldns_rr *rr)
+-{
+-	char *str = ldns_rr2str_fmt(fmt, rr);
+-	if (str) {
+-		fprintf(output, "%s", str);
+-	} else {
+-		fprintf(output, ";Unable to convert rr to string\n");
+-	}
+-	LDNS_FREE(str);
+-}
+-
+-void
+-ldns_rr_print(FILE *output, const ldns_rr *rr)
+-{
+-	ldns_rr_print_fmt(output, ldns_output_format_default, rr);
+-}
+-
+-void
+-ldns_pkt_print_fmt(FILE *output, 
+-		const ldns_output_format *fmt, const ldns_pkt *pkt)
+-{
+-	char *str = ldns_pkt2str_fmt(fmt, pkt);
+-	if (str) {
+-		fprintf(output, "%s", str);
+-	} else {
+-		fprintf(output, ";Unable to convert packet to string\n");
+-	}
+-	LDNS_FREE(str);
+-}
+-
+-void
+-ldns_pkt_print(FILE *output, const ldns_pkt *pkt)
+-{
+-	ldns_pkt_print_fmt(output, ldns_output_format_default, pkt);
+-}
+-
+-void
+-ldns_rr_list_print_fmt(FILE *output, 
+-		const ldns_output_format *fmt, const ldns_rr_list *lst)
+-{
+-	size_t i;
+-	for (i = 0; i < ldns_rr_list_rr_count(lst); i++) {
+-		ldns_rr_print_fmt(output, fmt, ldns_rr_list_rr(lst, i));
+-	}
+-}
+-
+-void
+-ldns_rr_list_print(FILE *output, const ldns_rr_list *lst)
+-{
+-	ldns_rr_list_print_fmt(output, ldns_output_format_default, lst);
+-}
+-
+-void
+-ldns_resolver_print_fmt(FILE *output, 
+-		const ldns_output_format *fmt, const ldns_resolver *r)
+-{
+-	uint16_t i;
+-	ldns_rdf **n;
+-	ldns_rdf **s;
+-	size_t *rtt;
+-	if (!r) {
+-		return;
+-	}
+-	n = ldns_resolver_nameservers(r);
+-	s = ldns_resolver_searchlist(r);
+-	rtt = ldns_resolver_rtt(r);
+-
+-	fprintf(output, "port: %d\n", (int)ldns_resolver_port(r));
+-	fprintf(output, "edns0 size: %d\n", (int)ldns_resolver_edns_udp_size(r));
+-	fprintf(output, "use ip6: %d\n", (int)ldns_resolver_ip6(r));
+-
+-	fprintf(output, "recursive: %d\n", ldns_resolver_recursive(r));
+-	fprintf(output, "usevc: %d\n", ldns_resolver_usevc(r));
+-	fprintf(output, "igntc: %d\n", ldns_resolver_igntc(r));
+-	fprintf(output, "fail: %d\n", ldns_resolver_fail(r));
+-	fprintf(output, "retry: %d\n", (int)ldns_resolver_retry(r));
+-	fprintf(output, "retrans: %d\n", (int)ldns_resolver_retrans(r));
+-	fprintf(output, "fallback: %d\n", ldns_resolver_fallback(r));
+-	fprintf(output, "random: %d\n", ldns_resolver_random(r));
+-	fprintf(output, "timeout: %d\n", (int)ldns_resolver_timeout(r).tv_sec);
+-	fprintf(output, "dnssec: %d\n", ldns_resolver_dnssec(r));
+-	fprintf(output, "dnssec cd: %d\n", ldns_resolver_dnssec_cd(r));
+-	fprintf(output, "trust anchors (%d listed):\n",
+-		(int)ldns_rr_list_rr_count(ldns_resolver_dnssec_anchors(r)));
+-	ldns_rr_list_print_fmt(output, fmt, ldns_resolver_dnssec_anchors(r));
+-	fprintf(output, "tsig: %s %s\n",
+-                ldns_resolver_tsig_keyname(r)?ldns_resolver_tsig_keyname(r):"-",
+-                ldns_resolver_tsig_algorithm(r)?ldns_resolver_tsig_algorithm(r):"-");
+-	fprintf(output, "debug: %d\n", ldns_resolver_debug(r));
+-
+-	fprintf(output, "default domain: ");
+-	ldns_rdf_print(output, ldns_resolver_domain(r));
+-	fprintf(output, "\n");
+-	fprintf(output, "apply default domain: %d\n", ldns_resolver_defnames(r));
+-
+-	fprintf(output, "searchlist (%d listed):\n",  (int)ldns_resolver_searchlist_count(r));
+-	for (i = 0; i < ldns_resolver_searchlist_count(r); i++) {
+-		fprintf(output, "\t");
+-		ldns_rdf_print(output, s[i]);
+-		fprintf(output, "\n");
+-	}
+-	fprintf(output, "apply search list: %d\n", ldns_resolver_dnsrch(r));
+-
+-	fprintf(output, "nameservers (%d listed):\n", (int)ldns_resolver_nameserver_count(r));
+-	for (i = 0; i < ldns_resolver_nameserver_count(r); i++) {
+-		fprintf(output, "\t");
+-		ldns_rdf_print(output, n[i]);
+-
+-		switch ((int)rtt[i]) {
+-			case LDNS_RESOLV_RTT_MIN:
+-			fprintf(output, " - reachable\n");
+-			break;
+-			case LDNS_RESOLV_RTT_INF:
+-			fprintf(output, " - unreachable\n");
+-			break;
+-		}
+-	}
+-}
+-
+-void
+-ldns_resolver_print(FILE *output, const ldns_resolver *r)
+-{
+-	ldns_resolver_print_fmt(output, ldns_output_format_default, r);
+-}
+-
+-void
+-ldns_zone_print_fmt(FILE *output, 
+-		const ldns_output_format *fmt, const ldns_zone *z)
+-{
+-	if(ldns_zone_soa(z))
+-		ldns_rr_print_fmt(output, fmt, ldns_zone_soa(z));
+-	ldns_rr_list_print_fmt(output, fmt, ldns_zone_rrs(z));
+-}
+-void
+-ldns_zone_print(FILE *output, const ldns_zone *z)
+-{
+-	ldns_zone_print_fmt(output, ldns_output_format_default, z);
+-}
+diff --git a/src/ldns/host2wire.c b/src/ldns/host2wire.c
+deleted file mode 100644
+index 06f45ba..0000000
+--- a/src/ldns/host2wire.c
++++ /dev/null
+@@ -1,494 +0,0 @@
+-/*
+- * host2wire.c
+- *
+- * conversion routines from the host to the wire format.
+- * This will usually just a re-ordering of the
+- * data (as we store it in network format)
+- *
+- * a Net::DNS like library for C
+- *
+- * (c) NLnet Labs, 2004-2006
+- *
+- * See the file LICENSE for the license
+- */
+-
+-#include <ldns/config.h>
+-
+-#include <ldns/ldns.h>
+-
+-ldns_status
+-ldns_dname2buffer_wire(ldns_buffer *buffer, const ldns_rdf *name)
+-{
+-	return ldns_dname2buffer_wire_compress(buffer, name, NULL);
+-}
+-
+-ldns_status
+-ldns_dname2buffer_wire_compress(ldns_buffer *buffer, const ldns_rdf *name, ldns_rbtree_t *compression_data)
+-{
+-	ldns_rbnode_t *node;
+-	uint8_t *data;
+-	size_t size;
+-	ldns_rdf *label;
+-	ldns_rdf *rest;
+-	ldns_status s;
+-
+-	/* If no tree, just add the data */
+-	if(!compression_data)
+-	{
+-		if (ldns_buffer_reserve(buffer, ldns_rdf_size(name)))
+-		{
+-			ldns_buffer_write(buffer, ldns_rdf_data(name), ldns_rdf_size(name));
+-		}
+-		return ldns_buffer_status(buffer);
+-	}
+-
+-	/* No labels left, write final zero */
+-	if(ldns_dname_label_count(name)==0)
+-	{
+-		if(ldns_buffer_reserve(buffer,1))
+-		{
+-			ldns_buffer_write_u8(buffer, 0);
+-		}
+-		return ldns_buffer_status(buffer);
+-	}
+-
+-	/* Can we find the name in the tree? */
+-	if((node = ldns_rbtree_search(compression_data, ldns_rdf_data(name))) != NULL)
+-	{
+-		/* Found */
+-		uint16_t position = (uint16_t) (intptr_t) node->data | 0xC000;
+-		if (ldns_buffer_reserve(buffer, 2))
+-		{
+-			ldns_buffer_write_u16(buffer, position);
+-		}
+-		return ldns_buffer_status(buffer);
+-	}
+-	else
+-	{
+-		/* Not found. Write cache entry, take off first label, write it, */
+-		/* try again with the rest of the name. */
+-		ldns_rbnode_t *node = LDNS_MALLOC(ldns_rbnode_t);
+-		if(!node)
+-		{
+-			return LDNS_STATUS_MEM_ERR;
+-		}
+-		if (ldns_buffer_position(buffer) < 16384) {
+-			node->key = strdup((const char *)ldns_rdf_data(name));
+-			node->data = (void *) (intptr_t) ldns_buffer_position(buffer);
+-			if(!ldns_rbtree_insert(compression_data,node))
+-			{
+-				/* fprintf(stderr,"Name not found but now it's there?\n"); */
+-			}
+-		}
+-		label = ldns_dname_label(name, 0);
+-		rest = ldns_dname_left_chop(name);
+-		size = ldns_rdf_size(label) - 1; /* Don't want the final zero */
+-		data = ldns_rdf_data(label);
+-		if(ldns_buffer_reserve(buffer, size))
+-		{
+-			ldns_buffer_write(buffer, data, size);
+-		}
+-		ldns_rdf_deep_free(label);
+-		s = ldns_dname2buffer_wire_compress(buffer, rest, compression_data);
+-		ldns_rdf_deep_free(rest);
+-		return s;
+-	}
+-}
+-
+-ldns_status
+-ldns_rdf2buffer_wire(ldns_buffer *buffer, const ldns_rdf *rdf)
+-{
+-	return ldns_rdf2buffer_wire_compress(buffer, rdf, NULL);
+-}
+-
+-ldns_status
+-ldns_rdf2buffer_wire_compress(ldns_buffer *buffer, const ldns_rdf *rdf, ldns_rbtree_t *compression_data)
+-{
+-	/* If it's a DNAME, call that function to get compression */
+-	if(compression_data && ldns_rdf_get_type(rdf) == LDNS_RDF_TYPE_DNAME)
+-	{
+-		return ldns_dname2buffer_wire_compress(buffer,rdf,compression_data);
+-	}
+-
+-	if (ldns_buffer_reserve(buffer, ldns_rdf_size(rdf))) {
+-		ldns_buffer_write(buffer, ldns_rdf_data(rdf), ldns_rdf_size(rdf));
+-	}
+-	return ldns_buffer_status(buffer);
+-}
+-
+-ldns_status
+-ldns_rdf2buffer_wire_canonical(ldns_buffer *buffer, const ldns_rdf *rdf)
+-{
+-	size_t i;
+-	uint8_t *rdf_data;
+-
+-	if (ldns_rdf_get_type(rdf) == LDNS_RDF_TYPE_DNAME) {
+-		if (ldns_buffer_reserve(buffer, ldns_rdf_size(rdf))) {
+-			rdf_data = ldns_rdf_data(rdf);
+-			for (i = 0; i < ldns_rdf_size(rdf); i++) {
+-				ldns_buffer_write_u8(buffer,
+-				    (uint8_t) LDNS_DNAME_NORMALIZE((int)rdf_data[i]));
+-			}
+-		}
+-	} else {
+-		/* direct copy for all other types */
+-		if (ldns_buffer_reserve(buffer, ldns_rdf_size(rdf))) {
+-			ldns_buffer_write(buffer,
+-						   ldns_rdf_data(rdf),
+-						   ldns_rdf_size(rdf));
+-		}
+-	}
+-	return ldns_buffer_status(buffer);
+-}
+-
+-/* convert a rr list to wireformat */
+-ldns_status
+-ldns_rr_list2buffer_wire(ldns_buffer *buffer,const ldns_rr_list *rr_list)
+-{
+-	uint16_t rr_count;
+-	uint16_t i;
+-
+-	rr_count = ldns_rr_list_rr_count(rr_list);
+-	for(i = 0; i < rr_count; i++) {
+-		(void)ldns_rr2buffer_wire(buffer, ldns_rr_list_rr(rr_list, i), 
+-					  LDNS_SECTION_ANY);
+-	}
+-	return ldns_buffer_status(buffer);
+-}
+-
+-
+-ldns_status
+-ldns_rr2buffer_wire_canonical(ldns_buffer *buffer,
+-						const ldns_rr *rr,
+-						int section)
+-{
+-	uint16_t i;
+-	uint16_t rdl_pos = 0;
+-	bool pre_rfc3597 = false;
+-	switch (ldns_rr_get_type(rr)) {
+-	case LDNS_RR_TYPE_NS:
+-	case LDNS_RR_TYPE_MD:
+-	case LDNS_RR_TYPE_MF:
+-	case LDNS_RR_TYPE_CNAME:
+-	case LDNS_RR_TYPE_SOA:
+-	case LDNS_RR_TYPE_MB:
+-	case LDNS_RR_TYPE_MG:
+-	case LDNS_RR_TYPE_MR:
+-	case LDNS_RR_TYPE_PTR:
+-	case LDNS_RR_TYPE_HINFO:
+-	case LDNS_RR_TYPE_MINFO:
+-	case LDNS_RR_TYPE_MX:
+-	case LDNS_RR_TYPE_RP:
+-	case LDNS_RR_TYPE_AFSDB:
+-	case LDNS_RR_TYPE_RT:
+-	case LDNS_RR_TYPE_SIG:
+-	case LDNS_RR_TYPE_PX:
+-	case LDNS_RR_TYPE_NXT:
+-	case LDNS_RR_TYPE_NAPTR:
+-	case LDNS_RR_TYPE_KX:
+-	case LDNS_RR_TYPE_SRV:
+-	case LDNS_RR_TYPE_DNAME:
+-	case LDNS_RR_TYPE_A6:
+-	case LDNS_RR_TYPE_RRSIG:
+-		pre_rfc3597 = true;
+-		break;
+-	default:
+-		break;
+-	}
+-	
+-	if (ldns_rr_owner(rr)) {
+-		(void) ldns_rdf2buffer_wire_canonical(buffer, ldns_rr_owner(rr));
+-	}
+-	
+-	if (ldns_buffer_reserve(buffer, 4)) {
+-		(void) ldns_buffer_write_u16(buffer, ldns_rr_get_type(rr));
+-		(void) ldns_buffer_write_u16(buffer, ldns_rr_get_class(rr));
+-	}
+-
+-	if (section != LDNS_SECTION_QUESTION) {
+-		if (ldns_buffer_reserve(buffer, 6)) {
+-			ldns_buffer_write_u32(buffer, ldns_rr_ttl(rr));
+-			/* remember pos for later */
+-			rdl_pos = ldns_buffer_position(buffer);
+-			ldns_buffer_write_u16(buffer, 0);
+-		}	
+-		for (i = 0; i < ldns_rr_rd_count(rr); i++) {
+-			if (pre_rfc3597) {
+-				(void) ldns_rdf2buffer_wire_canonical(
+-					buffer, ldns_rr_rdf(rr, i));
+-			} else {
+-				(void) ldns_rdf2buffer_wire(
+-					buffer, ldns_rr_rdf(rr, i));
+-			}
+-		}
+-		if (rdl_pos != 0) {
+-			ldns_buffer_write_u16_at(buffer, rdl_pos,
+-			                         ldns_buffer_position(buffer)
+-		        	                   - rdl_pos - 2);
+-		}
+-	}
+-	return ldns_buffer_status(buffer);
+-}
+-
+-ldns_status
+-ldns_rr2buffer_wire(ldns_buffer *buffer, const ldns_rr *rr, int section)
+-{
+-	return ldns_rr2buffer_wire_compress(buffer,rr,section,NULL);
+-}
+-
+-ldns_status
+-ldns_rr2buffer_wire_compress(ldns_buffer *buffer, const ldns_rr *rr, int section, ldns_rbtree_t *compression_data)
+-{
+-	uint16_t i;
+-	uint16_t rdl_pos = 0;
+-
+-	if (ldns_rr_owner(rr)) {
+-		(void) ldns_dname2buffer_wire_compress(buffer, ldns_rr_owner(rr), compression_data);
+-	}
+-	
+-	if (ldns_buffer_reserve(buffer, 4)) {
+-		(void) ldns_buffer_write_u16(buffer, ldns_rr_get_type(rr));
+-		(void) ldns_buffer_write_u16(buffer, ldns_rr_get_class(rr));
+-	}
+-
+-	if (section != LDNS_SECTION_QUESTION) {
+-		if (ldns_buffer_reserve(buffer, 6)) {
+-			ldns_buffer_write_u32(buffer, ldns_rr_ttl(rr));
+-			/* remember pos for later */
+-			rdl_pos = ldns_buffer_position(buffer);
+-			ldns_buffer_write_u16(buffer, 0);
+-		}
+-		if (LDNS_RR_COMPRESS ==
+-		    ldns_rr_descript(ldns_rr_get_type(rr))->_compress) {
+-
+-			for (i = 0; i < ldns_rr_rd_count(rr); i++) {
+-				(void) ldns_rdf2buffer_wire_compress(buffer,
+-				    ldns_rr_rdf(rr, i), compression_data);
+-			}
+-		} else {
+-			for (i = 0; i < ldns_rr_rd_count(rr); i++) {
+-				(void) ldns_rdf2buffer_wire(
+-				    buffer, ldns_rr_rdf(rr, i));
+-			}
+-		}
+-		if (rdl_pos != 0) {
+-			ldns_buffer_write_u16_at(buffer, rdl_pos,
+-			                         ldns_buffer_position(buffer)
+-		        	                   - rdl_pos - 2);
+-		}
+-	}
+-	return ldns_buffer_status(buffer);
+-}
+-
+-ldns_status
+-ldns_rrsig2buffer_wire(ldns_buffer *buffer, const ldns_rr *rr)
+-{
+-	uint16_t i;
+-
+-	/* it must be a sig RR */
+-	if (ldns_rr_get_type(rr) != LDNS_RR_TYPE_RRSIG) {
+-		return LDNS_STATUS_ERR;
+-	}
+-	
+-	/* Convert all the rdfs, except the actual signature data
+-	 * rdf number 8  - the last, hence: -1 */
+-	for (i = 0; i < ldns_rr_rd_count(rr) - 1; i++) {
+-		(void) ldns_rdf2buffer_wire_canonical(buffer, 
+-				ldns_rr_rdf(rr, i));
+-	}
+-
+-	return ldns_buffer_status(buffer);
+-}
+-
+-ldns_status
+-ldns_rr_rdata2buffer_wire(ldns_buffer *buffer, const ldns_rr *rr)
+-{
+-	uint16_t i;
+-
+-	/* convert all the rdf's */
+-	for (i = 0; i < ldns_rr_rd_count(rr); i++) {
+-		(void) ldns_rdf2buffer_wire(buffer, ldns_rr_rdf(rr,i));
+-	}
+-	return ldns_buffer_status(buffer);
+-}
+-
+-/*
+- * Copies the packet header data to the buffer in wire format
+- */
+-static ldns_status
+-ldns_hdr2buffer_wire(ldns_buffer *buffer, const ldns_pkt *packet)
+-{
+-	uint8_t flags;
+-	uint16_t arcount;
+-
+-	if (ldns_buffer_reserve(buffer, 12)) {
+-		ldns_buffer_write_u16(buffer, ldns_pkt_id(packet));
+-		
+-		flags = ldns_pkt_qr(packet) << 7
+-		        | ldns_pkt_get_opcode(packet) << 3
+-		        | ldns_pkt_aa(packet) << 2
+-		        | ldns_pkt_tc(packet) << 1 | ldns_pkt_rd(packet);
+-		ldns_buffer_write_u8(buffer, flags);
+-		
+-		flags = ldns_pkt_ra(packet) << 7
+-		        /*| ldns_pkt_z(packet) << 6*/
+-		        | ldns_pkt_ad(packet) << 5
+-		        | ldns_pkt_cd(packet) << 4
+-			| ldns_pkt_get_rcode(packet);
+-		ldns_buffer_write_u8(buffer, flags);
+-		
+-		ldns_buffer_write_u16(buffer, ldns_pkt_qdcount(packet));
+-		ldns_buffer_write_u16(buffer, ldns_pkt_ancount(packet));
+-		ldns_buffer_write_u16(buffer, ldns_pkt_nscount(packet));
+-		/* add EDNS0 and TSIG to additional if they are there */
+-		arcount = ldns_pkt_arcount(packet);
+-		if (ldns_pkt_tsig(packet)) {
+-			arcount++;
+-		}
+-		if (ldns_pkt_edns(packet)) {
+-			arcount++;
+-		}
+-		ldns_buffer_write_u16(buffer, arcount);
+-	}
+-	
+-	return ldns_buffer_status(buffer);
+-}
+-
+-void
+-compression_node_free(ldns_rbnode_t *node, void *arg)
+-{
+-	(void)arg; /* Yes, dear compiler, it is used */
+-	free((void *)node->key);
+-	LDNS_FREE(node);
+-}
+-
+-ldns_status
+-ldns_pkt2buffer_wire(ldns_buffer *buffer, const ldns_pkt *packet)
+-{
+-	ldns_rr_list *rr_list;
+-	uint16_t i;
+-
+-	/* edns tmp vars */
+-	ldns_rr *edns_rr;
+-	uint8_t edata[4];
+-
+-	ldns_rbtree_t *compression_data = ldns_rbtree_create((int (*)(const void *, const void *))strcasecmp);
+-	
+-	(void) ldns_hdr2buffer_wire(buffer, packet);
+-
+-	rr_list = ldns_pkt_question(packet);
+-	if (rr_list) {
+-		for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
+-			(void) ldns_rr2buffer_wire_compress(buffer, 
+-			             ldns_rr_list_rr(rr_list, i), LDNS_SECTION_QUESTION, compression_data);
+-		}
+-	}
+-	rr_list = ldns_pkt_answer(packet);
+-	if (rr_list) {
+-		for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
+-			(void) ldns_rr2buffer_wire_compress(buffer, 
+-			             ldns_rr_list_rr(rr_list, i), LDNS_SECTION_ANSWER, compression_data);
+-		}
+-	}
+-	rr_list = ldns_pkt_authority(packet);
+-	if (rr_list) {
+-		for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
+-			(void) ldns_rr2buffer_wire_compress(buffer, 
+-			             ldns_rr_list_rr(rr_list, i), LDNS_SECTION_AUTHORITY, compression_data);
+-		}
+-	}
+-	rr_list = ldns_pkt_additional(packet);
+-	if (rr_list) {
+-		for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
+-			(void) ldns_rr2buffer_wire_compress(buffer, 
+-			             ldns_rr_list_rr(rr_list, i), LDNS_SECTION_ADDITIONAL, compression_data);
+-		}
+-	}
+-	
+-	/* add EDNS to additional if it is needed */
+-	if (ldns_pkt_edns(packet)) {
+-		edns_rr = ldns_rr_new();
+-		if(!edns_rr) return LDNS_STATUS_MEM_ERR;
+-		ldns_rr_set_owner(edns_rr,
+-				ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, "."));
+-		ldns_rr_set_type(edns_rr, LDNS_RR_TYPE_OPT);
+-		ldns_rr_set_class(edns_rr, ldns_pkt_edns_udp_size(packet));
+-		edata[0] = ldns_pkt_edns_extended_rcode(packet);
+-		edata[1] = ldns_pkt_edns_version(packet);
+-		ldns_write_uint16(&edata[2], ldns_pkt_edns_z(packet));
+-		ldns_rr_set_ttl(edns_rr, ldns_read_uint32(edata));
+-		/* don't forget to add the edns rdata (if any) */
+-		if (packet->_edns_data)
+-			ldns_rr_push_rdf (edns_rr, packet->_edns_data);
+-		(void)ldns_rr2buffer_wire_compress(buffer, edns_rr, LDNS_SECTION_ADDITIONAL, compression_data);
+-		/* take the edns rdata back out of the rr before we free rr */
+-		if (packet->_edns_data)
+-			(void)ldns_rr_pop_rdf (edns_rr);
+-		ldns_rr_free(edns_rr);
+-	}
+-	
+-	/* add TSIG to additional if it is there */
+-	if (ldns_pkt_tsig(packet)) {
+-		(void) ldns_rr2buffer_wire_compress(buffer,
+-		                           ldns_pkt_tsig(packet), LDNS_SECTION_ADDITIONAL, compression_data);
+-	}
+-
+-	ldns_traverse_postorder(compression_data,compression_node_free,NULL);
+-	ldns_rbtree_free(compression_data);
+-
+-	return LDNS_STATUS_OK;
+-}
+-
+-ldns_status
+-ldns_rdf2wire(uint8_t **dest, const ldns_rdf *rdf, size_t *result_size)
+-{
+-	ldns_buffer *buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN);
+-	ldns_status status;
+-	*result_size = 0;
+-	*dest = NULL;
+-	if(!buffer) return LDNS_STATUS_MEM_ERR;
+-	
+-	status = ldns_rdf2buffer_wire(buffer, rdf);
+-	if (status == LDNS_STATUS_OK) {
+-		*result_size =  ldns_buffer_position(buffer);
+-		*dest = (uint8_t *) ldns_buffer_export(buffer);
+-	}
+-	ldns_buffer_free(buffer);
+-	return status;
+-}
+-
+-ldns_status
+-ldns_rr2wire(uint8_t **dest, const ldns_rr *rr, int section, size_t *result_size)
+-{
+-	ldns_buffer *buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN);
+-	ldns_status status;
+-	*result_size = 0;
+-	*dest = NULL;
+-	if(!buffer) return LDNS_STATUS_MEM_ERR;
+-	
+-	status = ldns_rr2buffer_wire(buffer, rr, section);
+-	if (status == LDNS_STATUS_OK) {
+-		*result_size =  ldns_buffer_position(buffer);
+-		*dest = (uint8_t *) ldns_buffer_export(buffer);
+-	}
+-	ldns_buffer_free(buffer);
+-	return status;
+-}
+-
+-ldns_status
+-ldns_pkt2wire(uint8_t **dest, const ldns_pkt *packet, size_t *result_size)
+-{
+-	ldns_buffer *buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN);
+-	ldns_status status;
+-	*result_size = 0;
+-	*dest = NULL;
+-	if(!buffer) return LDNS_STATUS_MEM_ERR;
+-	
+-	status = ldns_pkt2buffer_wire(buffer, packet);
+-	if (status == LDNS_STATUS_OK) {
+-		*result_size =  ldns_buffer_position(buffer);
+-		*dest = (uint8_t *) ldns_buffer_export(buffer);
+-	}
+-	ldns_buffer_free(buffer);
+-	return status;
+-}
+diff --git a/src/ldns/keys.c b/src/ldns/keys.c
+deleted file mode 100644
+index 8b43821..0000000
+--- a/src/ldns/keys.c
++++ /dev/null
+@@ -1,1726 +0,0 @@
+-/*
+- * keys.c handle private keys for use in DNSSEC
+- *
+- * This module should hide some of the openSSL complexities
+- * and give a general interface for private keys and hmac
+- * handling
+- *
+- * (c) NLnet Labs, 2004-2006
+- *
+- * See the file LICENSE for the license
+- */
+-
+-#include <ldns/config.h>
+-
+-#include <ldns/ldns.h>
+-
+-#ifdef HAVE_SSL
+-#include <openssl/ssl.h>
+-#include <openssl/engine.h>
+-#include <openssl/rand.h>
+-#endif /* HAVE_SSL */
+-
+-ldns_lookup_table ldns_signing_algorithms[] = {
+-        { LDNS_SIGN_RSAMD5, "RSAMD5" },
+-        { LDNS_SIGN_RSASHA1, "RSASHA1" },
+-        { LDNS_SIGN_RSASHA1_NSEC3, "RSASHA1-NSEC3-SHA1" },
+-#ifdef USE_SHA2
+-        { LDNS_SIGN_RSASHA256, "RSASHA256" },
+-        { LDNS_SIGN_RSASHA512, "RSASHA512" },
+-#endif
+-#ifdef USE_GOST
+-        { LDNS_SIGN_ECC_GOST, "ECC-GOST" },
+-#endif
+-#ifdef USE_ECDSA
+-        { LDNS_SIGN_ECDSAP256SHA256, "ECDSAP256SHA256" },
+-        { LDNS_SIGN_ECDSAP384SHA384, "ECDSAP384SHA384" },
+-#endif
+-        { LDNS_SIGN_DSA, "DSA" },
+-        { LDNS_SIGN_DSA_NSEC3, "DSA-NSEC3-SHA1" },
+-        { LDNS_SIGN_HMACMD5, "hmac-md5.sig-alg.reg.int" },
+-        { LDNS_SIGN_HMACSHA1, "hmac-sha1" },
+-        { LDNS_SIGN_HMACSHA256, "hmac-sha256" },
+-        { 0, NULL }
+-};
+-
+-ldns_key_list *
+-ldns_key_list_new(void)
+-{
+-	ldns_key_list *key_list = LDNS_MALLOC(ldns_key_list);
+-	if (!key_list) {
+-		return NULL;
+-	} else {
+-		key_list->_key_count = 0;
+-		key_list->_keys = NULL;
+-		return key_list;
+-	}
+-}
+-
+-ldns_key *
+-ldns_key_new(void)
+-{
+-	ldns_key *newkey;
+-
+-	newkey = LDNS_MALLOC(ldns_key);
+-	if (!newkey) {
+-		return NULL;
+-	} else {
+-		/* some defaults - not sure wether to do this */
+-		ldns_key_set_use(newkey, true);
+-		ldns_key_set_flags(newkey, LDNS_KEY_ZONE_KEY);
+-		ldns_key_set_origttl(newkey, 0);
+-		ldns_key_set_keytag(newkey, 0);
+-		ldns_key_set_inception(newkey, 0);
+-		ldns_key_set_expiration(newkey, 0);
+-		ldns_key_set_pubkey_owner(newkey, NULL);
+-#ifdef HAVE_SSL
+-		ldns_key_set_evp_key(newkey, NULL);
+-#endif /* HAVE_SSL */
+-		ldns_key_set_hmac_key(newkey, NULL);
+-		ldns_key_set_external_key(newkey, NULL);
+-		return newkey;
+-	}
+-}
+-
+-ldns_status
+-ldns_key_new_frm_fp(ldns_key **k, FILE *fp)
+-{
+-	return ldns_key_new_frm_fp_l(k, fp, NULL);
+-}
+-
+-#ifdef HAVE_SSL
+-ldns_status
+-ldns_key_new_frm_engine(ldns_key **key, ENGINE *e, char *key_id, ldns_algorithm alg)
+-{
+-	ldns_key *k;
+-
+-	k = ldns_key_new();
+-        if(!k) return LDNS_STATUS_MEM_ERR;
+-#ifndef S_SPLINT_S
+-	k->_key.key = ENGINE_load_private_key(e, key_id, UI_OpenSSL(), NULL);
+-        if(!k->_key.key) {
+-                ldns_key_free(k);
+-                return LDNS_STATUS_ERR;
+-        }
+-	ldns_key_set_algorithm(k, (ldns_signing_algorithm) alg);
+-	if (!k->_key.key) {
+-                ldns_key_free(k);
+-		return LDNS_STATUS_ENGINE_KEY_NOT_LOADED;
+-	} 
+-#endif /* splint */
+-	*key = k;
+-	return LDNS_STATUS_OK;
+-}
+-#endif
+-
+-#ifdef USE_GOST
+-/** store GOST engine reference loaded into OpenSSL library */
+-ENGINE* ldns_gost_engine = NULL;
+-
+-int
+-ldns_key_EVP_load_gost_id(void)
+-{
+-	static int gost_id = 0;
+-	const EVP_PKEY_ASN1_METHOD* meth;
+-	ENGINE* e;
+-
+-	if(gost_id) return gost_id;
+-
+-	/* see if configuration loaded gost implementation from other engine*/
+-	meth = EVP_PKEY_asn1_find_str(NULL, "gost2001", -1);
+-	if(meth) {
+-		EVP_PKEY_asn1_get0_info(&gost_id, NULL, NULL, NULL, NULL, meth);
+-		return gost_id;
+-	}
+-
+-	/* see if engine can be loaded already */
+-	e = ENGINE_by_id("gost");
+-	if(!e) {
+-		/* load it ourself, in case statically linked */
+-		ENGINE_load_builtin_engines();
+-		ENGINE_load_dynamic();
+-		e = ENGINE_by_id("gost");
+-	}
+-	if(!e) {
+-		/* no gost engine in openssl */
+-		return 0;
+-	}
+-	if(!ENGINE_set_default(e, ENGINE_METHOD_ALL)) {
+-		ENGINE_finish(e);
+-		ENGINE_free(e);
+-		return 0;
+-	}
+-
+-	meth = EVP_PKEY_asn1_find_str(&e, "gost2001", -1);
+-	if(!meth) {
+-		/* algo not found */
+-		ENGINE_finish(e);
+-		ENGINE_free(e);
+-		return 0;
+-	}
+-        /* Note: do not ENGINE_finish and ENGINE_free the acquired engine
+-         * on some platforms this frees up the meth and unloads gost stuff */
+-        ldns_gost_engine = e;
+-	
+-	EVP_PKEY_asn1_get0_info(&gost_id, NULL, NULL, NULL, NULL, meth);
+-	return gost_id;
+-} 
+-
+-void ldns_key_EVP_unload_gost(void)
+-{
+-        if(ldns_gost_engine) {
+-                ENGINE_finish(ldns_gost_engine);
+-                ENGINE_free(ldns_gost_engine);
+-                ldns_gost_engine = NULL;
+-        }
+-}
+-
+-/** read GOST private key */
+-static EVP_PKEY*
+-ldns_key_new_frm_fp_gost_l(FILE* fp, int* line_nr)
+-{
+-	char token[16384];
+-	const unsigned char* pp;
+-	int gost_id;
+-	EVP_PKEY* pkey;
+-	ldns_rdf* b64rdf = NULL;
+-
+-	gost_id = ldns_key_EVP_load_gost_id();
+-	if(!gost_id)
+-		return NULL;
+-
+-	if (ldns_fget_keyword_data_l(fp, "GostAsn1", ": ", token, "\n", 
+-		sizeof(token), line_nr) == -1)
+-		return NULL;
+-	while(strlen(token) < 96) {
+-		/* read more b64 from the file, b64 split on multiple lines */
+-		if(ldns_fget_token_l(fp, token+strlen(token), "\n",
+-			sizeof(token)-strlen(token), line_nr) == -1)
+-			return NULL;
+-	}
+-	if(ldns_str2rdf_b64(&b64rdf, token) != LDNS_STATUS_OK)
+-		return NULL;
+-	pp = (unsigned char*)ldns_rdf_data(b64rdf);
+-	pkey = d2i_PrivateKey(gost_id, NULL, &pp, (int)ldns_rdf_size(b64rdf));
+-	ldns_rdf_deep_free(b64rdf);
+-	return pkey;
+-}
+-#endif
+-
+-#ifdef USE_ECDSA
+-/** calculate public key from private key */
+-static int
+-ldns_EC_KEY_calc_public(EC_KEY* ec)
+-{
+-        EC_POINT* pub_key;
+-        const EC_GROUP* group;
+-        group = EC_KEY_get0_group(ec);
+-        pub_key = EC_POINT_new(group);
+-        if(!pub_key) return 0;
+-        if(!EC_POINT_copy(pub_key, EC_GROUP_get0_generator(group))) {
+-                EC_POINT_free(pub_key);
+-                return 0;
+-        }
+-        if(!EC_POINT_mul(group, pub_key, EC_KEY_get0_private_key(ec),
+-                NULL, NULL, NULL)) {
+-                EC_POINT_free(pub_key);
+-                return 0;
+-        }
+-        if(EC_KEY_set_public_key(ec, pub_key) == 0) {
+-                EC_POINT_free(pub_key);
+-                return 0;
+-        }
+-        EC_POINT_free(pub_key);
+-        return 1;
+-}
+-
+-/** read ECDSA private key */
+-static EVP_PKEY*
+-ldns_key_new_frm_fp_ecdsa_l(FILE* fp, ldns_algorithm alg, int* line_nr)
+-{
+-	char token[16384];
+-        ldns_rdf* b64rdf = NULL;
+-        unsigned char* pp;
+-        BIGNUM* bn;
+-        EVP_PKEY* evp_key;
+-        EC_KEY* ec;
+-	if (ldns_fget_keyword_data_l(fp, "PrivateKey", ": ", token, "\n", 
+-		sizeof(token), line_nr) == -1)
+-		return NULL;
+-	if(ldns_str2rdf_b64(&b64rdf, token) != LDNS_STATUS_OK)
+-		return NULL;
+-        pp = (unsigned char*)ldns_rdf_data(b64rdf);
+-
+-        if(alg == LDNS_ECDSAP256SHA256)
+-                ec = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
+-        else if(alg == LDNS_ECDSAP384SHA384)
+-                ec = EC_KEY_new_by_curve_name(NID_secp384r1);
+-        else    ec = NULL;
+-        if(!ec) {
+-	        ldns_rdf_deep_free(b64rdf);
+-                return NULL;
+-        }
+-	bn = BN_bin2bn(pp, (int)ldns_rdf_size(b64rdf), NULL);
+-	ldns_rdf_deep_free(b64rdf);
+-        if(!bn) {
+-                EC_KEY_free(ec);
+-                return NULL;
+-        }
+-        EC_KEY_set_private_key(ec, bn);
+-        BN_free(bn);
+-        if(!ldns_EC_KEY_calc_public(ec)) {
+-                EC_KEY_free(ec);
+-                return NULL;
+-        }
+-
+-        evp_key = EVP_PKEY_new();
+-        if(!evp_key) {
+-                EC_KEY_free(ec);
+-                return NULL;
+-        }
+-        if (!EVP_PKEY_assign_EC_KEY(evp_key, ec)) {
+-		EVP_PKEY_free(evp_key);
+-                EC_KEY_free(ec);
+-                return NULL;
+-	}
+-        return evp_key;
+-}
+-#endif
+-	
+-ldns_status
+-ldns_key_new_frm_fp_l(ldns_key **key, FILE *fp, int *line_nr)
+-{
+-	ldns_key *k;
+-	char *d;
+-	ldns_signing_algorithm alg;
+-	ldns_rr *key_rr;
+-#ifdef HAVE_SSL
+-	RSA *rsa;
+-	DSA *dsa;
+-	unsigned char *hmac;
+-	size_t hmac_size;
+-#endif /* HAVE_SSL */
+-
+-	k = ldns_key_new();
+-
+-	d = LDNS_XMALLOC(char, LDNS_MAX_LINELEN);
+-	if (!k || !d) {
+-                ldns_key_free(k);
+-                LDNS_FREE(d);
+-		return LDNS_STATUS_MEM_ERR;
+-	}
+-
+-	alg = 0;
+-
+-	/* the file is highly structured. Do this in sequence */
+-	/* RSA:
+-	 * Private-key-format: v1.x.
+- 	 * Algorithm: 1 (RSA)
+-
+-	 */
+-	/* get the key format version number */
+-	if (ldns_fget_keyword_data_l(fp, "Private-key-format", ": ", d, "\n",
+-				LDNS_MAX_LINELEN, line_nr) == -1) {
+-		/* no version information */
+-                ldns_key_free(k);
+-                LDNS_FREE(d);
+-		return LDNS_STATUS_SYNTAX_ERR;
+-	}
+-	if (strncmp(d, "v1.", 3) != 0) {
+-                ldns_key_free(k);
+-                LDNS_FREE(d);
+-		return LDNS_STATUS_SYNTAX_VERSION_ERR;
+-	}
+-
+-	/* get the algorithm type, our file function strip ( ) so there are
+-	 * not in the return string! */
+-	if (ldns_fget_keyword_data_l(fp, "Algorithm", ": ", d, "\n",
+-				LDNS_MAX_LINELEN, line_nr) == -1) {
+-		/* no alg information */
+-                ldns_key_free(k);
+-                LDNS_FREE(d);
+-		return LDNS_STATUS_SYNTAX_ALG_ERR;
+-	}
+-
+-	if (strncmp(d, "1 RSA", 2) == 0) {
+-		alg = LDNS_SIGN_RSAMD5;
+-	}
+-	if (strncmp(d, "2 DH", 2) == 0) {
+-		alg = (ldns_signing_algorithm)LDNS_DH;
+-	}
+-	if (strncmp(d, "3 DSA", 2) == 0) {
+-		alg = LDNS_SIGN_DSA;
+-	}
+-	if (strncmp(d, "4 ECC", 2) == 0) {
+-		alg = (ldns_signing_algorithm)LDNS_ECC;
+-	}
+-	if (strncmp(d, "5 RSASHA1", 2) == 0) {
+-		alg = LDNS_SIGN_RSASHA1;
+-	}
+-	if (strncmp(d, "6 DSA", 2) == 0) {
+-		alg = LDNS_SIGN_DSA_NSEC3;
+-	}
+-	if (strncmp(d, "7 RSASHA1", 2) == 0) {
+-		alg = LDNS_SIGN_RSASHA1_NSEC3;
+-	}
+-
+-	if (strncmp(d, "8 RSASHA256", 2) == 0) {
+-#ifdef USE_SHA2
+-		alg = LDNS_SIGN_RSASHA256;
+-#else
+-# ifdef STDERR_MSGS
+-		fprintf(stderr, "Warning: SHA256 not compiled into this ");
+-		fprintf(stderr, "version of ldns\n");
+-# endif
+-#endif
+-	}
+-	if (strncmp(d, "10 RSASHA512", 3) == 0) {
+-#ifdef USE_SHA2
+-		alg = LDNS_SIGN_RSASHA512;
+-#else
+-# ifdef STDERR_MSGS
+-		fprintf(stderr, "Warning: SHA512 not compiled into this ");
+-		fprintf(stderr, "version of ldns\n");
+-# endif
+-#endif
+-	}
+-	if (strncmp(d, "12 ECC-GOST", 3) == 0) {
+-#ifdef USE_GOST
+-		alg = LDNS_SIGN_ECC_GOST;
+-#else
+-# ifdef STDERR_MSGS
+-		fprintf(stderr, "Warning: ECC-GOST not compiled into this ");
+-		fprintf(stderr, "version of ldns, use --enable-gost\n");
+-# endif
+-#endif
+-	}
+-	if (strncmp(d, "13 ECDSAP256SHA256", 3) == 0) {
+-#ifdef USE_ECDSA
+-                alg = LDNS_SIGN_ECDSAP256SHA256;
+-#else
+-# ifdef STDERR_MSGS
+-		fprintf(stderr, "Warning: ECDSA not compiled into this ");
+-		fprintf(stderr, "version of ldns, use --enable-ecdsa\n");
+-# endif
+-#endif
+-        }
+-	if (strncmp(d, "14 ECDSAP384SHA384", 3) == 0) {
+-#ifdef USE_ECDSA
+-                alg = LDNS_SIGN_ECDSAP384SHA384;
+-#else
+-# ifdef STDERR_MSGS
+-		fprintf(stderr, "Warning: ECDSA not compiled into this ");
+-		fprintf(stderr, "version of ldns, use --enable-ecdsa\n");
+-# endif
+-#endif
+-        }
+-	if (strncmp(d, "157 HMAC-MD5", 4) == 0) {
+-		alg = LDNS_SIGN_HMACMD5;
+-	}
+-	if (strncmp(d, "158 HMAC-SHA1", 4) == 0) {
+-		alg = LDNS_SIGN_HMACSHA1;
+-	}
+-	if (strncmp(d, "159 HMAC-SHA256", 4) == 0) {
+-		alg = LDNS_SIGN_HMACSHA256;
+-	}
+-
+-	LDNS_FREE(d);
+-
+-	switch(alg) {
+-		case LDNS_SIGN_RSAMD5:
+-		case LDNS_SIGN_RSASHA1:
+-		case LDNS_SIGN_RSASHA1_NSEC3:
+-#ifdef USE_SHA2
+-		case LDNS_SIGN_RSASHA256:
+-		case LDNS_SIGN_RSASHA512:
+-#endif
+-			ldns_key_set_algorithm(k, alg);
+-#ifdef HAVE_SSL
+-			rsa = ldns_key_new_frm_fp_rsa_l(fp, line_nr);
+-			if (!rsa) {
+-				ldns_key_free(k);
+-				return LDNS_STATUS_ERR;
+-			}
+-			ldns_key_assign_rsa_key(k, rsa);
+-#endif /* HAVE_SSL */
+-			break;
+-		case LDNS_SIGN_DSA:
+-		case LDNS_SIGN_DSA_NSEC3:
+-			ldns_key_set_algorithm(k, alg);
+-#ifdef HAVE_SSL
+-			dsa = ldns_key_new_frm_fp_dsa_l(fp, line_nr);
+-			if (!dsa) {
+-				ldns_key_free(k);
+-				return LDNS_STATUS_ERR;
+-			}
+-			ldns_key_assign_dsa_key(k, dsa);
+-#endif /* HAVE_SSL */
+-			break;
+-		case LDNS_SIGN_HMACMD5:
+-		case LDNS_SIGN_HMACSHA1:
+-		case LDNS_SIGN_HMACSHA256:
+-			ldns_key_set_algorithm(k, alg);
+-#ifdef HAVE_SSL
+-			hmac = ldns_key_new_frm_fp_hmac_l(fp, line_nr, &hmac_size);
+-			if (!hmac) {
+-				ldns_key_free(k);
+-				return LDNS_STATUS_ERR;
+-			}
+-			ldns_key_set_hmac_size(k, hmac_size);
+-			ldns_key_set_hmac_key(k, hmac);
+-#endif /* HAVE_SSL */
+-			break;
+-		case LDNS_SIGN_ECC_GOST:
+-			ldns_key_set_algorithm(k, alg);
+-#if defined(HAVE_SSL) && defined(USE_GOST)
+-                        if(!ldns_key_EVP_load_gost_id()) {
+-				ldns_key_free(k);
+-                                return LDNS_STATUS_CRYPTO_ALGO_NOT_IMPL;
+-                        }
+-			ldns_key_set_evp_key(k, 
+-				ldns_key_new_frm_fp_gost_l(fp, line_nr));
+-#ifndef S_SPLINT_S
+-			if(!k->_key.key) {
+-				ldns_key_free(k);
+-				return LDNS_STATUS_ERR;
+-			}
+-#endif /* splint */
+-#endif
+-			break;
+-#ifdef USE_ECDSA
+-               case LDNS_SIGN_ECDSAP256SHA256:
+-               case LDNS_SIGN_ECDSAP384SHA384:
+-                        ldns_key_set_algorithm(k, alg);
+-                        ldns_key_set_evp_key(k,
+-                                ldns_key_new_frm_fp_ecdsa_l(fp, (ldns_algorithm)alg, line_nr));
+-#ifndef S_SPLINT_S
+-			if(!k->_key.key) {
+-				ldns_key_free(k);
+-				return LDNS_STATUS_ERR;
+-			}
+-#endif /* splint */
+-			break;
+-#endif
+-		default:
+-			ldns_key_free(k);
+-			return LDNS_STATUS_SYNTAX_ALG_ERR;
+-	}
+-	key_rr = ldns_key2rr(k);
+-	ldns_key_set_keytag(k, ldns_calc_keytag(key_rr));
+-	ldns_rr_free(key_rr);
+-
+-	if (key) {
+-		*key = k;
+-		return LDNS_STATUS_OK;
+-	}
+-	ldns_key_free(k);
+-	return LDNS_STATUS_ERR;
+-}
+-
+-#ifdef HAVE_SSL
+-RSA *
+-ldns_key_new_frm_fp_rsa(FILE *f)
+-{
+-	return ldns_key_new_frm_fp_rsa_l(f, NULL);
+-}
+-
+-RSA *
+-ldns_key_new_frm_fp_rsa_l(FILE *f, int *line_nr)
+-{
+-	/* we parse
+- 	 * Modulus:
+- 	 * PublicExponent:
+- 	 * PrivateExponent:
+- 	 * Prime1:
+- 	 * Prime2:
+- 	 * Exponent1:
+- 	 * Exponent2:
+- 	 * Coefficient:
+-	 *
+-	 * man 3 RSA:
+-	 *
+-	 * struct
+-         *     {
+-         *     BIGNUM *n;              // public modulus
+-         *     BIGNUM *e;              // public exponent
+-         *     BIGNUM *d;              // private exponent
+-         *     BIGNUM *p;              // secret prime factor
+-         *     BIGNUM *q;              // secret prime factor
+-         *     BIGNUM *dmp1;           // d mod (p-1)
+-         *     BIGNUM *dmq1;           // d mod (q-1)
+-         *     BIGNUM *iqmp;           // q^-1 mod p
+-         *     // ...
+-	 *
+-	 */
+-	char *d;
+-	RSA *rsa;
+-	uint8_t *buf;
+-	int i;
+-
+-	d = LDNS_XMALLOC(char, LDNS_MAX_LINELEN);
+-	buf = LDNS_XMALLOC(uint8_t, LDNS_MAX_LINELEN);
+-	rsa = RSA_new();
+-	if (!d || !rsa || !buf) {
+-                goto error;
+-	}
+-
+-	/* I could use functions again, but that seems an overkill,
+-	 * allthough this also looks tedious
+-	 */
+-
+-	/* Modules, rsa->n */
+-	if (ldns_fget_keyword_data_l(f, "Modulus", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) {
+-		goto error;
+-	}
+-	i = ldns_b64_pton((const char*)d, buf, ldns_b64_ntop_calculate_size(strlen(d)));
+-#ifndef S_SPLINT_S
+-	rsa->n = BN_bin2bn((const char unsigned*)buf, i, NULL);
+-	if (!rsa->n) {
+-		goto error;
+-	}
+-
+-	/* PublicExponent, rsa->e */
+-	if (ldns_fget_keyword_data_l(f, "PublicExponent", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) {
+-		goto error;
+-	}
+-	i = ldns_b64_pton((const char*)d, buf, ldns_b64_ntop_calculate_size(strlen(d)));
+-	rsa->e = BN_bin2bn((const char unsigned*)buf, i, NULL);
+-	if (!rsa->e) {
+-		goto error;
+-	}
+-
+-	/* PrivateExponent, rsa->d */
+-	if (ldns_fget_keyword_data_l(f, "PrivateExponent", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) {
+-		goto error;
+-	}
+-	i = ldns_b64_pton((const char*)d, buf, ldns_b64_ntop_calculate_size(strlen(d)));
+-	rsa->d = BN_bin2bn((const char unsigned*)buf, i, NULL);
+-	if (!rsa->d) {
+-		goto error;
+-	}
+-
+-	/* Prime1, rsa->p */
+-	if (ldns_fget_keyword_data_l(f, "Prime1", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) {
+-		goto error;
+-	}
+-	i = ldns_b64_pton((const char*)d, buf, ldns_b64_ntop_calculate_size(strlen(d)));
+-	rsa->p = BN_bin2bn((const char unsigned*)buf, i, NULL);
+-	if (!rsa->p) {
+-		goto error;
+-	}
+-
+-	/* Prime2, rsa->q */
+-	if (ldns_fget_keyword_data_l(f, "Prime2", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) {
+-		goto error;
+-	}
+-	i = ldns_b64_pton((const char*)d, buf, ldns_b64_ntop_calculate_size(strlen(d)));
+-	rsa->q = BN_bin2bn((const char unsigned*)buf, i, NULL);
+-	if (!rsa->q) {
+-		goto error;
+-	}
+-
+-	/* Exponent1, rsa->dmp1 */
+-	if (ldns_fget_keyword_data_l(f, "Exponent1", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) {
+-		goto error;
+-	}
+-	i = ldns_b64_pton((const char*)d, buf, ldns_b64_ntop_calculate_size(strlen(d)));
+-	rsa->dmp1 = BN_bin2bn((const char unsigned*)buf, i, NULL);
+-	if (!rsa->dmp1) {
+-		goto error;
+-	}
+-
+-	/* Exponent2, rsa->dmq1 */
+-	if (ldns_fget_keyword_data_l(f, "Exponent2", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) {
+-		goto error;
+-	}
+-	i = ldns_b64_pton((const char*)d, buf, ldns_b64_ntop_calculate_size(strlen(d)));
+-	rsa->dmq1 = BN_bin2bn((const char unsigned*)buf, i, NULL);
+-	if (!rsa->dmq1) {
+-		goto error;
+-	}
+-
+-	/* Coefficient, rsa->iqmp */
+-	if (ldns_fget_keyword_data_l(f, "Coefficient", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) {
+-		goto error;
+-	}
+-	i = ldns_b64_pton((const char*)d, buf, ldns_b64_ntop_calculate_size(strlen(d)));
+-	rsa->iqmp = BN_bin2bn((const char unsigned*)buf, i, NULL);
+-	if (!rsa->iqmp) {
+-		goto error;
+-	}
+-#endif /* splint */
+-
+-	LDNS_FREE(buf);
+-	LDNS_FREE(d);
+-	return rsa;
+-
+-error:
+-	RSA_free(rsa);
+-	LDNS_FREE(d);
+-	LDNS_FREE(buf);
+-	return NULL;
+-}
+-
+-DSA *
+-ldns_key_new_frm_fp_dsa(FILE *f)
+-{
+-	return ldns_key_new_frm_fp_dsa_l(f, NULL);
+-}
+-
+-DSA *
+-ldns_key_new_frm_fp_dsa_l(FILE *f, ATTR_UNUSED(int *line_nr))
+-{
+-	int i;
+-	char *d;
+-	DSA *dsa;
+-	uint8_t *buf;
+-
+-	d = LDNS_XMALLOC(char, LDNS_MAX_LINELEN);
+-	buf = LDNS_XMALLOC(uint8_t, LDNS_MAX_LINELEN);
+-	dsa = DSA_new();
+-	if (!d || !dsa || !buf) {
+-                goto error;
+-	}
+-
+-	/* the line parser removes the () from the input... */
+-
+-	/* Prime, dsa->p */
+-	if (ldns_fget_keyword_data_l(f, "Primep", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) {
+-		goto error;
+-	}
+-	i = ldns_b64_pton((const char*)d, buf, ldns_b64_ntop_calculate_size(strlen(d)));
+-#ifndef S_SPLINT_S
+-	dsa->p = BN_bin2bn((const char unsigned*)buf, i, NULL);
+-	if (!dsa->p) {
+-		goto error;
+-	}
+-
+-	/* Subprime, dsa->q */
+-	if (ldns_fget_keyword_data_l(f, "Subprimeq", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) {
+-		goto error;
+-	}
+-	i = ldns_b64_pton((const char*)d, buf, ldns_b64_ntop_calculate_size(strlen(d)));
+-	dsa->q = BN_bin2bn((const char unsigned*)buf, i, NULL);
+-	if (!dsa->q) {
+-		goto error;
+-	}
+-
+-	/* Base, dsa->g */
+-	if (ldns_fget_keyword_data_l(f, "Baseg", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) {
+-		goto error;
+-	}
+-	i = ldns_b64_pton((const char*)d, buf, ldns_b64_ntop_calculate_size(strlen(d)));
+-	dsa->g = BN_bin2bn((const char unsigned*)buf, i, NULL);
+-	if (!dsa->g) {
+-		goto error;
+-	}
+-
+-	/* Private key, dsa->priv_key */
+-	if (ldns_fget_keyword_data_l(f, "Private_valuex", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) {
+-		goto error;
+-	}
+-	i = ldns_b64_pton((const char*)d, buf, ldns_b64_ntop_calculate_size(strlen(d)));
+-	dsa->priv_key = BN_bin2bn((const char unsigned*)buf, i, NULL);
+-	if (!dsa->priv_key) {
+-		goto error;
+-	}
+-
+-	/* Public key, dsa->priv_key */
+-	if (ldns_fget_keyword_data_l(f, "Public_valuey", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) {
+-		goto error;
+-	}
+-	i = ldns_b64_pton((const char*)d, buf, ldns_b64_ntop_calculate_size(strlen(d)));
+-	dsa->pub_key = BN_bin2bn((const char unsigned*)buf, i, NULL);
+-	if (!dsa->pub_key) {
+-		goto error;
+-	}
+-#endif /* splint */
+-
+-	LDNS_FREE(buf);
+-	LDNS_FREE(d);
+-
+-	return dsa;
+-
+-error:
+-	LDNS_FREE(d);
+-	LDNS_FREE(buf);
+-        DSA_free(dsa);
+-	return NULL;
+-}
+-
+-unsigned char *
+-ldns_key_new_frm_fp_hmac(FILE *f, size_t *hmac_size)
+-{
+-	return ldns_key_new_frm_fp_hmac_l(f, NULL, hmac_size);
+-}
+-
+-unsigned char *
+-ldns_key_new_frm_fp_hmac_l( FILE *f
+-			  , ATTR_UNUSED(int *line_nr)
+-			  , size_t *hmac_size
+-			  )
+-{
+-	size_t i, bufsz;
+-	char d[LDNS_MAX_LINELEN];
+-	unsigned char *buf = NULL;
+-
+-	if (ldns_fget_keyword_data_l(f, "Key", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) {
+-		goto error;
+-	}
+-	bufsz = ldns_b64_ntop_calculate_size(strlen(d));
+-	buf = LDNS_XMALLOC(unsigned char, bufsz);
+-	i = (size_t) ldns_b64_pton((const char*)d, buf, bufsz);
+-
+-	*hmac_size = i;
+-	return buf;
+-
+-	error:
+-	LDNS_FREE(buf);
+-	*hmac_size = 0;
+-	return NULL;
+-}
+-#endif /* HAVE_SSL */
+-
+-#ifdef USE_GOST
+-static EVP_PKEY*
+-ldns_gen_gost_key(void)
+-{
+-	EVP_PKEY_CTX* ctx;
+-	EVP_PKEY* p = NULL;
+-	int gost_id = ldns_key_EVP_load_gost_id();
+-	if(!gost_id)
+-		return NULL;
+-	ctx = EVP_PKEY_CTX_new_id(gost_id, NULL);
+-	if(!ctx) {
+-		/* the id should be available now */
+-		return NULL;
+-	}
+-	if(EVP_PKEY_CTX_ctrl_str(ctx, "paramset", "A") <= 0) {
+-		/* cannot set paramset */
+-		EVP_PKEY_CTX_free(ctx);
+-		return NULL;
+-	}
+-
+-	if(EVP_PKEY_keygen_init(ctx) <= 0) {
+-		EVP_PKEY_CTX_free(ctx);
+-		return NULL;
+-	}
+-	if(EVP_PKEY_keygen(ctx, &p) <= 0) {
+-		EVP_PKEY_free(p);
+-		EVP_PKEY_CTX_free(ctx);
+-		return NULL;
+-	}
+-	EVP_PKEY_CTX_free(ctx);
+-	return p;
+-}
+-#endif
+-
+-ldns_key *
+-ldns_key_new_frm_algorithm(ldns_signing_algorithm alg, uint16_t size)
+-{
+-	ldns_key *k;
+-#ifdef HAVE_SSL
+-	DSA *d;
+-	RSA *r;
+-#  ifdef USE_ECDSA
+-        EC_KEY *ec = NULL;
+-#  endif
+-#else
+-	int i;
+-	uint16_t offset = 0;
+-#endif
+-	unsigned char *hmac;
+-
+-	k = ldns_key_new();
+-	if (!k) {
+-		return NULL;
+-	}
+-	switch(alg) {
+-		case LDNS_SIGN_RSAMD5:
+-		case LDNS_SIGN_RSASHA1:
+-		case LDNS_SIGN_RSASHA1_NSEC3:
+-		case LDNS_SIGN_RSASHA256:
+-		case LDNS_SIGN_RSASHA512:
+-#ifdef HAVE_SSL
+-			r = RSA_generate_key((int)size, RSA_F4, NULL, NULL);
+-                        if(!r) {
+-				ldns_key_free(k);
+-				return NULL;
+-			}
+-			if (RSA_check_key(r) != 1) {
+-				ldns_key_free(k);
+-				return NULL;
+-			}
+-			ldns_key_set_rsa_key(k, r);
+-			RSA_free(r);
+-#endif /* HAVE_SSL */
+-			break;
+-		case LDNS_SIGN_DSA:
+-		case LDNS_SIGN_DSA_NSEC3:
+-#ifdef HAVE_SSL
+-			d = DSA_generate_parameters((int)size, NULL, 0, NULL, NULL, NULL, NULL);
+-			if (!d) {
+-				ldns_key_free(k);
+-				return NULL;
+-			}
+-			if (DSA_generate_key(d) != 1) {
+-				ldns_key_free(k);
+-				return NULL;
+-			}
+-			ldns_key_set_dsa_key(k, d);
+-			DSA_free(d);
+-#endif /* HAVE_SSL */
+-			break;
+-		case LDNS_SIGN_HMACMD5:
+-		case LDNS_SIGN_HMACSHA1:
+-		case LDNS_SIGN_HMACSHA256:
+-#ifdef HAVE_SSL
+-#ifndef S_SPLINT_S
+-			k->_key.key = NULL;
+-#endif /* splint */
+-#endif /* HAVE_SSL */
+-			size = size / 8;
+-			ldns_key_set_hmac_size(k, size);
+-
+-			hmac = LDNS_XMALLOC(unsigned char, size);
+-                        if(!hmac) {
+-				ldns_key_free(k);
+-				return NULL;
+-                        }
+-#ifdef HAVE_SSL
+-			if (RAND_bytes(hmac, (int) size) != 1) {
+-				LDNS_FREE(hmac);
+-				ldns_key_free(k);
+-				return NULL;
+-			}
+-#else
+-			while (offset + sizeof(i) < size) {
+-			  i = random();
+-			  memcpy(&hmac[offset], &i, sizeof(i));
+-			  offset += sizeof(i);
+-			}
+-			if (offset < size) {
+-			  i = random();
+-			  memcpy(&hmac[offset], &i, size - offset);
+-			}
+-#endif /* HAVE_SSL */
+-			ldns_key_set_hmac_key(k, hmac);
+-
+-			ldns_key_set_flags(k, 0);
+-			break;
+-		case LDNS_SIGN_ECC_GOST:
+-#if defined(HAVE_SSL) && defined(USE_GOST)
+-			ldns_key_set_evp_key(k, ldns_gen_gost_key());
+-#ifndef S_SPLINT_S
+-                        if(!k->_key.key) {
+-                                ldns_key_free(k);
+-                                return NULL;
+-                        }
+-#endif /* splint */
+-#else
+-			ldns_key_free(k);
+-			return NULL;
+-#endif /* HAVE_SSL and USE_GOST */
+-                        break;
+-                case LDNS_SIGN_ECDSAP256SHA256:
+-                case LDNS_SIGN_ECDSAP384SHA384:
+-#ifdef USE_ECDSA
+-                        if(alg == LDNS_SIGN_ECDSAP256SHA256)
+-                                ec = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
+-                        else if(alg == LDNS_SIGN_ECDSAP384SHA384)
+-                                ec = EC_KEY_new_by_curve_name(NID_secp384r1);
+-                        if(!ec) {
+-                                ldns_key_free(k);
+-                                return NULL;
+-                        }
+-                        if(!EC_KEY_generate_key(ec)) {
+-                                ldns_key_free(k);
+-                                EC_KEY_free(ec);
+-                                return NULL;
+-                        }
+-#ifndef S_SPLINT_S
+-                        k->_key.key = EVP_PKEY_new();
+-                        if(!k->_key.key) {
+-                                ldns_key_free(k);
+-                                EC_KEY_free(ec);
+-                                return NULL;
+-                        }
+-                        if (!EVP_PKEY_assign_EC_KEY(k->_key.key, ec)) {
+-                                ldns_key_free(k);
+-                                EC_KEY_free(ec);
+-                                return NULL;
+-			}
+-#endif /* splint */
+-#else
+-			ldns_key_free(k);
+-			return NULL;
+-#endif /* ECDSA */
+-			break;
+-	}
+-	ldns_key_set_algorithm(k, alg);
+-	return k;
+-}
+-
+-void
+-ldns_key_print(FILE *output, const ldns_key *k)
+-{
+-	char *str = ldns_key2str(k);
+-	if (str) {
+-                fprintf(output, "%s", str);
+-        } else {
+-                fprintf(output, "Unable to convert private key to string\n");
+-        }
+-        LDNS_FREE(str);
+-}
+-
+-
+-void
+-ldns_key_set_algorithm(ldns_key *k, ldns_signing_algorithm l)
+-{
+-	k->_alg = l;
+-}
+-
+-void
+-ldns_key_set_flags(ldns_key *k, uint16_t f)
+-{
+-	k->_extra.dnssec.flags = f;
+-}
+-
+-#ifdef HAVE_SSL
+-#ifndef S_SPLINT_S
+-void
+-ldns_key_set_evp_key(ldns_key *k, EVP_PKEY *e)
+-{
+-	k->_key.key = e;
+-}
+-
+-void
+-ldns_key_set_rsa_key(ldns_key *k, RSA *r)
+-{
+-	EVP_PKEY *key = EVP_PKEY_new();
+-	EVP_PKEY_set1_RSA(key, r);
+-	k->_key.key = key;
+-}
+-
+-void
+-ldns_key_set_dsa_key(ldns_key *k, DSA *d)
+-{
+-	EVP_PKEY *key = EVP_PKEY_new();
+-	EVP_PKEY_set1_DSA(key, d);
+-	k->_key.key  = key;
+-}
+-
+-void
+-ldns_key_assign_rsa_key(ldns_key *k, RSA *r)
+-{
+-	EVP_PKEY *key = EVP_PKEY_new();
+-	EVP_PKEY_assign_RSA(key, r);
+-	k->_key.key = key;
+-}
+-
+-void
+-ldns_key_assign_dsa_key(ldns_key *k, DSA *d)
+-{
+-	EVP_PKEY *key = EVP_PKEY_new();
+-	EVP_PKEY_assign_DSA(key, d);
+-	k->_key.key  = key;
+-}
+-#endif /* splint */
+-#endif /* HAVE_SSL */
+-
+-void
+-ldns_key_set_hmac_key(ldns_key *k, unsigned char *hmac)
+-{
+-	k->_key.hmac.key = hmac;
+-}
+-
+-void
+-ldns_key_set_hmac_size(ldns_key *k, size_t hmac_size)
+-{
+-	k->_key.hmac.size = hmac_size;
+-}
+-
+-void
+-ldns_key_set_external_key(ldns_key *k, void *external_key)
+-{
+-	k->_key.external_key = external_key;
+-}
+-
+-void
+-ldns_key_set_origttl(ldns_key *k, uint32_t t)
+-{
+-	k->_extra.dnssec.orig_ttl = t;
+-}
+-
+-void
+-ldns_key_set_inception(ldns_key *k, uint32_t i)
+-{
+-	k->_extra.dnssec.inception = i;
+-}
+-
+-void
+-ldns_key_set_expiration(ldns_key *k, uint32_t e)
+-{
+-	k->_extra.dnssec.expiration = e;
+-}
+-
+-void
+-ldns_key_set_pubkey_owner(ldns_key *k, ldns_rdf *r)
+-{
+-	k->_pubkey_owner = r;
+-}
+-
+-void
+-ldns_key_set_keytag(ldns_key *k, uint16_t tag)
+-{
+-	k->_extra.dnssec.keytag = tag;
+-}
+-
+-/* read */
+-size_t
+-ldns_key_list_key_count(const ldns_key_list *key_list)
+-{
+-	        return key_list->_key_count;
+-}       
+-
+-ldns_key *
+-ldns_key_list_key(const ldns_key_list *key, size_t nr)
+-{       
+-	if (nr < ldns_key_list_key_count(key)) {
+-		return key->_keys[nr];
+-	} else {
+-		return NULL;
+-	}
+-}
+-
+-ldns_signing_algorithm
+-ldns_key_algorithm(const ldns_key *k) 
+-{
+-	return k->_alg;
+-}
+-
+-void
+-ldns_key_set_use(ldns_key *k, bool v)
+-{
+-	if (k) {
+-		k->_use = v;
+-	}
+-}
+-
+-bool
+-ldns_key_use(const ldns_key *k)
+-{
+-	if (k) {
+-		return k->_use;
+-	}
+-	return false;
+-}
+-
+-#ifdef HAVE_SSL
+-#ifndef S_SPLINT_S
+-EVP_PKEY *
+-ldns_key_evp_key(const ldns_key *k)
+-{
+-	return k->_key.key;
+-}
+-
+-RSA *
+-ldns_key_rsa_key(const ldns_key *k)
+-{
+-	if (k->_key.key) {
+-		return EVP_PKEY_get1_RSA(k->_key.key);
+-	} else {
+-		return NULL;
+-	}
+-}
+-
+-DSA *
+-ldns_key_dsa_key(const ldns_key *k)
+-{
+-	if (k->_key.key) {
+-		return EVP_PKEY_get1_DSA(k->_key.key);
+-	} else {
+-		return NULL;
+-	}
+-}
+-#endif /* splint */
+-#endif /* HAVE_SSL */
+-
+-unsigned char *
+-ldns_key_hmac_key(const ldns_key *k)
+-{
+-	if (k->_key.hmac.key) {
+-		return k->_key.hmac.key;
+-	} else {
+-		return NULL;
+-	}
+-}
+-
+-size_t
+-ldns_key_hmac_size(const ldns_key *k)
+-{
+-	if (k->_key.hmac.size) {
+-		return k->_key.hmac.size;
+-	} else {
+-		return 0;
+-	}
+-}
+-
+-void *
+-ldns_key_external_key(const ldns_key *k)
+-{
+-	return k->_key.external_key;
+-}
+-
+-uint32_t
+-ldns_key_origttl(const ldns_key *k)
+-{
+-	return k->_extra.dnssec.orig_ttl;
+-}
+-
+-uint16_t
+-ldns_key_flags(const ldns_key *k)
+-{
+-	return k->_extra.dnssec.flags;
+-}
+-
+-uint32_t
+-ldns_key_inception(const ldns_key *k)
+-{
+-	return k->_extra.dnssec.inception;
+-}
+-
+-uint32_t
+-ldns_key_expiration(const ldns_key *k)
+-{
+-	return k->_extra.dnssec.expiration;
+-}
+-
+-uint16_t
+-ldns_key_keytag(const ldns_key *k)
+-{
+-	return k->_extra.dnssec.keytag;
+-}
+-
+-ldns_rdf *
+-ldns_key_pubkey_owner(const ldns_key *k)
+-{
+-	return k->_pubkey_owner;
+-}
+-
+-/* write */
+-void
+-ldns_key_list_set_use(ldns_key_list *keys, bool v)
+-{
+-	size_t i;
+-
+-	for (i = 0; i < ldns_key_list_key_count(keys); i++) {
+-		ldns_key_set_use(ldns_key_list_key(keys, i), v);
+-	}
+-}
+-
+-void            
+-ldns_key_list_set_key_count(ldns_key_list *key, size_t count)
+-{
+-	        key->_key_count = count;
+-}       
+-
+-bool             
+-ldns_key_list_push_key(ldns_key_list *key_list, ldns_key *key)
+-{       
+-        size_t key_count;
+-        ldns_key **keys;
+-
+-        key_count = ldns_key_list_key_count(key_list);
+-
+-        /* grow the array */
+-        keys = LDNS_XREALLOC(
+-                key_list->_keys, ldns_key *, key_count + 1);
+-        if (!keys) {
+-                return false;
+-        }
+-
+-        /* add the new member */
+-        key_list->_keys = keys;
+-        key_list->_keys[key_count] = key;
+-
+-        ldns_key_list_set_key_count(key_list, key_count + 1);
+-        return true;
+-}
+-
+-ldns_key *
+-ldns_key_list_pop_key(ldns_key_list *key_list)
+-{                               
+-        size_t key_count;
+-        ldns_key** a;
+-        ldns_key *pop;
+-
+-	if (!key_list) {
+-		return NULL;
+-	}
+-        
+-        key_count = ldns_key_list_key_count(key_list);
+-        if (key_count == 0) {
+-                return NULL;
+-        }       
+-        
+-        pop = ldns_key_list_key(key_list, key_count);
+-        
+-        /* shrink the array */
+-        a = LDNS_XREALLOC(key_list->_keys, ldns_key *, key_count - 1);
+-        if(a) {
+-                key_list->_keys = a;
+-        }
+-
+-        ldns_key_list_set_key_count(key_list, key_count - 1);
+-
+-        return pop;
+-}       
+-
+-#ifdef HAVE_SSL
+-#ifndef S_SPLINT_S
+-/* data pointer must be large enough (LDNS_MAX_KEYLEN) */
+-static bool
+-ldns_key_rsa2bin(unsigned char *data, RSA *k, uint16_t *size)
+-{
+-	int i,j;
+-	
+-	if (!k) {
+-		return false;
+-	}
+-	
+-	if (BN_num_bytes(k->e) <= 256) {
+-		/* normally only this path is executed (small factors are
+-		 * more common 
+-		 */
+-		data[0] = (unsigned char) BN_num_bytes(k->e);
+-		i = BN_bn2bin(k->e, data + 1);  
+-		j = BN_bn2bin(k->n, data + i + 1);
+-		*size = (uint16_t) i + j;
+-	} else if (BN_num_bytes(k->e) <= 65536) {
+-		data[0] = 0;
+-		/* BN_bn2bin does bigendian, _uint16 also */
+-		ldns_write_uint16(data + 1, (uint16_t) BN_num_bytes(k->e)); 
+-
+-		BN_bn2bin(k->e, data + 3); 
+-		BN_bn2bin(k->n, data + 4 + BN_num_bytes(k->e));
+-		*size = (uint16_t) BN_num_bytes(k->n) + 6;
+-	} else {
+-		return false;
+-	}
+-	return true;
+-}
+-
+-/* data pointer must be large enough (LDNS_MAX_KEYLEN) */
+-static bool
+-ldns_key_dsa2bin(unsigned char *data, DSA *k, uint16_t *size)
+-{
+-	uint8_t T;
+-
+-	if (!k) {
+-		return false;
+-	}
+-	
+-	/* See RFC2536 */
+-	*size = (uint16_t)BN_num_bytes(k->p);
+-	T = (*size - 64) / 8;
+-
+-	if (T > 8) {
+-#ifdef STDERR_MSGS
+-		fprintf(stderr, "DSA key with T > 8 (ie. > 1024 bits)");
+-		fprintf(stderr, " not implemented\n");
+-#endif
+-		return false;
+-	}
+-
+-	/* size = 64 + (T * 8); */
+-	memset(data, 0, 21 + *size * 3);
+-	data[0] = (unsigned char)T;
+-	BN_bn2bin(k->q, data + 1 ); 		/* 20 octects */
+-	BN_bn2bin(k->p, data + 21 ); 		/* offset octects */
+-	BN_bn2bin(k->g, data + 21 + *size * 2 - BN_num_bytes(k->g));
+-	BN_bn2bin(k->pub_key,data + 21 + *size * 3 - BN_num_bytes(k->pub_key));
+-	*size = 21 + *size * 3;
+-	return true;
+-}
+-
+-#ifdef USE_GOST
+-static bool
+-ldns_key_gost2bin(unsigned char* data, EVP_PKEY* k, uint16_t* size)
+-{
+-	int i;
+-	unsigned char* pp = NULL;
+-	if(i2d_PUBKEY(k, &pp) != 37 + 64) {
+-		/* expect 37 byte(ASN header) and 64 byte(X and Y) */
+-		CRYPTO_free(pp);
+-		return false;
+-	}
+-	/* omit ASN header */
+-	for(i=0; i<64; i++)
+-		data[i] = pp[i+37];
+-	CRYPTO_free(pp);
+-	*size = 64;
+-	return true;
+-}
+-#endif /* USE_GOST */
+-#endif /* splint */
+-#endif /* HAVE_SSL */
+-
+-ldns_rr *
+-ldns_key2rr(const ldns_key *k)
+-{
+-	/* this function will convert a the keydata contained in
+-	 * rsa/dsa pointers to a DNSKEY rr. It will fill in as
+-	 * much as it can, but it does not know about key-flags
+-	 * for instance
+-	 */
+-	ldns_rr *pubkey;
+-	ldns_rdf *keybin;
+-	unsigned char *bin = NULL;
+-	uint16_t size = 0;
+-#ifdef HAVE_SSL
+-	RSA *rsa = NULL;
+-	DSA *dsa = NULL;
+-#endif /* HAVE_SSL */
+-#ifdef USE_ECDSA
+-        EC_KEY* ec;
+-#endif
+-	int internal_data = 0;
+-
+-	if (!k) {
+-		return NULL;
+-	}
+-	pubkey = ldns_rr_new();
+-
+-	switch (ldns_key_algorithm(k)) {
+-	case LDNS_SIGN_HMACMD5:
+-	case LDNS_SIGN_HMACSHA1:
+-	case LDNS_SIGN_HMACSHA256:
+-		ldns_rr_set_type(pubkey, LDNS_RR_TYPE_KEY);
+-        	break;
+-	default:
+-		ldns_rr_set_type(pubkey, LDNS_RR_TYPE_DNSKEY);
+-		break;
+-        }
+-	/* zero-th rdf - flags */
+-	ldns_rr_push_rdf(pubkey,
+-			ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16,
+-				ldns_key_flags(k)));
+-	/* first - proto */
+-	ldns_rr_push_rdf(pubkey,
+-			ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8, LDNS_DNSSEC_KEYPROTO));
+-
+-	if (ldns_key_pubkey_owner(k)) {
+-		ldns_rr_set_owner(pubkey, ldns_rdf_clone(ldns_key_pubkey_owner(k)));
+-	}
+-
+-	/* third - da algorithm */
+-	switch(ldns_key_algorithm(k)) {
+-		case LDNS_SIGN_RSAMD5:
+-		case LDNS_SIGN_RSASHA1:
+-		case LDNS_SIGN_RSASHA1_NSEC3:
+-		case LDNS_SIGN_RSASHA256:
+-		case LDNS_SIGN_RSASHA512:
+-			ldns_rr_push_rdf(pubkey,
+-						  ldns_native2rdf_int8(LDNS_RDF_TYPE_ALG, ldns_key_algorithm(k)));
+-#ifdef HAVE_SSL
+-			rsa =  ldns_key_rsa_key(k);
+-			if (rsa) {
+-				bin = LDNS_XMALLOC(unsigned char, LDNS_MAX_KEYLEN);
+-				if (!bin) {
+-                                        ldns_rr_free(pubkey);
+-					return NULL;
+-				}
+-				if (!ldns_key_rsa2bin(bin, rsa, &size)) {
+-		                        LDNS_FREE(bin);
+-                                        ldns_rr_free(pubkey);
+-					return NULL;
+-				}
+-				RSA_free(rsa);
+-				internal_data = 1;
+-			}
+-#endif
+-			size++;
+-			break;
+-		case LDNS_SIGN_DSA:
+-			ldns_rr_push_rdf(pubkey,
+-					ldns_native2rdf_int8(LDNS_RDF_TYPE_ALG, LDNS_DSA));
+-#ifdef HAVE_SSL
+-			dsa = ldns_key_dsa_key(k);
+-			if (dsa) {
+-				bin = LDNS_XMALLOC(unsigned char, LDNS_MAX_KEYLEN);
+-				if (!bin) {
+-                                        ldns_rr_free(pubkey);
+-					return NULL;
+-				}
+-				if (!ldns_key_dsa2bin(bin, dsa, &size)) {
+-		                        LDNS_FREE(bin);
+-                                        ldns_rr_free(pubkey);
+-					return NULL;
+-				}
+-				DSA_free(dsa);
+-				internal_data = 1;
+-			}
+-#endif /* HAVE_SSL */
+-			break;
+-		case LDNS_SIGN_DSA_NSEC3:
+-			ldns_rr_push_rdf(pubkey,
+-					ldns_native2rdf_int8(LDNS_RDF_TYPE_ALG, LDNS_DSA_NSEC3));
+-#ifdef HAVE_SSL
+-			dsa = ldns_key_dsa_key(k);
+-			if (dsa) {
+-				bin = LDNS_XMALLOC(unsigned char, LDNS_MAX_KEYLEN);
+-				if (!bin) {
+-                                        ldns_rr_free(pubkey);
+-					return NULL;
+-				}
+-				if (!ldns_key_dsa2bin(bin, dsa, &size)) {
+-		                        LDNS_FREE(bin);
+-                                        ldns_rr_free(pubkey);
+-					return NULL;
+-				}
+-				DSA_free(dsa);
+-				internal_data = 1;
+-			}
+-#endif /* HAVE_SSL */
+-			break;
+-		case LDNS_SIGN_ECC_GOST:
+-			ldns_rr_push_rdf(pubkey, ldns_native2rdf_int8(
+-				LDNS_RDF_TYPE_ALG, ldns_key_algorithm(k)));
+-#if defined(HAVE_SSL) && defined(USE_GOST)
+-			bin = LDNS_XMALLOC(unsigned char, LDNS_MAX_KEYLEN);
+-			if (!bin) {
+-                                ldns_rr_free(pubkey);
+-				return NULL;
+-                        }
+-#ifndef S_SPLINT_S
+-			if (!ldns_key_gost2bin(bin, k->_key.key, &size)) {
+-		                LDNS_FREE(bin);
+-                                ldns_rr_free(pubkey);
+-				return NULL;
+-			}
+-#endif /* splint */
+-			internal_data = 1;
+-#else
+-                        ldns_rr_free(pubkey);
+-			return NULL;
+-#endif /* HAVE_SSL and USE_GOST */
+-			break;
+-                case LDNS_SIGN_ECDSAP256SHA256:
+-                case LDNS_SIGN_ECDSAP384SHA384:
+-#ifdef USE_ECDSA
+-			ldns_rr_push_rdf(pubkey, ldns_native2rdf_int8(
+-				LDNS_RDF_TYPE_ALG, ldns_key_algorithm(k)));
+-                        bin = NULL;
+-#ifndef S_SPLINT_S
+-                        ec = EVP_PKEY_get1_EC_KEY(k->_key.key);
+-#endif
+-                        EC_KEY_set_conv_form(ec, POINT_CONVERSION_UNCOMPRESSED);
+-                        size = (uint16_t)i2o_ECPublicKey(ec, NULL);
+-                        if(!i2o_ECPublicKey(ec, &bin)) {
+-                                EC_KEY_free(ec);
+-                                ldns_rr_free(pubkey);
+-                                return NULL;
+-                        }
+-			if(size > 1) {
+-				/* move back one byte to shave off the 0x02
+-				 * 'uncompressed' indicator that openssl made
+-				 * Actually its 0x04 (from implementation).
+-				 */
+-				assert(bin[0] == POINT_CONVERSION_UNCOMPRESSED);
+-				size -= 1;
+-				memmove(bin, bin+1, size);
+-			}
+-                        /* down the reference count for ec, its still assigned
+-                         * to the pkey */
+-                        EC_KEY_free(ec);
+-			internal_data = 1;
+-#else
+-                        ldns_rr_free(pubkey);
+-			return NULL;
+-#endif /* ECDSA */
+-                        break;
+-		case LDNS_SIGN_HMACMD5:
+-		case LDNS_SIGN_HMACSHA1:
+-		case LDNS_SIGN_HMACSHA256:
+-			bin = LDNS_XMALLOC(unsigned char, ldns_key_hmac_size(k));
+-			if (!bin) {
+-                                ldns_rr_free(pubkey);
+-				return NULL;
+-			}
+-			ldns_rr_push_rdf(pubkey,
+-			                 ldns_native2rdf_int8(LDNS_RDF_TYPE_ALG,
+-			                 ldns_key_algorithm(k)));
+-			size = ldns_key_hmac_size(k);
+-			memcpy(bin, ldns_key_hmac_key(k), size);
+-			internal_data = 1;
+-			break;
+-	}
+-	/* fourth the key bin material */
+-	if (internal_data) {
+-		keybin = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, size, bin);
+-		LDNS_FREE(bin);
+-		ldns_rr_push_rdf(pubkey, keybin);
+-	}
+-	return pubkey;
+-}
+-
+-void
+-ldns_key_free(ldns_key *key)
+-{
+-	LDNS_FREE(key);
+-}
+-
+-void
+-ldns_key_deep_free(ldns_key *key)
+-{
+-	unsigned char* hmac;
+-	if (ldns_key_pubkey_owner(key)) {
+-		ldns_rdf_deep_free(ldns_key_pubkey_owner(key));
+-	}
+-#ifdef HAVE_SSL
+-	if (ldns_key_evp_key(key)) {
+-		EVP_PKEY_free(ldns_key_evp_key(key));
+-	}
+-#endif /* HAVE_SSL */
+-	if (ldns_key_hmac_key(key)) {
+-		hmac = ldns_key_hmac_key(key);
+-		LDNS_FREE(hmac);
+-	}
+-	LDNS_FREE(key);
+-}
+-
+-void
+-ldns_key_list_free(ldns_key_list *key_list)
+-{
+-	size_t i;
+-	for (i = 0; i < ldns_key_list_key_count(key_list); i++) {
+-		ldns_key_deep_free(ldns_key_list_key(key_list, i));
+-	}
+-	LDNS_FREE(key_list->_keys);
+-	LDNS_FREE(key_list);
+-}
+-
+-ldns_rr *
+-ldns_read_anchor_file(const char *filename)
+-{
+-	FILE *fp;
+-	/*char line[LDNS_MAX_PACKETLEN];*/
+-	char *line = LDNS_XMALLOC(char, LDNS_MAX_PACKETLEN);
+-	int c;
+-	size_t i = 0;
+-	ldns_rr *r;
+-	ldns_status status;
+-        if(!line) {
+-                return NULL;
+-        }
+-
+-	fp = fopen(filename, "r");
+-	if (!fp) {
+-#ifdef STDERR_MSGS
+-		fprintf(stderr, "Unable to open %s: %s\n", filename, strerror(errno));
+-#endif
+-		LDNS_FREE(line);
+-		return NULL;
+-	}
+-	
+-	while ((c = fgetc(fp)) && i+1 < LDNS_MAX_PACKETLEN && c != EOF) {
+-		line[i] = c;
+-		i++;
+-	}
+-	line[i] = '\0';
+-	
+-	fclose(fp);
+-	
+-	if (i <= 0) {
+-#ifdef STDERR_MSGS
+-		fprintf(stderr, "nothing read from %s", filename);
+-#endif
+-		LDNS_FREE(line);
+-		return NULL;
+-	} else {
+-		status = ldns_rr_new_frm_str(&r, line, 0, NULL, NULL);
+-		if (status == LDNS_STATUS_OK && (ldns_rr_get_type(r) == LDNS_RR_TYPE_DNSKEY || ldns_rr_get_type(r) == LDNS_RR_TYPE_DS)) {
+-			LDNS_FREE(line);
+-			return r;
+-		} else {
+-#ifdef STDERR_MSGS
+-			fprintf(stderr, "Error creating DNSKEY or DS rr from %s: %s\n", filename, ldns_get_errorstr_by_id(status));
+-#endif
+-			LDNS_FREE(line);
+-			return NULL;
+-		}
+-	}
+-}
+-
+-char *
+-ldns_key_get_file_base_name(ldns_key *key)
+-{
+-	ldns_buffer *buffer;
+-	char *file_base_name;
+-	
+-	buffer = ldns_buffer_new(255);
+-	ldns_buffer_printf(buffer, "K");
+-	(void)ldns_rdf2buffer_str_dname(buffer, ldns_key_pubkey_owner(key));
+-	ldns_buffer_printf(buffer,
+-	                   "+%03u+%05u",
+-			   ldns_key_algorithm(key),
+-			   ldns_key_keytag(key));
+-	file_base_name = ldns_buffer_export(buffer);
+-	ldns_buffer_free(buffer);
+-	return file_base_name;
+-}
+-
+-int ldns_key_algo_supported(int algo)
+-{
+-	ldns_lookup_table *lt = ldns_signing_algorithms;
+-	while(lt->name) {
+-		if(lt->id == algo)
+-			return 1;
+-		lt++;
+-	}
+-	return 0;
+-}
+-
+-ldns_signing_algorithm ldns_get_signing_algorithm_by_name(const char* name)
+-{
+-        /* list of (signing algorithm id, alias_name) */
+-        ldns_lookup_table aliases[] = {
+-                /* from bind dnssec-keygen */
+-                {LDNS_SIGN_HMACMD5, "HMAC-MD5"},
+-                {LDNS_SIGN_DSA_NSEC3, "NSEC3DSA"},
+-                {LDNS_SIGN_RSASHA1_NSEC3, "NSEC3RSASHA1"},
+-                /* old ldns usage, now RFC names */
+-                {LDNS_SIGN_DSA_NSEC3, "DSA_NSEC3" },
+-                {LDNS_SIGN_RSASHA1_NSEC3, "RSASHA1_NSEC3" },
+-#ifdef USE_GOST
+-                {LDNS_SIGN_ECC_GOST, "GOST"},
+-#endif
+-                /* compat with possible output */
+-                {LDNS_DH, "DH"},
+-                {LDNS_ECC, "ECC"},
+-                {LDNS_INDIRECT, "INDIRECT"},
+-                {LDNS_PRIVATEDNS, "PRIVATEDNS"},
+-                {LDNS_PRIVATEOID, "PRIVATEOID"},
+-                {0, NULL}};
+-        ldns_lookup_table* lt = ldns_signing_algorithms;
+-	ldns_signing_algorithm a;
+-	char *endptr;
+-
+-        while(lt->name) {
+-                if(strcasecmp(lt->name, name) == 0)
+-                        return lt->id;
+-                lt++;
+-        }
+-        lt = aliases;
+-        while(lt->name) {
+-                if(strcasecmp(lt->name, name) == 0)
+-                        return lt->id;
+-                lt++;
+-        }
+-	a = strtol(name, &endptr, 10);
+-	if (*name && !*endptr)
+-		return a;
+-
+-        return 0;
+-}
+diff --git a/src/ldns/net.c b/src/ldns/net.c
+deleted file mode 100644
+index b8a5385..0000000
+--- a/src/ldns/net.c
++++ /dev/null
+@@ -1,1002 +0,0 @@
+-/*
+- * net.c
+- *
+- * Network implementation
+- * All network related functions are grouped here
+- *
+- * a Net::DNS like library for C
+- *
+- * (c) NLnet Labs, 2004-2006
+- *
+- * See the file LICENSE for the license
+- */
+-
+-#include <ldns/config.h>
+-
+-#include <ldns/ldns.h>
+-
+-#ifdef HAVE_NETINET_IN_H
+-#include <netinet/in.h>
+-#endif
+-#ifdef HAVE_SYS_SOCKET_H
+-#include <sys/socket.h>
+-#endif
+-#ifdef HAVE_NETDB_H
+-#include <netdb.h>
+-#endif
+-#ifdef HAVE_ARPA_INET_H
+-#include <arpa/inet.h>
+-#endif
+-#include <sys/time.h>
+-#include <errno.h>
+-#include <fcntl.h>
+-
+-ldns_status
+-ldns_send(ldns_pkt **result_packet, ldns_resolver *r, const ldns_pkt *query_pkt)
+-{
+-	ldns_buffer *qb;
+-	ldns_status result;
+-	ldns_rdf *tsig_mac = NULL;
+-
+-	qb = ldns_buffer_new(LDNS_MIN_BUFLEN);
+-
+-	if (query_pkt && ldns_pkt_tsig(query_pkt)) {
+-		tsig_mac = ldns_rr_rdf(ldns_pkt_tsig(query_pkt), 3);
+-	}
+-
+-	if (!query_pkt ||
+-	    ldns_pkt2buffer_wire(qb, query_pkt) != LDNS_STATUS_OK) {
+-		result = LDNS_STATUS_ERR;
+-	} else {
+-        	result = ldns_send_buffer(result_packet, r, qb, tsig_mac);
+-	}
+-
+-	ldns_buffer_free(qb);
+-
+-	return result;
+-}
+-
+-/* code from rdata.c */
+-static struct sockaddr_storage *
+-ldns_rdf2native_sockaddr_storage_port(
+-		const ldns_rdf *rd, uint16_t port, size_t *size)
+-{
+-        struct sockaddr_storage *data;
+-        struct sockaddr_in  *data_in;
+-        struct sockaddr_in6 *data_in6;
+-
+-        data = LDNS_MALLOC(struct sockaddr_storage);
+-        if (!data) {
+-                return NULL;
+-        }
+-	/* zero the structure for portability */
+-	memset(data, 0, sizeof(struct sockaddr_storage));
+-
+-        switch(ldns_rdf_get_type(rd)) {
+-                case LDNS_RDF_TYPE_A:
+-#ifndef S_SPLINT_S
+-                        data->ss_family = AF_INET;
+-#endif
+-                        data_in = (struct sockaddr_in*) data;
+-                        data_in->sin_port = (in_port_t)htons(port);
+-                        memcpy(&(data_in->sin_addr), ldns_rdf_data(rd), ldns_rdf_size(rd));
+-                        *size = sizeof(struct sockaddr_in);
+-                        return data;
+-                case LDNS_RDF_TYPE_AAAA:
+-#ifndef S_SPLINT_S
+-                        data->ss_family = AF_INET6;
+-#endif
+-                        data_in6 = (struct sockaddr_in6*) data;
+-                        data_in6->sin6_port = (in_port_t)htons(port);
+-                        memcpy(&data_in6->sin6_addr, ldns_rdf_data(rd), ldns_rdf_size(rd));
+-                        *size = sizeof(struct sockaddr_in6);
+-                        return data;
+-                default:
+-                        LDNS_FREE(data);
+-                        return NULL;
+-        }
+-}
+-
+-struct sockaddr_storage *
+-ldns_rdf2native_sockaddr_storage(
+-		const ldns_rdf *rd, uint16_t port, size_t *size)
+-{
+-	return ldns_rdf2native_sockaddr_storage_port(
+-			rd, (port == 0 ? (uint16_t)LDNS_PORT : port), size);
+-}
+-
+-/** best effort to set nonblocking */
+-static void
+-ldns_sock_nonblock(int sockfd)
+-{
+-#ifdef HAVE_FCNTL
+-	int flag;
+-	if((flag = fcntl(sockfd, F_GETFL)) != -1) {
+-		flag |= O_NONBLOCK;
+-		if(fcntl(sockfd, F_SETFL, flag) == -1) {
+-			/* ignore error, continue blockingly */
+-		}
+-	}
+-#elif defined(HAVE_IOCTLSOCKET)
+-	unsigned long on = 1;
+-	if(ioctlsocket(sockfd, FIONBIO, &on) != 0) {
+-		/* ignore error, continue blockingly */
+-	}
+-#endif
+-}
+-
+-/** best effort to set blocking */
+-static void
+-ldns_sock_block(int sockfd)
+-{
+-#ifdef HAVE_FCNTL
+-	int flag;
+-	if((flag = fcntl(sockfd, F_GETFL)) != -1) {
+-		flag &= ~O_NONBLOCK;
+-		if(fcntl(sockfd, F_SETFL, flag) == -1) {
+-			/* ignore error, continue */
+-		}
+-	}
+-#elif defined(HAVE_IOCTLSOCKET)
+-	unsigned long off = 0;
+-	if(ioctlsocket(sockfd, FIONBIO, &off) != 0) {
+-		/* ignore error, continue */
+-	}
+-#endif
+-}
+-
+-/** wait for a socket to become ready */
+-static int
+-ldns_sock_wait(int sockfd, struct timeval timeout, int write)
+-{
+-	int ret;
+-#ifndef S_SPLINT_S
+-	fd_set fds;
+-	FD_ZERO(&fds);
+-	FD_SET(FD_SET_T sockfd, &fds);
+-	if(write)
+-		ret = select(sockfd+1, NULL, &fds, NULL, &timeout);
+-	else
+-		ret = select(sockfd+1, &fds, NULL, NULL, &timeout);
+-#endif
+-	if(ret == 0)
+-		/* timeout expired */
+-		return 0;
+-	else if(ret == -1)
+-		/* error */
+-		return 0;
+-	return 1;
+-}
+-
+-
+-static int
+-ldns_tcp_connect_from(const struct sockaddr_storage *to, socklen_t tolen, 
+-	       	const struct sockaddr_storage *from, socklen_t fromlen,
+-		struct timeval timeout)
+-{
+-	int sockfd;
+-
+-#ifndef S_SPLINT_S
+-	if ((sockfd = socket((int)((struct sockaddr*)to)->sa_family, SOCK_STREAM, 
+-					IPPROTO_TCP)) == -1) {
+-		return 0;
+-	}
+-#endif
+-	if (from && bind(sockfd, (const struct sockaddr*)from, fromlen) == -1){
+-		return 0;
+-	}
+-
+-	/* perform nonblocking connect, to be able to wait with select() */
+-	ldns_sock_nonblock(sockfd);
+-	if (connect(sockfd, (struct sockaddr*)to, tolen) == -1) {
+-#ifndef USE_WINSOCK
+-#ifdef EINPROGRESS
+-		if(errno != EINPROGRESS) {
+-#else
+-		if(1) {
+-#endif
+-			close(sockfd);
+-			return 0;
+-		}
+-#else /* USE_WINSOCK */
+-		if(WSAGetLastError() != WSAEINPROGRESS &&
+-			WSAGetLastError() != WSAEWOULDBLOCK) {
+-			closesocket(sockfd);
+-			return 0;
+-		}
+-#endif
+-		/* error was only telling us that it would block */
+-	}
+-
+-	/* wait(write) until connected or error */
+-	while(1) {
+-		int error = 0;
+-		socklen_t len = (socklen_t)sizeof(error);
+-
+-		if(!ldns_sock_wait(sockfd, timeout, 1)) {
+-#ifndef USE_WINSOCK
+-			close(sockfd);
+-#else
+-			closesocket(sockfd);
+-#endif
+-			return 0;
+-		}
+-
+-		/* check if there is a pending error for nonblocking connect */
+-		if(getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void*)&error,
+-			&len) < 0) {
+-#ifndef USE_WINSOCK
+-			error = errno; /* on solaris errno is error */
+-#else
+-			error = WSAGetLastError();
+-#endif
+-		}
+-#ifndef USE_WINSOCK
+-#if defined(EINPROGRESS) && defined(EWOULDBLOCK)
+-		if(error == EINPROGRESS || error == EWOULDBLOCK)
+-			continue; /* try again */
+-#endif
+-		else if(error != 0) {
+-			close(sockfd);
+-			/* error in errno for our user */
+-			errno = error;
+-			return 0;
+-		}
+-#else /* USE_WINSOCK */
+-		if(error == WSAEINPROGRESS)
+-			continue;
+-		else if(error == WSAEWOULDBLOCK)
+-			continue;
+-		else if(error != 0) {
+-			closesocket(sockfd);
+-			errno = error;
+-			return 0;
+-		}
+-#endif /* USE_WINSOCK */
+-		/* connected */
+-		break;
+-	}
+-
+-	/* set the socket blocking again */
+-	ldns_sock_block(sockfd);
+-
+-	return sockfd;
+-}
+-
+-int
+-ldns_tcp_connect(const struct sockaddr_storage *to, socklen_t tolen, 
+-		struct timeval timeout)
+-{
+-	return ldns_tcp_connect_from(to, tolen, NULL, 0, timeout);
+-}
+-
+-static int
+-ldns_tcp_bgsend_from(ldns_buffer *qbin,
+-		const struct sockaddr_storage *to, socklen_t tolen, 
+-	       	const struct sockaddr_storage *from, socklen_t fromlen,
+-		struct timeval timeout)
+-{
+-	int sockfd;
+-	
+-	sockfd = ldns_tcp_connect_from(to, tolen, from, fromlen, timeout);
+-	
+-	if (sockfd == 0) {
+-		return 0;
+-	}
+-	
+-	if (ldns_tcp_send_query(qbin, sockfd, to, tolen) == 0) {
+-#ifndef USE_WINSOCK
+-		close(sockfd);
+-#else
+-		closesocket(sockfd);
+-#endif
+-		return 0;
+-	}
+-	
+-	return sockfd;
+-}
+-
+-int
+-ldns_tcp_bgsend(ldns_buffer *qbin,
+-		const struct sockaddr_storage *to, socklen_t tolen, 
+-		struct timeval timeout)
+-{
+-	return ldns_tcp_bgsend_from(qbin, to, tolen, NULL, 0, timeout);
+-}
+-
+-
+-/* keep in mind that in DNS tcp messages the first 2 bytes signal the
+- * amount data to expect
+- */
+-static ldns_status
+-ldns_tcp_send_from(uint8_t **result,  ldns_buffer *qbin,
+-	       	const struct sockaddr_storage *to, socklen_t tolen,
+-	       	const struct sockaddr_storage *from, socklen_t fromlen,
+-		struct timeval timeout, size_t *answer_size)
+-{
+-	int sockfd;
+-	uint8_t *answer;
+-	
+-	sockfd = ldns_tcp_bgsend_from(qbin, to, tolen, from, fromlen, timeout);
+-	
+-	if (sockfd == 0) {
+-		return LDNS_STATUS_ERR;
+-	}
+-
+-	answer = ldns_tcp_read_wire_timeout(sockfd, answer_size, timeout);
+-#ifndef USE_WINSOCK
+-	close(sockfd);
+-#else
+-	closesocket(sockfd);
+-#endif
+-
+-	if (*answer_size == 0) {
+-		/* oops */
+-		return LDNS_STATUS_NETWORK_ERR;
+-	}
+-
+-	/* resize accordingly */
+-	*result = LDNS_XREALLOC(answer, uint8_t, (size_t)*answer_size);
+-        if(!*result) {
+-                LDNS_FREE(answer);
+-                return LDNS_STATUS_MEM_ERR;
+-        }
+-	return LDNS_STATUS_OK;
+-}
+-
+-ldns_status
+-ldns_tcp_send(uint8_t **result,  ldns_buffer *qbin,
+-		const struct sockaddr_storage *to, socklen_t tolen,
+-		struct timeval timeout, size_t *answer_size)
+-{
+-	return ldns_tcp_send_from(result, qbin,
+-			to, tolen, NULL, 0, timeout, answer_size);
+-}
+-
+-int
+-ldns_udp_connect(const struct sockaddr_storage *to, struct timeval ATTR_UNUSED(timeout))
+-{
+-	int sockfd;
+-
+-#ifndef S_SPLINT_S
+-	if ((sockfd = socket((int)((struct sockaddr*)to)->sa_family, SOCK_DGRAM, 
+-					IPPROTO_UDP)) 
+-			== -1) {
+-                return 0;
+-        }
+-#endif
+-	return sockfd;
+-}
+-
+-static int
+-ldns_udp_bgsend_from(ldns_buffer *qbin,
+-		const struct sockaddr_storage *to  , socklen_t tolen, 
+-		const struct sockaddr_storage *from, socklen_t fromlen, 
+-		struct timeval timeout)
+-{
+-	int sockfd;
+-
+-	sockfd = ldns_udp_connect(to, timeout);
+-
+-	if (sockfd == 0) {
+-		return 0;
+-	}
+-
+-	if (from && bind(sockfd, (const struct sockaddr*)from, fromlen) == -1){
+-		return 0;
+-	}
+-
+-	if (ldns_udp_send_query(qbin, sockfd, to, tolen) == 0) {
+-#ifndef USE_WINSOCK
+-		close(sockfd);
+-#else
+-		closesocket(sockfd);
+-#endif
+-		return 0;
+-	}
+-	return sockfd;
+-}
+-
+-int
+-ldns_udp_bgsend(ldns_buffer *qbin,
+-		const struct sockaddr_storage *to  , socklen_t tolen, 
+-		struct timeval timeout)
+-{
+-	return ldns_udp_bgsend_from(qbin, to, tolen, NULL, 0, timeout);
+-}
+-
+-static ldns_status
+-ldns_udp_send_from(uint8_t **result, ldns_buffer *qbin,
+-		const struct sockaddr_storage *to  , socklen_t tolen,
+-		const struct sockaddr_storage *from, socklen_t fromlen,
+-		struct timeval timeout, size_t *answer_size)
+-{
+-	int sockfd;
+-	uint8_t *answer;
+-
+-	sockfd = ldns_udp_bgsend_from(qbin, to, tolen, from, fromlen, timeout);
+-
+-	if (sockfd == 0) {
+-		return LDNS_STATUS_SOCKET_ERROR;
+-	}
+-
+-	/* wait for an response*/
+-	if(!ldns_sock_wait(sockfd, timeout, 0)) {
+-#ifndef USE_WINSOCK
+-		close(sockfd);
+-#else
+-                closesocket(sockfd);
+-#endif
+-		return LDNS_STATUS_NETWORK_ERR;
+-	}
+-
+-        /* set to nonblocking, so if the checksum is bad, it becomes
+-         * an EGAIN error and the ldns_udp_send function does not block,
+-         * but returns a 'NETWORK_ERROR' much like a timeout. */
+-        ldns_sock_nonblock(sockfd);
+-
+-	answer = ldns_udp_read_wire(sockfd, answer_size, NULL, NULL);
+-#ifndef USE_WINSOCK
+-	close(sockfd);
+-#else
+-        closesocket(sockfd);
+-#endif
+-
+-	if (*answer_size == 0) {
+-		/* oops */
+-		return LDNS_STATUS_NETWORK_ERR;
+-	}
+-
+-	*result = answer;
+-	return LDNS_STATUS_OK;
+-}
+-
+-ldns_status
+-ldns_udp_send(uint8_t **result, ldns_buffer *qbin,
+-		const struct sockaddr_storage *to  , socklen_t tolen,
+-		struct timeval timeout, size_t *answer_size)
+-{
+-	return ldns_udp_send_from(result, qbin, to, tolen, NULL, 0,
+-			timeout, answer_size);
+-}
+-
+-ldns_status
+-ldns_send_buffer(ldns_pkt **result, ldns_resolver *r, ldns_buffer *qb, ldns_rdf *tsig_mac)
+-{
+-	uint8_t i;
+-
+-	struct sockaddr_storage *src = NULL;
+-	size_t src_len;
+-	struct sockaddr_storage *ns;
+-	size_t ns_len;
+-	struct timeval tv_s;
+-	struct timeval tv_e;
+-
+-	ldns_rdf **ns_array;
+-	size_t *rtt;
+-	ldns_pkt *reply;
+-	bool all_servers_rtt_inf;
+-	uint8_t retries;
+-
+-	uint8_t *reply_bytes = NULL;
+-	size_t reply_size = 0;
+-	ldns_status status, send_status;
+-
+-	assert(r != NULL);
+-
+-	status = LDNS_STATUS_OK;
+-	rtt = ldns_resolver_rtt(r);
+-	ns_array = ldns_resolver_nameservers(r);
+-	reply = NULL; 
+-	ns_len = 0;
+-
+-	all_servers_rtt_inf = true;
+-
+-	if (ldns_resolver_random(r)) {
+-		ldns_resolver_nameservers_randomize(r);
+-	}
+-
+-	if(ldns_resolver_source(r)) {
+-		src = ldns_rdf2native_sockaddr_storage_port(
+-				ldns_resolver_source(r), 0, &src_len);
+-	}
+-
+-	/* loop through all defined nameservers */
+-	for (i = 0; i < ldns_resolver_nameserver_count(r); i++) {
+-		if (rtt[i] == LDNS_RESOLV_RTT_INF) {
+-			/* not reachable nameserver! */
+-			continue;
+-		}
+-
+-		/* maybe verbosity setting?
+-		printf("Sending to ");
+-		ldns_rdf_print(stdout, ns_array[i]);
+-		printf("\n");
+-		*/
+-		ns = ldns_rdf2native_sockaddr_storage(ns_array[i],
+-				ldns_resolver_port(r), &ns_len);
+-
+-
+-#ifndef S_SPLINT_S
+-		if ((ns->ss_family == AF_INET) &&
+-				(ldns_resolver_ip6(r) == LDNS_RESOLV_INET6)) {
+-			/* not reachable */
+-			LDNS_FREE(ns);
+-			continue;
+-		}
+-
+-		if ((ns->ss_family == AF_INET6) &&
+-				 (ldns_resolver_ip6(r) == LDNS_RESOLV_INET)) {
+-			/* not reachable */
+-			LDNS_FREE(ns);
+-			continue;
+-		}
+-#endif
+-
+-		all_servers_rtt_inf = false;
+-
+-		gettimeofday(&tv_s, NULL);
+-
+-		send_status = LDNS_STATUS_ERR;
+-
+-		/* reply_bytes implicitly handles our error */
+-		if (ldns_resolver_usevc(r)) {
+-			for (retries = ldns_resolver_retry(r); retries > 0; retries--) {
+-				send_status = 
+-					ldns_tcp_send_from(&reply_bytes, qb, 
+-						ns, (socklen_t)ns_len,
+-						src, (socklen_t)src_len,
+-						ldns_resolver_timeout(r),
+-						&reply_size);
+-				if (send_status == LDNS_STATUS_OK) {
+-					break;
+-				}
+-			}
+-		} else {
+-			for (retries = ldns_resolver_retry(r); retries > 0; retries--) {
+-				/* ldns_rdf_print(stdout, ns_array[i]); */
+-				send_status = 
+-					ldns_udp_send_from(&reply_bytes, qb,
+-						ns,  (socklen_t)ns_len,
+-						src, (socklen_t)src_len,
+-						ldns_resolver_timeout(r),
+-						&reply_size);
+-				if (send_status == LDNS_STATUS_OK) {
+-					break;
+-				}
+-			}
+-		}
+-
+-		if (send_status != LDNS_STATUS_OK) {
+-			ldns_resolver_set_nameserver_rtt(r, i, LDNS_RESOLV_RTT_INF);
+-			status = send_status;
+-		}
+-		
+-		/* obey the fail directive */
+-		if (!reply_bytes) {
+-			/* the current nameserver seems to have a problem, blacklist it */
+-			if (ldns_resolver_fail(r)) {
+-				LDNS_FREE(ns);
+-				return LDNS_STATUS_ERR;
+-			} else {
+-				LDNS_FREE(ns);
+-				continue;
+-			}
+-		} 
+-		
+-		status = ldns_wire2pkt(&reply, reply_bytes, reply_size);
+-		if (status != LDNS_STATUS_OK) {
+-			LDNS_FREE(reply_bytes);
+-			LDNS_FREE(ns);
+-			return status;
+-		}
+-		
+-		LDNS_FREE(ns);
+-		gettimeofday(&tv_e, NULL);
+-
+-		if (reply) {
+-			ldns_pkt_set_querytime(reply, (uint32_t)
+-				((tv_e.tv_sec - tv_s.tv_sec) * 1000) +
+-				(tv_e.tv_usec - tv_s.tv_usec) / 1000);
+-			ldns_pkt_set_answerfrom(reply,
+-					ldns_rdf_clone(ns_array[i]));
+-			ldns_pkt_set_timestamp(reply, tv_s);
+-			ldns_pkt_set_size(reply, reply_size);
+-			break;
+-		} else {
+-			if (ldns_resolver_fail(r)) {
+-				/* if fail is set bail out, after the first
+-				 * one */
+-				break;
+-			}
+-		}
+-
+-		/* wait retrans seconds... */
+-		sleep((unsigned int) ldns_resolver_retrans(r));
+-	}
+-
+-	if(src) {
+-		LDNS_FREE(src);
+-	}
+-	if (all_servers_rtt_inf) {
+-		LDNS_FREE(reply_bytes);
+-		return LDNS_STATUS_RES_NO_NS;
+-	}
+-#ifdef HAVE_SSL
+-	if (tsig_mac && reply && reply_bytes) {
+-		if (!ldns_pkt_tsig_verify(reply,
+-		                          reply_bytes,
+-					  reply_size,
+-		                          ldns_resolver_tsig_keyname(r),
+-		                          ldns_resolver_tsig_keydata(r), tsig_mac)) {
+-			status = LDNS_STATUS_CRYPTO_TSIG_BOGUS;
+-		}
+-	}
+-#else
+-	(void)tsig_mac;
+-#endif /* HAVE_SSL */
+-
+-	LDNS_FREE(reply_bytes);
+-	if (result) {
+-		*result = reply;
+-	}
+-
+-	return status;
+-}
+-
+-ssize_t
+-ldns_tcp_send_query(ldns_buffer *qbin, int sockfd, 
+-                    const struct sockaddr_storage *to, socklen_t tolen)
+-{
+-	uint8_t *sendbuf;
+-	ssize_t bytes;
+-
+-	/* add length of packet */
+-	sendbuf = LDNS_XMALLOC(uint8_t, ldns_buffer_position(qbin) + 2);
+-	if(!sendbuf) return 0;
+-	ldns_write_uint16(sendbuf, ldns_buffer_position(qbin));
+-	memcpy(sendbuf + 2, ldns_buffer_begin(qbin), ldns_buffer_position(qbin));
+-
+-	bytes = sendto(sockfd, (void*)sendbuf,
+-			ldns_buffer_position(qbin) + 2, 0, (struct sockaddr *)to, tolen);
+-
+-        LDNS_FREE(sendbuf);
+-
+-	if (bytes == -1 || (size_t) bytes != ldns_buffer_position(qbin) + 2 ) {
+-		return 0;
+-	}
+-	return bytes;
+-}
+-
+-/* don't wait for an answer */
+-ssize_t
+-ldns_udp_send_query(ldns_buffer *qbin, int sockfd, const struct sockaddr_storage *to, 
+-		socklen_t tolen)
+-{
+-	ssize_t bytes;
+-
+-	bytes = sendto(sockfd, (void*)ldns_buffer_begin(qbin),
+-			ldns_buffer_position(qbin), 0, (struct sockaddr *)to, tolen);
+-
+-	if (bytes == -1 || (size_t)bytes != ldns_buffer_position(qbin)) {
+-		return 0;
+-	}
+-	if ((size_t) bytes != ldns_buffer_position(qbin)) {
+-		return 0;
+-	}
+-	return bytes;
+-}
+-
+-uint8_t *
+-ldns_udp_read_wire(int sockfd, size_t *size, struct sockaddr_storage *from,
+-		socklen_t *fromlen)
+-{
+-	uint8_t *wire, *wireout;
+-	ssize_t wire_size;
+-
+-	wire = LDNS_XMALLOC(uint8_t, LDNS_MAX_PACKETLEN);
+-	if (!wire) {
+-		*size = 0;
+-		return NULL;
+-	}
+-
+-	wire_size = recvfrom(sockfd, (void*)wire, LDNS_MAX_PACKETLEN, 0, 
+-			(struct sockaddr *)from, fromlen);
+-
+-	/* recvfrom can also return 0 */
+-	if (wire_size == -1 || wire_size == 0) {
+-		*size = 0;
+-		LDNS_FREE(wire);
+-		return NULL;
+-	}
+-
+-	*size = (size_t)wire_size;
+-	wireout = LDNS_XREALLOC(wire, uint8_t, (size_t)wire_size);
+-	if(!wireout) LDNS_FREE(wire);
+-
+-	return wireout;
+-}
+-
+-uint8_t *
+-ldns_tcp_read_wire_timeout(int sockfd, size_t *size, struct timeval timeout)
+-{
+-	uint8_t *wire;
+-	uint16_t wire_size;
+-	ssize_t bytes = 0, rc = 0;
+-
+-	wire = LDNS_XMALLOC(uint8_t, 2);
+-	if (!wire) {
+-		*size = 0;
+-		return NULL;
+-	}
+-	
+-	while (bytes < 2) {
+-		if(!ldns_sock_wait(sockfd, timeout, 0)) {
+-			*size = 0;
+-			LDNS_FREE(wire);
+-			return NULL;
+-		}
+-		rc = recv(sockfd, (void*) (wire + bytes), 
+-				(size_t) (2 - bytes), 0);
+-		if (rc == -1 || rc == 0) {
+-			*size = 0;
+-			LDNS_FREE(wire);
+-			return NULL;
+-		}
+-                bytes += rc;
+-	}
+-
+-	wire_size = ldns_read_uint16(wire);
+-	
+-	LDNS_FREE(wire);
+-	wire = LDNS_XMALLOC(uint8_t, wire_size);
+-	if (!wire) {
+-		*size = 0;
+-		return NULL;
+-	}
+-	bytes = 0;
+-
+-	while (bytes < (ssize_t) wire_size) {
+-		if(!ldns_sock_wait(sockfd, timeout, 0)) {
+-			*size = 0;
+-			LDNS_FREE(wire);
+-			return NULL;
+-		}
+-		rc = recv(sockfd, (void*) (wire + bytes), 
+-				(size_t) (wire_size - bytes), 0);
+-		if (rc == -1 || rc == 0) {
+-			LDNS_FREE(wire);
+-			*size = 0;
+-			return NULL;
+-		}
+-                bytes += rc;
+-	}
+-	
+-	*size = (size_t) bytes;
+-	return wire;
+-}
+-
+-uint8_t *
+-ldns_tcp_read_wire(int sockfd, size_t *size)
+-{
+-	uint8_t *wire;
+-	uint16_t wire_size;
+-	ssize_t bytes = 0, rc = 0;
+-
+-	wire = LDNS_XMALLOC(uint8_t, 2);
+-	if (!wire) {
+-		*size = 0;
+-		return NULL;
+-	}
+-	
+-	while (bytes < 2) {
+-		rc = recv(sockfd, (void*) (wire + bytes), 
+-				(size_t) (2 - bytes), 0);
+-		if (rc == -1 || rc == 0) {
+-			*size = 0;
+-			LDNS_FREE(wire);
+-			return NULL;
+-		}
+-                bytes += rc;
+-	}
+-
+-	wire_size = ldns_read_uint16(wire);
+-	
+-	LDNS_FREE(wire);
+-	wire = LDNS_XMALLOC(uint8_t, wire_size);
+-	if (!wire) {
+-		*size = 0;
+-		return NULL;
+-	}
+-	bytes = 0;
+-
+-	while (bytes < (ssize_t) wire_size) {
+-		rc = recv(sockfd, (void*) (wire + bytes), 
+-				(size_t) (wire_size - bytes), 0);
+-		if (rc == -1 || rc == 0) {
+-			LDNS_FREE(wire);
+-			*size = 0;
+-			return NULL;
+-		}
+-                bytes += rc;
+-	}
+-	
+-	*size = (size_t) bytes;
+-	return wire;
+-}
+-
+-#ifndef S_SPLINT_S
+-ldns_rdf *
+-ldns_sockaddr_storage2rdf(struct sockaddr_storage *sock, uint16_t *port)
+-{
+-        ldns_rdf *addr;
+-        struct sockaddr_in *data_in;
+-        struct sockaddr_in6 *data_in6;
+-
+-        switch(sock->ss_family) {
+-                case AF_INET:
+-                        data_in = (struct sockaddr_in*)sock;
+-                        if (port) {
+-                                *port = ntohs((uint16_t)data_in->sin_port);
+-                        }
+-                        addr = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_A,
+-                                        LDNS_IP4ADDRLEN, &data_in->sin_addr);
+-                        break;
+-                case AF_INET6:
+-                        data_in6 = (struct sockaddr_in6*)sock;
+-                        if (port) {
+-                                *port = ntohs((uint16_t)data_in6->sin6_port);
+-                        }
+-                        addr = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_AAAA,
+-                                        LDNS_IP6ADDRLEN, &data_in6->sin6_addr);
+-                        break;
+-                default:
+-                        if (port) {
+-                                *port = 0;
+-                        }
+-                        return NULL;
+-        }
+-        return addr;
+-}
+-#endif
+-
+-/* code from resolver.c */
+-ldns_status
+-ldns_axfr_start(ldns_resolver *resolver, ldns_rdf *domain, ldns_rr_class class) 
+-{
+-        ldns_pkt *query;
+-        ldns_buffer *query_wire;
+-
+-        struct sockaddr_storage *src = NULL;
+-        size_t src_len = 0;
+-        struct sockaddr_storage *ns = NULL;
+-        size_t ns_len = 0;
+-        size_t ns_i;
+-        ldns_status status;
+-
+-        if (!resolver || ldns_resolver_nameserver_count(resolver) < 1) {
+-                return LDNS_STATUS_ERR;
+-        }
+-
+-        query = ldns_pkt_query_new(ldns_rdf_clone(domain), LDNS_RR_TYPE_AXFR, class, 0);
+-
+-        if (!query) {
+-                return LDNS_STATUS_ADDRESS_ERR;
+-        }
+-	if(ldns_resolver_source(resolver)) {
+-		src = ldns_rdf2native_sockaddr_storage_port(
+-				ldns_resolver_source(resolver), 0, &src_len);
+-	}
+-        /* For AXFR, we have to make the connection ourselves */
+-        /* try all nameservers (which usually would mean v4 fallback if
+-         * @hostname is used */
+-        for (ns_i = 0;
+-             ns_i < ldns_resolver_nameserver_count(resolver) &&
+-             resolver->_socket == 0;
+-             ns_i++) {
+-		if (ns != NULL) {
+-			LDNS_FREE(ns);
+-		}
+-	        ns = ldns_rdf2native_sockaddr_storage(
+-	        	resolver->_nameservers[ns_i],
+-			ldns_resolver_port(resolver), &ns_len);
+-
+-		resolver->_socket = ldns_tcp_connect_from(
+-				ns, (socklen_t)ns_len,
+-				src, (socklen_t)src_len,
+-				ldns_resolver_timeout(resolver));
+-	}
+-
+-	if (resolver->_socket == 0) {
+-		ldns_pkt_free(query);
+-		LDNS_FREE(ns);
+-		return LDNS_STATUS_NETWORK_ERR;
+-	}
+-
+-#ifdef HAVE_SSL
+-	if (ldns_resolver_tsig_keyname(resolver) && ldns_resolver_tsig_keydata(resolver)) {
+-		status = ldns_pkt_tsig_sign(query,
+-		                            ldns_resolver_tsig_keyname(resolver),
+-		                            ldns_resolver_tsig_keydata(resolver),
+-		                            300, ldns_resolver_tsig_algorithm(resolver), NULL);
+-		if (status != LDNS_STATUS_OK) {
+-			/* to prevent problems on subsequent calls to 
+-			 * ldns_axfr_start we have to close the socket here! */
+-#ifndef USE_WINSOCK
+-			close(resolver->_socket);
+-#else
+-			closesocket(resolver->_socket);
+-#endif
+-			resolver->_socket = 0;
+-
+-			ldns_pkt_free(query);
+-			LDNS_FREE(ns);
+-
+-			return LDNS_STATUS_CRYPTO_TSIG_ERR;
+-		}
+-	}
+-#endif /* HAVE_SSL */
+-
+-        /* Convert the query to a buffer
+-         * Is this necessary?
+-         */
+-        query_wire = ldns_buffer_new(LDNS_MAX_PACKETLEN);
+-        if(!query_wire) {
+-                ldns_pkt_free(query);
+-                LDNS_FREE(ns);
+-#ifndef USE_WINSOCK
+-		close(resolver->_socket);
+-#else
+-		closesocket(resolver->_socket);
+-#endif
+-		resolver->_socket = 0;
+-
+-                return LDNS_STATUS_MEM_ERR;
+-        }
+-        status = ldns_pkt2buffer_wire(query_wire, query);
+-        if (status != LDNS_STATUS_OK) {
+-                ldns_pkt_free(query);
+-		ldns_buffer_free(query_wire);
+-                LDNS_FREE(ns);
+-
+-		/* to prevent problems on subsequent calls to ldns_axfr_start
+-		 * we have to close the socket here! */
+-#ifndef USE_WINSOCK
+-		close(resolver->_socket);
+-#else
+-		closesocket(resolver->_socket);
+-#endif
+-		resolver->_socket = 0;
+-
+-                return status;
+-        }
+-        /* Send the query */
+-        if (ldns_tcp_send_query(query_wire, resolver->_socket, ns,
+-				(socklen_t)ns_len) == 0) {
+-                ldns_pkt_free(query);
+-                ldns_buffer_free(query_wire);
+-                LDNS_FREE(ns);
+-
+-		/* to prevent problems on subsequent calls to ldns_axfr_start
+-		 * we have to close the socket here! */
+-
+-#ifndef USE_WINSOCK
+-		close(resolver->_socket);
+-#else
+-		closesocket(resolver->_socket);
+-#endif
+-		resolver->_socket = 0;
+-
+-                return LDNS_STATUS_NETWORK_ERR;
+-        }
+-
+-        ldns_pkt_free(query);
+-        ldns_buffer_free(query_wire);
+-        LDNS_FREE(ns);
+-
+-        /*
+-         * The AXFR is done once the second SOA record is sent
+-         */
+-        resolver->_axfr_soa_count = 0;
+-        return LDNS_STATUS_OK;
+-}
+diff --git a/src/ldns/packet.c b/src/ldns/packet.c
+deleted file mode 100644
+index 62bfd07..0000000
+--- a/src/ldns/packet.c
++++ /dev/null
+@@ -1,1159 +0,0 @@
+-/*
+- * packet.c
+- *
+- * dns packet implementation
+- *
+- * a Net::DNS like library for C
+- *
+- * (c) NLnet Labs, 2004-2006
+- *
+- * See the file LICENSE for the license
+- */
+-
+-#include <ldns/config.h>
+-
+-#include <ldns/ldns.h>
+-
+-#include <strings.h>
+-#include <limits.h>
+-
+-#ifdef HAVE_SSL
+-#include <openssl/rand.h>
+-#endif
+-
+-/* Access functions 
+- * do this as functions to get type checking
+- */
+-
+-#define LDNS_EDNS_MASK_DO_BIT 0x8000
+-
+-/* TODO defines for 3600 */
+-/* convert to and from numerical flag values */
+-ldns_lookup_table ldns_edns_flags[] = {
+-	{ 3600, "do"},
+-	{ 0, NULL}
+-};
+-
+-/* read */
+-uint16_t
+-ldns_pkt_id(const ldns_pkt *packet)
+-{
+-	return packet->_header->_id;
+-}
+-
+-bool
+-ldns_pkt_qr(const ldns_pkt *packet)
+-{
+-	return packet->_header->_qr;
+-}
+-
+-bool
+-ldns_pkt_aa(const ldns_pkt *packet)
+-{
+-	return packet->_header->_aa;
+-}
+-
+-bool
+-ldns_pkt_tc(const ldns_pkt *packet)
+-{
+-	return packet->_header->_tc;
+-}
+-
+-bool
+-ldns_pkt_rd(const ldns_pkt *packet)
+-{
+-	return packet->_header->_rd;
+-}
+-
+-bool
+-ldns_pkt_cd(const ldns_pkt *packet)
+-{
+-	return packet->_header->_cd;
+-}
+-
+-bool
+-ldns_pkt_ra(const ldns_pkt *packet)
+-{
+-	return packet->_header->_ra;
+-}
+-
+-bool
+-ldns_pkt_ad(const ldns_pkt *packet)
+-{
+-	return packet->_header->_ad;
+-}
+-
+-ldns_pkt_opcode
+-ldns_pkt_get_opcode(const ldns_pkt *packet)
+-{
+-	return packet->_header->_opcode;
+-}
+-
+-ldns_pkt_rcode
+-ldns_pkt_get_rcode(const ldns_pkt *packet)
+-{
+-	return packet->_header->_rcode;
+-}
+-
+-uint16_t
+-ldns_pkt_qdcount(const ldns_pkt *packet)
+-{
+-	return packet->_header->_qdcount;
+-}
+-
+-uint16_t
+-ldns_pkt_ancount(const ldns_pkt *packet)
+-{
+-	return packet->_header->_ancount;
+-}
+-
+-uint16_t
+-ldns_pkt_nscount(const ldns_pkt *packet)
+-{
+-	return packet->_header->_nscount;
+-}
+-
+-uint16_t
+-ldns_pkt_arcount(const ldns_pkt *packet)
+-{
+-	return packet->_header->_arcount;
+-}
+-
+-ldns_rr_list *
+-ldns_pkt_question(const ldns_pkt *packet)
+-{
+-	return packet->_question;
+-}
+-
+-ldns_rr_list *
+-ldns_pkt_answer(const ldns_pkt *packet)
+-{
+-	return packet->_answer;
+-}
+-
+-ldns_rr_list *
+-ldns_pkt_authority(const ldns_pkt *packet)
+-{
+-	return packet->_authority;
+-}
+-
+-ldns_rr_list *
+-ldns_pkt_additional(const ldns_pkt *packet)
+-{
+-	return packet->_additional;
+-}
+-
+-/* return ALL section concatenated */
+-ldns_rr_list *
+-ldns_pkt_all(const ldns_pkt *packet)
+-{
+-	ldns_rr_list *all, *prev_all;
+-
+-	all = ldns_rr_list_cat_clone(
+-			ldns_pkt_question(packet),
+-			ldns_pkt_answer(packet));
+-	prev_all = all;
+-	all = ldns_rr_list_cat_clone(all,
+-			ldns_pkt_authority(packet));
+-	ldns_rr_list_deep_free(prev_all);
+-	prev_all = all;
+-	all = ldns_rr_list_cat_clone(all,
+-			ldns_pkt_additional(packet));
+-	ldns_rr_list_deep_free(prev_all);
+-	return all;
+-}
+-
+-ldns_rr_list *
+-ldns_pkt_all_noquestion(const ldns_pkt *packet)
+-{
+-	ldns_rr_list *all, *all2;
+-
+-	all = ldns_rr_list_cat_clone(
+-			ldns_pkt_answer(packet),
+-			ldns_pkt_authority(packet));
+-	all2 = ldns_rr_list_cat_clone(all,
+-			ldns_pkt_additional(packet));
+-	
+-	ldns_rr_list_deep_free(all);
+-	return all2;
+-}
+-
+-size_t
+-ldns_pkt_size(const ldns_pkt *packet)
+-{
+-	return packet->_size;
+-}
+-
+-uint32_t 
+-ldns_pkt_querytime(const ldns_pkt *packet)
+-{
+-	return packet->_querytime;
+-}
+-
+-ldns_rdf *
+-ldns_pkt_answerfrom(const ldns_pkt *packet)
+-{
+-	return packet->_answerfrom;
+-}
+-
+-struct timeval
+-ldns_pkt_timestamp(const ldns_pkt *packet)
+-{
+-	return packet->timestamp;
+-}
+-
+-uint16_t
+-ldns_pkt_edns_udp_size(const ldns_pkt *packet)
+-{
+-	return packet->_edns_udp_size;
+-}
+-
+-uint8_t
+-ldns_pkt_edns_extended_rcode(const ldns_pkt *packet)
+-{
+-	return packet->_edns_extended_rcode;
+-}
+-
+-uint8_t
+-ldns_pkt_edns_version(const ldns_pkt *packet)
+-{
+-	return packet->_edns_version;
+-}
+-
+-uint16_t
+-ldns_pkt_edns_z(const ldns_pkt *packet)
+-{
+-	return packet->_edns_z;
+-}
+-
+-bool
+-ldns_pkt_edns_do(const ldns_pkt *packet)
+-{
+-	return (packet->_edns_z & LDNS_EDNS_MASK_DO_BIT);
+-}
+-
+-void
+-ldns_pkt_set_edns_do(ldns_pkt *packet, bool value)
+-{
+-	if (value) {
+-		packet->_edns_z = packet->_edns_z | LDNS_EDNS_MASK_DO_BIT;
+-	} else {
+-		packet->_edns_z = packet->_edns_z & ~LDNS_EDNS_MASK_DO_BIT;
+-	}
+-}
+-
+-ldns_rdf *
+-ldns_pkt_edns_data(const ldns_pkt *packet)
+-{
+-	return packet->_edns_data;
+-}
+-
+-/* return only those rr that share the ownername */
+-ldns_rr_list *
+-ldns_pkt_rr_list_by_name(ldns_pkt *packet,
+-                         ldns_rdf *ownername,
+-                         ldns_pkt_section sec)
+-{
+-	ldns_rr_list *rrs;
+-	ldns_rr_list *ret;
+-	uint16_t i;
+-
+-	if (!packet) {
+-		return NULL;
+-	}
+-
+-	rrs = ldns_pkt_get_section_clone(packet, sec);
+-	ret = NULL;
+-
+-	for(i = 0; i < ldns_rr_list_rr_count(rrs); i++) {
+-		if (ldns_dname_compare(ldns_rr_owner(
+-						ldns_rr_list_rr(rrs, i)), 
+-					ownername) == 0) {
+-			/* owner names match */
+-			if (ret == NULL) {
+-				ret = ldns_rr_list_new();
+-			}
+-			ldns_rr_list_push_rr(ret,
+-					     ldns_rr_clone(
+-						ldns_rr_list_rr(rrs, i))
+-					    );
+-		}
+-	}
+-
+-	ldns_rr_list_deep_free(rrs);
+-
+-	return ret;
+-}
+-
+-/* return only those rr that share a type */
+-ldns_rr_list *
+-ldns_pkt_rr_list_by_type(const ldns_pkt *packet,
+-                         ldns_rr_type type,
+-                         ldns_pkt_section sec)
+-{
+-	ldns_rr_list *rrs;
+-	ldns_rr_list *new;
+-	uint16_t i;
+-
+-	if(!packet) {
+-		return NULL;
+-	}
+-	
+-	rrs = ldns_pkt_get_section_clone(packet, sec);
+-	new = ldns_rr_list_new();
+-	
+-	for(i = 0; i < ldns_rr_list_rr_count(rrs); i++) {
+-		if (type == ldns_rr_get_type(ldns_rr_list_rr(rrs, i))) {
+-			/* types match */
+-			ldns_rr_list_push_rr(new, 
+-			                     ldns_rr_clone(
+-			                     	ldns_rr_list_rr(rrs, i))
+-					     );
+-		}
+-	}
+-	ldns_rr_list_deep_free(rrs);
+-
+-	if (ldns_rr_list_rr_count(new) == 0) {
+-		ldns_rr_list_free(new);
+-		return NULL;
+-	} else {
+-		return new;
+-	}
+-}
+-
+-/* return only those rrs that share name and type */
+-ldns_rr_list *
+-ldns_pkt_rr_list_by_name_and_type(const ldns_pkt *packet,
+-                                  const ldns_rdf *ownername,
+-                                  ldns_rr_type type,
+-                                  ldns_pkt_section sec)
+-{
+-	ldns_rr_list *rrs;
+-	ldns_rr_list *new;
+-	ldns_rr_list *ret;
+-	uint16_t i;
+-
+-	if(!packet) {
+-		return NULL;
+-	}
+-	
+-	rrs = ldns_pkt_get_section_clone(packet, sec);
+-	new = ldns_rr_list_new();
+-	ret = NULL;
+-
+-	for(i = 0; i < ldns_rr_list_rr_count(rrs); i++) {
+-		if (type == ldns_rr_get_type(ldns_rr_list_rr(rrs, i)) &&
+-		    ldns_dname_compare(ldns_rr_owner(ldns_rr_list_rr(rrs, i)),
+-		                     ownername
+-		                    ) == 0
+-		   ) {
+-			/* types match */
+-			ldns_rr_list_push_rr(new, ldns_rr_clone(ldns_rr_list_rr(rrs, i)));
+-			ret = new;
+-		}
+-	}
+-	ldns_rr_list_deep_free(rrs);
+-	if (!ret) {
+-		ldns_rr_list_free(new);
+-	}
+-	return ret;
+-}
+-
+-bool
+-ldns_pkt_rr(ldns_pkt *pkt, ldns_pkt_section sec, ldns_rr *rr)
+-{
+-	bool result = false;
+-
+-	switch (sec) {
+-	case LDNS_SECTION_QUESTION:
+-		return ldns_rr_list_contains_rr(ldns_pkt_question(pkt), rr);
+-	case LDNS_SECTION_ANSWER:
+-		return ldns_rr_list_contains_rr(ldns_pkt_answer(pkt), rr);
+-	case LDNS_SECTION_AUTHORITY:
+-		return ldns_rr_list_contains_rr(ldns_pkt_authority(pkt), rr);
+-	case LDNS_SECTION_ADDITIONAL:
+-		return ldns_rr_list_contains_rr(ldns_pkt_additional(pkt), rr);
+-	case LDNS_SECTION_ANY:
+-		result = ldns_rr_list_contains_rr(ldns_pkt_question(pkt), rr);
+-	case LDNS_SECTION_ANY_NOQUESTION:
+-		result = result
+-		    || ldns_rr_list_contains_rr(ldns_pkt_answer(pkt), rr)
+-		    || ldns_rr_list_contains_rr(ldns_pkt_authority(pkt), rr)
+-		    || ldns_rr_list_contains_rr(ldns_pkt_additional(pkt), rr);
+-	}
+-
+-	return result;
+-}
+-
+-uint16_t
+-ldns_pkt_section_count(const ldns_pkt *packet, ldns_pkt_section s)
+-{
+-	switch(s) {
+-	case LDNS_SECTION_QUESTION:
+-		return ldns_pkt_qdcount(packet);
+-	case LDNS_SECTION_ANSWER:
+-		return ldns_pkt_ancount(packet);
+-	case LDNS_SECTION_AUTHORITY:
+-		return ldns_pkt_nscount(packet);
+-	case LDNS_SECTION_ADDITIONAL:
+-		return ldns_pkt_arcount(packet);
+-	case LDNS_SECTION_ANY:
+-		return ldns_pkt_qdcount(packet) +
+-			ldns_pkt_ancount(packet) +
+-			ldns_pkt_nscount(packet) +
+-			ldns_pkt_arcount(packet);
+-	case LDNS_SECTION_ANY_NOQUESTION:
+-		return ldns_pkt_ancount(packet) +
+-			ldns_pkt_nscount(packet) +
+-			ldns_pkt_arcount(packet);
+-	default:
+-		return 0;
+-	}
+-}
+-
+-bool
+-ldns_pkt_empty(ldns_pkt *p)
+-{
+-	if (!p) {
+-		return true; /* NULL is empty? */
+-	}
+-	if (ldns_pkt_section_count(p, LDNS_SECTION_ANY) > 0) {
+-		return false;
+-	} else {
+-		return true;
+-    }
+-}
+-
+-
+-ldns_rr_list *
+-ldns_pkt_get_section_clone(const ldns_pkt *packet, ldns_pkt_section s)
+-{
+-	switch(s) {
+-	case LDNS_SECTION_QUESTION:
+-		return ldns_rr_list_clone(ldns_pkt_question(packet));
+-	case LDNS_SECTION_ANSWER:
+-		return ldns_rr_list_clone(ldns_pkt_answer(packet));
+-	case LDNS_SECTION_AUTHORITY:
+-		return ldns_rr_list_clone(ldns_pkt_authority(packet));
+-	case LDNS_SECTION_ADDITIONAL:
+-		return ldns_rr_list_clone(ldns_pkt_additional(packet));
+-	case LDNS_SECTION_ANY:
+-		/* these are already clones */
+-		return ldns_pkt_all(packet);
+-	case LDNS_SECTION_ANY_NOQUESTION:
+-		return ldns_pkt_all_noquestion(packet);
+-	default:
+-		return NULL;
+-	}
+-}
+-
+-ldns_rr *ldns_pkt_tsig(const ldns_pkt *pkt) {
+-	return pkt->_tsig_rr;
+-}
+-
+-/* write */
+-void
+-ldns_pkt_set_id(ldns_pkt *packet, uint16_t id)
+-{
+-	packet->_header->_id = id;
+-}
+-
+-void
+-ldns_pkt_set_random_id(ldns_pkt *packet)
+-{
+-	uint16_t rid = ldns_get_random();
+-	ldns_pkt_set_id(packet, rid);
+-}
+-
+-
+-void
+-ldns_pkt_set_qr(ldns_pkt *packet, bool qr)
+-{
+-	packet->_header->_qr = qr;
+-}
+-
+-void
+-ldns_pkt_set_aa(ldns_pkt *packet, bool aa)
+-{
+-	packet->_header->_aa = aa;
+-}
+-
+-void
+-ldns_pkt_set_tc(ldns_pkt *packet, bool tc)
+-{
+-	packet->_header->_tc = tc;
+-}
+-
+-void
+-ldns_pkt_set_rd(ldns_pkt *packet, bool rd)
+-{
+-	packet->_header->_rd = rd;
+-}
+-
+-void
+-ldns_pkt_set_additional(ldns_pkt *p, ldns_rr_list *rr)
+-{
+-	p->_additional = rr;
+-}
+-
+-void
+-ldns_pkt_set_question(ldns_pkt *p, ldns_rr_list *rr)
+-{
+-	p->_question = rr;
+-}
+-
+-void
+-ldns_pkt_set_answer(ldns_pkt *p, ldns_rr_list *rr)
+-{
+-	p->_answer = rr;
+-}
+-
+-void
+-ldns_pkt_set_authority(ldns_pkt *p, ldns_rr_list *rr)
+-{
+-	p->_authority = rr;
+-}
+-
+-void
+-ldns_pkt_set_cd(ldns_pkt *packet, bool cd)
+-{
+-	packet->_header->_cd = cd;
+-}
+-
+-void
+-ldns_pkt_set_ra(ldns_pkt *packet, bool ra)
+-{
+-	packet->_header->_ra = ra;
+-}
+-
+-void
+-ldns_pkt_set_ad(ldns_pkt *packet, bool ad)
+-{
+-	packet->_header->_ad = ad;
+-}
+-
+-void
+-ldns_pkt_set_opcode(ldns_pkt *packet, ldns_pkt_opcode opcode)
+-{
+-	packet->_header->_opcode = opcode;
+-}
+-
+-void
+-ldns_pkt_set_rcode(ldns_pkt *packet, uint8_t rcode)
+-{
+-	packet->_header->_rcode = rcode;
+-}
+-
+-void
+-ldns_pkt_set_qdcount(ldns_pkt *packet, uint16_t qdcount)
+-{
+-	packet->_header->_qdcount = qdcount;
+-}
+-
+-void
+-ldns_pkt_set_ancount(ldns_pkt *packet, uint16_t ancount)
+-{
+-	packet->_header->_ancount = ancount;
+-}
+-
+-void
+-ldns_pkt_set_nscount(ldns_pkt *packet, uint16_t nscount)
+-{
+-	packet->_header->_nscount = nscount;
+-}
+-
+-void
+-ldns_pkt_set_arcount(ldns_pkt *packet, uint16_t arcount)
+-{
+-	packet->_header->_arcount = arcount;
+-}
+-
+-void
+-ldns_pkt_set_querytime(ldns_pkt *packet, uint32_t time) 
+-{
+-	packet->_querytime = time;
+-}
+-
+-void
+-ldns_pkt_set_answerfrom(ldns_pkt *packet, ldns_rdf *answerfrom)
+-{
+-	packet->_answerfrom = answerfrom;
+-}
+-
+-void
+-ldns_pkt_set_timestamp(ldns_pkt *packet, struct timeval timeval)
+-{
+-	packet->timestamp.tv_sec = timeval.tv_sec;
+-	packet->timestamp.tv_usec = timeval.tv_usec;
+-}
+-
+-void
+-ldns_pkt_set_size(ldns_pkt *packet, size_t s)
+-{
+-	packet->_size = s;
+-}
+-
+-void
+-ldns_pkt_set_edns_udp_size(ldns_pkt *packet, uint16_t s)
+-{
+-	packet->_edns_udp_size = s;
+-}
+-
+-void
+-ldns_pkt_set_edns_extended_rcode(ldns_pkt *packet, uint8_t c)
+-{
+-	packet->_edns_extended_rcode = c;
+-}
+-
+-void
+-ldns_pkt_set_edns_version(ldns_pkt *packet, uint8_t v)
+-{
+-	packet->_edns_version = v;
+-}
+-
+-void
+-ldns_pkt_set_edns_z(ldns_pkt *packet, uint16_t z)
+-{
+-	packet->_edns_z = z;
+-}
+-
+-void
+-ldns_pkt_set_edns_data(ldns_pkt *packet, ldns_rdf *data)
+-{
+-	packet->_edns_data = data;
+-}
+-
+-void
+-ldns_pkt_set_section_count(ldns_pkt *packet, ldns_pkt_section s, uint16_t count)
+-{
+-	switch(s) {
+-		case LDNS_SECTION_QUESTION:
+-			ldns_pkt_set_qdcount(packet, count);
+-			break;
+-		case LDNS_SECTION_ANSWER:
+-			ldns_pkt_set_ancount(packet, count);
+-			break;
+-		case LDNS_SECTION_AUTHORITY:
+-			ldns_pkt_set_nscount(packet, count);
+-			break;
+-		case LDNS_SECTION_ADDITIONAL:
+-			ldns_pkt_set_arcount(packet, count);
+-			break;
+-		case LDNS_SECTION_ANY:
+-		case LDNS_SECTION_ANY_NOQUESTION:
+-			break;
+-	}
+-}
+-
+-void ldns_pkt_set_tsig(ldns_pkt *pkt, ldns_rr *rr)
+-{
+-	pkt->_tsig_rr = rr;
+-}
+-
+-bool
+-ldns_pkt_push_rr(ldns_pkt *packet, ldns_pkt_section section, ldns_rr *rr)
+-{
+-	switch(section) {
+-		case LDNS_SECTION_QUESTION:
+-			if (!ldns_rr_list_push_rr(ldns_pkt_question(packet), rr)) {
+-				return false;
+-			}
+-			ldns_pkt_set_qdcount(packet, ldns_pkt_qdcount(packet) + 1);
+-			break;
+-		case LDNS_SECTION_ANSWER:
+-			if (!ldns_rr_list_push_rr(ldns_pkt_answer(packet), rr)) {
+-				return false;
+-			}
+-			ldns_pkt_set_ancount(packet, ldns_pkt_ancount(packet) + 1);
+-			break;
+-		case LDNS_SECTION_AUTHORITY:
+-			if (!ldns_rr_list_push_rr(ldns_pkt_authority(packet), rr)) {
+-				return false;
+-			}
+-			ldns_pkt_set_nscount(packet, ldns_pkt_nscount(packet) + 1);
+-			break;
+-		case LDNS_SECTION_ADDITIONAL:
+-			if (!ldns_rr_list_push_rr(ldns_pkt_additional(packet), rr)) {
+-				return false;
+-			}
+-			ldns_pkt_set_arcount(packet, ldns_pkt_arcount(packet) + 1);
+-			break;
+-		case LDNS_SECTION_ANY:
+-		case LDNS_SECTION_ANY_NOQUESTION:
+-			/* shouldn't this error? */
+-			break;
+-	}
+-	return true;
+-}
+-
+-bool
+-ldns_pkt_safe_push_rr(ldns_pkt *pkt, ldns_pkt_section sec, ldns_rr *rr)
+-{
+-
+-	/* check to see if its there */
+-	if (ldns_pkt_rr(pkt, sec, rr)) {
+-		/* already there */
+-		return false;
+-	}
+-	return ldns_pkt_push_rr(pkt, sec, rr);
+-}
+-
+-bool
+-ldns_pkt_push_rr_list(ldns_pkt *p, ldns_pkt_section s, ldns_rr_list *list)
+-{
+-	size_t i;
+-	for(i = 0; i < ldns_rr_list_rr_count(list); i++) {
+-		if (!ldns_pkt_push_rr(p, s, ldns_rr_list_rr(list, i))) {
+-			return false;
+-		}
+-	}
+-	return true;
+-}
+-
+-bool
+-ldns_pkt_safe_push_rr_list(ldns_pkt *p, ldns_pkt_section s, ldns_rr_list *list)
+-{
+-	size_t i;
+-	for(i = 0; i < ldns_rr_list_rr_count(list); i++) {
+-		if (!ldns_pkt_safe_push_rr(p, s, ldns_rr_list_rr(list, i))) {
+-			return false;
+-		}
+-	}
+-	return true;
+-}
+-
+-bool
+-ldns_pkt_edns(const ldns_pkt *pkt) {
+-	return (ldns_pkt_edns_udp_size(pkt) > 0 ||
+-		ldns_pkt_edns_extended_rcode(pkt) > 0 ||
+-		ldns_pkt_edns_data(pkt) ||
+-		ldns_pkt_edns_do(pkt) ||
+-                pkt->_edns_present
+-	       );
+-}
+-
+-
+-/* Create/destroy/convert functions
+- */
+-ldns_pkt *
+-ldns_pkt_new(void)
+-{
+-	ldns_pkt *packet;
+-	packet = LDNS_MALLOC(ldns_pkt);
+-	if (!packet) {
+-		return NULL;
+-	}
+-
+-	packet->_header = LDNS_MALLOC(ldns_hdr);
+-	if (!packet->_header) {
+-		LDNS_FREE(packet);
+-		return NULL;
+-	}
+-
+-	packet->_question = ldns_rr_list_new();
+-	packet->_answer = ldns_rr_list_new();
+-	packet->_authority = ldns_rr_list_new();
+-	packet->_additional = ldns_rr_list_new();
+-
+-	/* default everything to false */
+-	ldns_pkt_set_qr(packet, false);
+-	ldns_pkt_set_aa(packet, false);
+-	ldns_pkt_set_tc(packet, false);
+-	ldns_pkt_set_rd(packet, false);
+-	ldns_pkt_set_ra(packet, false);
+-	ldns_pkt_set_ad(packet, false);
+-	ldns_pkt_set_cd(packet, false);
+-
+-	ldns_pkt_set_opcode(packet, LDNS_PACKET_QUERY);
+-	ldns_pkt_set_rcode(packet, 0);
+-	ldns_pkt_set_id(packet, 0); 
+-	ldns_pkt_set_size(packet, 0);
+-	ldns_pkt_set_querytime(packet, 0);
+-	memset(&packet->timestamp, 0, sizeof(packet->timestamp));
+-	ldns_pkt_set_answerfrom(packet, NULL);
+-	ldns_pkt_set_section_count(packet, LDNS_SECTION_QUESTION, 0);
+-	ldns_pkt_set_section_count(packet, LDNS_SECTION_ANSWER, 0);
+-	ldns_pkt_set_section_count(packet, LDNS_SECTION_AUTHORITY, 0);
+-	ldns_pkt_set_section_count(packet, LDNS_SECTION_ADDITIONAL, 0);
+-	
+-	ldns_pkt_set_edns_udp_size(packet, 0);
+-	ldns_pkt_set_edns_extended_rcode(packet, 0);
+-	ldns_pkt_set_edns_version(packet, 0);
+-	ldns_pkt_set_edns_z(packet, 0);
+-	ldns_pkt_set_edns_data(packet, NULL);
+-	packet->_edns_present = false;
+-	
+-	ldns_pkt_set_tsig(packet, NULL);
+-	
+-	return packet;
+-}
+-
+-void
+-ldns_pkt_free(ldns_pkt *packet)
+-{
+-	if (packet) {
+-		LDNS_FREE(packet->_header);
+-		ldns_rr_list_deep_free(packet->_question);
+-		ldns_rr_list_deep_free(packet->_answer);
+-		ldns_rr_list_deep_free(packet->_authority);
+-		ldns_rr_list_deep_free(packet->_additional);
+-		ldns_rr_free(packet->_tsig_rr);
+-		ldns_rdf_deep_free(packet->_edns_data);
+-		ldns_rdf_deep_free(packet->_answerfrom);
+-		LDNS_FREE(packet);
+-	}
+-}
+-
+-bool
+-ldns_pkt_set_flags(ldns_pkt *packet, uint16_t flags)
+-{
+-	if (!packet) {
+-		return false;
+-	}
+-	if ((flags & LDNS_QR) == LDNS_QR) {
+-		ldns_pkt_set_qr(packet, true);
+-	}
+-	if ((flags & LDNS_AA) == LDNS_AA) {
+-		ldns_pkt_set_aa(packet, true);
+-	}
+-	if ((flags & LDNS_RD) == LDNS_RD) {
+-		ldns_pkt_set_rd(packet, true);
+-	}
+-	if ((flags & LDNS_TC) == LDNS_TC) {
+-		ldns_pkt_set_tc(packet, true);
+-	}
+-	if ((flags & LDNS_CD) == LDNS_CD) {
+-		ldns_pkt_set_cd(packet, true);
+-	}
+-	if ((flags & LDNS_RA) == LDNS_RA) {
+-		ldns_pkt_set_ra(packet, true);
+-	}
+-	if ((flags & LDNS_AD) == LDNS_AD) {
+-		ldns_pkt_set_ad(packet, true);
+-	}
+-	return true;
+-}
+-
+-
+-static ldns_rr*
+-ldns_pkt_authsoa(ldns_rdf* rr_name, ldns_rr_class rr_class)
+-{
+-	ldns_rr* soa_rr = ldns_rr_new();
+-	ldns_rdf *owner_rdf;
+-	ldns_rdf *mname_rdf;
+-	ldns_rdf *rname_rdf;
+-	ldns_rdf *serial_rdf;
+-	ldns_rdf *refresh_rdf;
+-	ldns_rdf *retry_rdf;
+-	ldns_rdf *expire_rdf;
+-	ldns_rdf *minimum_rdf;
+-
+-	if (!soa_rr) {
+-		return NULL;
+-	}
+-	owner_rdf = ldns_rdf_clone(rr_name);
+-	if (!owner_rdf) {
+-		ldns_rr_free(soa_rr);
+-		return NULL;
+-	}
+-
+-	ldns_rr_set_owner(soa_rr, owner_rdf);
+-	ldns_rr_set_type(soa_rr, LDNS_RR_TYPE_SOA);
+-	ldns_rr_set_class(soa_rr, rr_class);
+-	ldns_rr_set_question(soa_rr, false);
+-
+-	if (ldns_str2rdf_dname(&mname_rdf, ".") != LDNS_STATUS_OK) {
+-		ldns_rr_free(soa_rr);
+-		return NULL;
+-	} else {
+-		ldns_rr_push_rdf(soa_rr, mname_rdf);
+-	}
+-	if (ldns_str2rdf_dname(&rname_rdf, ".") != LDNS_STATUS_OK) {
+-		ldns_rr_free(soa_rr);
+-		return NULL;
+-	} else {
+-		ldns_rr_push_rdf(soa_rr, rname_rdf);
+-	}
+-	serial_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0);
+-	if (!serial_rdf) {
+-		ldns_rr_free(soa_rr);
+-		return NULL;
+-	} else {
+-		ldns_rr_push_rdf(soa_rr, serial_rdf);
+-	}
+-	refresh_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0);
+-	if (!refresh_rdf) {
+-		ldns_rr_free(soa_rr);
+-		return NULL;
+-	} else {
+-		ldns_rr_push_rdf(soa_rr, refresh_rdf);
+-	}
+-	retry_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0);
+-	if (!retry_rdf) {
+-		ldns_rr_free(soa_rr);
+-		return NULL;
+-	} else {
+-		ldns_rr_push_rdf(soa_rr, retry_rdf);
+-	}
+-	expire_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0);
+-	if (!expire_rdf) {
+-		ldns_rr_free(soa_rr);
+-		return NULL;
+-	} else {
+-		ldns_rr_push_rdf(soa_rr, expire_rdf);
+-	}
+-	minimum_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0);
+-	if (!minimum_rdf) {
+-		ldns_rr_free(soa_rr);
+-		return NULL;
+-	} else {
+-		ldns_rr_push_rdf(soa_rr, minimum_rdf);
+-	}
+-	return soa_rr;
+-}
+-
+-
+-static ldns_status
+-ldns_pkt_query_new_frm_str_internal(ldns_pkt **p, const char *name,
+-	ldns_rr_type rr_type, ldns_rr_class rr_class, uint16_t flags,
+-	ldns_rr* authsoa_rr)
+-{
+-	ldns_pkt *packet;
+-	ldns_rr *question_rr;
+-	ldns_rdf *name_rdf;
+-
+-	packet = ldns_pkt_new();
+-	if (!packet) {
+-		return LDNS_STATUS_MEM_ERR;
+-	}
+-
+-	if (!ldns_pkt_set_flags(packet, flags)) {
+-		return LDNS_STATUS_ERR;
+-	}
+-
+-	question_rr = ldns_rr_new();
+-	if (!question_rr) {
+-		return LDNS_STATUS_MEM_ERR;
+-	}
+-
+-	if (rr_type == 0) {
+-		rr_type = LDNS_RR_TYPE_A;
+-	}
+-	if (rr_class == 0) {
+-		rr_class = LDNS_RR_CLASS_IN;
+-	}
+-
+-	if (ldns_str2rdf_dname(&name_rdf, name) == LDNS_STATUS_OK) {
+-		ldns_rr_set_owner(question_rr, name_rdf);
+-		ldns_rr_set_type(question_rr, rr_type);
+-		ldns_rr_set_class(question_rr, rr_class);
+-                ldns_rr_set_question(question_rr, true);
+-
+-		ldns_pkt_push_rr(packet, LDNS_SECTION_QUESTION, question_rr);
+-	} else {
+-		ldns_rr_free(question_rr);
+-		ldns_pkt_free(packet);
+-		return LDNS_STATUS_ERR;
+-	}
+-
+-	if (authsoa_rr) {
+-		ldns_pkt_push_rr(packet, LDNS_SECTION_AUTHORITY, authsoa_rr);
+-	}
+-
+-	packet->_tsig_rr = NULL;
+-	ldns_pkt_set_answerfrom(packet, NULL);
+-	if (p) {
+-		*p = packet;
+-		return LDNS_STATUS_OK;
+-	} else {
+-		ldns_pkt_free(packet);
+-		return LDNS_STATUS_NULL;
+-	}
+-}
+-
+-ldns_status
+-ldns_pkt_query_new_frm_str(ldns_pkt **p, const char *name,
+-	ldns_rr_type rr_type, ldns_rr_class rr_class, uint16_t flags)
+-{
+-	return ldns_pkt_query_new_frm_str_internal(p, name, rr_type,
+-		rr_class, flags, NULL);
+-}
+-
+-ldns_status
+-ldns_pkt_ixfr_request_new_frm_str(ldns_pkt **p, const char *name,
+-	ldns_rr_class rr_class, uint16_t flags, ldns_rr *soa)
+-{
+-	ldns_rr* authsoa_rr = soa;
+-	if (!authsoa_rr) {
+-		ldns_rdf *name_rdf;
+-		if (ldns_str2rdf_dname(&name_rdf, name) == LDNS_STATUS_OK) {
+-			authsoa_rr = ldns_pkt_authsoa(name_rdf, rr_class);
+-		}
+-		ldns_rdf_free(name_rdf);
+-	}
+-	return ldns_pkt_query_new_frm_str_internal(p, name, LDNS_RR_TYPE_IXFR,
+-		rr_class, flags, authsoa_rr);
+-}
+-
+-static ldns_pkt *
+-ldns_pkt_query_new_internal(ldns_rdf *rr_name, ldns_rr_type rr_type,
+-	ldns_rr_class rr_class,	uint16_t flags, ldns_rr* authsoa_rr)
+-{
+-	ldns_pkt *packet;
+-	ldns_rr *question_rr;
+-
+-	packet = ldns_pkt_new();
+-	if (!packet) {
+-		return NULL;
+-	}
+-
+-	if (!ldns_pkt_set_flags(packet, flags)) {
+-		return NULL;
+-	}
+-
+-	question_rr = ldns_rr_new();
+-	if (!question_rr) {
+-		ldns_pkt_free(packet);
+-		return NULL;
+-	}
+-
+-	if (rr_type == 0) {
+-		rr_type = LDNS_RR_TYPE_A;
+-	}
+-	if (rr_class == 0) {
+-		rr_class = LDNS_RR_CLASS_IN;
+-	}
+-
+-	ldns_rr_set_owner(question_rr, rr_name);
+-	ldns_rr_set_type(question_rr, rr_type);
+-	ldns_rr_set_class(question_rr, rr_class);
+-        ldns_rr_set_question(question_rr, true);
+-	ldns_pkt_push_rr(packet, LDNS_SECTION_QUESTION, question_rr);
+-
+-	if (authsoa_rr) {
+-		ldns_pkt_push_rr(packet, LDNS_SECTION_AUTHORITY, authsoa_rr);
+-	}
+-
+-	packet->_tsig_rr = NULL;
+-	return packet;
+-}
+-
+-ldns_pkt *
+-ldns_pkt_query_new(ldns_rdf *rr_name, ldns_rr_type rr_type,
+-	ldns_rr_class rr_class,	uint16_t flags)
+-{
+-	return ldns_pkt_query_new_internal(rr_name, rr_type,
+-		rr_class, flags, NULL);
+-}
+-
+-ldns_pkt *
+-ldns_pkt_ixfr_request_new(ldns_rdf *rr_name, ldns_rr_class rr_class,
+-	uint16_t flags, ldns_rr* soa)
+-{
+-	ldns_rr* authsoa_rr = soa;
+-	if (!authsoa_rr) {
+-		authsoa_rr = ldns_pkt_authsoa(rr_name, rr_class);
+-	}
+-	return ldns_pkt_query_new_internal(rr_name, LDNS_RR_TYPE_IXFR,
+-		rr_class, flags, authsoa_rr);
+-}
+-
+-ldns_pkt_type
+-ldns_pkt_reply_type(ldns_pkt *p)
+-{
+-	ldns_rr_list *tmp;
+-
+-	if (!p) {
+-		return LDNS_PACKET_UNKNOWN;
+-	}
+-
+-	if (ldns_pkt_get_rcode(p) == LDNS_RCODE_NXDOMAIN) {
+-		return LDNS_PACKET_NXDOMAIN;
+-	}
+-
+-	if (ldns_pkt_ancount(p) == 0 && ldns_pkt_arcount(p) == 0
+-			&& ldns_pkt_nscount(p) == 1) {
+-
+-		/* check for SOA */
+-		tmp = ldns_pkt_rr_list_by_type(p, LDNS_RR_TYPE_SOA, 
+-					LDNS_SECTION_AUTHORITY);
+-		if (tmp) {
+-			ldns_rr_list_deep_free(tmp);
+-			return LDNS_PACKET_NODATA;
+-		} else {
+-			/* I have no idea ... */
+-		}
+-	}
+-
+-	if (ldns_pkt_ancount(p) == 0 && ldns_pkt_nscount(p) > 0) {
+-		tmp = ldns_pkt_rr_list_by_type(p, LDNS_RR_TYPE_NS,
+-		                               LDNS_SECTION_AUTHORITY);
+-		if (tmp) {
+-			/* there are nameservers here */
+-			ldns_rr_list_deep_free(tmp);
+-			return LDNS_PACKET_REFERRAL;
+-		} else {
+-			/* I have no idea */
+-		}
+-		ldns_rr_list_deep_free(tmp);
+-	}
+-	
+-	/* if we cannot determine the packet type, we say it's an 
+-	 * answer...
+-	 */
+-	return LDNS_PACKET_ANSWER;
+-}
+-
+-ldns_pkt *
+-ldns_pkt_clone(const ldns_pkt *pkt)
+-{
+-	ldns_pkt *new_pkt;
+-	
+-	if (!pkt) {
+-		return NULL;
+-	}
+-	new_pkt = ldns_pkt_new();
+-
+-	ldns_pkt_set_id(new_pkt, ldns_pkt_id(pkt));
+-	ldns_pkt_set_qr(new_pkt, ldns_pkt_qr(pkt));
+-	ldns_pkt_set_aa(new_pkt, ldns_pkt_aa(pkt));
+-	ldns_pkt_set_tc(new_pkt, ldns_pkt_tc(pkt));
+-	ldns_pkt_set_rd(new_pkt, ldns_pkt_rd(pkt));
+-	ldns_pkt_set_cd(new_pkt, ldns_pkt_cd(pkt));
+-	ldns_pkt_set_ra(new_pkt, ldns_pkt_ra(pkt));
+-	ldns_pkt_set_ad(new_pkt, ldns_pkt_ad(pkt));
+-	ldns_pkt_set_opcode(new_pkt, ldns_pkt_get_opcode(pkt));
+-	ldns_pkt_set_rcode(new_pkt, ldns_pkt_get_rcode(pkt));
+-	ldns_pkt_set_qdcount(new_pkt, ldns_pkt_qdcount(pkt));
+-	ldns_pkt_set_ancount(new_pkt, ldns_pkt_ancount(pkt));
+-	ldns_pkt_set_nscount(new_pkt, ldns_pkt_nscount(pkt));
+-	ldns_pkt_set_arcount(new_pkt, ldns_pkt_arcount(pkt));
+-	if (ldns_pkt_answerfrom(pkt))
+-		ldns_pkt_set_answerfrom(new_pkt,
+-			ldns_rdf_clone(ldns_pkt_answerfrom(pkt)));
+-	ldns_pkt_set_timestamp(new_pkt, ldns_pkt_timestamp(pkt));
+-	ldns_pkt_set_querytime(new_pkt, ldns_pkt_querytime(pkt));
+-	ldns_pkt_set_size(new_pkt, ldns_pkt_size(pkt));
+-	ldns_pkt_set_tsig(new_pkt, ldns_rr_clone(ldns_pkt_tsig(pkt)));
+-	
+-	ldns_pkt_set_edns_udp_size(new_pkt, ldns_pkt_edns_udp_size(pkt));
+-	ldns_pkt_set_edns_extended_rcode(new_pkt, 
+-		ldns_pkt_edns_extended_rcode(pkt));
+-	ldns_pkt_set_edns_version(new_pkt, ldns_pkt_edns_version(pkt));
+-	new_pkt->_edns_present = pkt->_edns_present;
+-	ldns_pkt_set_edns_z(new_pkt, ldns_pkt_edns_z(pkt));
+-	if(ldns_pkt_edns_data(pkt))
+-		ldns_pkt_set_edns_data(new_pkt, 
+-			ldns_rdf_clone(ldns_pkt_edns_data(pkt)));
+-	ldns_pkt_set_edns_do(new_pkt, ldns_pkt_edns_do(pkt));
+-
+-	ldns_rr_list_deep_free(new_pkt->_question);
+-	ldns_rr_list_deep_free(new_pkt->_answer);
+-	ldns_rr_list_deep_free(new_pkt->_authority);
+-	ldns_rr_list_deep_free(new_pkt->_additional);
+-	new_pkt->_question = ldns_rr_list_clone(ldns_pkt_question(pkt));
+-	new_pkt->_answer = ldns_rr_list_clone(ldns_pkt_answer(pkt));
+-	new_pkt->_authority = ldns_rr_list_clone(ldns_pkt_authority(pkt));
+-	new_pkt->_additional = ldns_rr_list_clone(ldns_pkt_additional(pkt));
+-	return new_pkt;
+-}
+diff --git a/src/ldns/parse.c b/src/ldns/parse.c
+deleted file mode 100644
+index e68627c..0000000
+--- a/src/ldns/parse.c
++++ /dev/null
+@@ -1,434 +0,0 @@
+-/*
+- * a generic (simple) parser. Use to parse rr's, private key
+- * information and /etc/resolv.conf files
+- *
+- * a Net::DNS like library for C
+- * LibDNS Team @ NLnet Labs
+- * (c) NLnet Labs, 2005-2006
+- * See the file LICENSE for the license
+- */
+-#include <ldns/config.h>
+-#include <ldns/ldns.h>
+-
+-#include <limits.h>
+-#include <strings.h>
+-
+-ldns_lookup_table ldns_directive_types[] = {
+-        { LDNS_DIR_TTL, "$TTL" },
+-        { LDNS_DIR_ORIGIN, "$ORIGIN" },
+-        { LDNS_DIR_INCLUDE, "$INCLUDE" },
+-        { 0, NULL }
+-};
+-
+-/* add max_limit here? */
+-ssize_t
+-ldns_fget_token(FILE *f, char *token, const char *delim, size_t limit)
+-{
+-	return ldns_fget_token_l(f, token, delim, limit, NULL);
+-}
+-
+-ssize_t
+-ldns_fget_token_l(FILE *f, char *token, const char *delim, size_t limit, int *line_nr)
+-{
+-	int c, prev_c;
+-	int p; /* 0 -> no parenthese seen, >0 nr of ( seen */
+-	int com, quoted;
+-	char *t;
+-	size_t i;
+-	const char *d;
+-	const char *del;
+-
+-	/* standard delimeters */
+-	if (!delim) {
+-		/* from isspace(3) */
+-		del = LDNS_PARSE_NORMAL;
+-	} else {
+-		del = delim;
+-	}
+-
+-	p = 0;
+-	i = 0;
+-	com = 0;
+-	quoted = 0;
+-	prev_c = 0;
+-	t = token;
+-	if (del[0] == '"') {
+-		quoted = 1;
+-	}
+-	while ((c = getc(f)) != EOF) {
+-		if (c == '\r') /* carriage return */
+-			c = ' ';
+-		if (c == '(' && prev_c != '\\' && !quoted) {
+-			/* this only counts for non-comments */
+-			if (com == 0) {
+-				p++;
+-			}
+-			prev_c = c;
+-			continue;
+-		}
+-
+-		if (c == ')' && prev_c != '\\' && !quoted) {
+-			/* this only counts for non-comments */
+-			if (com == 0) {
+-				p--;
+-			}
+-			prev_c = c;
+-			continue;
+-		}
+-
+-		if (p < 0) {
+-			/* more ) then ( - close off the string */
+-			*t = '\0';
+-			return 0;
+-		}
+-
+-		/* do something with comments ; */
+-		if (c == ';' && quoted == 0) {
+-			if (prev_c != '\\') {
+-				com = 1;
+-			}
+-		}
+-		if (c == '\"' && com == 0 && prev_c != '\\') {
+-			quoted = 1 - quoted;
+-		}
+-
+-		if (c == '\n' && com != 0) {
+-			/* comments */
+-			com = 0;
+-			*t = ' ';
+-			if (line_nr) {
+-				*line_nr = *line_nr + 1;
+-			}
+-			if (p == 0 && i > 0) {
+-				goto tokenread;
+-			} else {
+-				prev_c = c;
+-				continue;
+-			}
+-		}
+-
+-		if (com == 1) {
+-			*t = ' ';
+-			prev_c = c;
+-			continue;
+-		}
+-
+-		if (c == '\n' && p != 0 && t > token) {
+-			/* in parentheses */
+-			if (line_nr) {
+-				*line_nr = *line_nr + 1;
+-			}
+-			*t++ = ' ';
+-			prev_c = c;
+-			continue;
+-		}
+-
+-		/* check if we hit the delim */
+-		for (d = del; *d; d++) {
+-			if (c == *d && i > 0 && prev_c != '\\' && p == 0) {
+-				if (c == '\n' && line_nr) {
+-					*line_nr = *line_nr + 1;
+-				}
+-				goto tokenread;
+-			}
+-		}
+-		if (c != '\0' && c != '\n') {
+-			i++;
+-		}
+-		if (limit > 0 && (i >= limit || (size_t)(t-token) >= limit)) {
+-			*t = '\0';
+-			return -1;
+-		}
+-		if (c != '\0' && c != '\n') {
+-			*t++ = c;
+-		}
+-		if (c == '\\' && prev_c == '\\')
+-			prev_c = 0;
+-		else	prev_c = c;
+-	}
+-	*t = '\0';
+-	if (c == EOF) {
+-		return (ssize_t)i;
+-	}
+-
+-	if (i == 0) {
+-		/* nothing read */
+-		return -1;
+-	}
+-	if (p != 0) {
+-		return -1;
+-	}
+-	return (ssize_t)i;
+-
+-tokenread:
+-	if(*del == '"') /* do not skip over quotes, they are significant */
+-		ldns_fskipcs_l(f, del+1, line_nr);
+-	else	ldns_fskipcs_l(f, del, line_nr);
+-	*t = '\0';
+-	if (p != 0) {
+-		return -1;
+-	}
+-
+-	return (ssize_t)i;
+-}
+-
+-ssize_t
+-ldns_fget_keyword_data(FILE *f, const char *keyword, const char *k_del, char *data,
+-               const char *d_del, size_t data_limit)
+-{
+-       return ldns_fget_keyword_data_l(f, keyword, k_del, data, d_del,
+-		       data_limit, NULL);
+-}
+-
+-ssize_t
+-ldns_fget_keyword_data_l(FILE *f, const char *keyword, const char *k_del, char *data,
+-               const char *d_del, size_t data_limit, int *line_nr)
+-{
+-       /* we assume: keyword|sep|data */
+-       char *fkeyword;
+-       ssize_t i;
+-
+-       if(strlen(keyword) >= LDNS_MAX_KEYWORDLEN)
+-               return -1;
+-       fkeyword = LDNS_XMALLOC(char, LDNS_MAX_KEYWORDLEN);
+-       if(!fkeyword)
+-               return -1;
+-
+-       i = ldns_fget_token(f, fkeyword, k_del, LDNS_MAX_KEYWORDLEN);
+-       if(i==0 || i==-1) {
+-               LDNS_FREE(fkeyword);
+-               return -1;
+-       }
+-
+-       /* case??? i instead of strlen? */
+-       if (strncmp(fkeyword, keyword, LDNS_MAX_KEYWORDLEN - 1) == 0) {
+-               /* whee! */
+-               /* printf("%s\n%s\n", "Matching keyword", fkeyword); */
+-               i = ldns_fget_token_l(f, data, d_del, data_limit, line_nr);
+-               LDNS_FREE(fkeyword);
+-               return i;
+-       } else {
+-               /*printf("no match for %s (read: %s)\n", keyword, fkeyword);*/
+-               LDNS_FREE(fkeyword);
+-               return -1;
+-       }
+-}
+-
+-
+-ssize_t
+-ldns_bget_token(ldns_buffer *b, char *token, const char *delim, size_t limit)
+-{
+-	int c, lc;
+-	int p; /* 0 -> no parenthese seen, >0 nr of ( seen */
+-	int com, quoted;
+-	char *t;
+-	size_t i;
+-	const char *d;
+-	const char *del;
+-
+-	/* standard delimiters */
+-	if (!delim) {
+-		/* from isspace(3) */
+-		del = LDNS_PARSE_NORMAL;
+-	} else {
+-		del = delim;
+-	}
+-
+-	p = 0;
+-	i = 0;
+-	com = 0;
+-	quoted = 0;
+-	t = token;
+-	lc = 0;
+-	if (del[0] == '"') {
+-		quoted = 1;
+-	}
+-
+-	while ((c = ldns_bgetc(b)) != EOF) {
+-		if (c == '\r') /* carriage return */
+-			c = ' ';
+-		if (c == '(' && lc != '\\' && !quoted) {
+-			/* this only counts for non-comments */
+-			if (com == 0) {
+-				p++;
+-			}
+-			lc = c;
+-			continue;
+-		}
+-
+-		if (c == ')' && lc != '\\' && !quoted) {
+-			/* this only counts for non-comments */
+-			if (com == 0) {
+-				p--;
+-			}
+-			lc = c;
+-			continue;
+-		}
+-
+-		if (p < 0) {
+-			/* more ) then ( */
+-			*t = '\0';
+-			return 0;
+-		}
+-
+-		/* do something with comments ; */
+-		if (c == ';' && quoted == 0) {
+-			if (lc != '\\') {
+-				com = 1;
+-			}
+-		}
+-		if (c == '"' && com == 0 && lc != '\\') {
+-			quoted = 1 - quoted;
+-		}
+-
+-		if (c == '\n' && com != 0) {
+-			/* comments */
+-			com = 0;
+-			*t = ' ';
+-			lc = c;
+-			continue;
+-		}
+-
+-		if (com == 1) {
+-			*t = ' ';
+-			lc = c;
+-			continue;
+-		}
+-
+-		if (c == '\n' && p != 0) {
+-			/* in parentheses */
+-			*t++ = ' ';
+-			lc = c;
+-			continue;
+-		}
+-
+-		/* check if we hit the delim */
+-		for (d = del; *d; d++) {
+-                        if (c == *d && lc != '\\' && p == 0) {
+-				goto tokenread;
+-                        }
+-		}
+-
+-		i++;
+-		if (limit > 0 && (i >= limit || (size_t)(t-token) >= limit)) {
+-			*t = '\0';
+-			return -1;
+-		}
+-		*t++ = c;
+-
+-		if (c == '\\' && lc == '\\') {
+-			lc = 0;
+-		} else {
+-			lc = c;
+-		}
+-	}
+-	*t = '\0';
+-	if (i == 0) {
+-		/* nothing read */
+-		return -1;
+-	}
+-	if (p != 0) {
+-		return -1;
+-	}
+-	return (ssize_t)i;
+-
+-tokenread:
+-	if(*del == '"') /* do not skip over quotes, they are significant */
+-		ldns_bskipcs(b, del+1);
+-	else	ldns_bskipcs(b, del);
+-	*t = '\0';
+-
+-	if (p != 0) {
+-		return -1;
+-	}
+-	return (ssize_t)i;
+-}
+-
+-
+-void
+-ldns_bskipcs(ldns_buffer *buffer, const char *s)
+-{
+-        bool found;
+-        char c;
+-        const char *d;
+-
+-        while(ldns_buffer_available_at(buffer, buffer->_position, sizeof(char))) {
+-                c = (char) ldns_buffer_read_u8_at(buffer, buffer->_position);
+-                found = false;
+-                for (d = s; *d; d++) {
+-                        if (*d == c) {
+-                                found = true;
+-                        }
+-                }
+-                if (found && buffer->_limit > buffer->_position) {
+-                        buffer->_position += sizeof(char);
+-                } else {
+-                        return;
+-                }
+-        }
+-}
+-
+-void
+-ldns_fskipcs(FILE *fp, const char *s)
+-{
+-	ldns_fskipcs_l(fp, s, NULL);
+-}
+-
+-void
+-ldns_fskipcs_l(FILE *fp, const char *s, int *line_nr)
+-{
+-        bool found;
+-        int c;
+-        const char *d;
+-
+-	while ((c = fgetc(fp)) != EOF) {
+-		if (line_nr && c == '\n') {
+-			*line_nr = *line_nr + 1;
+-		}
+-                found = false;
+-                for (d = s; *d; d++) {
+-                        if (*d == c) {
+-                                found = true;
+-                        }
+-                }
+-		if (!found) {
+-			/* with getc, we've read too far */
+-			ungetc(c, fp);
+-			return;
+-		}
+-	}
+-}
+-
+-ssize_t
+-ldns_bget_keyword_data(ldns_buffer *b, const char *keyword, const char *k_del, char
+-*data, const char *d_del, size_t data_limit)
+-{
+-       /* we assume: keyword|sep|data */
+-       char *fkeyword;
+-       ssize_t i;
+-
+-       if(strlen(keyword) >= LDNS_MAX_KEYWORDLEN)
+-               return -1;
+-       fkeyword = LDNS_XMALLOC(char, LDNS_MAX_KEYWORDLEN);
+-       if(!fkeyword)
+-               return -1; /* out of memory */
+-
+-       i = ldns_bget_token(b, fkeyword, k_del, data_limit);
+-       if(i==0 || i==-1) {
+-               LDNS_FREE(fkeyword);
+-               return -1; /* nothing read */
+-       }
+-
+-       /* case??? */
+-       if (strncmp(fkeyword, keyword, strlen(keyword)) == 0) {
+-               LDNS_FREE(fkeyword);
+-               /* whee, the match! */
+-               /* retrieve it's data */
+-               i = ldns_bget_token(b, data, d_del, 0);
+-               return i;
+-       } else {
+-               LDNS_FREE(fkeyword);
+-               return -1;
+-       }
+-}
+-
+diff --git a/src/ldns/radix.c b/src/ldns/radix.c
+deleted file mode 100644
+index 7aac258..0000000
+--- a/src/ldns/radix.c
++++ /dev/null
+@@ -1,1590 +0,0 @@
+-/*
+- * radix.c -- generic radix tree
+- *
+- * Taken from NSD4, modified for ldns
+- *
+- * Copyright (c) 2012, NLnet Labs. All rights reserved.
+- *
+- * This software is open source.
+- *
+- * Redistribution and use in source and binary forms, with or without
+- * modification, are permitted provided that the following conditions
+- * are met:
+- *
+- * Redistributions of source code must retain the above copyright notice,
+- * this list of conditions and the following disclaimer.
+- *
+- * Redistributions in binary form must reproduce the above copyright notice,
+- * this list of conditions and the following disclaimer in the documentation
+- * and/or other materials provided with the distribution.
+- *
+- * Neither the name of the NLNET LABS nor the names of its contributors may
+- * be used to endorse or promote products derived from this software without
+- * specific prior written permission.
+- *
+- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+- * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+- * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+- *
+- */
+-
+-/**
+- * \file
+- * Implementation of a radix tree.
+- */
+-
+-#include <ldns/config.h>
+-#include <ldns/radix.h>
+-#include <ldns/util.h>
+-#include <stdlib.h>
+-
+-/** Helper functions */
+-static ldns_radix_node_t* ldns_radix_new_node(void* data, uint8_t* key,
+-	radix_strlen_t len);
+-static int ldns_radix_find_prefix(ldns_radix_t* tree, uint8_t* key,
+-	radix_strlen_t len, ldns_radix_node_t** result, radix_strlen_t* pos);
+-static int ldns_radix_array_space(ldns_radix_node_t* node, uint8_t byte);
+-static int ldns_radix_array_grow(ldns_radix_node_t* node, unsigned need);
+-static int ldns_radix_str_create(ldns_radix_array_t* array, uint8_t* key,
+-	radix_strlen_t pos, radix_strlen_t len);
+-static int ldns_radix_prefix_remainder(radix_strlen_t prefix_len,
+-	uint8_t* longer_str, radix_strlen_t longer_len, uint8_t** split_str,
+-	radix_strlen_t* split_len);
+-static int ldns_radix_array_split(ldns_radix_array_t* array, uint8_t* key,
+-	radix_strlen_t pos, radix_strlen_t len, ldns_radix_node_t* add);
+-static int ldns_radix_str_is_prefix(uint8_t* str1, radix_strlen_t len1,
+-	uint8_t* str2, radix_strlen_t len2);
+-static radix_strlen_t ldns_radix_str_common(uint8_t* str1, radix_strlen_t len1,
+-	uint8_t* str2, radix_strlen_t len2);
+-static ldns_radix_node_t* ldns_radix_next_in_subtree(ldns_radix_node_t* node);
+-static ldns_radix_node_t* ldns_radix_prev_from_index(ldns_radix_node_t* node,
+-	uint8_t index);
+-static ldns_radix_node_t* ldns_radix_last_in_subtree_incl_self(
+-	ldns_radix_node_t* node);
+-static ldns_radix_node_t* ldns_radix_last_in_subtree(ldns_radix_node_t* node);
+-static void ldns_radix_del_fix(ldns_radix_t* tree, ldns_radix_node_t* node);
+-static void ldns_radix_cleanup_onechild(ldns_radix_node_t* node);
+-static void ldns_radix_cleanup_leaf(ldns_radix_node_t* node);
+-static void ldns_radix_node_free(ldns_radix_node_t* node, void* arg);
+-static void ldns_radix_node_array_free(ldns_radix_node_t* node);
+-static void ldns_radix_node_array_free_front(ldns_radix_node_t* node);
+-static void ldns_radix_node_array_free_end(ldns_radix_node_t* node);
+-static void ldns_radix_array_reduce(ldns_radix_node_t* node);
+-static void ldns_radix_self_or_prev(ldns_radix_node_t* node,
+-	ldns_radix_node_t** result);
+-
+-
+-/**
+- * Create a new radix node.
+- *
+- */
+-static ldns_radix_node_t*
+-ldns_radix_new_node(void* data, uint8_t* key, radix_strlen_t len)
+-{
+-	ldns_radix_node_t* node = LDNS_MALLOC(ldns_radix_node_t);
+-	if (!node) {
+-		return NULL;
+-	}
+-	node->data = data;
+-	node->key = key;
+-	node->klen = len;
+-	node->parent = NULL;
+-	node->parent_index = 0;
+-	node->len = 0;
+-	node->offset = 0;
+-	node->capacity = 0;
+-	node->array = NULL;
+-	return node;
+-}
+-
+-
+-/**
+- * Create a new radix tree.
+- *
+- */
+-ldns_radix_t *
+-ldns_radix_create(void)
+-{
+-	ldns_radix_t* tree;
+-
+-	/** Allocate memory for it */
+-	tree = (ldns_radix_t *) LDNS_MALLOC(ldns_radix_t);
+-	if (!tree) {
+-		return NULL;
+-	}
+-	/** Initialize it */
+-	ldns_radix_init(tree);
+-	return tree;
+-}
+-
+-
+-/**
+- * Initialize radix tree.
+- *
+- */
+-void
+-ldns_radix_init(ldns_radix_t* tree)
+-{
+-	/** Initialize it */
+-	if (tree) {
+-		tree->root = NULL;
+-		tree->count = 0;
+-	}
+-	return;
+-}
+-
+-
+-/**
+- * Free radix tree.
+- *
+- */
+-void
+-ldns_radix_free(ldns_radix_t* tree)
+-{
+-	if (tree) {
+-		if (tree->root) {
+-			ldns_radix_traverse_postorder(tree->root,
+-				ldns_radix_node_free, NULL);
+-		}
+-		LDNS_FREE(tree);
+-	}
+-	return;
+-}
+-
+-
+-/**
+- * Insert data into the tree.
+- *
+- */
+-ldns_status
+-ldns_radix_insert(ldns_radix_t* tree, uint8_t* key, radix_strlen_t len,
+-	void* data)
+-{
+-	radix_strlen_t pos = 0;
+-	ldns_radix_node_t* add = NULL;
+-	ldns_radix_node_t* prefix = NULL;
+-
+-	if (!tree || !key || !data) {
+-		return LDNS_STATUS_NULL;
+-	}
+-	add = ldns_radix_new_node(data, key, len);
+-	if (!add) {
+-		return LDNS_STATUS_MEM_ERR;
+-	}
+-	/** Search the trie until we can make no further process. */
+-	if (!ldns_radix_find_prefix(tree, key, len, &prefix, &pos)) {
+-		/** No prefix found */
+-		assert(tree->root == NULL);
+-		if (len == 0) {
+-			/**
+-			 * Example 1: The root:
+-			 * | [0]
+-			 **/
+-			tree->root = add;
+-		} else {
+-			/** Example 2: 'dns':
+-			 * | [0]
+-			 * --| [d+ns] dns
+-			 **/
+-			prefix = ldns_radix_new_node(NULL, (uint8_t*)"", 0);
+-			if (!prefix) {
+-				LDNS_FREE(add);
+-				return LDNS_STATUS_MEM_ERR;
+-			}
+-			/** Find some space in the array for the first byte */
+-			if (!ldns_radix_array_space(prefix, key[0])) {
+-				LDNS_FREE(add);
+-				LDNS_FREE(prefix->array);
+-				LDNS_FREE(prefix);
+-				return LDNS_STATUS_MEM_ERR;
+-			}
+-			/** Set relational pointers */
+-			add->parent = prefix;
+-			add->parent_index = 0;
+-			prefix->array[0].edge = add;
+-			if (len > 1) {
+-				/** Store the remainder of the prefix */
+-				if (!ldns_radix_prefix_remainder(1, key,
+-					len, &prefix->array[0].str,
+-					&prefix->array[0].len)) {
+-					LDNS_FREE(add);
+-					LDNS_FREE(prefix->array);
+-					LDNS_FREE(prefix);
+-					return LDNS_STATUS_MEM_ERR;
+-				}
+-			}
+-			tree->root = prefix;
+-		}
+-	} else if (pos == len) {
+-		/** Exact match found */
+-		if (prefix->data) {
+-			/* Element already exists */
+-			LDNS_FREE(add);
+-			return LDNS_STATUS_EXISTS_ERR;
+-		}
+-		prefix->data = data;
+-		prefix->key = key;
+-		prefix->klen = len; /* redundant */
+-	} else {
+-		/** Prefix found */
+-		uint8_t byte = key[pos];
+-		assert(pos < len);
+-		if (byte < prefix->offset ||
+-			(byte - prefix->offset) >= prefix->len) {
+-			/** Find some space in the array for the byte. */
+-			/**
+-			 * Example 3: 'ldns'
+-			 * | [0]
+-			 * --| [d+ns] dns
+-			 * --| [l+dns] ldns
+-			 **/
+-			if (!ldns_radix_array_space(prefix, byte)) {
+-				LDNS_FREE(add);
+-				return LDNS_STATUS_MEM_ERR;
+-			}
+-			assert(byte >= prefix->offset);
+-			assert((byte - prefix->offset) <= prefix->len);
+-			byte -= prefix->offset;
+-			if (pos+1 < len) {
+-				/** Create remainder of the string. */
+-				if (!ldns_radix_str_create(
+-					&prefix->array[byte], key, pos+1,
+-					len)) {
+-					LDNS_FREE(add);
+-					return LDNS_STATUS_MEM_ERR;
+-				}
+-			}
+-			/** Add new node. */
+-			add->parent = prefix;
+-			add->parent_index = byte;
+-			prefix->array[byte].edge = add;
+-		} else if (prefix->array[byte-prefix->offset].edge == NULL) {
+-			/** Use existing element. */
+-			/**
+-			 * Example 4: 'edns'
+-			 * | [0]
+-			 * --| [d+ns] dns
+-			 * --| [e+dns] edns
+-			 * --| [l+dns] ldns
+-			 **/
+-			byte -= prefix->offset;
+-			if (pos+1 < len) {
+-				/** Create remainder of the string. */
+-				if (!ldns_radix_str_create(
+-					&prefix->array[byte], key, pos+1,
+-					len)) {
+-					LDNS_FREE(add);
+-					return LDNS_STATUS_MEM_ERR;
+-				}
+-			}
+-			/** Add new node. */
+-			add->parent = prefix;
+-			add->parent_index = byte;
+-			prefix->array[byte].edge = add;
+-		} else {
+-			/**
+-			 * Use existing element, but it has a shared prefix,
+-			 * we need a split.
+-			 */
+-			if (!ldns_radix_array_split(&prefix->array[byte-(prefix->offset)],
+-				key, pos+1, len, add)) {
+-				LDNS_FREE(add);
+-				return LDNS_STATUS_MEM_ERR;
+-			}
+-		}
+-	}
+-
+-	tree->count ++;
+-	return LDNS_STATUS_OK;
+-}
+-
+-
+-/**
+- * Delete data from the tree.
+- *
+- */
+-void* ldns_radix_delete(ldns_radix_t* tree, uint8_t* key, radix_strlen_t len)
+-{
+-    ldns_radix_node_t* del = ldns_radix_search(tree, key, len);
+-    void* data = NULL;
+-    if (del) {
+-        tree->count--;
+-        data = del->data;
+-        del->data = NULL;
+-        ldns_radix_del_fix(tree, del);
+-        return data;
+-    }
+-    return NULL;
+-}
+-
+-
+-/**
+- * Search data in the tree.
+- *
+- */
+-ldns_radix_node_t*
+-ldns_radix_search(ldns_radix_t* tree, uint8_t* key, radix_strlen_t len)
+-{
+-	ldns_radix_node_t* node = NULL;
+-	radix_strlen_t pos = 0;
+-	uint8_t byte = 0;
+-
+-	if (!tree || !key) {
+-		return NULL;
+-	}
+-	node = tree->root;
+-	while (node) {
+-		if (pos == len) {
+-			return node->data?node:NULL;
+-		}
+-		byte = key[pos];
+-		if (byte < node->offset) {
+-			return NULL;
+-		}
+-		byte -= node->offset;
+-		if (byte >= node->len) {
+-			return NULL;
+-		}
+-		pos++;
+-		if (node->array[byte].len > 0) {
+-			/** Must match additional string. */
+-			if (pos + node->array[byte].len > len) {
+-				return NULL;
+-			}
+-			if (memcmp(&key[pos], node->array[byte].str,
+-				node->array[byte].len) != 0) {
+-				return NULL;
+-			}
+-			pos += node->array[byte].len;
+-		}
+-		node = node->array[byte].edge;
+-	}
+-	return NULL;
+-}
+-
+-
+-/**
+- * Search data in the tree, and if not found, find the closest smaller
+- * element in the tree.
+- *
+- */
+-int
+-ldns_radix_find_less_equal(ldns_radix_t* tree, uint8_t* key,
+-	radix_strlen_t len, ldns_radix_node_t** result)
+-{
+-	ldns_radix_node_t* node = NULL;
+-	radix_strlen_t pos = 0;
+-	uint8_t byte;
+-	int memcmp_res = 0;
+-
+-	if (!tree || !tree->root || !key) {
+-		*result = NULL;
+-		return 0;
+-	}
+-
+-	node = tree->root;
+-	while (pos < len) {
+-		byte = key[pos];
+-		if (byte < node->offset) {
+-			/**
+-			 * No exact match. The lesser is in this or the
+-			 * previous node.
+-			 */
+-			ldns_radix_self_or_prev(node, result);
+-			return 0;
+-		}
+-		byte -= node->offset;
+-		if (byte >= node->len) {
+-			/**
+-			 * No exact match. The lesser is in this node or the
+-			 * last of this array, or something before this node.
+-			 */
+-			*result = ldns_radix_last_in_subtree_incl_self(node);
+-			if (*result == NULL) {
+-				*result = ldns_radix_prev(node);
+-			}
+-			return 0;
+-		}
+-		pos++;
+-		if (!node->array[byte].edge) {
+-			/**
+-			 * No exact match. Find the previous in the array
+-			 * from this index.
+-			 */
+-			*result = ldns_radix_prev_from_index(node, byte);
+-			if (*result == NULL) {
+-				ldns_radix_self_or_prev(node, result);
+-			}
+-			return 0;
+-		}
+-		if (node->array[byte].len != 0) {
+-			/** Must match additional string. */
+-			if (pos + node->array[byte].len > len) {
+-				/** Additional string is longer than key. */
+-				if (memcmp(&key[pos], node->array[byte].str,
+-					len-pos) <= 0) {
+-					/** Key is before this node. */
+-					*result = ldns_radix_prev(
+-						node->array[byte].edge);
+-				} else {
+-					/** Key is after additional string. */
+-					*result = ldns_radix_last_in_subtree_incl_self(node->array[byte].edge);
+-					if (*result == NULL) {
+-						 *result = ldns_radix_prev(node->array[byte].edge);
+-					}
+-				}
+-				return 0;
+-			}
+-			memcmp_res = memcmp(&key[pos], node->array[byte].str,
+-				node->array[byte].len);
+-			if (memcmp_res < 0) {
+-				*result = ldns_radix_prev(
+-					node->array[byte].edge);
+-				return 0;
+-			} else if (memcmp_res > 0) {
+-				*result = ldns_radix_last_in_subtree_incl_self(node->array[byte].edge);
+-				if (*result == NULL) {
+-					 *result = ldns_radix_prev(node->array[byte].edge);
+-				}
+-				return 0;
+-			}
+-
+-			pos += node->array[byte].len;
+-		}
+-		node = node->array[byte].edge;
+-	}
+-	if (node->data) {
+-		/** Exact match. */
+-		*result = node;
+-		return 1;
+-	}
+-	/** There is a node which is an exact match, but has no element. */
+-	*result = ldns_radix_prev(node);
+-	return 0;
+-}
+-
+-
+-/**
+- * Get the first element in the tree.
+- *
+- */
+-ldns_radix_node_t*
+-ldns_radix_first(ldns_radix_t* tree)
+-{
+-	ldns_radix_node_t* first = NULL;
+-	if (!tree || !tree->root) {
+-		return NULL;
+-	}
+-	first = tree->root;
+-	if (first->data) {
+-		return first;
+-	}
+-	return ldns_radix_next(first);
+-}
+-
+-
+-/**
+- * Get the last element in the tree.
+- *
+- */
+-ldns_radix_node_t*
+-ldns_radix_last(ldns_radix_t* tree)
+-{
+-	if (!tree || !tree->root) {
+-		return NULL;
+-	}
+-	return ldns_radix_last_in_subtree_incl_self(tree->root);
+-}
+-
+-
+-/**
+- * Next element.
+- *
+- */
+-ldns_radix_node_t*
+-ldns_radix_next(ldns_radix_node_t* node)
+-{
+-	if (!node) {
+-		return NULL;
+-	}
+-	if (node->len) {
+-		/** Go down: most-left child is the next. */
+-		ldns_radix_node_t* next = ldns_radix_next_in_subtree(node);
+-		if (next) {
+-			return next;
+-		}
+-	}
+-	/** No elements in subtree, get to parent and go down next branch. */
+-	while (node->parent) {
+-		uint8_t index = node->parent_index;
+-		node = node->parent;
+-		index++;
+-		for (; index < node->len; index++) {
+-			if (node->array[index].edge) {
+-				ldns_radix_node_t* next;
+-				/** Node itself. */
+-				if (node->array[index].edge->data) {
+-					return node->array[index].edge;
+-				}
+-				/** Dive into subtree. */
+-				next = ldns_radix_next_in_subtree(node);
+-				if (next) {
+-					return next;
+-				}
+-			}
+-		}
+-	}
+-	return NULL;
+-}
+-
+-
+-/**
+- * Previous element.
+- *
+- */
+-ldns_radix_node_t*
+-ldns_radix_prev(ldns_radix_node_t* node)
+-{
+-	if (!node) {
+-		return NULL;
+-	}
+-
+-	/** Get to parent and go down previous branch. */
+-	while (node->parent) {
+-		uint8_t index = node->parent_index;
+-		ldns_radix_node_t* prev;
+-		node = node->parent;
+-		assert(node->len > 0);
+-		prev = ldns_radix_prev_from_index(node, index);
+-		if (prev) {
+-			return prev;
+-		}
+-		if (node->data) {
+-			return node;
+-		}
+-	}
+-	return NULL;
+-}
+-
+-
+-/**
+- * Print node.
+- *
+- */
+-static void
+-ldns_radix_node_print(FILE* fd, ldns_radix_node_t* node,
+-	uint8_t i, uint8_t* str, radix_strlen_t len, unsigned d)
+-{
+-	uint8_t j;
+-	if (!node) {
+-		return;
+-	}
+-	for (j = 0; j < d; j++) {
+-		fprintf(fd, "--");
+-	}
+-	if (str) {
+-		radix_strlen_t l;
+-		fprintf(fd, "| [%u+", (unsigned) i);
+-		for (l=0; l < len; l++) {
+-			fprintf(fd, "%c", (char) str[l]);
+-		}
+-		fprintf(fd, "]%u", (unsigned) len);
+-	} else {
+-		fprintf(fd, "| [%u]", (unsigned) i);
+-	}
+-
+-	if (node->data) {
+-		fprintf(fd, " %s", (char*) node->data);
+-	}
+-	fprintf(fd, "\n");
+-
+-	for (j = 0; j < node->len; j++) {
+-		if (node->array[j].edge) {
+-			ldns_radix_node_print(fd, node->array[j].edge, j,
+-				node->array[j].str, node->array[j].len, d+1);
+-		}
+-	}
+-	return;
+-}
+-
+-
+-/**
+- * Print radix tree.
+- *
+- */
+-void
+-ldns_radix_printf(FILE* fd, ldns_radix_t* tree)
+-{
+-	if (!fd || !tree) {
+-		return;
+-	}
+-	if (!tree->root) {
+-		fprintf(fd, "; empty radix tree\n");
+-		return;
+-	}
+-	ldns_radix_node_print(fd, tree->root, 0, NULL, 0, 0);
+-	return;
+-}
+-
+-
+-/**
+- * Join two radix trees.
+- *
+- */
+-ldns_status
+-ldns_radix_join(ldns_radix_t* tree1, ldns_radix_t* tree2)
+-{
+-	ldns_radix_node_t* cur_node, *next_node;
+-	ldns_status status;
+-	if (!tree2 || !tree2->root) {
+-		return LDNS_STATUS_OK;
+-	}
+-	/** Add all elements from tree2 into tree1. */
+-
+-	cur_node = ldns_radix_first(tree2);
+-	while (cur_node) {
+-		status = LDNS_STATUS_NO_DATA;
+-		/** Insert current node into tree1 */
+-		if (cur_node->data) {
+-			status = ldns_radix_insert(tree1, cur_node->key,
+-				cur_node->klen, cur_node->data);
+-			/** Exist errors may occur */
+-			if (status != LDNS_STATUS_OK &&
+-			    status != LDNS_STATUS_EXISTS_ERR) {
+-				return status;
+-			}
+-		}
+-		next_node = ldns_radix_next(cur_node);
+-		if (status == LDNS_STATUS_OK) {
+-			(void) ldns_radix_delete(tree2, cur_node->key,
+-				cur_node->klen);
+-		}
+-		cur_node = next_node;
+-	}
+-
+-	return LDNS_STATUS_OK;
+-}
+-
+-
+-/**
+- * Split a radix tree intwo.
+- *
+- */
+-ldns_status
+-ldns_radix_split(ldns_radix_t* tree1, size_t num, ldns_radix_t** tree2)
+-{
+-	size_t count = 0;
+-	ldns_radix_node_t* cur_node;
+-	ldns_status status = LDNS_STATUS_OK;
+-	if (!tree1 || !tree1->root || num == 0) {
+-		return LDNS_STATUS_OK;
+-	}
+-	if (!tree2) {
+-		return LDNS_STATUS_NULL;
+-	}
+-	if (!*tree2) {
+-		*tree2 = ldns_radix_create();
+-		if (!*tree2) {
+-			return LDNS_STATUS_MEM_ERR;
+-		}
+-	}
+-	cur_node = ldns_radix_first(tree1);
+-	while (count < num && cur_node) {
+-		if (cur_node->data) {
+-			/** Delete current node from tree1. */
+-			uint8_t* cur_key = cur_node->key;
+-			radix_strlen_t cur_len = cur_node->klen;
+-			void* cur_data = ldns_radix_delete(tree1, cur_key,
+-				cur_len);
+-			/** Insert current node into tree2/ */
+-			if (!cur_data) {
+-				return LDNS_STATUS_NO_DATA;
+-			}
+-			status = ldns_radix_insert(*tree2, cur_key, cur_len,
+-				cur_data);
+-			if (status != LDNS_STATUS_OK &&
+-			    status != LDNS_STATUS_EXISTS_ERR) {
+-				return status;
+-			}
+-/*
+-			if (status == LDNS_STATUS_OK) {
+-				cur_node->key = NULL;
+-				cur_node->klen = 0;
+-			}
+-*/
+-			/** Update count; get first element from tree1 again. */
+-			count++;
+-			cur_node = ldns_radix_first(tree1);
+-		} else {
+-			cur_node = ldns_radix_next(cur_node);
+-		}
+-	}
+-	return LDNS_STATUS_OK;
+-}
+-
+-
+-/**
+- * Call function for all nodes in the tree, such that leaf nodes are
+- * called before parent nodes.
+- *
+- */
+-void
+-ldns_radix_traverse_postorder(ldns_radix_node_t* node,
+-	void (*func)(ldns_radix_node_t*, void*), void* arg)
+-{
+-	uint8_t i;
+-	if (!node) {
+-		return;
+-	}
+-	for (i=0; i < node->len; i++) {
+-		ldns_radix_traverse_postorder(node->array[i].edge,
+-			func, arg);
+-	}
+-	/** Call user function */
+-	(*func)(node, arg);
+-	return;
+-}
+-
+-
+-/** Static helper functions */
+-
+-/**
+- * Find a prefix of the key.
+- * @param tree:   tree.
+- * @param key:    key.
+- * @param len:    length of key.
+- * @param result: the longest prefix, the entry itself if *pos==len,
+- *                otherwise an array entry.
+- * @param pos:    position in string where next unmatched byte is.
+- *                If *pos==len, an exact match is found.
+- *                If *pos== 0, a "" match was found.
+- * @return 0 (false) if no prefix found.
+- *
+- */
+-static int
+-ldns_radix_find_prefix(ldns_radix_t* tree, uint8_t* key,
+-	radix_strlen_t len, ldns_radix_node_t** result, radix_strlen_t* respos)
+-{
+-	/** Start searching at the root node */
+-	ldns_radix_node_t* n = tree->root;
+-	radix_strlen_t pos = 0;
+-	uint8_t byte;
+-	*respos = 0;
+-	*result = n;
+-        if (!n) {
+-		/** No root, no prefix found */
+-		return 0;
+-	}
+-	/** For each node, look if we can make further progress */
+-	while (n) {
+-		if (pos == len) {
+-			/** Exact match */
+-			return 1;
+-		}
+-		byte = key[pos];
+-		if (byte < n->offset) {
+-			/** key < node */
+-			return 1;
+-		}
+-		byte -= n->offset;
+-		if (byte >= n->len) {
+-			/** key > node */
+-			return 1;
+-		}
+-		/** So far, the trie matches */
+-		pos++;
+-		if (n->array[byte].len != 0) {
+-			/** Must match additional string */
+-			if (pos + n->array[byte].len > len) {
+-				return 1; /* no match at child node */
+-			}
+-			if (memcmp(&key[pos], n->array[byte].str,
+-				n->array[byte].len) != 0) {
+-				return 1; /* no match at child node */
+-			}
+-			pos += n->array[byte].len;
+-		}
+-		/** Continue searching prefix at this child node */
+-		n = n->array[byte].edge;
+-		if (!n) {
+-			return 1;
+-		}
+-		/** Update the prefix node */
+-		*respos = pos;
+-		*result = n;
+-	}
+-	/** Done */
+-	return 1;
+-}
+-
+-
+-/**
+- * Make space in the node's array for another byte.
+- * @param node: node.
+- * @param byte: byte.
+- * @return 1 if successful, 0 otherwise.
+- *
+- */
+-static int
+-ldns_radix_array_space(ldns_radix_node_t* node, uint8_t byte)
+-{
+-	/** Is there an array? */
+-	if (!node->array) {
+-		assert(node->capacity == 0);
+-		/** No array, create new array */
+-		node->array = LDNS_MALLOC(ldns_radix_array_t);
+-		if (!node->array) {
+-			return 0;
+-		}
+-		memset(&node->array[0], 0, sizeof(ldns_radix_array_t));
+-		node->len = 1;
+-		node->capacity = 1;
+-		node->offset = byte;
+-		return 1;
+-	}
+-	/** Array exist */
+-	assert(node->array != NULL);
+-	assert(node->capacity > 0);
+-
+-	if (node->len == 0) {
+-		/** Unused array */
+-		node->len = 1;
+-		node->offset = byte;
+-	} else if (byte < node->offset) {
+-		/** Byte is below the offset */
+-		uint8_t index;
+-		uint16_t need = node->offset - byte;
+-		/** Is there enough capacity? */
+-		if (node->len + need > node->capacity) {
+-			/** Not enough capacity, grow array */
+-			if (!ldns_radix_array_grow(node,
+-				(unsigned) (node->len + need))) {
+-				return 0; /* failed to grow array */
+-			}
+-		}
+-		/** Move items to the end */
+-		memmove(&node->array[need], &node->array[0],
+-			node->len*sizeof(ldns_radix_array_t));
+-		/** Fix parent index */
+-		for (index = 0; index < node->len; index++) {
+-			if (node->array[index+need].edge) {
+-				node->array[index+need].edge->parent_index =
+-					index + need;
+-			}
+-		}
+-		/** Zero the first */
+-		memset(&node->array[0], 0, need*sizeof(ldns_radix_array_t));
+-		node->len += need;
+-		node->offset = byte;
+-	} else if (byte - node->offset >= node->len) {
+-		/** Byte does not fit in array */
+-		uint16_t need = (byte - node->offset) - node->len + 1;
+-		/** Is there enough capacity? */
+-		if (node->len + need > node->capacity) {
+-			/** Not enough capacity, grow array */
+-			if (!ldns_radix_array_grow(node,
+-				(unsigned) (node->len + need))) {
+-				return 0; /* failed to grow array */
+-			}
+-		}
+-		/** Zero the added items */
+-		memset(&node->array[node->len], 0,
+-			need*sizeof(ldns_radix_array_t));
+-		node->len += need;
+-	}
+-	return 1;
+-}
+-
+-
+-/**
+- * Grow the array.
+- * @param node: node.
+- * @param need: number of elements the array at least need to grow.
+- *              Can't be bigger than 256.
+- * @return: 0 if failed, 1 if was successful.
+- *
+- */
+-static int
+-ldns_radix_array_grow(ldns_radix_node_t* node, unsigned need)
+-{
+-	unsigned size = ((unsigned)node->capacity)*2;
+-	ldns_radix_array_t* a = NULL;
+-	if (need > size) {
+-		size = need;
+-	}
+-	if (size > 256) {
+-		size = 256;
+-	}
+-	a = LDNS_XMALLOC(ldns_radix_array_t, size);
+-	if (!a) {
+-		return 0;
+-	}
+-	assert(node->len <= node->capacity);
+-	assert(node->capacity < size);
+-	memcpy(&a[0], &node->array[0], node->len*sizeof(ldns_radix_array_t));
+-	LDNS_FREE(node->array);
+-	node->array = a;
+-	node->capacity = size;
+-	return 1;
+-}
+-
+-
+-/**
+- * Create a prefix in the array string.
+- * @param array: array.
+- * @param key:   key.
+- * @param pos:   start position in key.
+- * @param len:   length of key.
+- * @return 0 if failed, 1 if was successful.
+- *
+- */
+-static int
+-ldns_radix_str_create(ldns_radix_array_t* array, uint8_t* key,
+-	radix_strlen_t pos, radix_strlen_t len)
+-{
+-	array->str = LDNS_XMALLOC(uint8_t, (len-pos));
+-	if (!array->str) {
+-		return 0;
+-	}
+-	memmove(array->str, key+pos, len-pos);
+-	array->len = (len-pos);
+-	return 1;
+-}
+-
+-
+-/**
+- * Allocate remainder from prefixes for a split.
+- * @param prefixlen:  length of prefix.
+- * @param longer_str: the longer string.
+- * @param longer_len: the longer string length.
+- * @param split_str:  the split string.
+- * @param split_len:  the split string length.
+- * @return 0 if failed, 1 if successful.
+- *
+- */
+-static int
+-ldns_radix_prefix_remainder(radix_strlen_t prefix_len,
+-	uint8_t* longer_str, radix_strlen_t longer_len,
+-	uint8_t** split_str, radix_strlen_t* split_len)
+-{
+-	*split_len = longer_len - prefix_len;
+-	*split_str = LDNS_XMALLOC(uint8_t, (*split_len));
+-	if (!*split_str) {
+-		return 0;
+-	}
+-	memmove(*split_str, longer_str+prefix_len, longer_len-prefix_len);
+-	return 1;
+-}
+-
+-
+-/**
+- * Create a split when two nodes have a shared prefix.
+- * @param array: array.
+- * @param key:   key.
+- * @param pos:   start position in key.
+- * @param len:   length of the key.
+- * @param add:   node to be added.
+- * @return 0 if failed, 1 if was successful.
+- *
+- */
+-static int
+-ldns_radix_array_split(ldns_radix_array_t* array, uint8_t* key,
+-	radix_strlen_t pos, radix_strlen_t len, ldns_radix_node_t* add)
+-{
+-	uint8_t* str_to_add = key + pos;
+-	radix_strlen_t strlen_to_add = len - pos;
+-
+-	if (ldns_radix_str_is_prefix(str_to_add, strlen_to_add,
+-		array->str, array->len)) {
+-		/** The string to add is a prefix of the existing string */
+-		uint8_t* split_str = NULL, *dup_str = NULL;
+-		radix_strlen_t split_len = 0;
+-		/**
+-		 * Example 5: 'ld'
+-		 * | [0]
+-		 * --| [d+ns] dns
+-		 * --| [e+dns] edns
+-		 * --| [l+d] ld
+-		 * ----| [n+s] ldns
+-		 **/
+-		assert(strlen_to_add < array->len);
+-		/** Store the remainder in the split string */
+-		if (array->len - strlen_to_add > 1) {
+-			if (!ldns_radix_prefix_remainder(strlen_to_add+1,
+-				array->str, array->len, &split_str,
+-				&split_len)) {
+-				return 0;
+-			}
+-		}
+-		/** Duplicate the string to add */
+-		if (strlen_to_add != 0) {
+-			dup_str = LDNS_XMALLOC(uint8_t, strlen_to_add);
+-			if (!dup_str) {
+-				LDNS_FREE(split_str);
+-				return 0;
+-			}
+-			memcpy(dup_str, str_to_add, strlen_to_add);
+-		}
+-		/** Make space in array for the new node */
+-		if (!ldns_radix_array_space(add,
+-			array->str[strlen_to_add])) {
+-			LDNS_FREE(split_str);
+-			LDNS_FREE(dup_str);
+-			return 0;
+-		}
+-		/**
+-		 * The added node should go direct under the existing parent.
+-		 * The existing node should go under the added node.
+-		 */
+-		add->parent = array->edge->parent;
+-		add->parent_index = array->edge->parent_index;
+-		add->array[0].edge = array->edge;
+-		add->array[0].str = split_str;
+-		add->array[0].len = split_len;
+-		array->edge->parent = add;
+-		array->edge->parent_index = 0;
+-		LDNS_FREE(array->str);
+-		array->edge = add;
+-		array->str = dup_str;
+-		array->len = strlen_to_add;
+-	} else if (ldns_radix_str_is_prefix(array->str, array->len,
+-		str_to_add, strlen_to_add)) {
+-		/** The existing string is a prefix of the string to add */
+-		/**
+-		 * Example 6: 'dns-ng'
+-		 * | [0]
+-		 * --| [d+ns] dns
+-		 * ----| [-+ng] dns-ng
+-		 * --| [e+dns] edns
+-		 * --| [l+d] ld
+-		 * ----| [n+s] ldns
+-		 **/
+-		uint8_t* split_str = NULL;
+-		radix_strlen_t split_len = 0;
+-		assert(array->len < strlen_to_add);
+-		if (strlen_to_add - array->len > 1) {
+-			if (!ldns_radix_prefix_remainder(array->len+1,
+-				str_to_add, strlen_to_add, &split_str,
+-				&split_len)) {
+-				return 0;
+-			}
+-		}
+-		/** Make space in array for the new node */
+-		if (!ldns_radix_array_space(array->edge,
+-			str_to_add[array->len])) {
+-			LDNS_FREE(split_str);
+-			return 0;
+-		}
+-		/**
+-		 * The added node should go direct under the existing node.
+-		 */
+-		add->parent = array->edge;
+-		add->parent_index = str_to_add[array->len] -
+-							array->edge->offset;
+-		array->edge->array[add->parent_index].edge = add;
+-		array->edge->array[add->parent_index].str = split_str;
+-		array->edge->array[add->parent_index].len = split_len;
+-	} else {
+-		/** Create a new split node. */
+-		/**
+-		 * Example 7: 'dndns'
+-		 * | [0]
+-		 * --| [d+n]
+-		 * ----| [d+ns] dndns
+-		 * ----| [s] dns
+-		 * ------| [-+ng] dns-ng
+-		 * --| [e+dns] edns
+-		 * --| [l+d] ld
+-		 * ----| [n+s] ldns
+-		 **/
+-		ldns_radix_node_t* common = NULL;
+-		uint8_t* common_str = NULL, *s1 = NULL, *s2 = NULL;
+-		radix_strlen_t common_len = 0, l1 = 0, l2 = 0;
+-		common_len = ldns_radix_str_common(array->str, array->len,
+-			str_to_add, strlen_to_add);
+-		assert(common_len < array->len);
+-		assert(common_len < strlen_to_add);
+-		/** Create the new common node. */
+-		common = ldns_radix_new_node(NULL, (uint8_t*)"", 0);
+-		if (!common) {
+-			return 0;
+-		}
+-		if (array->len - common_len > 1) {
+-			if (!ldns_radix_prefix_remainder(common_len+1,
+-				array->str, array->len, &s1, &l1)) {
+-				return 0;
+-			}
+-		}
+-		if (strlen_to_add - common_len > 1) {
+-			if (!ldns_radix_prefix_remainder(common_len+1,
+-				str_to_add, strlen_to_add, &s2, &l2)) {
+-				return 0;
+-			}
+-		}
+-		/** Create the shared prefix. */
+-		if (common_len > 0) {
+-			common_str = LDNS_XMALLOC(uint8_t, common_len);
+-			if (!common_str) {
+-				LDNS_FREE(common);
+-				LDNS_FREE(s1);
+-				LDNS_FREE(s2);
+-				return 0;
+-			}
+-			memcpy(common_str, str_to_add, common_len);
+-		}
+-		/** Make space in the common node array. */
+-		if (!ldns_radix_array_space(common, array->str[common_len]) ||
+-		    !ldns_radix_array_space(common, str_to_add[common_len])) {
+-			LDNS_FREE(common->array);
+-			LDNS_FREE(common);
+-			LDNS_FREE(common_str);
+-			LDNS_FREE(s1);
+-			LDNS_FREE(s2);
+-			return 0;
+-		}
+-		/**
+-		 * The common node should go direct under the parent node.
+-		 * The added and existing nodes go under the common node.
+-		 */
+-		common->parent = array->edge->parent;
+-		common->parent_index = array->edge->parent_index;
+-		array->edge->parent = common;
+-		array->edge->parent_index = array->str[common_len] -
+-								common->offset;
+-		add->parent = common;
+-		add->parent_index = str_to_add[common_len] - common->offset;
+-		common->array[array->edge->parent_index].edge = array->edge;
+-		common->array[array->edge->parent_index].str = s1;
+-		common->array[array->edge->parent_index].len = l1;
+-		common->array[add->parent_index].edge = add;
+-		common->array[add->parent_index].str = s2;
+-		common->array[add->parent_index].len = l2;
+-		LDNS_FREE(array->str);
+-		array->edge = common;
+-		array->str = common_str;
+-		array->len = common_len;
+-	}
+-	return 1;
+-}
+-
+-
+-/**
+- * Check if one string prefix of other string.
+- * @param str1: one string.
+- * @param len1: one string length.
+- * @param str2: other string.
+- * @param len2: other string length.
+- * @return 1 if prefix, 0 otherwise.
+- *
+- */
+-static int
+-ldns_radix_str_is_prefix(uint8_t* str1, radix_strlen_t len1,
+-	uint8_t* str2, radix_strlen_t len2)
+-{
+-	if (len1 == 0) {
+-		return 1; /* empty prefix is also a prefix */
+-	}
+-	if (len1 > len2) {
+-		return 0; /* len1 is longer so str1 cannot be a prefix */
+-	}
+-	return (memcmp(str1, str2, len1) == 0);
+-}
+-
+-
+-/**
+- * Return the number of bytes in common for the two strings.
+- * @param str1: one string.
+- * @param len1: one string length.
+- * @param str2: other string.
+- * @param len2: other string length.
+- * @return length of substring that the two strings have in common.
+- *
+- */
+-static radix_strlen_t
+-ldns_radix_str_common(uint8_t* str1, radix_strlen_t len1,
+-	uint8_t* str2, radix_strlen_t len2)
+-{
+-	radix_strlen_t i, max = (len1<len2)?len1:len2;
+-	for (i=0; i<max; i++) {
+-		if (str1[i] != str2[i]) {
+-			return i;
+-		}
+-	}
+-	return max;
+-}
+-
+-
+-/**
+- * Find the next element in the subtree of this node.
+- * @param node: node.
+- * @return: node with next element.
+- *
+- */
+-static ldns_radix_node_t*
+-ldns_radix_next_in_subtree(ldns_radix_node_t* node)
+-{
+-	uint16_t i;
+-	ldns_radix_node_t* next;
+-	/** Try every subnode. */
+-	for (i = 0; i < node->len; i++) {
+-		if (node->array[i].edge) {
+-			/** Node itself. */
+-			if (node->array[i].edge->data) {
+-				return node->array[i].edge;
+-			}
+-			/** Dive into subtree. */
+-			next = ldns_radix_next_in_subtree(node->array[i].edge);
+-			if (next) {
+-				return next;
+-			}
+-		}
+-	}
+-	return NULL;
+-}
+-
+-
+-/**
+- * Find the previous element in the array of this node, from index.
+- * @param node: node.
+- * @param index: index.
+- * @return previous node from index.
+- *
+- */
+-static ldns_radix_node_t*
+-ldns_radix_prev_from_index(ldns_radix_node_t* node, uint8_t index)
+-{
+-	uint8_t i = index;
+-	while (i > 0) {
+-		i--;
+-		if (node->array[i].edge) {
+-			ldns_radix_node_t* prev =
+-				ldns_radix_last_in_subtree_incl_self(node);
+-			if (prev) {
+-				return prev;
+-			}
+-		}
+-	}
+-	return NULL;
+-}
+-
+-
+-/**
+- * Find last node in subtree, or this node (if have data).
+- * @param node: node.
+- * @return last node in subtree, or this node, or NULL.
+- *
+- */
+-static ldns_radix_node_t*
+-ldns_radix_last_in_subtree_incl_self(ldns_radix_node_t* node)
+-{
+-	ldns_radix_node_t* last = ldns_radix_last_in_subtree(node);
+-	if (last) {
+-		return last;
+-	} else if (node->data) {
+-		return node;
+-	}
+-	return NULL;
+-}
+-
+-
+-/**
+- * Find last node in subtree.
+- * @param node: node.
+- * @return last node in subtree.
+- *
+- */
+-static ldns_radix_node_t*
+-ldns_radix_last_in_subtree(ldns_radix_node_t* node)
+-{
+-	int i;
+-	/** Look for the most right leaf node. */
+-	for (i=(int)(node->len)-1; i >= 0; i--) {
+-		if (node->array[i].edge) {
+-			/** Keep looking for the most right leaf node. */
+-			if (node->array[i].edge->len > 0) {
+-				ldns_radix_node_t* last =
+-					ldns_radix_last_in_subtree(
+-					node->array[i].edge);
+-				if (last) {
+-					return last;
+-				}
+-			}
+-			/** Could this be the most right leaf node? */
+-			if (node->array[i].edge->data) {
+-				return node->array[i].edge;
+-			}
+-		}
+-	}
+-	return NULL;
+-}
+-
+-
+-/**
+- * Fix tree after deleting element.
+- * @param tree: tree.
+- * @param node: node with deleted element.
+- *
+- */
+-static void
+-ldns_radix_del_fix(ldns_radix_t* tree, ldns_radix_node_t* node)
+-{
+-	while (node) {
+-		if (node->data) {
+-			/** Thou should not delete nodes with data attached. */
+-			return;
+-		} else if (node->len == 1 && node->parent) {
+-			/** Node with one child is fold back into. */
+-			ldns_radix_cleanup_onechild(node);
+-			return;
+-		} else if (node->len == 0) {
+-			/** Leaf node. */
+-			ldns_radix_node_t* parent = node->parent;
+-			if (!parent) {
+-				/** The root is a leaf node. */
+-				ldns_radix_node_free(node, NULL);
+-				tree->root = NULL;
+-				return;
+-			}
+-			/** Cleanup leaf node and continue with parent. */
+-			ldns_radix_cleanup_leaf(node);
+-			node = parent;
+-		} else {
+-			/**
+-			 * Node cannot be deleted, because it has edge nodes
+-			 * and no parent to fix up to.
+-			 */
+-			return;
+-		}
+-	}
+-	/** Not reached. */
+-	return;
+-}
+-
+-
+-/**
+- * Clean up a node with one child.
+- * @param node: node with one child.
+- *
+- */
+-static void
+-ldns_radix_cleanup_onechild(ldns_radix_node_t* node)
+-{
+-	uint8_t* join_str;
+-	radix_strlen_t join_len;
+-	uint8_t parent_index = node->parent_index;
+-	ldns_radix_node_t* child = node->array[0].edge;
+-	ldns_radix_node_t* parent = node->parent;
+-
+-	/** Node has one child, merge the child node into the parent node. */
+-	assert(parent_index < parent->len);
+-	join_len = parent->array[parent_index].len + node->array[0].len + 1;
+-
+-	join_str = LDNS_XMALLOC(uint8_t, join_len);
+-	if (!join_str) {
+-		/**
+-		 * Cleanup failed due to out of memory.
+-		 * This tree is now inefficient, with the empty node still
+-		 * existing, but it is still valid.
+-		 */
+-		return;
+-	}
+-
+-	memcpy(join_str, parent->array[parent_index].str,
+-		parent->array[parent_index].len);
+-	join_str[parent->array[parent_index].len] = child->parent_index +
+-		node->offset;
+-	memmove(join_str + parent->array[parent_index].len+1,
+-		node->array[0].str, node->array[0].len);
+-
+-	LDNS_FREE(parent->array[parent_index].str);
+-	parent->array[parent_index].str = join_str;
+-	parent->array[parent_index].len = join_len;
+-	parent->array[parent_index].edge = child;
+-	child->parent = parent;
+-	child->parent_index = parent_index;
+-	ldns_radix_node_free(node, NULL);
+-	return;
+-}
+-
+-
+-/**
+- * Clean up a leaf node.
+- * @param node: leaf node.
+- *
+- */
+-static void
+-ldns_radix_cleanup_leaf(ldns_radix_node_t* node)
+-{
+-	uint8_t parent_index = node->parent_index;
+-	ldns_radix_node_t* parent = node->parent;
+-	/** Delete lead node and fix parent array. */
+-	assert(parent_index < parent->len);
+-	ldns_radix_node_free(node, NULL);
+-	LDNS_FREE(parent->array[parent_index].str);
+-	parent->array[parent_index].str = NULL;
+-	parent->array[parent_index].len = 0;
+-	parent->array[parent_index].edge = NULL;
+-	/** Fix array in parent. */
+-	if (parent->len == 1) {
+-		ldns_radix_node_array_free(parent);
+-	} else if (parent_index == 0) {
+-		ldns_radix_node_array_free_front(parent);
+-	} else {
+-		ldns_radix_node_array_free_end(parent);
+-	}
+-	return;
+-}
+-
+-
+-/**
+- * Free a radix node.
+- * @param node: node.
+- * @param arg: user argument.
+- *
+- */
+-static void
+-ldns_radix_node_free(ldns_radix_node_t* node, void* arg)
+-{
+-	uint16_t i;
+-	(void) arg;
+-	if (!node) {
+-		return;
+-	}
+-	for (i=0; i < node->len; i++) {
+-		LDNS_FREE(node->array[i].str);
+-	}
+-	node->key = NULL;
+-	node->klen = 0;
+-	LDNS_FREE(node->array);
+-	LDNS_FREE(node);
+-	return;
+-}
+-
+-
+-/**
+- * Free select edge array.
+- * @param node: node.
+- *
+- */
+-static void
+-ldns_radix_node_array_free(ldns_radix_node_t* node)
+-{
+-	node->offset = 0;
+-	node->len = 0;
+-	LDNS_FREE(node->array);
+-	node->array = NULL;
+-	node->capacity = 0;
+-	return;
+-}
+-
+-
+-/**
+- * Free front of select edge array.
+- * @param node: node.
+- *
+- */
+-static void
+-ldns_radix_node_array_free_front(ldns_radix_node_t* node)
+-{
+-	uint16_t i, n = 0;
+-	/** Remove until a non NULL entry. */
+-   	while (n < node->len && node->array[n].edge == NULL) {
+-		n++;
+-	}
+-	if (n == 0) {
+-		return;
+-	}
+-	if (n == node->len) {
+-		ldns_radix_node_array_free(node);
+-		return;
+-	}
+-	assert(n < node->len);
+-	assert((int) n <= (255 - (int) node->offset));
+-	memmove(&node->array[0], &node->array[n],
+-		(node->len - n)*sizeof(ldns_radix_array_t));
+-	node->offset += n;
+-	node->len -= n;
+-	for (i=0; i < node->len; i++) {
+-		if (node->array[i].edge) {
+-			node->array[i].edge->parent_index = i;
+-		}
+-	}
+-	ldns_radix_array_reduce(node);
+-	return;
+-}
+-
+-
+-/**
+- * Free front of select edge array.
+- * @param node: node.
+- *
+- */
+-static void
+-ldns_radix_node_array_free_end(ldns_radix_node_t* node)
+-{
+-	uint16_t n = 0;
+-	/** Shorten array. */
+-	while (n < node->len && node->array[node->len-1-n].edge == NULL) {
+-		n++;
+-	}
+-	if (n == 0) {
+-		return;
+-	}
+-	if (n == node->len) {
+-		ldns_radix_node_array_free(node);
+-		return;
+-	}
+-	assert(n < node->len);
+-	node->len -= n;
+-	ldns_radix_array_reduce(node);
+-	return;
+-}
+-
+-
+-/**
+- * Reduce the capacity of the array if needed.
+- * @param node: node.
+- *
+- */
+-static void
+-ldns_radix_array_reduce(ldns_radix_node_t* node)
+-{
+-	if (node->len <= node->capacity/2 && node->len != node->capacity) {
+-		ldns_radix_array_t* a = LDNS_XMALLOC(ldns_radix_array_t,
+-								node->len);
+-		if (!a) {
+-			return;
+-		}
+-		memcpy(a, node->array, sizeof(ldns_radix_array_t)*node->len);
+-		LDNS_FREE(node->array);
+-		node->array = a;
+-		node->capacity = node->len;
+-	}
+-	return;
+-}
+-
+-
+-/**
+- * Return this element if it exists, the previous otherwise.
+- * @param node: from this node.
+- * @param result: result node.
+- *
+- */
+-static void
+-ldns_radix_self_or_prev(ldns_radix_node_t* node, ldns_radix_node_t** result)
+-{
+-	if (node->data) {
+-		*result = node;
+-	} else {
+-		*result = ldns_radix_prev(node);
+-	}
+-	return;
+-}
+diff --git a/src/ldns/rbtree.c b/src/ldns/rbtree.c
+deleted file mode 100644
+index b89dff7..0000000
+--- a/src/ldns/rbtree.c
++++ /dev/null
+@@ -1,670 +0,0 @@
+-/*
+- * rbtree.c -- generic red black tree
+- *
+- * Taken from Unbound, modified for ldns
+- *
+- * Copyright (c) 2001-2008, NLnet Labs. All rights reserved.
+- * 
+- * This software is open source.
+- * 
+- * Redistribution and use in source and binary forms, with or without
+- * modification, are permitted provided that the following conditions
+- * are met:
+- * 
+- * Redistributions of source code must retain the above copyright notice,
+- * this list of conditions and the following disclaimer.
+- * 
+- * Redistributions in binary form must reproduce the above copyright notice,
+- * this list of conditions and the following disclaimer in the documentation
+- * and/or other materials provided with the distribution.
+- * 
+- * Neither the name of the NLNET LABS nor the names of its contributors may
+- * be used to endorse or promote products derived from this software without
+- * specific prior written permission.
+- * 
+- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+- * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+- * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+- *
+- */
+-
+-/**
+- * \file
+- * Implementation of a redblack tree.
+- */
+-
+-#include <ldns/config.h>
+-#include <ldns/rbtree.h>
+-#include <ldns/util.h>
+-#include <stdlib.h>
+-
+-/** Node colour black */
+-#define	BLACK	0
+-/** Node colour red */
+-#define	RED	1
+-
+-/** the NULL node, global alloc */
+-ldns_rbnode_t	ldns_rbtree_null_node = {
+-	LDNS_RBTREE_NULL,	/* Parent.  */
+-	LDNS_RBTREE_NULL,	/* Left.  */
+-	LDNS_RBTREE_NULL,	/* Right.  */
+-	NULL,			/* Key.  */
+-	NULL,               /* Data. */
+-	BLACK		     /* Color.  */
+-};
+-
+-/** rotate subtree left (to preserve redblack property) */
+-static void ldns_rbtree_rotate_left(ldns_rbtree_t *rbtree, ldns_rbnode_t *node);
+-/** rotate subtree right (to preserve redblack property) */
+-static void ldns_rbtree_rotate_right(ldns_rbtree_t *rbtree, ldns_rbnode_t *node);
+-/** Fixup node colours when insert happened */
+-static void ldns_rbtree_insert_fixup(ldns_rbtree_t *rbtree, ldns_rbnode_t *node);
+-/** Fixup node colours when delete happened */
+-static void ldns_rbtree_delete_fixup(ldns_rbtree_t* rbtree, ldns_rbnode_t* child, ldns_rbnode_t* child_parent);
+-
+-/*
+- * Creates a new red black tree, intializes and returns a pointer to it.
+- *
+- * Return NULL on failure.
+- *
+- */
+-ldns_rbtree_t *
+-ldns_rbtree_create (int (*cmpf)(const void *, const void *))
+-{
+-	ldns_rbtree_t *rbtree;
+-
+-	/* Allocate memory for it */
+-	rbtree = (ldns_rbtree_t *) LDNS_MALLOC(ldns_rbtree_t);
+-	if (!rbtree) {
+-		return NULL;
+-	}
+-
+-	/* Initialize it */
+-	ldns_rbtree_init(rbtree, cmpf);
+-
+-	return rbtree;
+-}
+-
+-void 
+-ldns_rbtree_init(ldns_rbtree_t *rbtree, int (*cmpf)(const void *, const void *))
+-{
+-	/* Initialize it */
+-	rbtree->root = LDNS_RBTREE_NULL;
+-	rbtree->count = 0;
+-	rbtree->cmp = cmpf;
+-}
+-
+-void 
+-ldns_rbtree_free(ldns_rbtree_t *rbtree)
+-{
+-	LDNS_FREE(rbtree);
+-}
+-
+-/*
+- * Rotates the node to the left.
+- *
+- */
+-static void
+-ldns_rbtree_rotate_left(ldns_rbtree_t *rbtree, ldns_rbnode_t *node)
+-{
+-	ldns_rbnode_t *right = node->right;
+-	node->right = right->left;
+-	if (right->left != LDNS_RBTREE_NULL)
+-		right->left->parent = node;
+-
+-	right->parent = node->parent;
+-
+-	if (node->parent != LDNS_RBTREE_NULL) {
+-		if (node == node->parent->left) {
+-			node->parent->left = right;
+-		} else  {
+-			node->parent->right = right;
+-		}
+-	} else {
+-		rbtree->root = right;
+-	}
+-	right->left = node;
+-	node->parent = right;
+-}
+-
+-/*
+- * Rotates the node to the right.
+- *
+- */
+-static void
+-ldns_rbtree_rotate_right(ldns_rbtree_t *rbtree, ldns_rbnode_t *node)
+-{
+-	ldns_rbnode_t *left = node->left;
+-	node->left = left->right;
+-	if (left->right != LDNS_RBTREE_NULL)
+-		left->right->parent = node;
+-
+-	left->parent = node->parent;
+-
+-	if (node->parent != LDNS_RBTREE_NULL) {
+-		if (node == node->parent->right) {
+-			node->parent->right = left;
+-		} else  {
+-			node->parent->left = left;
+-		}
+-	} else {
+-		rbtree->root = left;
+-	}
+-	left->right = node;
+-	node->parent = left;
+-}
+-
+-static void
+-ldns_rbtree_insert_fixup(ldns_rbtree_t *rbtree, ldns_rbnode_t *node)
+-{
+-	ldns_rbnode_t	*uncle;
+-
+-	/* While not at the root and need fixing... */
+-	while (node != rbtree->root && node->parent->color == RED) {
+-		/* If our parent is left child of our grandparent... */
+-		if (node->parent == node->parent->parent->left) {
+-			uncle = node->parent->parent->right;
+-
+-			/* If our uncle is red... */
+-			if (uncle->color == RED) {
+-				/* Paint the parent and the uncle black... */
+-				node->parent->color = BLACK;
+-				uncle->color = BLACK;
+-
+-				/* And the grandparent red... */
+-				node->parent->parent->color = RED;
+-
+-				/* And continue fixing the grandparent */
+-				node = node->parent->parent;
+-			} else {				/* Our uncle is black... */
+-				/* Are we the right child? */
+-				if (node == node->parent->right) {
+-					node = node->parent;
+-					ldns_rbtree_rotate_left(rbtree, node);
+-				}
+-				/* Now we're the left child, repaint and rotate... */
+-				node->parent->color = BLACK;
+-				node->parent->parent->color = RED;
+-				ldns_rbtree_rotate_right(rbtree, node->parent->parent);
+-			}
+-		} else {
+-			uncle = node->parent->parent->left;
+-
+-			/* If our uncle is red... */
+-			if (uncle->color == RED) {
+-				/* Paint the parent and the uncle black... */
+-				node->parent->color = BLACK;
+-				uncle->color = BLACK;
+-
+-				/* And the grandparent red... */
+-				node->parent->parent->color = RED;
+-
+-				/* And continue fixing the grandparent */
+-				node = node->parent->parent;
+-			} else {				/* Our uncle is black... */
+-				/* Are we the right child? */
+-				if (node == node->parent->left) {
+-					node = node->parent;
+-					ldns_rbtree_rotate_right(rbtree, node);
+-				}
+-				/* Now we're the right child, repaint and rotate... */
+-				node->parent->color = BLACK;
+-				node->parent->parent->color = RED;
+-				ldns_rbtree_rotate_left(rbtree, node->parent->parent);
+-			}
+-		}
+-	}
+-	rbtree->root->color = BLACK;
+-}
+-
+-void
+-ldns_rbtree_insert_vref(ldns_rbnode_t *data, void *rbtree)
+-{
+-	(void) ldns_rbtree_insert((ldns_rbtree_t *) rbtree,
+-						 data);
+-}
+-
+-/*
+- * Inserts a node into a red black tree.
+- *
+- * Returns NULL on failure or the pointer to the newly added node
+- * otherwise.
+- */
+-ldns_rbnode_t *
+-ldns_rbtree_insert (ldns_rbtree_t *rbtree, ldns_rbnode_t *data)
+-{
+-	/* XXX Not necessary, but keeps compiler quiet... */
+-	int r = 0;
+-
+-	/* We start at the root of the tree */
+-	ldns_rbnode_t	*node = rbtree->root;
+-	ldns_rbnode_t	*parent = LDNS_RBTREE_NULL;
+-
+-	/* Lets find the new parent... */
+-	while (node != LDNS_RBTREE_NULL) {
+-		/* Compare two keys, do we have a duplicate? */
+-		if ((r = rbtree->cmp(data->key, node->key)) == 0) {
+-			return NULL;
+-		}
+-		parent = node;
+-
+-		if (r < 0) {
+-			node = node->left;
+-		} else {
+-			node = node->right;
+-		}
+-	}
+-
+-	/* Initialize the new node */
+-	data->parent = parent;
+-	data->left = data->right = LDNS_RBTREE_NULL;
+-	data->color = RED;
+-	rbtree->count++;
+-
+-	/* Insert it into the tree... */
+-	if (parent != LDNS_RBTREE_NULL) {
+-		if (r < 0) {
+-			parent->left = data;
+-		} else {
+-			parent->right = data;
+-		}
+-	} else {
+-		rbtree->root = data;
+-	}
+-
+-	/* Fix up the red-black properties... */
+-	ldns_rbtree_insert_fixup(rbtree, data);
+-
+-	return data;
+-}
+-
+-/*
+- * Searches the red black tree, returns the data if key is found or NULL otherwise.
+- *
+- */
+-ldns_rbnode_t *
+-ldns_rbtree_search (ldns_rbtree_t *rbtree, const void *key)
+-{
+-	ldns_rbnode_t *node;
+-
+-	if (ldns_rbtree_find_less_equal(rbtree, key, &node)) {
+-		return node;
+-	} else {
+-		return NULL;
+-	}
+-}
+-
+-/** helpers for delete: swap node colours */
+-static void swap_int8(uint8_t* x, uint8_t* y) 
+-{ 
+-	uint8_t t = *x; *x = *y; *y = t; 
+-}
+-
+-/** helpers for delete: swap node pointers */
+-static void swap_np(ldns_rbnode_t** x, ldns_rbnode_t** y) 
+-{
+-	ldns_rbnode_t* t = *x; *x = *y; *y = t; 
+-}
+-
+-/** Update parent pointers of child trees of 'parent' */
+-static void change_parent_ptr(ldns_rbtree_t* rbtree, ldns_rbnode_t* parent, ldns_rbnode_t* old, ldns_rbnode_t* new)
+-{
+-	if(parent == LDNS_RBTREE_NULL)
+-	{
+-		if(rbtree->root == old) rbtree->root = new;
+-		return;
+-	}
+-	if(parent->left == old) parent->left = new;
+-	if(parent->right == old) parent->right = new;
+-}
+-/** Update parent pointer of a node 'child' */
+-static void change_child_ptr(ldns_rbnode_t* child, ldns_rbnode_t* old, ldns_rbnode_t* new)
+-{
+-	if(child == LDNS_RBTREE_NULL) return;
+-	if(child->parent == old) child->parent = new;
+-}
+-
+-ldns_rbnode_t* 
+-ldns_rbtree_delete(ldns_rbtree_t *rbtree, const void *key)
+-{
+-	ldns_rbnode_t *to_delete;
+-	ldns_rbnode_t *child;
+-	if((to_delete = ldns_rbtree_search(rbtree, key)) == 0) return 0;
+-	rbtree->count--;
+-
+-	/* make sure we have at most one non-leaf child */
+-	if(to_delete->left != LDNS_RBTREE_NULL &&
+-	   to_delete->right != LDNS_RBTREE_NULL)
+-	{
+-		/* swap with smallest from right subtree (or largest from left) */
+-		ldns_rbnode_t *smright = to_delete->right;
+-		while(smright->left != LDNS_RBTREE_NULL)
+-			smright = smright->left;
+-		/* swap the smright and to_delete elements in the tree,
+-		 * but the ldns_rbnode_t is first part of user data struct
+-		 * so cannot just swap the keys and data pointers. Instead
+-		 * readjust the pointers left,right,parent */
+-
+-		/* swap colors - colors are tied to the position in the tree */
+-		swap_int8(&to_delete->color, &smright->color);
+-
+-		/* swap child pointers in parents of smright/to_delete */
+-		change_parent_ptr(rbtree, to_delete->parent, to_delete, smright);
+-		if(to_delete->right != smright)
+-			change_parent_ptr(rbtree, smright->parent, smright, to_delete);
+-
+-		/* swap parent pointers in children of smright/to_delete */
+-		change_child_ptr(smright->left, smright, to_delete);
+-		change_child_ptr(smright->left, smright, to_delete);
+-		change_child_ptr(smright->right, smright, to_delete);
+-		change_child_ptr(smright->right, smright, to_delete);
+-		change_child_ptr(to_delete->left, to_delete, smright);
+-		if(to_delete->right != smright)
+-			change_child_ptr(to_delete->right, to_delete, smright);
+-		if(to_delete->right == smright)
+-		{
+-			/* set up so after swap they work */
+-			to_delete->right = to_delete;
+-			smright->parent = smright;
+-		}
+-
+-		/* swap pointers in to_delete/smright nodes */
+-		swap_np(&to_delete->parent, &smright->parent);
+-		swap_np(&to_delete->left, &smright->left);
+-		swap_np(&to_delete->right, &smright->right);
+-
+-		/* now delete to_delete (which is at the location where the smright previously was) */
+-	}
+-
+-	if(to_delete->left != LDNS_RBTREE_NULL) child = to_delete->left;
+-	else child = to_delete->right;
+-
+-	/* unlink to_delete from the tree, replace to_delete with child */
+-	change_parent_ptr(rbtree, to_delete->parent, to_delete, child);
+-	change_child_ptr(child, to_delete, to_delete->parent);
+-
+-	if(to_delete->color == RED)
+-	{
+-		/* if node is red then the child (black) can be swapped in */
+-	}
+-	else if(child->color == RED)
+-	{
+-		/* change child to BLACK, removing a RED node is no problem */
+-		if(child!=LDNS_RBTREE_NULL) child->color = BLACK;
+-	}
+-	else ldns_rbtree_delete_fixup(rbtree, child, to_delete->parent);
+-
+-	/* unlink completely */
+-	to_delete->parent = LDNS_RBTREE_NULL;
+-	to_delete->left = LDNS_RBTREE_NULL;
+-	to_delete->right = LDNS_RBTREE_NULL;
+-	to_delete->color = BLACK;
+-	return to_delete;
+-}
+-
+-static void ldns_rbtree_delete_fixup(ldns_rbtree_t* rbtree, ldns_rbnode_t* child, ldns_rbnode_t* child_parent)
+-{
+-	ldns_rbnode_t* sibling;
+-	int go_up = 1;
+-
+-	/* determine sibling to the node that is one-black short */
+-	if(child_parent->right == child) sibling = child_parent->left;
+-	else sibling = child_parent->right;
+-
+-	while(go_up)
+-	{
+-		if(child_parent == LDNS_RBTREE_NULL)
+-		{
+-			/* removed parent==black from root, every path, so ok */
+-			return;
+-		}
+-
+-		if(sibling->color == RED)
+-		{	/* rotate to get a black sibling */
+-			child_parent->color = RED;
+-			sibling->color = BLACK;
+-			if(child_parent->right == child)
+-				ldns_rbtree_rotate_right(rbtree, child_parent);
+-			else	ldns_rbtree_rotate_left(rbtree, child_parent);
+-			/* new sibling after rotation */
+-			if(child_parent->right == child) sibling = child_parent->left;
+-			else sibling = child_parent->right;
+-		}
+-
+-		if(child_parent->color == BLACK 
+-			&& sibling->color == BLACK
+-			&& sibling->left->color == BLACK
+-			&& sibling->right->color == BLACK)
+-		{	/* fixup local with recolor of sibling */
+-			if(sibling != LDNS_RBTREE_NULL)
+-				sibling->color = RED;
+-
+-			child = child_parent;
+-			child_parent = child_parent->parent;
+-			/* prepare to go up, new sibling */
+-			if(child_parent->right == child) sibling = child_parent->left;
+-			else sibling = child_parent->right;
+-		}
+-		else go_up = 0;
+-	}
+-
+-	if(child_parent->color == RED
+-		&& sibling->color == BLACK
+-		&& sibling->left->color == BLACK
+-		&& sibling->right->color == BLACK) 
+-	{
+-		/* move red to sibling to rebalance */
+-		if(sibling != LDNS_RBTREE_NULL)
+-			sibling->color = RED;
+-		child_parent->color = BLACK;
+-		return;
+-	}
+-
+-	/* get a new sibling, by rotating at sibling. See which child
+-	   of sibling is red */
+-	if(child_parent->right == child
+-		&& sibling->color == BLACK
+-		&& sibling->right->color == RED
+-		&& sibling->left->color == BLACK)
+-	{
+-		sibling->color = RED;
+-		sibling->right->color = BLACK;
+-		ldns_rbtree_rotate_left(rbtree, sibling);
+-		/* new sibling after rotation */
+-		if(child_parent->right == child) sibling = child_parent->left;
+-		else sibling = child_parent->right;
+-	}
+-	else if(child_parent->left == child
+-		&& sibling->color == BLACK
+-		&& sibling->left->color == RED
+-		&& sibling->right->color == BLACK)
+-	{
+-		sibling->color = RED;
+-		sibling->left->color = BLACK;
+-		ldns_rbtree_rotate_right(rbtree, sibling);
+-		/* new sibling after rotation */
+-		if(child_parent->right == child) sibling = child_parent->left;
+-		else sibling = child_parent->right;
+-	}
+-
+-	/* now we have a black sibling with a red child. rotate and exchange colors. */
+-	sibling->color = child_parent->color;
+-	child_parent->color = BLACK;
+-	if(child_parent->right == child)
+-	{
+-		sibling->left->color = BLACK;
+-		ldns_rbtree_rotate_right(rbtree, child_parent);
+-	}
+-	else
+-	{
+-		sibling->right->color = BLACK;
+-		ldns_rbtree_rotate_left(rbtree, child_parent);
+-	}
+-}
+-
+-int
+-ldns_rbtree_find_less_equal(ldns_rbtree_t *rbtree, const void *key, ldns_rbnode_t **result)
+-{
+-	int r;
+-	ldns_rbnode_t *node;
+-
+-	/* We start at root... */
+-	node = rbtree->root;
+-
+-	*result = NULL;
+-
+-	/* While there are children... */
+-	while (node != LDNS_RBTREE_NULL) {
+-		r = rbtree->cmp(key, node->key);
+-		if (r == 0) {
+-			/* Exact match */
+-			*result = node;
+-			return 1;
+-		} 
+-		if (r < 0) {
+-			node = node->left;
+-		} else {
+-			/* Temporary match */
+-			*result = node;
+-			node = node->right;
+-		}
+-	}
+-	return 0;
+-}
+-
+-/*
+- * Finds the first element in the red black tree
+- *
+- */
+-ldns_rbnode_t *
+-ldns_rbtree_first (ldns_rbtree_t *rbtree)
+-{
+-	ldns_rbnode_t *node = rbtree->root;
+-
+-	if (rbtree->root != LDNS_RBTREE_NULL) {
+-		for (node = rbtree->root; node->left != LDNS_RBTREE_NULL; node = node->left);
+-	}
+-	return node;
+-}
+-
+-ldns_rbnode_t *
+-ldns_rbtree_last (ldns_rbtree_t *rbtree)
+-{
+-	ldns_rbnode_t *node = rbtree->root;
+-
+-	if (rbtree->root != LDNS_RBTREE_NULL) {
+-		for (node = rbtree->root; node->right != LDNS_RBTREE_NULL; node = node->right);
+-	}
+-	return node;
+-}
+-
+-/*
+- * Returns the next node...
+- *
+- */
+-ldns_rbnode_t *
+-ldns_rbtree_next (ldns_rbnode_t *node)
+-{
+-	ldns_rbnode_t *parent;
+-
+-	if (node->right != LDNS_RBTREE_NULL) {
+-		/* One right, then keep on going left... */
+-		for (node = node->right;
+-			node->left != LDNS_RBTREE_NULL;
+-			node = node->left);
+-	} else {
+-		parent = node->parent;
+-		while (parent != LDNS_RBTREE_NULL && node == parent->right) {
+-			node = parent;
+-			parent = parent->parent;
+-		}
+-		node = parent;
+-	}
+-	return node;
+-}
+-
+-ldns_rbnode_t *
+-ldns_rbtree_previous(ldns_rbnode_t *node)
+-{
+-	ldns_rbnode_t *parent;
+-
+-	if (node->left != LDNS_RBTREE_NULL) {
+-		/* One left, then keep on going right... */
+-		for (node = node->left;
+-			node->right != LDNS_RBTREE_NULL;
+-			node = node->right);
+-	} else {
+-		parent = node->parent;
+-		while (parent != LDNS_RBTREE_NULL && node == parent->left) {
+-			node = parent;
+-			parent = parent->parent;
+-		}
+-		node = parent;
+-	}
+-	return node;
+-}
+-
+-/**
+- * split off elements number of elements from the start
+- * of the name tree and return a new tree 
+- */
+-ldns_rbtree_t *
+-ldns_rbtree_split(ldns_rbtree_t *tree,
+-			   size_t elements)
+-{
+-	ldns_rbtree_t *new_tree;
+-	ldns_rbnode_t *cur_node;
+-	ldns_rbnode_t *move_node;
+-	size_t count = 0;
+-
+-	new_tree = ldns_rbtree_create(tree->cmp);
+-
+-	cur_node = ldns_rbtree_first(tree);
+-	while (count < elements && cur_node != LDNS_RBTREE_NULL) {
+-		move_node = ldns_rbtree_delete(tree, cur_node->key);
+-		(void)ldns_rbtree_insert(new_tree, move_node);
+-		cur_node = ldns_rbtree_first(tree);
+-		count++;
+-	}
+-
+-	return new_tree;
+-}
+-
+-/*
+- * add all node from the second tree to the first (removing them from the
+- * second), and fix up nsec(3)s if present
+- */
+-void
+-ldns_rbtree_join(ldns_rbtree_t *tree1, ldns_rbtree_t *tree2)
+-{
+-	ldns_traverse_postorder(tree2, ldns_rbtree_insert_vref, tree1);
+-}
+-
+-/** recursive descent traverse */
+-static void 
+-traverse_post(void (*func)(ldns_rbnode_t*, void*), void* arg, 
+-	ldns_rbnode_t* node)
+-{
+-	if(!node || node == LDNS_RBTREE_NULL)
+-		return;
+-	/* recurse */
+-	traverse_post(func, arg, node->left);
+-	traverse_post(func, arg, node->right);
+-	/* call user func */
+-	(*func)(node, arg);
+-}
+-
+-void 
+-ldns_traverse_postorder(ldns_rbtree_t* tree, 
+-	void (*func)(ldns_rbnode_t*, void*), void* arg)
+-{
+-	traverse_post(func, arg, tree->root);
+-}
+diff --git a/src/ldns/rdata.c b/src/ldns/rdata.c
+deleted file mode 100644
+index 6eb0096..0000000
+--- a/src/ldns/rdata.c
++++ /dev/null
+@@ -1,757 +0,0 @@
+-/*
+- * rdata.c
+- *
+- * rdata implementation
+- *
+- * a Net::DNS like library for C
+- *
+- * (c) NLnet Labs, 2004-2006
+- *
+- * See the file LICENSE for the license
+- */
+-
+-#include <ldns/config.h>
+-
+-#include <ldns/ldns.h>
+-
+-/*
+- * Access functions 
+- * do this as functions to get type checking
+- */
+-
+-/* read */
+-size_t
+-ldns_rdf_size(const ldns_rdf *rd)
+-{
+-	assert(rd != NULL);
+-	return rd->_size;
+-}
+-
+-ldns_rdf_type
+-ldns_rdf_get_type(const ldns_rdf *rd)
+-{
+-	assert(rd != NULL);
+-	return rd->_type;
+-}
+-
+-uint8_t *
+-ldns_rdf_data(const ldns_rdf *rd)
+-{
+-	assert(rd != NULL);
+-	return rd->_data;
+-}
+-
+-/* write */
+-void
+-ldns_rdf_set_size(ldns_rdf *rd, size_t size)
+-{
+-	assert(rd != NULL);
+-	rd->_size = size;
+-}
+-
+-void
+-ldns_rdf_set_type(ldns_rdf *rd, ldns_rdf_type type)
+-{
+-	assert(rd != NULL);
+-	rd->_type = type;
+-}
+-
+-void
+-ldns_rdf_set_data(ldns_rdf *rd, void *data)
+-{
+-	/* only copy the pointer */
+-	assert(rd != NULL);
+-	rd->_data = data;
+-}
+-
+-/* for types that allow it, return
+- * the native/host order type */
+-uint8_t
+-ldns_rdf2native_int8(const ldns_rdf *rd)
+-{
+-	uint8_t data;
+-
+-	/* only allow 8 bit rdfs */
+-	if (ldns_rdf_size(rd) != LDNS_RDF_SIZE_BYTE) {
+-		return 0;
+-	}
+-	
+-	memcpy(&data, ldns_rdf_data(rd), sizeof(data));
+-	return data;
+-}
+-
+-uint16_t
+-ldns_rdf2native_int16(const ldns_rdf *rd)
+-{
+-	uint16_t data;
+-
+-	/* only allow 16 bit rdfs */
+-	if (ldns_rdf_size(rd) != LDNS_RDF_SIZE_WORD) {
+-		return 0;
+-	}
+-	
+-	memcpy(&data, ldns_rdf_data(rd), sizeof(data));
+-	return ntohs(data);
+-}
+-
+-uint32_t
+-ldns_rdf2native_int32(const ldns_rdf *rd)
+-{
+-	uint32_t data;
+-
+-	/* only allow 32 bit rdfs */
+-	if (ldns_rdf_size(rd) != LDNS_RDF_SIZE_DOUBLEWORD) {
+-		return 0;
+-	}
+-	
+-	memcpy(&data, ldns_rdf_data(rd), sizeof(data));
+-	return ntohl(data);
+-}
+-
+-time_t
+-ldns_rdf2native_time_t(const ldns_rdf *rd)
+-{
+-	uint32_t data;
+-
+-	/* only allow 32 bit rdfs */
+-	if (ldns_rdf_size(rd) != LDNS_RDF_SIZE_DOUBLEWORD ||
+-			ldns_rdf_get_type(rd) != LDNS_RDF_TYPE_TIME) {
+-		return 0;
+-	}
+-	memcpy(&data, ldns_rdf_data(rd), sizeof(data));
+-	return (time_t)ntohl(data);
+-}
+-
+-ldns_rdf *
+-ldns_native2rdf_int8(ldns_rdf_type type, uint8_t value)
+-{
+-	return ldns_rdf_new_frm_data(type, LDNS_RDF_SIZE_BYTE, &value);
+-}
+-
+-ldns_rdf *
+-ldns_native2rdf_int16(ldns_rdf_type type, uint16_t value)
+-{
+-	uint16_t *rdf_data = LDNS_XMALLOC(uint16_t, 1);
+-        ldns_rdf* rdf;
+-	if (!rdf_data) {
+-		return NULL;
+-	}
+-	ldns_write_uint16(rdf_data, value);
+-	rdf = ldns_rdf_new(type, LDNS_RDF_SIZE_WORD, rdf_data);
+-        if(!rdf)
+-                LDNS_FREE(rdf_data);
+-        return rdf;
+-}
+-
+-ldns_rdf *
+-ldns_native2rdf_int32(ldns_rdf_type type, uint32_t value)
+-{
+-	uint32_t *rdf_data = LDNS_XMALLOC(uint32_t, 1);
+-        ldns_rdf* rdf;
+-	if (!rdf_data) {
+-		return NULL;
+-	}
+-	ldns_write_uint32(rdf_data, value);
+-	rdf = ldns_rdf_new(type, LDNS_RDF_SIZE_DOUBLEWORD, rdf_data);
+-        if(!rdf)
+-                LDNS_FREE(rdf_data);
+-        return rdf;
+-}
+-
+-ldns_rdf *
+-ldns_native2rdf_int16_data(size_t size, uint8_t *data)
+-{
+-	uint8_t *rdf_data = LDNS_XMALLOC(uint8_t, size + 2);
+-        ldns_rdf* rdf;
+-	if (!rdf_data) {
+-		return NULL;
+-	}
+-	ldns_write_uint16(rdf_data, size);
+-	memcpy(rdf_data + 2, data, size);
+-	rdf = ldns_rdf_new(LDNS_RDF_TYPE_INT16_DATA, size + 2, rdf_data);
+-        if(!rdf)
+-                LDNS_FREE(rdf_data);
+-        return rdf;
+-}
+-
+-/* note: data must be allocated memory */
+-ldns_rdf *
+-ldns_rdf_new(ldns_rdf_type type, size_t size, void *data)
+-{
+-	ldns_rdf *rd;
+-	rd = LDNS_MALLOC(ldns_rdf);
+-	if (!rd) {
+-		return NULL;
+-	}
+-	ldns_rdf_set_size(rd, size);
+-	ldns_rdf_set_type(rd, type);
+-	ldns_rdf_set_data(rd, data);
+-	return rd;
+-}
+-
+-ldns_rdf *
+-ldns_rdf_new_frm_data(ldns_rdf_type type, size_t size, const void *data)
+-{
+-	ldns_rdf *rdf;
+-
+-	/* if the size is too big, fail */
+-	if (size > LDNS_MAX_RDFLEN) {
+-		return NULL;
+-	}
+-
+-	/* allocate space */
+-	rdf = LDNS_MALLOC(ldns_rdf);
+-	if (!rdf) {
+-		return NULL;
+-	}
+-	rdf->_data = LDNS_XMALLOC(uint8_t, size);
+-	if (!rdf->_data) {
+-		LDNS_FREE(rdf);
+-		return NULL;
+-	}
+-	
+-	/* set the values */
+-	ldns_rdf_set_type(rdf, type);
+-	ldns_rdf_set_size(rdf, size);
+-	memcpy(rdf->_data, data, size);
+-
+-	return rdf;
+-}
+-
+-ldns_rdf *
+-ldns_rdf_clone(const ldns_rdf *rd)
+-{
+-	assert(rd != NULL);
+-	return (ldns_rdf_new_frm_data( ldns_rdf_get_type(rd),
+-		ldns_rdf_size(rd), ldns_rdf_data(rd)));
+-}
+-
+-void
+-ldns_rdf_deep_free(ldns_rdf *rd)
+-{
+-	if (rd) {
+-		if (rd->_data) {
+-			LDNS_FREE(rd->_data);
+-		}
+-		LDNS_FREE(rd);
+-	}
+-}
+-
+-void 
+-ldns_rdf_free(ldns_rdf *rd)
+-{
+-	if (rd) {
+-		LDNS_FREE(rd);
+-	}
+-}
+-
+-ldns_rdf *
+-ldns_rdf_new_frm_str(ldns_rdf_type type, const char *str)
+-{
+-	ldns_rdf *rdf = NULL;
+-	ldns_status status;
+-
+-	switch (type) {
+-	case LDNS_RDF_TYPE_DNAME:
+-		status = ldns_str2rdf_dname(&rdf, str);
+-		break;
+-	case LDNS_RDF_TYPE_INT8:
+-		status = ldns_str2rdf_int8(&rdf, str);
+-		break;
+-	case LDNS_RDF_TYPE_INT16:
+-		status = ldns_str2rdf_int16(&rdf, str);
+-		break;
+-	case LDNS_RDF_TYPE_INT32:
+-		status = ldns_str2rdf_int32(&rdf, str);
+-		break;
+-	case LDNS_RDF_TYPE_A:
+-		status = ldns_str2rdf_a(&rdf, str);
+-		break;
+-	case LDNS_RDF_TYPE_AAAA:
+-		status = ldns_str2rdf_aaaa(&rdf, str);
+-		break;
+-	case LDNS_RDF_TYPE_STR:
+-		status = ldns_str2rdf_str(&rdf, str);
+-		break;
+-	case LDNS_RDF_TYPE_APL:
+-		status = ldns_str2rdf_apl(&rdf, str);
+-		break;
+-	case LDNS_RDF_TYPE_B64:
+-		status = ldns_str2rdf_b64(&rdf, str);
+-		break;
+-	case LDNS_RDF_TYPE_B32_EXT:
+-		status = ldns_str2rdf_b32_ext(&rdf, str);
+-		break;
+-	case LDNS_RDF_TYPE_HEX:
+-		status = ldns_str2rdf_hex(&rdf, str);
+-		break;
+-	case LDNS_RDF_TYPE_NSEC:
+-		status = ldns_str2rdf_nsec(&rdf, str);
+-		break;
+-	case LDNS_RDF_TYPE_TYPE:
+-		status = ldns_str2rdf_type(&rdf, str);
+-		break;
+-	case LDNS_RDF_TYPE_CLASS:
+-		status = ldns_str2rdf_class(&rdf, str);
+-		break;
+-	case LDNS_RDF_TYPE_CERT_ALG:
+-		status = ldns_str2rdf_cert_alg(&rdf, str);
+-		break;
+-	case LDNS_RDF_TYPE_ALG:
+-		status = ldns_str2rdf_alg(&rdf, str);
+-		break;
+-	case LDNS_RDF_TYPE_UNKNOWN:
+-		status = ldns_str2rdf_unknown(&rdf, str);
+-		break;
+-	case LDNS_RDF_TYPE_TIME:
+-		status = ldns_str2rdf_time(&rdf, str);
+-		break;
+-	case LDNS_RDF_TYPE_PERIOD:
+-		status = ldns_str2rdf_period(&rdf, str);
+-		break;
+-	case LDNS_RDF_TYPE_HIP:
+-		status = ldns_str2rdf_hip(&rdf, str);
+-		break;
+-	case LDNS_RDF_TYPE_SERVICE:
+-		status = ldns_str2rdf_service(&rdf, str);
+-		break;
+-	case LDNS_RDF_TYPE_LOC:
+-		status = ldns_str2rdf_loc(&rdf, str);
+-		break;
+-	case LDNS_RDF_TYPE_WKS:
+-		status = ldns_str2rdf_wks(&rdf, str);
+-		break;
+-	case LDNS_RDF_TYPE_NSAP:
+-		status = ldns_str2rdf_nsap(&rdf, str);
+-		break;
+-	case LDNS_RDF_TYPE_ATMA:
+-		status = ldns_str2rdf_atma(&rdf, str);
+-		break;
+-	case LDNS_RDF_TYPE_IPSECKEY:
+-		status = ldns_str2rdf_ipseckey(&rdf, str);
+-		break;
+-	case LDNS_RDF_TYPE_NSEC3_SALT:
+-		status = ldns_str2rdf_nsec3_salt(&rdf, str);
+-		break;
+-	case LDNS_RDF_TYPE_NSEC3_NEXT_OWNER:
+-		status = ldns_str2rdf_b32_ext(&rdf, str);
+-		break;
+-	case LDNS_RDF_TYPE_ILNP64:
+-		status = ldns_str2rdf_ilnp64(&rdf, str);
+-		break;
+-	case LDNS_RDF_TYPE_EUI48:
+-		status = ldns_str2rdf_eui48(&rdf, str);
+-		break;
+-	case LDNS_RDF_TYPE_EUI64:
+-		status = ldns_str2rdf_eui64(&rdf, str);
+-		break;
+-	case LDNS_RDF_TYPE_TAG:
+-		status = ldns_str2rdf_tag(&rdf, str);
+-		break;
+-	case LDNS_RDF_TYPE_LONG_STR:
+-		status = ldns_str2rdf_long_str(&rdf, str);
+-		break;
+-	case LDNS_RDF_TYPE_CERTIFICATE_USAGE:
+-		status = ldns_str2rdf_certificate_usage(&rdf, str);
+-		break;
+-	case LDNS_RDF_TYPE_SELECTOR:
+-		status = ldns_str2rdf_selector(&rdf, str);
+-		break;
+-	case LDNS_RDF_TYPE_MATCHING_TYPE:
+-		status = ldns_str2rdf_matching_type(&rdf, str);
+-		break;
+-	case LDNS_RDF_TYPE_NONE:
+-	default:
+-		/* default default ??? */
+-		status = LDNS_STATUS_ERR;
+-		break;
+-	}
+-	if (LDNS_STATUS_OK == status) {
+-		ldns_rdf_set_type(rdf, type);
+-		return rdf;
+-	}
+-	if (rdf) {
+-		LDNS_FREE(rdf);
+-	}
+-	return NULL;
+-}
+-
+-ldns_status
+-ldns_rdf_new_frm_fp(ldns_rdf **rdf, ldns_rdf_type type, FILE *fp)
+-{
+-	return ldns_rdf_new_frm_fp_l(rdf, type, fp, NULL);
+-}
+-
+-ldns_status
+-ldns_rdf_new_frm_fp_l(ldns_rdf **rdf, ldns_rdf_type type, FILE *fp, int *line_nr)
+-{
+-	char *line;
+-	ldns_rdf *r;
+-	ssize_t t;
+-
+-	line = LDNS_XMALLOC(char, LDNS_MAX_LINELEN + 1);
+-	if (!line) {
+-		return LDNS_STATUS_MEM_ERR;
+-	}
+-
+-	/* read an entire line in from the file */
+-	if ((t = ldns_fget_token_l(fp, line, LDNS_PARSE_SKIP_SPACE, 0, line_nr)) == -1 || t == 0) {
+-		LDNS_FREE(line);
+-		return LDNS_STATUS_SYNTAX_RDATA_ERR;
+-	}
+-	r =  ldns_rdf_new_frm_str(type, (const char*) line);
+-	LDNS_FREE(line);
+-	if (rdf) {
+-		*rdf = r;
+-		return LDNS_STATUS_OK;
+-	} else {
+-		return LDNS_STATUS_NULL;
+-	}
+-}
+-
+-ldns_rdf *
+-ldns_rdf_address_reverse(ldns_rdf *rd)
+-{
+-	uint8_t buf_4[LDNS_IP4ADDRLEN];
+-	uint8_t buf_6[LDNS_IP6ADDRLEN * 2];
+-	ldns_rdf *rev;
+-	ldns_rdf *in_addr;
+-	ldns_rdf *ret_dname;
+-	uint8_t octet;
+-	uint8_t nnibble;
+-	uint8_t nibble;
+-	uint8_t i, j;
+-
+-	char *char_dname;
+-	int nbit;
+-
+-	if (ldns_rdf_get_type(rd) != LDNS_RDF_TYPE_A &&
+-			ldns_rdf_get_type(rd) != LDNS_RDF_TYPE_AAAA) {
+-		return NULL;
+-	}
+-
+-	in_addr = NULL;
+-	ret_dname = NULL;
+-
+-	switch(ldns_rdf_get_type(rd)) {
+-		case LDNS_RDF_TYPE_A:
+-			/* the length of the buffer is 4 */
+-			buf_4[3] = ldns_rdf_data(rd)[0];
+-			buf_4[2] = ldns_rdf_data(rd)[1];
+-			buf_4[1] = ldns_rdf_data(rd)[2];
+-			buf_4[0] = ldns_rdf_data(rd)[3];
+-			in_addr = ldns_dname_new_frm_str("in-addr.arpa.");
+-			if (!in_addr) {
+-				return NULL;
+-			}
+-			/* make a new rdf and convert that back  */
+-			rev = ldns_rdf_new_frm_data( LDNS_RDF_TYPE_A,
+-				LDNS_IP4ADDRLEN, (void*)&buf_4);
+-			if (!rev) {
+-				LDNS_FREE(in_addr);
+-				return NULL;
+-			}
+-
+-			/* convert rev to a string */
+-			char_dname = ldns_rdf2str(rev);
+-			if (!char_dname) {
+-				LDNS_FREE(in_addr);
+-				ldns_rdf_deep_free(rev);
+-				return NULL;
+-			}
+-			/* transform back to rdf with type dname */
+-			ret_dname = ldns_dname_new_frm_str(char_dname);
+-			if (!ret_dname) {
+-				LDNS_FREE(in_addr);
+-				ldns_rdf_deep_free(rev);
+-				LDNS_FREE(char_dname);
+-				return NULL;
+-			}
+-			/* not needed anymore */
+-			ldns_rdf_deep_free(rev);
+-			LDNS_FREE(char_dname);
+-			break;
+-		case LDNS_RDF_TYPE_AAAA:
+-			/* some foo magic to reverse the nibbles ... */
+-
+-			for (nbit = 127; nbit >= 0; nbit = nbit - 4) {
+-				/* calculate octett (8 bit) */
+-				octet = ( ((unsigned int) nbit) & 0x78) >> 3;
+-				/* calculate nibble */
+-				nnibble = ( ((unsigned int) nbit) & 0x04) >> 2;
+-				/* extract nibble */
+-				nibble = (ldns_rdf_data(rd)[octet] & ( 0xf << (4 * (1 -
+-						 nnibble)) ) ) >> ( 4 * (1 - 
+-						nnibble));
+-
+-				buf_6[(LDNS_IP6ADDRLEN * 2 - 1) -
+-					(octet * 2 + nnibble)] = 
+-						(uint8_t)ldns_int_to_hexdigit((int)nibble);
+-			}
+-
+-			char_dname = LDNS_XMALLOC(char, (LDNS_IP6ADDRLEN * 4));
+-			if (!char_dname) {
+-				return NULL;
+-			}
+-			char_dname[LDNS_IP6ADDRLEN * 4 - 1] = '\0'; /* closure */
+-
+-			/* walk the string and add . 's */
+-			for (i = 0, j = 0; i < LDNS_IP6ADDRLEN * 2; i++, j = j + 2) {
+-				char_dname[j] = (char)buf_6[i];
+-				if (i != LDNS_IP6ADDRLEN * 2 - 1) {
+-					char_dname[j + 1] = '.';
+-				}
+-			}
+-			in_addr = ldns_dname_new_frm_str("ip6.arpa.");
+-			if (!in_addr) {
+-				LDNS_FREE(char_dname);
+-				return NULL;
+-			}
+-
+-			/* convert rev to a string */
+-			ret_dname = ldns_dname_new_frm_str(char_dname);
+-			LDNS_FREE(char_dname);
+-			if (!ret_dname) {
+-				ldns_rdf_deep_free(in_addr);
+-				return NULL;
+-			}
+-			break;
+-		default:
+-			break;
+-	}
+-	/* add the suffix */
+-	rev = ldns_dname_cat_clone(ret_dname, in_addr);
+-
+-	ldns_rdf_deep_free(ret_dname);
+-	ldns_rdf_deep_free(in_addr);
+-	return rev;
+-}
+-
+-ldns_status
+-ldns_rdf_hip_get_alg_hit_pk(ldns_rdf *rdf, uint8_t* alg,
+-                            uint8_t *hit_size, uint8_t** hit,
+-                            uint16_t *pk_size, uint8_t** pk)
+-{
+-	uint8_t *data;
+-	size_t rdf_size;
+-
+-	if (! rdf || ! alg || ! hit || ! hit_size || ! pk || ! pk_size) {
+-		return LDNS_STATUS_INVALID_POINTER;
+-	} else if (ldns_rdf_get_type(rdf) != LDNS_RDF_TYPE_HIP) {
+-		return LDNS_STATUS_INVALID_RDF_TYPE;
+-	} else if ((rdf_size = ldns_rdf_size(rdf)) < 6) {
+-		return LDNS_STATUS_WIRE_RDATA_ERR;
+-	}
+-	data = ldns_rdf_data(rdf);
+-	*hit_size = data[0];
+-	*alg      = data[1];
+-	*pk_size  = ldns_read_uint16(data + 2);
+-	*hit      = data + 4;
+-	*pk       = data + 4 + *hit_size;
+-	if (*hit_size == 0 || *pk_size == 0 ||
+-			rdf_size < (size_t) *hit_size + *pk_size + 4) {
+-		return LDNS_STATUS_WIRE_RDATA_ERR;
+-	}
+-	return LDNS_STATUS_OK;
+-}
+-
+-ldns_status
+-ldns_rdf_hip_new_frm_alg_hit_pk(ldns_rdf** rdf, uint8_t alg,
+-                                uint8_t hit_size, uint8_t *hit,
+-				uint16_t pk_size, uint8_t *pk)
+-{
+-	uint8_t *data;
+-
+-	if (! rdf) {
+-		return LDNS_STATUS_INVALID_POINTER;
+-	}
+-	if (4 + hit_size + pk_size > LDNS_MAX_RDFLEN) {
+-		return LDNS_STATUS_RDATA_OVERFLOW;
+-	}
+-	data = LDNS_XMALLOC(uint8_t, 4 + hit_size + pk_size);
+-	if (data == NULL) {
+-		return LDNS_STATUS_MEM_ERR;
+-	}
+-	data[0] = hit_size;
+-	data[1] = alg;
+-	ldns_write_uint16(data + 2, pk_size);
+-	memcpy(data + 4, hit, hit_size);
+-	memcpy(data + 4 + hit_size, pk, pk_size);
+-	*rdf = ldns_rdf_new(LDNS_RDF_TYPE_HIP, 4 + hit_size + pk_size, data);
+-	if (! *rdf) {
+-		LDNS_FREE(data);
+-		return LDNS_STATUS_MEM_ERR;
+-	}
+-	return LDNS_STATUS_OK;
+-}
+-
+-ldns_status
+-ldns_octet(char *word, size_t *length)
+-{
+-    char *s; 
+-    char *p;
+-    *length = 0;
+-
+-    for (s = p = word; *s != '\0'; s++,p++) {
+-        switch (*s) {
+-            case '.':
+-                if (s[1] == '.') {
+-		    return LDNS_STATUS_EMPTY_LABEL;
+-                }
+-                *p = *s;
+-                (*length)++;
+-                break;
+-            case '\\':
+-                if ('0' <= s[1] && s[1] <= '9' &&
+-                    '0' <= s[2] && s[2] <= '9' &&
+-                    '0' <= s[3] && s[3] <= '9') {
+-                    /* \DDD seen */
+-                    int val = ((s[1] - '0') * 100 +
+-                           (s[2] - '0') * 10 + (s[3] - '0'));
+-
+-                    if (0 <= val && val <= 255) {
+-                        /* this also handles \0 */
+-                        s += 3;
+-                        *p = val;
+-                        (*length)++;
+-                    } else {
+-                        return LDNS_STATUS_DDD_OVERFLOW;
+-                    }
+-                } else {
+-                    /* an espaced character, like \<space> ? 
+-                    * remove the '\' keep the rest */
+-                    *p = *++s;
+-                    (*length)++;
+-                }
+-                break;
+-            case '\"':
+-                /* non quoted " Is either first or the last character in
+-                 * the string */
+-
+-                *p = *++s; /* skip it */
+-                (*length)++;
+-		/* I'm not sure if this is needed in libdns... MG */
+-                if ( *s == '\0' ) {
+-                    /* ok, it was the last one */
+-                    *p  = '\0'; 
+-		    return LDNS_STATUS_OK;
+-                }
+-                break;
+-            default:
+-                *p = *s;
+-                (*length)++;
+-                break;
+-        }
+-    }
+-    *p = '\0';
+-    return LDNS_STATUS_OK;
+-}
+-
+-int
+-ldns_rdf_compare(const ldns_rdf *rd1, const ldns_rdf *rd2)
+-{
+-	uint16_t i1, i2, i;
+-	uint8_t *d1, *d2;
+-
+-	/* only when both are not NULL we can say anything about them */
+-	if (!rd1 && !rd2) {
+-		return 0;
+-	}
+-	if (!rd1 || !rd2) {
+-		return -1;
+-	}
+-	i1 = ldns_rdf_size(rd1);
+-	i2 = ldns_rdf_size(rd2);
+-
+-	if (i1 < i2) {
+-		return -1;
+-	} else if (i1 > i2) {
+-		return +1;
+-	} else {
+-		d1 = (uint8_t*)ldns_rdf_data(rd1);
+-		d2 = (uint8_t*)ldns_rdf_data(rd2);
+-		for(i = 0; i < i1; i++) {
+-			if (d1[i] < d2[i]) {
+-				return -1;
+-			} else if (d1[i] > d2[i]) {
+-				return +1;
+-			}
+-		}
+-	}
+-	return 0;
+-}
+-
+-uint32_t
+-ldns_str2period(const char *nptr, const char **endptr)
+-{
+-	int sign = 0;
+-	uint32_t i = 0;
+-	uint32_t seconds = 0;
+-
+-	for(*endptr = nptr; **endptr; (*endptr)++) {
+-		switch (**endptr) {
+-			case ' ':
+-			case '\t':
+-				break;
+-			case '-':
+-				if(sign == 0) {
+-					sign = -1;
+-				} else {
+-					return seconds;
+-				}
+-				break;
+-			case '+':
+-				if(sign == 0) {
+-					sign = 1;
+-				} else {
+-					return seconds;
+-				}
+-				break;
+-			case 's':
+-			case 'S':
+-				seconds += i;
+-				i = 0;
+-				break;
+-			case 'm':
+-			case 'M':
+-				seconds += i * 60;
+-				i = 0;
+-				break;
+-			case 'h':
+-			case 'H':
+-				seconds += i * 60 * 60;
+-				i = 0;
+-				break;
+-			case 'd':
+-			case 'D':
+-				seconds += i * 60 * 60 * 24;
+-				i = 0;
+-				break;
+-			case 'w':
+-			case 'W':
+-				seconds += i * 60 * 60 * 24 * 7;
+-				i = 0;
+-				break;
+-			case '0':
+-			case '1':
+-			case '2':
+-			case '3':
+-			case '4':
+-			case '5':
+-			case '6':
+-			case '7':
+-			case '8':
+-			case '9':
+-				i *= 10;
+-				i += (**endptr - '0');
+-				break;
+-			default:
+-				seconds += i;
+-				/* disregard signedness */
+-				return seconds;
+-		}
+-	}
+-	seconds += i;
+-	/* disregard signedness */
+-	return seconds;
+-}
+diff --git a/src/ldns/resolver.c b/src/ldns/resolver.c
+deleted file mode 100644
+index b092404..0000000
+--- a/src/ldns/resolver.c
++++ /dev/null
+@@ -1,1603 +0,0 @@
+-/*
+- * resolver.c
+- *
+- * resolver implementation
+- *
+- * a Net::DNS like library for C
+- *
+- * (c) NLnet Labs, 2004-2006
+- *
+- * See the file LICENSE for the license
+- */
+-
+-#include <ldns/config.h>
+-
+-#include <ldns/ldns.h>
+-#include <strings.h>
+-
+-/* Access function for reading
+- * and setting the different Resolver
+- * options */
+-
+-/* read */
+-uint16_t
+-ldns_resolver_port(const ldns_resolver *r)
+-{
+-	return r->_port;
+-}
+-
+-ldns_rdf *
+-ldns_resolver_source(const ldns_resolver *r)
+-{
+-	return r->_source;
+-}
+-
+-uint16_t
+-ldns_resolver_edns_udp_size(const ldns_resolver *r)
+-{
+-	        return r->_edns_udp_size;
+-}
+-
+-uint8_t
+-ldns_resolver_retry(const ldns_resolver *r)
+-{
+-	return r->_retry;
+-}
+-
+-uint8_t
+-ldns_resolver_retrans(const ldns_resolver *r)
+-{
+-	return r->_retrans;
+-}
+-
+-bool
+-ldns_resolver_fallback(const ldns_resolver *r)
+-{
+-	return r->_fallback;
+-}
+-
+-uint8_t
+-ldns_resolver_ip6(const ldns_resolver *r)
+-{
+-	return r->_ip6;
+-}
+-
+-bool
+-ldns_resolver_recursive(const ldns_resolver *r)
+-{
+-	return r->_recursive;
+-}
+-
+-bool
+-ldns_resolver_debug(const ldns_resolver *r)
+-{
+-	return r->_debug;
+-}
+-
+-bool
+-ldns_resolver_dnsrch(const ldns_resolver *r)
+-{
+-	return r->_dnsrch;
+-}
+-
+-bool
+-ldns_resolver_fail(const ldns_resolver *r)
+-{
+-	return r->_fail;
+-}
+-
+-bool
+-ldns_resolver_defnames(const ldns_resolver *r)
+-{
+-	return r->_defnames;
+-}
+-
+-ldns_rdf *
+-ldns_resolver_domain(const ldns_resolver *r)
+-{
+-	return r->_domain;
+-}
+-
+-ldns_rdf **
+-ldns_resolver_searchlist(const ldns_resolver *r)
+-{
+-	return r->_searchlist;
+-}
+-
+-ldns_rdf **
+-ldns_resolver_nameservers(const ldns_resolver *r)
+-{
+-	return r->_nameservers;
+-}
+-
+-size_t
+-ldns_resolver_nameserver_count(const ldns_resolver *r)
+-{
+-	return r->_nameserver_count;
+-}
+-
+-bool
+-ldns_resolver_dnssec(const ldns_resolver *r)
+-{
+-	return r->_dnssec;
+-}
+-
+-bool
+-ldns_resolver_dnssec_cd(const ldns_resolver *r)
+-{
+-	return r->_dnssec_cd;
+-}
+-
+-ldns_rr_list *
+-ldns_resolver_dnssec_anchors(const ldns_resolver *r)
+-{
+-    return r->_dnssec_anchors;
+-}
+-
+-bool
+-ldns_resolver_trusted_key(const ldns_resolver *r, ldns_rr_list * keys, ldns_rr_list * trusted_keys)
+-{
+-  size_t i;
+-  bool result = false;
+-
+-  ldns_rr_list * trust_anchors;
+-  ldns_rr * cur_rr;
+-
+-  if (!r || !keys) { return false; }
+-
+-  trust_anchors = ldns_resolver_dnssec_anchors(r);
+-
+-  if (!trust_anchors) { return false; }
+-
+-  for (i = 0; i < ldns_rr_list_rr_count(keys); i++) {
+-
+-    cur_rr = ldns_rr_list_rr(keys, i);
+-    if (ldns_rr_list_contains_rr(trust_anchors, cur_rr)) {
+-      if (trusted_keys) { ldns_rr_list_push_rr(trusted_keys, cur_rr); }
+-      result = true;
+-    }
+-  }
+-
+-  return result;
+-}
+-
+-bool
+-ldns_resolver_igntc(const ldns_resolver *r)
+-{
+-	return r->_igntc;
+-}
+-
+-bool
+-ldns_resolver_usevc(const ldns_resolver *r)
+-{
+-	return r->_usevc;
+-}
+-
+-size_t *
+-ldns_resolver_rtt(const ldns_resolver *r)
+-{
+-	return r->_rtt;
+-}
+-
+-size_t
+-ldns_resolver_nameserver_rtt(const ldns_resolver *r, size_t pos)
+-{
+-	size_t *rtt;
+-
+-	assert(r != NULL);
+-
+-	rtt = ldns_resolver_rtt(r);
+-
+-	if (pos >= ldns_resolver_nameserver_count(r)) {
+-		/* error ?*/
+-		return 0;
+-	} else {
+-		return rtt[pos];
+-	}
+-
+-}
+-
+-struct timeval
+-ldns_resolver_timeout(const ldns_resolver *r)
+-{
+-	return r->_timeout;
+-}
+-
+-char *
+-ldns_resolver_tsig_keyname(const ldns_resolver *r)
+-{
+-	return r->_tsig_keyname;
+-}
+-
+-char *
+-ldns_resolver_tsig_algorithm(const ldns_resolver *r)
+-{
+-	return r->_tsig_algorithm;
+-}
+-
+-char *
+-ldns_resolver_tsig_keydata(const ldns_resolver *r)
+-{
+-	return r->_tsig_keydata;
+-}
+-
+-bool
+-ldns_resolver_random(const ldns_resolver *r)
+-{
+-	return r->_random;
+-}
+-
+-size_t
+-ldns_resolver_searchlist_count(const ldns_resolver *r)
+-{
+-	return r->_searchlist_count;
+-}
+-
+-/* write */
+-void
+-ldns_resolver_set_port(ldns_resolver *r, uint16_t p)
+-{
+-	r->_port = p;
+-}
+-
+-void
+-ldns_resolver_set_source(ldns_resolver *r, ldns_rdf *s)
+-{
+-	r->_source = s;
+-}
+-
+-ldns_rdf *
+-ldns_resolver_pop_nameserver(ldns_resolver *r)
+-{
+-	ldns_rdf **nameservers;
+-	ldns_rdf *pop;
+-	size_t ns_count;
+-	size_t *rtt;
+-
+-	assert(r != NULL);
+-
+-	ns_count = ldns_resolver_nameserver_count(r);
+-	nameservers = ldns_resolver_nameservers(r);
+-	rtt = ldns_resolver_rtt(r);
+-	if (ns_count == 0 || !nameservers) {
+-		return NULL;
+-	}
+-
+-	pop = nameservers[ns_count - 1];
+-
+-	if (ns_count == 1) {
+-		LDNS_FREE(nameservers);
+-		LDNS_FREE(rtt);
+-
+-		ldns_resolver_set_nameservers(r, NULL);
+-		ldns_resolver_set_rtt(r, NULL);
+-	} else {
+-		nameservers = LDNS_XREALLOC(nameservers, ldns_rdf *, 
+-				(ns_count - 1));
+-		rtt = LDNS_XREALLOC(rtt, size_t, (ns_count - 1));
+-
+-	        ldns_resolver_set_nameservers(r, nameservers);
+-	        ldns_resolver_set_rtt(r, rtt);
+-	}
+-	/* decr the count */
+-	ldns_resolver_dec_nameserver_count(r);
+-	return pop;
+-}
+-
+-ldns_status
+-ldns_resolver_push_nameserver(ldns_resolver *r, ldns_rdf *n)
+-{
+-	ldns_rdf **nameservers;
+-	size_t ns_count;
+-	size_t *rtt;
+-
+-	if (ldns_rdf_get_type(n) != LDNS_RDF_TYPE_A &&
+-			ldns_rdf_get_type(n) != LDNS_RDF_TYPE_AAAA) {
+-		return LDNS_STATUS_ERR;
+-	}
+-
+-	ns_count = ldns_resolver_nameserver_count(r);
+-	nameservers = ldns_resolver_nameservers(r);
+-	rtt = ldns_resolver_rtt(r);
+-
+-	/* make room for the next one */
+-	if (ns_count == 0) {
+-		nameservers = LDNS_XMALLOC(ldns_rdf *, 1);
+-	} else {
+-		nameservers = LDNS_XREALLOC(nameservers, ldns_rdf *, (ns_count + 1));
+-	}
+-        if(!nameservers)
+-                return LDNS_STATUS_MEM_ERR;
+-
+-	/* set the new value in the resolver */
+-	ldns_resolver_set_nameservers(r, nameservers);
+-
+-	/* don't forget the rtt */
+-	if (ns_count == 0) {
+-		rtt = LDNS_XMALLOC(size_t, 1);
+-	} else {
+-		rtt = LDNS_XREALLOC(rtt, size_t, (ns_count + 1));
+-	}
+-        if(!rtt)
+-                return LDNS_STATUS_MEM_ERR;
+-
+-	/* slide n in its slot. */
+-	/* we clone it here, because then we can free the original
+-	 * rr's where it stood */
+-	nameservers[ns_count] = ldns_rdf_clone(n);
+-	rtt[ns_count] = LDNS_RESOLV_RTT_MIN;
+-	ldns_resolver_incr_nameserver_count(r);
+-	ldns_resolver_set_rtt(r, rtt);
+-	return LDNS_STATUS_OK;
+-}
+-
+-ldns_status
+-ldns_resolver_push_nameserver_rr(ldns_resolver *r, ldns_rr *rr)
+-{
+-	ldns_rdf *address;
+-	if ((!rr) || (ldns_rr_get_type(rr) != LDNS_RR_TYPE_A &&
+-			ldns_rr_get_type(rr) != LDNS_RR_TYPE_AAAA)) {
+-		return LDNS_STATUS_ERR;
+-	}
+-	address = ldns_rr_rdf(rr, 0); /* extract the ip number */
+-	if (address) {
+-		return ldns_resolver_push_nameserver(r, address);
+-	} else {
+-		return LDNS_STATUS_ERR;
+-	}
+-}
+-
+-ldns_status
+-ldns_resolver_push_nameserver_rr_list(ldns_resolver *r, ldns_rr_list *rrlist)
+-{
+-	ldns_rr *rr;
+-	ldns_status stat;
+-	size_t i;
+-
+-	stat = LDNS_STATUS_OK;
+-	if (rrlist) {
+-		for(i = 0; i < ldns_rr_list_rr_count(rrlist); i++) {
+-			rr = ldns_rr_list_rr(rrlist, i);
+-			if (ldns_resolver_push_nameserver_rr(r, rr) != LDNS_STATUS_OK) {
+-				stat = LDNS_STATUS_ERR;
+-				break;
+-			}
+-		}
+-		return stat;
+-	} else {
+-		return LDNS_STATUS_ERR;
+-	}
+-}
+-
+-void
+-ldns_resolver_set_edns_udp_size(ldns_resolver *r, uint16_t s)
+-{
+-	        r->_edns_udp_size = s;
+-}
+-
+-void
+-ldns_resolver_set_recursive(ldns_resolver *r, bool re)
+-{
+-	r->_recursive = re;
+-}
+-
+-void
+-ldns_resolver_set_dnssec(ldns_resolver *r, bool d)
+-{
+-	r->_dnssec = d;
+-}
+-
+-void
+-ldns_resolver_set_dnssec_cd(ldns_resolver *r, bool d)
+-{
+-	r->_dnssec_cd = d;
+-}
+-
+-void
+-ldns_resolver_set_dnssec_anchors(ldns_resolver *r, ldns_rr_list * l)
+-{
+-  r->_dnssec_anchors = l;
+-}
+-
+-ldns_status
+-ldns_resolver_push_dnssec_anchor(ldns_resolver *r, ldns_rr *rr)
+-{
+-  ldns_rr_list * trust_anchors;
+-
+-  if ((!rr) || (ldns_rr_get_type(rr) != LDNS_RR_TYPE_DNSKEY &&
+-                ldns_rr_get_type(rr) != LDNS_RR_TYPE_DS)) {
+-
+-    return LDNS_STATUS_ERR;
+-  }
+-
+-  if (!(trust_anchors = ldns_resolver_dnssec_anchors(r))) { /* Initialize */
+-    trust_anchors = ldns_rr_list_new();
+-    ldns_resolver_set_dnssec_anchors(r, trust_anchors);
+-  }
+-
+-  return (ldns_rr_list_push_rr(trust_anchors, ldns_rr_clone(rr))) ? LDNS_STATUS_OK : LDNS_STATUS_ERR;
+-}
+-
+-void
+-ldns_resolver_set_igntc(ldns_resolver *r, bool i)
+-{
+-	r->_igntc = i;
+-}
+-
+-void
+-ldns_resolver_set_usevc(ldns_resolver *r, bool vc)
+-{
+-	r->_usevc = vc;
+-}
+-
+-void
+-ldns_resolver_set_debug(ldns_resolver *r, bool d)
+-{
+-	r->_debug = d;
+-}
+-
+-void
+-ldns_resolver_set_ip6(ldns_resolver *r, uint8_t ip6)
+-{
+-	r->_ip6 = ip6;
+-}
+-
+-void
+-ldns_resolver_set_fail(ldns_resolver *r, bool f)
+-{
+-	r->_fail =f;
+-}
+-
+-static void
+-ldns_resolver_set_searchlist_count(ldns_resolver *r, size_t c)
+-{
+-	r->_searchlist_count = c;
+-}
+-
+-void
+-ldns_resolver_set_nameserver_count(ldns_resolver *r, size_t c)
+-{
+-	r->_nameserver_count = c;
+-}
+-
+-void
+-ldns_resolver_set_dnsrch(ldns_resolver *r, bool d)
+-{
+-	r->_dnsrch = d;
+-}
+-
+-void
+-ldns_resolver_set_retry(ldns_resolver *r, uint8_t retry)
+-{
+-	r->_retry = retry;
+-}
+-
+-void
+-ldns_resolver_set_retrans(ldns_resolver *r, uint8_t retrans)
+-{
+-	r->_retrans = retrans;
+-}
+-
+-void
+-ldns_resolver_set_fallback(ldns_resolver *r, bool fallback)
+-{
+-	r->_fallback = fallback;
+-}
+-
+-void
+-ldns_resolver_set_nameservers(ldns_resolver *r, ldns_rdf **n)
+-{
+-	r->_nameservers = n;
+-}
+-
+-void
+-ldns_resolver_set_defnames(ldns_resolver *r, bool d)
+-{
+-	r->_defnames = d;
+-}
+-
+-void
+-ldns_resolver_set_rtt(ldns_resolver *r, size_t *rtt)
+-{
+-	r->_rtt = rtt;
+-}
+-
+-void
+-ldns_resolver_set_nameserver_rtt(ldns_resolver *r, size_t pos, size_t value)
+-{
+-	size_t *rtt;
+-
+-	assert(r != NULL);
+-
+-	rtt = ldns_resolver_rtt(r);
+-
+-	if (pos >= ldns_resolver_nameserver_count(r)) {
+-		/* error ?*/
+-	} else {
+-		rtt[pos] = value;
+-	}
+-
+-}
+-
+-void
+-ldns_resolver_incr_nameserver_count(ldns_resolver *r)
+-{
+-	size_t c;
+-
+-	c = ldns_resolver_nameserver_count(r);
+-	ldns_resolver_set_nameserver_count(r, ++c);
+-}
+-
+-void
+-ldns_resolver_dec_nameserver_count(ldns_resolver *r)
+-{
+-	size_t c;
+-
+-	c = ldns_resolver_nameserver_count(r);
+-	if (c == 0) {
+-		return;
+-	} else {
+-		ldns_resolver_set_nameserver_count(r, --c);
+-	}
+-}
+-
+-void
+-ldns_resolver_set_domain(ldns_resolver *r, ldns_rdf *d)
+-{
+-	r->_domain = d;
+-}
+-
+-void
+-ldns_resolver_set_timeout(ldns_resolver *r, struct timeval timeout)
+-{
+-	r->_timeout.tv_sec = timeout.tv_sec;
+-	r->_timeout.tv_usec = timeout.tv_usec;
+-}
+-
+-void
+-ldns_resolver_push_searchlist(ldns_resolver *r, ldns_rdf *d)
+-{
+-	ldns_rdf **searchlist;
+-	size_t list_count;
+-
+-	if (ldns_rdf_get_type(d) != LDNS_RDF_TYPE_DNAME) {
+-		return;
+-	}
+-
+-	list_count = ldns_resolver_searchlist_count(r);
+-	searchlist = ldns_resolver_searchlist(r);
+-
+-	searchlist = LDNS_XREALLOC(searchlist, ldns_rdf *, (list_count + 1));
+-	if (searchlist) {
+-		r->_searchlist = searchlist;
+-
+-		searchlist[list_count] = ldns_rdf_clone(d);
+-		ldns_resolver_set_searchlist_count(r, list_count + 1);
+-	} /* no way to report mem err */
+-}
+-
+-void
+-ldns_resolver_set_tsig_keyname(ldns_resolver *r, char *tsig_keyname)
+-{
+-	LDNS_FREE(r->_tsig_keyname);
+-	r->_tsig_keyname = strdup(tsig_keyname);
+-}
+-
+-void
+-ldns_resolver_set_tsig_algorithm(ldns_resolver *r, char *tsig_algorithm)
+-{
+-	LDNS_FREE(r->_tsig_algorithm);
+-	r->_tsig_algorithm = strdup(tsig_algorithm);
+-}
+-
+-void
+-ldns_resolver_set_tsig_keydata(ldns_resolver *r, char *tsig_keydata)
+-{
+-	LDNS_FREE(r->_tsig_keydata);
+-	r->_tsig_keydata = strdup(tsig_keydata);
+-}
+-
+-void
+-ldns_resolver_set_random(ldns_resolver *r, bool b)
+-{
+-	r->_random = b;
+-}
+-
+-/* more sophisticated functions */
+-ldns_resolver *
+-ldns_resolver_new(void)
+-{
+-	ldns_resolver *r;
+-
+-	r = LDNS_MALLOC(ldns_resolver);
+-	if (!r) {
+-		return NULL;
+-	}
+-
+-	r->_searchlist = NULL;
+-	r->_nameservers = NULL;
+-	r->_rtt = NULL;
+-
+-	/* defaults are filled out */
+-	ldns_resolver_set_searchlist_count(r, 0);
+-	ldns_resolver_set_nameserver_count(r, 0);
+-	ldns_resolver_set_usevc(r, 0);
+-	ldns_resolver_set_port(r, LDNS_PORT);
+-	ldns_resolver_set_domain(r, NULL);
+-	ldns_resolver_set_defnames(r, false);
+-	ldns_resolver_set_retry(r, 3);
+-	ldns_resolver_set_retrans(r, 2);
+-	ldns_resolver_set_fallback(r, true);
+-	ldns_resolver_set_fail(r, false);
+-	ldns_resolver_set_edns_udp_size(r, 0);
+-	ldns_resolver_set_dnssec(r, false);
+-	ldns_resolver_set_dnssec_cd(r, false);
+-	ldns_resolver_set_dnssec_anchors(r, NULL);
+-	ldns_resolver_set_ip6(r, LDNS_RESOLV_INETANY);
+-	ldns_resolver_set_igntc(r, false);
+-	ldns_resolver_set_recursive(r, false);
+-	ldns_resolver_set_dnsrch(r, true);
+-	ldns_resolver_set_source(r, NULL);
+-	ldns_resolver_set_ixfr_serial(r, 0);
+-
+-	/* randomize the nameserver to be queried
+-	 * when there are multiple
+-	 */
+-	ldns_resolver_set_random(r, true);
+-
+-	ldns_resolver_set_debug(r, 0);
+-
+-	r->_timeout.tv_sec = LDNS_DEFAULT_TIMEOUT_SEC;
+-	r->_timeout.tv_usec = LDNS_DEFAULT_TIMEOUT_USEC;
+-
+-	/* TODO: fd=0 is actually a valid socket (stdin),
+-           replace with -1 */
+-	r->_socket = 0;
+-	r->_axfr_soa_count = 0;
+-	r->_axfr_i = 0;
+-	r->_cur_axfr_pkt = NULL;
+-
+-	r->_tsig_keyname = NULL;
+-	r->_tsig_keydata = NULL;
+-	r->_tsig_algorithm = NULL;
+-	return r;
+-}
+-
+-ldns_resolver *
+-ldns_resolver_clone(ldns_resolver *src)
+-{
+-	ldns_resolver *dst;
+-	size_t i;
+-
+-	assert(src != NULL);
+-
+-	if (!(dst = LDNS_MALLOC(ldns_resolver))) return NULL;
+-	(void) memcpy(dst, src, sizeof(ldns_resolver));
+-
+-	if (dst->_searchlist_count == 0)
+-		dst->_searchlist = NULL;
+-	else {
+-		if (!(dst->_searchlist =
+-		    LDNS_XMALLOC(ldns_rdf *, dst->_searchlist_count)))
+-			goto error;
+-		for (i = 0; i < dst->_searchlist_count; i++)
+-			if (!(dst->_searchlist[i] =
+-			    ldns_rdf_clone(src->_searchlist[i]))) {
+-				dst->_searchlist_count = i;
+-				goto error_searchlist;
+-			}
+-	}
+-	if (dst->_nameserver_count == 0) {
+-		dst->_nameservers = NULL;
+-		dst->_rtt = NULL;
+-	} else {
+-		if (!(dst->_nameservers =
+-		    LDNS_XMALLOC(ldns_rdf *, dst->_nameserver_count)))
+-			goto error_searchlist;
+-		for (i = 0; i < dst->_nameserver_count; i++)
+-			if (!(dst->_nameservers[i] =
+-			    ldns_rdf_clone(src->_nameservers[i]))) {
+-				dst->_nameserver_count = i;
+-				goto error_nameservers;
+-			}
+-		if (!(dst->_rtt =
+-		    LDNS_XMALLOC(size_t, dst->_nameserver_count)))
+-			goto error_nameservers;
+-		(void) memcpy(dst->_rtt, src->_rtt,
+-		    sizeof(size_t) * dst->_nameserver_count);
+-	}
+-	if (dst->_domain && (!(dst->_domain = ldns_rdf_clone(src->_domain))))
+-		goto error_rtt;
+-
+-	if (dst->_tsig_keyname &&
+-	    (!(dst->_tsig_keyname = strdup(src->_tsig_keyname))))
+-		goto error_domain;
+-
+-	if (dst->_tsig_keydata &&
+-	    (!(dst->_tsig_keydata = strdup(src->_tsig_keydata))))
+-		goto error_tsig_keyname;
+-
+-	if (dst->_tsig_algorithm &&
+-	    (!(dst->_tsig_algorithm = strdup(src->_tsig_algorithm))))
+-		goto error_tsig_keydata;
+-
+-	if (dst->_cur_axfr_pkt &&
+-	    (!(dst->_cur_axfr_pkt = ldns_pkt_clone(src->_cur_axfr_pkt))))
+-		goto error_tsig_algorithm;
+-
+-	if (dst->_dnssec_anchors &&
+-	    (!(dst->_dnssec_anchors=ldns_rr_list_clone(src->_dnssec_anchors))))
+-		goto error_cur_axfr_pkt;
+-
+-	return dst;
+-
+-error_cur_axfr_pkt:
+-	ldns_pkt_free(dst->_cur_axfr_pkt);
+-error_tsig_algorithm:
+-	LDNS_FREE(dst->_tsig_algorithm);
+-error_tsig_keydata:
+-	LDNS_FREE(dst->_tsig_keydata);
+-error_tsig_keyname:
+-	LDNS_FREE(dst->_tsig_keyname);
+-error_domain:
+-	ldns_rdf_deep_free(dst->_domain);
+-error_rtt:
+-	LDNS_FREE(dst->_rtt);
+-error_nameservers:
+-	for (i = 0; i < dst->_nameserver_count; i++)
+-		ldns_rdf_deep_free(dst->_nameservers[i]);
+-	LDNS_FREE(dst->_nameservers);
+-error_searchlist:
+-	for (i = 0; i < dst->_searchlist_count; i++)
+-		ldns_rdf_deep_free(dst->_searchlist[i]);
+-	LDNS_FREE(dst->_searchlist);
+-error:
+-	LDNS_FREE(dst);
+-	return NULL;
+-}
+-
+-
+-ldns_status
+-ldns_resolver_new_frm_fp(ldns_resolver **res, FILE *fp)
+-{
+-	return ldns_resolver_new_frm_fp_l(res, fp, NULL);
+-}
+-
+-ldns_status
+-ldns_resolver_new_frm_fp_l(ldns_resolver **res, FILE *fp, int *line_nr)
+-{
+-	ldns_resolver *r;
+-	const char *keyword[LDNS_RESOLV_KEYWORDS];
+-	char word[LDNS_MAX_LINELEN + 1];
+-	int8_t expect;
+-	uint8_t i;
+-	ldns_rdf *tmp;
+-#ifdef HAVE_SSL
+-	ldns_rr *tmp_rr;
+-#endif
+-	ssize_t gtr, bgtr;
+-	ldns_buffer *b;
+-        int lnr = 0, oldline;
+-	FILE* myfp = fp;
+-        if(!line_nr) line_nr = &lnr;
+-
+-	if(!fp) {
+-		myfp = fopen("/etc/resolv.conf", "r");
+-		if(!myfp)
+-			return LDNS_STATUS_FILE_ERR;
+-	}
+-
+-	/* do this better
+-	 * expect =
+-	 * 0: keyword
+-	 * 1: default domain dname
+-	 * 2: NS aaaa or a record
+-	 */
+-
+-	/* recognized keywords */
+-	keyword[LDNS_RESOLV_NAMESERVER] = "nameserver";
+-	keyword[LDNS_RESOLV_DEFDOMAIN] = "domain";
+-	keyword[LDNS_RESOLV_SEARCH] = "search";
+-	/* these two are read but not used atm TODO */
+-	keyword[LDNS_RESOLV_SORTLIST] = "sortlist";
+-	keyword[LDNS_RESOLV_OPTIONS] = "options";
+-	keyword[LDNS_RESOLV_ANCHOR] = "anchor";
+-	expect = LDNS_RESOLV_KEYWORD;
+-
+-	r = ldns_resolver_new();
+-	if (!r) {
+-		if(!fp) fclose(myfp);
+-		return LDNS_STATUS_MEM_ERR;
+-	}
+-
+-	gtr = 1;
+-	word[0] = 0;
+-        oldline = *line_nr;
+-        expect = LDNS_RESOLV_KEYWORD;
+-	while (gtr > 0) {
+-		/* check comments */
+-		if (word[0] == '#') {
+-                        word[0]='x';
+-                        if(oldline == *line_nr) {
+-                                /* skip until end of line */
+-                                int c;
+-                                do {
+-                                        c = fgetc(myfp);
+-                                } while(c != EOF && c != '\n');
+-                                if(c=='\n') (*line_nr)++;
+-                        }
+-			/* and read next to prepare for further parsing */
+-                        oldline = *line_nr;
+-			continue;
+-		}
+-                oldline = *line_nr;
+-		switch(expect) {
+-			case LDNS_RESOLV_KEYWORD:
+-				/* keyword */
+-				gtr = ldns_fget_token_l(myfp, word, LDNS_PARSE_NORMAL, 0, line_nr);
+-				if (gtr != 0) {
+-                                        if(word[0] == '#') continue;
+-					for(i = 0; i < LDNS_RESOLV_KEYWORDS; i++) {
+-						if (strcasecmp(keyword[i], word) == 0) {
+-							/* chosen the keyword and
+-							 * expect values carefully
+-	        					 */
+-							expect = i;
+-							break;
+-						}
+-					}
+-					/* no keyword recognized */
+-					if (expect == LDNS_RESOLV_KEYWORD) {
+-						/* skip line */
+-						/*
+-						ldns_resolver_deep_free(r);
+-						if(!fp) fclose(myfp);
+-						return LDNS_STATUS_SYNTAX_KEYWORD_ERR;
+-						*/
+-					}
+-				}
+-				break;
+-			case LDNS_RESOLV_DEFDOMAIN:
+-				/* default domain dname */
+-				gtr = ldns_fget_token_l(myfp, word, LDNS_PARSE_NORMAL, 0, line_nr);
+-				if (gtr == 0) {
+-					if(!fp) fclose(myfp);
+-					return LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR;
+-				}
+-                                if(word[0] == '#') {
+-                                        expect = LDNS_RESOLV_KEYWORD;
+-                                        continue;
+-                                }
+-				tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, word);
+-				if (!tmp) {
+-					ldns_resolver_deep_free(r);
+-					if(!fp) fclose(myfp);
+-					return LDNS_STATUS_SYNTAX_DNAME_ERR;
+-				}
+-
+-				/* DOn't free, because we copy the pointer */
+-				ldns_resolver_set_domain(r, tmp);
+-				expect = LDNS_RESOLV_KEYWORD;
+-				break;
+-			case LDNS_RESOLV_NAMESERVER:
+-				/* NS aaaa or a record */
+-				gtr = ldns_fget_token_l(myfp, word, LDNS_PARSE_NORMAL, 0, line_nr);
+-				if (gtr == 0) {
+-					if(!fp) fclose(myfp);
+-					return LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR;
+-				}
+-                                if(word[0] == '#') {
+-                                        expect = LDNS_RESOLV_KEYWORD;
+-                                        continue;
+-                                }
+-                                if(strchr(word, '%')) {
+-                                        /* snip off interface labels,
+-                                         * fe80::222:19ff:fe31:4222%eth0 */
+-                                        strchr(word, '%')[0]=0;
+-                                }
+-				tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_AAAA, word);
+-				if (!tmp) {
+-					/* try ip4 */
+-					tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_A, word);
+-				}
+-				/* could not parse it, exit */
+-				if (!tmp) {
+-					ldns_resolver_deep_free(r);
+-					if(!fp) fclose(myfp);
+-					return LDNS_STATUS_SYNTAX_ERR;
+-				}
+-				(void)ldns_resolver_push_nameserver(r, tmp);
+-				ldns_rdf_deep_free(tmp);
+-				expect = LDNS_RESOLV_KEYWORD;
+-				break;
+-			case LDNS_RESOLV_SEARCH:
+-				/* search list domain dname */
+-				gtr = ldns_fget_token_l(myfp, word, LDNS_PARSE_SKIP_SPACE, 0, line_nr);
+-				b = LDNS_MALLOC(ldns_buffer);
+-				if(!b) {
+-					ldns_resolver_deep_free(r);
+-					if(!fp) fclose(myfp);
+-					return LDNS_STATUS_MEM_ERR;
+-				}
+-
+-				ldns_buffer_new_frm_data(b, word, (size_t) gtr);
+-				if(ldns_buffer_status(b) != LDNS_STATUS_OK) {
+-					LDNS_FREE(b);
+-					ldns_resolver_deep_free(r);
+-					if(!fp) fclose(myfp);
+-					return LDNS_STATUS_MEM_ERR;
+-				}
+-				bgtr = ldns_bget_token(b, word, LDNS_PARSE_NORMAL, (size_t) gtr + 1);
+-				while (bgtr > 0) {
+-					gtr -= bgtr;
+-                                        if(word[0] == '#') {
+-                                                expect = LDNS_RESOLV_KEYWORD;
+-                                                break;
+-                                        }
+-					tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, word);
+-					if (!tmp) {
+-						ldns_resolver_deep_free(r);
+-						ldns_buffer_free(b);
+-						if(!fp) fclose(myfp);
+-						return LDNS_STATUS_SYNTAX_DNAME_ERR;
+-					}
+-
+-					ldns_resolver_push_searchlist(r, tmp);
+-
+-					ldns_rdf_deep_free(tmp);
+-					bgtr = ldns_bget_token(b, word, LDNS_PARSE_NORMAL,
+-					    (size_t) gtr + 1);
+-				}
+-				ldns_buffer_free(b);
+-				if (expect != LDNS_RESOLV_KEYWORD) {
+-					gtr = 1;
+-					expect = LDNS_RESOLV_KEYWORD;
+-				}
+-				break;
+-			case LDNS_RESOLV_SORTLIST:
+-				gtr = ldns_fget_token_l(myfp, word, LDNS_PARSE_SKIP_SPACE, 0, line_nr);
+-				/* sortlist not implemented atm */
+-				expect = LDNS_RESOLV_KEYWORD;
+-				break;
+-			case LDNS_RESOLV_OPTIONS:
+-				gtr = ldns_fget_token_l(myfp, word, LDNS_PARSE_SKIP_SPACE, 0, line_nr);
+-				/* options not implemented atm */
+-				expect = LDNS_RESOLV_KEYWORD;
+-				break;
+-			case LDNS_RESOLV_ANCHOR:
+-				/* a file containing a DNSSEC trust anchor */
+-				gtr = ldns_fget_token_l(myfp, word, LDNS_PARSE_NORMAL, 0, line_nr);
+-				if (gtr == 0) {
+-					ldns_resolver_deep_free(r);
+-					if(!fp) fclose(myfp);
+-					return LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR;
+-				}
+-                                if(word[0] == '#') {
+-                                        expect = LDNS_RESOLV_KEYWORD;
+-                                        continue;
+-                                }
+-
+-#ifdef HAVE_SSL
+-				tmp_rr = ldns_read_anchor_file(word);
+-				(void) ldns_resolver_push_dnssec_anchor(r, tmp_rr);
+-				ldns_rr_free(tmp_rr);
+-#endif
+-				expect = LDNS_RESOLV_KEYWORD;
+-				break;
+-		}
+-	}
+-
+-	if(!fp)
+-		fclose(myfp);
+-
+-	if (res) {
+-		*res = r;
+-		return LDNS_STATUS_OK;
+-	} else {
+-		ldns_resolver_deep_free(r);
+-		return LDNS_STATUS_NULL;
+-	}
+-}
+-
+-ldns_status
+-ldns_resolver_new_frm_file(ldns_resolver **res, const char *filename)
+-{
+-	ldns_resolver *r;
+-	FILE *fp;
+-	ldns_status s;
+-
+-	if (!filename) {
+-		fp = fopen(LDNS_RESOLV_CONF, "r");
+-
+-	} else {
+-		fp = fopen(filename, "r");
+-	}
+-	if (!fp) {
+-		return LDNS_STATUS_FILE_ERR;
+-	}
+-
+-	s = ldns_resolver_new_frm_fp(&r, fp);
+-	fclose(fp);
+-	if (s == LDNS_STATUS_OK) {
+-		if (res) {
+-			*res = r;
+-			return LDNS_STATUS_OK;
+-		} else  {
+-			ldns_resolver_free(r);
+-			return LDNS_STATUS_NULL;
+-		}
+-	}
+-	return s;
+-}
+-
+-void
+-ldns_resolver_free(ldns_resolver *res)
+-{
+-	LDNS_FREE(res);
+-}
+-
+-void
+-ldns_resolver_deep_free(ldns_resolver *res)
+-{
+-	size_t i;
+-
+-	if (res) {
+-		if (res->_searchlist) {
+-			for (i = 0; i < ldns_resolver_searchlist_count(res); i++) {
+-				ldns_rdf_deep_free(res->_searchlist[i]);
+-			}
+-			LDNS_FREE(res->_searchlist);
+-		}
+-		if (res->_nameservers) {
+-			for (i = 0; i < res->_nameserver_count; i++) {
+-				ldns_rdf_deep_free(res->_nameservers[i]);
+-			}
+-			LDNS_FREE(res->_nameservers);
+-		}
+-		if (ldns_resolver_domain(res)) {
+-			ldns_rdf_deep_free(ldns_resolver_domain(res));
+-		}
+-		if (res->_tsig_keyname) {
+-			LDNS_FREE(res->_tsig_keyname);
+-		}
+-		if (res->_tsig_keydata) {
+-			LDNS_FREE(res->_tsig_keydata);
+-		}
+-		if (res->_tsig_algorithm) {
+-			LDNS_FREE(res->_tsig_algorithm);
+-		}
+-
+-		if (res->_cur_axfr_pkt) {
+-			ldns_pkt_free(res->_cur_axfr_pkt);
+-		}
+-
+-		if (res->_rtt) {
+-			LDNS_FREE(res->_rtt);
+-		}
+-		if (res->_dnssec_anchors) {
+-			ldns_rr_list_deep_free(res->_dnssec_anchors);
+-		}
+-		LDNS_FREE(res);
+-	}
+-}
+-
+-ldns_status
+-ldns_resolver_search_status(ldns_pkt** pkt,
+-		ldns_resolver *r, const  ldns_rdf *name,
+-		ldns_rr_type t, ldns_rr_class c, uint16_t flags)
+-{
+-	ldns_rdf *new_name;
+-	ldns_rdf **search_list;
+-	size_t i;
+-	ldns_status s = LDNS_STATUS_OK;
+-	ldns_rdf root_dname = { 1, LDNS_RDF_TYPE_DNAME, (void *)"" };
+-
+-	if (ldns_dname_absolute(name)) {
+-		/* query as-is */
+-		return ldns_resolver_query_status(pkt, r, name, t, c, flags);
+-	} else if (ldns_resolver_dnsrch(r)) {
+-		search_list = ldns_resolver_searchlist(r);
+-		for (i = 0; i <= ldns_resolver_searchlist_count(r); i++) {
+-			if (i == ldns_resolver_searchlist_count(r)) {
+-				new_name = ldns_dname_cat_clone(name,
+-						&root_dname);
+-			} else {
+-				new_name = ldns_dname_cat_clone(name,
+-						search_list[i]);
+-			}
+-
+-			s = ldns_resolver_query_status(pkt, r,
+-					new_name, t, c, flags);
+-			ldns_rdf_free(new_name);
+-			if (pkt && *pkt) {
+-				if (s == LDNS_STATUS_OK && 
+-						ldns_pkt_get_rcode(*pkt) ==
+-						LDNS_RCODE_NOERROR) {
+-
+-					return LDNS_STATUS_OK;
+-				}
+-				ldns_pkt_free(*pkt);
+-				*pkt = NULL;
+-			}
+-		}
+-	}
+-	return s;
+-}
+-
+-ldns_pkt *
+-ldns_resolver_search(const ldns_resolver *r,const  ldns_rdf *name,
+-	ldns_rr_type t, ldns_rr_class c, uint16_t flags)
+-{
+-	ldns_pkt* pkt = NULL;
+-	if (ldns_resolver_search_status(&pkt, (ldns_resolver *)r,
+-				name, t, c, flags) != LDNS_STATUS_OK) {
+-		ldns_pkt_free(pkt);
+-	}
+-	return pkt;
+-}
+-
+-ldns_status
+-ldns_resolver_query_status(ldns_pkt** pkt,
+-		ldns_resolver *r, const ldns_rdf *name,
+-		ldns_rr_type t, ldns_rr_class c, uint16_t flags)
+-{
+-	ldns_rdf *newname;
+-	ldns_status status;
+-
+-	if (!ldns_resolver_defnames(r) || !ldns_resolver_domain(r)) {
+-		return ldns_resolver_send(pkt, r, name, t, c, flags);
+-	}
+-
+-	newname = ldns_dname_cat_clone(name, ldns_resolver_domain(r));
+-	if (!newname) {
+-		return LDNS_STATUS_MEM_ERR;
+-	}
+-	status = ldns_resolver_send(pkt, r, newname, t, c, flags);
+-	ldns_rdf_free(newname);
+-	return status;
+-}
+-
+-ldns_pkt *
+-ldns_resolver_query(const ldns_resolver *r, const ldns_rdf *name,
+-	ldns_rr_type t, ldns_rr_class c, uint16_t flags)
+-{
+-	ldns_pkt* pkt = NULL;
+-	if (ldns_resolver_query_status(&pkt, (ldns_resolver *)r,
+-				name, t, c, flags) != LDNS_STATUS_OK) {
+-		ldns_pkt_free(pkt);
+-	}
+-	return pkt;
+-}
+-
+-static size_t *
+-ldns_resolver_backup_rtt(ldns_resolver *r)
+-{
+-	size_t *new_rtt;
+-	size_t *old_rtt = ldns_resolver_rtt(r);
+-
+-	if (old_rtt && ldns_resolver_nameserver_count(r)) {
+-		new_rtt = LDNS_XMALLOC(size_t
+-				, ldns_resolver_nameserver_count(r));
+-		memcpy(new_rtt, old_rtt, sizeof(size_t)
+-				* ldns_resolver_nameserver_count(r));
+-		ldns_resolver_set_rtt(r, new_rtt);
+-		return old_rtt;
+-	}
+-	return NULL;
+-}
+-
+-static void
+-ldns_resolver_restore_rtt(ldns_resolver *r, size_t *old_rtt)
+-{
+-	size_t *cur_rtt = ldns_resolver_rtt(r);
+-
+-	if (cur_rtt) {
+-		LDNS_FREE(cur_rtt);
+-	}
+-	ldns_resolver_set_rtt(r, old_rtt);
+-}
+-
+-ldns_status
+-ldns_resolver_send_pkt(ldns_pkt **answer, ldns_resolver *r,
+-				   ldns_pkt *query_pkt)
+-{
+-	ldns_pkt *answer_pkt = NULL;
+-	ldns_status stat = LDNS_STATUS_OK;
+-	size_t *rtt;
+-
+-	stat = ldns_send(&answer_pkt, (ldns_resolver *)r, query_pkt);
+-	if (stat != LDNS_STATUS_OK) {
+-		if(answer_pkt) {
+-			ldns_pkt_free(answer_pkt);
+-			answer_pkt = NULL;
+-		}
+-	} else {
+-		/* if tc=1 fall back to EDNS and/or TCP */
+-		/* check for tcp first (otherwise we don't care about tc=1) */
+-		if (!ldns_resolver_usevc(r) && ldns_resolver_fallback(r)) {
+-			if (ldns_pkt_tc(answer_pkt)) {
+-				/* was EDNS0 set? */
+-				if (ldns_pkt_edns_udp_size(query_pkt) == 0) {
+-					ldns_pkt_set_edns_udp_size(query_pkt
+-							, 4096);
+-					ldns_pkt_free(answer_pkt);
+-					answer_pkt = NULL;
+-					/* Nameservers should not become 
+-					 * unreachable because fragments are
+-					 * dropped (network error). We might
+-					 * still have success with TCP.
+-					 * Therefore maintain reachability
+-					 * statuses of the nameservers by
+-					 * backup and restore the rtt list.
+-					 */
+-					rtt = ldns_resolver_backup_rtt(r);
+-					stat = ldns_send(&answer_pkt, r
+-							, query_pkt);
+-					ldns_resolver_restore_rtt(r, rtt);
+-				}
+-				/* either way, if it is still truncated, use TCP */
+-				if (stat != LDNS_STATUS_OK ||
+-				    ldns_pkt_tc(answer_pkt)) {
+-					ldns_resolver_set_usevc(r, true);
+-					ldns_pkt_free(answer_pkt);
+-					stat = ldns_send(&answer_pkt, r, query_pkt);
+-					ldns_resolver_set_usevc(r, false);
+-				}
+-			}
+-		}
+-	}
+-
+-	if (answer) {
+-		*answer = answer_pkt;
+-	}
+-
+-	return stat;
+-}
+-
+-ldns_status
+-ldns_resolver_prepare_query_pkt(ldns_pkt **query_pkt, ldns_resolver *r,
+-                                const ldns_rdf *name, ldns_rr_type t,
+-                                ldns_rr_class c, uint16_t flags)
+-{
+-	struct timeval now;
+-	ldns_rr* soa = NULL;
+-
+-	/* prepare a question pkt from the parameters
+-	 * and then send this */
+-	if (t == LDNS_RR_TYPE_IXFR) {
+-		ldns_rdf *owner_rdf;
+-		ldns_rdf *mname_rdf;
+-		ldns_rdf *rname_rdf;
+-		ldns_rdf *serial_rdf;
+-		ldns_rdf *refresh_rdf;
+-		ldns_rdf *retry_rdf;
+-		ldns_rdf *expire_rdf;
+-		ldns_rdf *minimum_rdf;
+-		soa = ldns_rr_new();
+-
+-		if (!soa) {
+-			return LDNS_STATUS_ERR;
+-		}
+-		owner_rdf = ldns_rdf_clone(name);
+-		if (!owner_rdf) {
+-			ldns_rr_free(soa);
+-			return LDNS_STATUS_ERR;
+-		}
+-		ldns_rr_set_owner(soa, owner_rdf);
+-		ldns_rr_set_type(soa, LDNS_RR_TYPE_SOA);
+-		ldns_rr_set_class(soa, c);
+-		ldns_rr_set_question(soa, false);
+-		if (ldns_str2rdf_dname(&mname_rdf, ".") != LDNS_STATUS_OK) {
+-			ldns_rr_free(soa);
+-			return LDNS_STATUS_ERR;
+-		} else	ldns_rr_push_rdf(soa, mname_rdf);
+-		if (ldns_str2rdf_dname(&rname_rdf, ".") != LDNS_STATUS_OK) {
+-			ldns_rr_free(soa);
+-			return LDNS_STATUS_ERR;
+-		} else	ldns_rr_push_rdf(soa, rname_rdf);
+-		serial_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, ldns_resolver_get_ixfr_serial(r));
+-		if (!serial_rdf) {
+-			ldns_rr_free(soa);
+-			return LDNS_STATUS_ERR;
+-		} else	ldns_rr_push_rdf(soa, serial_rdf);
+-		refresh_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0);
+-		if (!refresh_rdf) {
+-			ldns_rr_free(soa);
+-			return LDNS_STATUS_ERR;
+-		} else	ldns_rr_push_rdf(soa, refresh_rdf);
+-		retry_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0);
+-		if (!retry_rdf) {
+-			ldns_rr_free(soa);
+-			return LDNS_STATUS_ERR;
+-		} else	ldns_rr_push_rdf(soa, retry_rdf);
+-		expire_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0);
+-		if (!expire_rdf) {
+-			ldns_rr_free(soa);
+-			return LDNS_STATUS_ERR;
+-		} else	ldns_rr_push_rdf(soa, expire_rdf);
+-		minimum_rdf = ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 0);
+-		if (!minimum_rdf) {
+-			ldns_rr_free(soa);
+-			return LDNS_STATUS_ERR;
+-		} else	ldns_rr_push_rdf(soa, minimum_rdf);
+-
+-		*query_pkt = ldns_pkt_ixfr_request_new(ldns_rdf_clone(name),
+-			c, flags, soa);
+-	} else {
+-		*query_pkt = ldns_pkt_query_new(ldns_rdf_clone(name), t, c, flags);
+-	}
+-	if (!*query_pkt) {
+-		ldns_rr_free(soa);
+-		return LDNS_STATUS_ERR;
+-	}
+-
+-	/* set DO bit if necessary */
+-	if (ldns_resolver_dnssec(r)) {
+-		if (ldns_resolver_edns_udp_size(r) == 0) {
+-			ldns_resolver_set_edns_udp_size(r, 4096);
+-		}
+-		ldns_pkt_set_edns_do(*query_pkt, true);
+-		if (ldns_resolver_dnssec_cd(r) || (flags & LDNS_CD)) {
+-			ldns_pkt_set_cd(*query_pkt, true);
+-		}
+-	}
+-
+-	/* transfer the udp_edns_size from the resolver to the packet */
+-	if (ldns_resolver_edns_udp_size(r) != 0) {
+-		ldns_pkt_set_edns_udp_size(*query_pkt, ldns_resolver_edns_udp_size(r));
+-	}
+-
+-	/* set the timestamp */
+-	now.tv_sec = time(NULL);
+-	now.tv_usec = 0;
+-	ldns_pkt_set_timestamp(*query_pkt, now);
+-
+-
+-	if (ldns_resolver_debug(r)) {
+-		ldns_pkt_print(stdout, *query_pkt);
+-	}
+-
+-	/* only set the id if it is not set yet */
+-	if (ldns_pkt_id(*query_pkt) == 0) {
+-		ldns_pkt_set_random_id(*query_pkt);
+-	}
+-
+-	return LDNS_STATUS_OK;
+-}
+-
+-ldns_status
+-ldns_resolver_send(ldns_pkt **answer, ldns_resolver *r, const ldns_rdf *name,
+-		ldns_rr_type t, ldns_rr_class c, uint16_t flags)
+-{
+-	ldns_pkt *query_pkt;
+-	ldns_pkt *answer_pkt;
+-	ldns_status status;
+-
+-	assert(r != NULL);
+-	assert(name != NULL);
+-
+-	answer_pkt = NULL;
+-
+-	/* do all the preprocessing here, then fire of an query to
+-	 * the network */
+-
+-	if (0 == t) {
+-		t= LDNS_RR_TYPE_A;
+-	}
+-	if (0 == c) {
+-		c= LDNS_RR_CLASS_IN;
+-	}
+-	if (0 == ldns_resolver_nameserver_count(r)) {
+-		return LDNS_STATUS_RES_NO_NS;
+-	}
+-	if (ldns_rdf_get_type(name) != LDNS_RDF_TYPE_DNAME) {
+-		return LDNS_STATUS_RES_QUERY;
+-	}
+-
+-	status = ldns_resolver_prepare_query_pkt(&query_pkt, r, name,
+-	                                         t, c, flags);
+-	if (status != LDNS_STATUS_OK) {
+-		return status;
+-	}
+-
+-	/* if tsig values are set, tsign it */
+-	/* TODO: make last 3 arguments optional too? maybe make complete
+-	         rr instead of separate values in resolver (and packet)
+-	  Jelte
+-	  should this go in pkt_prepare?
+-	*/
+-	if (ldns_resolver_tsig_keyname(r) && ldns_resolver_tsig_keydata(r)) {
+-#ifdef HAVE_SSL
+-		status = ldns_pkt_tsig_sign(query_pkt,
+-		                            ldns_resolver_tsig_keyname(r),
+-		                            ldns_resolver_tsig_keydata(r),
+-		                            300, ldns_resolver_tsig_algorithm(r), NULL);
+-		if (status != LDNS_STATUS_OK) {
+-			ldns_pkt_free(query_pkt);
+-			return LDNS_STATUS_CRYPTO_TSIG_ERR;
+-		}
+-#else
+-		ldns_pkt_free(query_pkt);
+-	        return LDNS_STATUS_CRYPTO_TSIG_ERR;
+-#endif /* HAVE_SSL */
+-	}
+-
+-	status = ldns_resolver_send_pkt(&answer_pkt, r, query_pkt);
+-	ldns_pkt_free(query_pkt);
+-
+-	/* allows answer to be NULL when not interested in return value */
+-	if (answer) {
+-		*answer = answer_pkt;
+-	}
+-	return status;
+-}
+-
+-ldns_rr *
+-ldns_axfr_next(ldns_resolver *resolver)
+-{
+-	ldns_rr *cur_rr;
+-	uint8_t *packet_wire;
+-	size_t packet_wire_size;
+-	ldns_status status;
+-
+-	/* check if start() has been called */
+-	if (!resolver || resolver->_socket == 0) {
+-		return NULL;
+-	}
+-
+-	if (resolver->_cur_axfr_pkt) {
+-		if (resolver->_axfr_i == ldns_pkt_ancount(resolver->_cur_axfr_pkt)) {
+-			ldns_pkt_free(resolver->_cur_axfr_pkt);
+-			resolver->_cur_axfr_pkt = NULL;
+-			return ldns_axfr_next(resolver);
+-		}
+-		cur_rr = ldns_rr_clone(ldns_rr_list_rr(
+-					ldns_pkt_answer(resolver->_cur_axfr_pkt),
+-					resolver->_axfr_i));
+-		resolver->_axfr_i++;
+-		if (ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_SOA) {
+-			resolver->_axfr_soa_count++;
+-			if (resolver->_axfr_soa_count >= 2) {
+-#ifndef USE_WINSOCK
+-				close(resolver->_socket);
+-#else
+-				closesocket(resolver->_socket);
+-#endif
+-				resolver->_socket = 0;
+-				ldns_pkt_free(resolver->_cur_axfr_pkt);
+-				resolver->_cur_axfr_pkt = NULL;
+-			}
+-		}
+-		return cur_rr;
+-	} else {
+-               packet_wire = ldns_tcp_read_wire_timeout(resolver->_socket, &packet_wire_size, resolver->_timeout);
+-		if(!packet_wire)
+-			return NULL;
+-
+-		status = ldns_wire2pkt(&resolver->_cur_axfr_pkt, packet_wire,
+-				     packet_wire_size);
+-		LDNS_FREE(packet_wire);
+-
+-		resolver->_axfr_i = 0;
+-		if (status != LDNS_STATUS_OK) {
+-			/* TODO: make status return type of this function (...api change) */
+-#ifdef STDERR_MSGS
+-			fprintf(stderr, "Error parsing rr during AXFR: %s\n", ldns_get_errorstr_by_id(status));
+-#endif
+-
+-			/* we must now also close the socket, otherwise subsequent uses of the
+-			   same resolver structure will fail because the link is still open or
+-			   in an undefined state */
+-#ifndef USE_WINSOCK
+-			close(resolver->_socket);
+-#else
+-			closesocket(resolver->_socket);
+-#endif
+-			resolver->_socket = 0;
+-
+-			return NULL;
+-		} else if (ldns_pkt_get_rcode(resolver->_cur_axfr_pkt) != 0) {
+-#ifdef STDERR_MSGS
+-			ldns_lookup_table *rcode = ldns_lookup_by_id(
+-				ldns_rcodes,(int) ldns_pkt_get_rcode(
+-				resolver->_cur_axfr_pkt));
+-			if (rcode) {
+-				fprintf(stderr, "Error in AXFR: %s\n", 
+-						rcode->name);
+-			} else {
+-				fprintf(stderr, "Error in AXFR: %d\n", 
+-						(int) ldns_pkt_get_rcode(
+-						resolver->_cur_axfr_pkt));
+-			}
+-#endif
+-
+-			/* we must now also close the socket, otherwise subsequent uses of the
+-			   same resolver structure will fail because the link is still open or
+-			   in an undefined state */
+-#ifndef USE_WINSOCK
+-			close(resolver->_socket);
+-#else
+-			closesocket(resolver->_socket);
+-#endif
+-			resolver->_socket = 0;
+-
+-			return NULL;
+-		} else {
+-			return ldns_axfr_next(resolver);
+-		}
+-
+-	}
+-
+-}
+-
+-/* this function is needed to abort a transfer that is in progress;
+- * without it an aborted transfer will lead to the AXFR code in the
+- * library staying in an indetermined state because the socket for the
+- * AXFR is never closed
+- */
+-void
+-ldns_axfr_abort(ldns_resolver *resolver)
+-{
+-	/* Only abort if an actual AXFR is in progress */
+-	if (resolver->_socket != 0)
+-	{
+-#ifndef USE_WINSOCK
+-		close(resolver->_socket);
+-#else
+-		closesocket(resolver->_socket);
+-#endif
+-		resolver->_socket = 0;
+-	}
+-}
+-
+-bool
+-ldns_axfr_complete(const ldns_resolver *res)
+-{
+-	/* complete when soa count is 2? */
+-	return res->_axfr_soa_count == 2;
+-}
+-
+-ldns_pkt *
+-ldns_axfr_last_pkt(const ldns_resolver *res)
+-{
+-	return res->_cur_axfr_pkt;
+-}
+-
+-void
+-ldns_resolver_set_ixfr_serial(ldns_resolver *r, uint32_t serial)
+-{
+-	r->_serial = serial;
+-}
+-
+-uint32_t
+-ldns_resolver_get_ixfr_serial(const ldns_resolver *res)
+-{
+-	return res->_serial;
+-}
+-
+-
+-/* random isn't really that good */
+-void
+-ldns_resolver_nameservers_randomize(ldns_resolver *r)
+-{
+-	uint16_t i, j;
+-	ldns_rdf **ns, *tmpns;
+-	size_t *rtt, tmprtt;
+-
+-	/* should I check for ldns_resolver_random?? */
+-	assert(r != NULL);
+-
+-	ns = ldns_resolver_nameservers(r);
+-	rtt = ldns_resolver_rtt(r);
+-	for (i = 0; i < ldns_resolver_nameserver_count(r); i++) {
+-		j = ldns_get_random() % ldns_resolver_nameserver_count(r);
+-		tmpns = ns[i];
+-		ns[i] = ns[j];
+-		ns[j] = tmpns;
+-		tmprtt = rtt[i];
+-		rtt[i] = rtt[j];
+-		rtt[j] = tmprtt;
+-	}
+-	ldns_resolver_set_nameservers(r, ns);
+-}
+-
+diff --git a/src/ldns/rr.c b/src/ldns/rr.c
+deleted file mode 100644
+index e52ea80..0000000
+--- a/src/ldns/rr.c
++++ /dev/null
+@@ -1,2705 +0,0 @@
+-/* rr.c
+- *
+- * access functions for ldns_rr -
+- * a Net::DNS like library for C
+- * LibDNS Team @ NLnet Labs
+- *
+- * (c) NLnet Labs, 2004-2006
+- * See the file LICENSE for the license
+- */
+-#include <ldns/config.h>
+-
+-#include <ldns/ldns.h>
+-
+-#include <strings.h>
+-#include <limits.h>
+-
+-#include <errno.h>
+-
+-#define LDNS_SYNTAX_DATALEN 16
+-#define LDNS_TTL_DATALEN    21
+-#define LDNS_RRLIST_INIT    8
+-
+-ldns_rr *
+-ldns_rr_new(void)
+-{
+-	ldns_rr *rr;
+-	rr = LDNS_MALLOC(ldns_rr);
+-        if (!rr) {
+-                return NULL;
+-	}
+-
+-	ldns_rr_set_owner(rr, NULL);
+-	ldns_rr_set_question(rr, false);
+-	ldns_rr_set_rd_count(rr, 0);
+-	rr->_rdata_fields = NULL;
+-	ldns_rr_set_class(rr, LDNS_RR_CLASS_IN);
+-	ldns_rr_set_ttl(rr, LDNS_DEFAULT_TTL);
+-        return rr;
+-}
+-
+-ldns_rr *
+-ldns_rr_new_frm_type(ldns_rr_type t)
+-{
+-	ldns_rr *rr;
+-	const ldns_rr_descriptor *desc;
+-	size_t i;
+-
+-	rr = LDNS_MALLOC(ldns_rr);
+-        if (!rr) {
+-                return NULL;
+-	}
+-
+-	desc = ldns_rr_descript(t);
+-
+-	rr->_rdata_fields = LDNS_XMALLOC(ldns_rdf *, ldns_rr_descriptor_minimum(desc));
+-        if(!rr->_rdata_fields) {
+-                LDNS_FREE(rr);
+-                return NULL;
+-        }
+-	for (i = 0; i < ldns_rr_descriptor_minimum(desc); i++) {
+-		rr->_rdata_fields[i] = NULL;
+-	}
+-
+-	ldns_rr_set_owner(rr, NULL);
+-	ldns_rr_set_question(rr, false);
+-	/* set the count to minimum */
+-	ldns_rr_set_rd_count(rr, ldns_rr_descriptor_minimum(desc));
+-	ldns_rr_set_class(rr, LDNS_RR_CLASS_IN);
+-	ldns_rr_set_ttl(rr, LDNS_DEFAULT_TTL);
+-	ldns_rr_set_type(rr, t);
+-	return rr;
+-}
+-
+-void
+-ldns_rr_free(ldns_rr *rr)
+-{
+-	size_t i;
+-	if (rr) {
+-		if (ldns_rr_owner(rr)) {
+-			ldns_rdf_deep_free(ldns_rr_owner(rr));
+-		}
+-		for (i = 0; i < ldns_rr_rd_count(rr); i++) {
+-			ldns_rdf_deep_free(ldns_rr_rdf(rr, i));
+-		}
+-		LDNS_FREE(rr->_rdata_fields);
+-		LDNS_FREE(rr);
+-	}
+-}
+-
+-/* Syntactic sugar for ldns_rr_new_frm_str_internal */
+-INLINE bool
+-ldns_rdf_type_maybe_quoted(ldns_rdf_type rdf_type)
+-{
+-	return  rdf_type == LDNS_RDF_TYPE_STR ||
+-		rdf_type == LDNS_RDF_TYPE_LONG_STR;
+-}
+-
+-/*
+- * trailing spaces are allowed
+- * leading spaces are not allowed
+- * allow ttl to be optional
+- * class is optional too
+- * if ttl is missing, and default_ttl is 0, use DEF_TTL
+- * allow ttl to be written as 1d3h
+- * So the RR should look like. e.g.
+- * miek.nl. 3600 IN MX 10 elektron.atoom.net
+- * or
+- * miek.nl. 1h IN MX 10 elektron.atoom.net
+- * or
+- * miek.nl. IN MX 10 elektron.atoom.net
+- */
+-static ldns_status
+-ldns_rr_new_frm_str_internal(ldns_rr **newrr, const char *str,
+-                             uint32_t default_ttl, ldns_rdf *origin,
+-		             ldns_rdf **prev, bool question)
+-{
+-	ldns_rr *new;
+-	const ldns_rr_descriptor *desc;
+-	ldns_rr_type rr_type;
+-	ldns_buffer *rr_buf = NULL;
+-	ldns_buffer *rd_buf = NULL;
+-	uint32_t ttl_val;
+-	char  *owner = NULL;
+-	char  *ttl = NULL;
+-	ldns_rr_class clas_val;
+-	char  *clas = NULL;
+-	char  *type = NULL;
+-	char  *rdata = NULL;
+-	char  *rd = NULL;
+-	char  *xtok = NULL; /* For RDF types with spaces (i.e. extra tokens) */
+-	size_t rd_strlen;
+-	const char *delimiters;
+-	ssize_t c;
+-	ldns_rdf *owner_dname;
+-        const char* endptr;
+-        int was_unknown_rr_format = 0;
+-	ldns_status status = LDNS_STATUS_OK;
+-
+-	/* used for types with unknown number of rdatas */
+-	bool done;
+-	bool quoted;
+-
+-	ldns_rdf *r = NULL;
+-	uint16_t r_cnt;
+-	uint16_t r_min;
+-	uint16_t r_max;
+-        size_t pre_data_pos;
+-
+-	uint16_t hex_data_size;
+-	char *hex_data_str = NULL;
+-	uint16_t cur_hex_data_size;
+-	size_t hex_pos = 0;
+-	uint8_t *hex_data = NULL;
+-
+-	new = ldns_rr_new();
+-
+-	owner = LDNS_XMALLOC(char, LDNS_MAX_DOMAINLEN + 1);
+-	ttl = LDNS_XMALLOC(char, LDNS_TTL_DATALEN);
+-	clas = LDNS_XMALLOC(char, LDNS_SYNTAX_DATALEN);
+-	rdata = LDNS_XMALLOC(char, LDNS_MAX_PACKETLEN + 1);
+-	rr_buf = LDNS_MALLOC(ldns_buffer);
+-	rd_buf = LDNS_MALLOC(ldns_buffer);
+-	rd = LDNS_XMALLOC(char, LDNS_MAX_RDFLEN);
+-	xtok = LDNS_XMALLOC(char, LDNS_MAX_RDFLEN);
+-	if (rr_buf) {
+-		rr_buf->_data = NULL;
+-	}
+-	if (rd_buf) {
+-		rd_buf->_data = NULL;
+-	}
+-	if (!new || !owner || !ttl || !clas || !rdata ||
+-			!rr_buf || !rd_buf || !rd || !xtok) {
+-
+-		goto memerror;
+-	}
+-
+-	ldns_buffer_new_frm_data(rr_buf, (char*)str, strlen(str));
+-
+-	/* split the rr in its parts -1 signals trouble */
+-	if (ldns_bget_token(rr_buf, owner, "\t\n ", LDNS_MAX_DOMAINLEN) == -1){
+-
+-		status = LDNS_STATUS_SYNTAX_ERR;
+-		goto error;
+-	}
+-
+-	if (ldns_bget_token(rr_buf, ttl, "\t\n ", LDNS_TTL_DATALEN) == -1) {
+-
+-		status = LDNS_STATUS_SYNTAX_TTL_ERR;
+-		goto error;
+-	}
+-	ttl_val = (uint32_t) ldns_str2period(ttl, &endptr);
+-
+-	if (strlen(ttl) > 0 && !isdigit((int) ttl[0])) {
+-		/* ah, it's not there or something */
+-		if (default_ttl == 0) {
+-			ttl_val = LDNS_DEFAULT_TTL;
+-		} else {
+-			ttl_val = default_ttl;
+-		}
+-		/* we not ASSUMING the TTL is missing and that
+-		 * the rest of the RR is still there. That is
+-		 * CLASS TYPE RDATA
+-		 * so ttl value we read is actually the class
+-		 */
+-		clas_val = ldns_get_rr_class_by_name(ttl);
+-		/* class can be left out too, assume IN, current
+-		 * token must be type
+-		 */
+-		if (clas_val == 0) {
+-			clas_val = LDNS_RR_CLASS_IN;
+-			type = LDNS_XMALLOC(char, strlen(ttl) + 1);
+-			if (!type) {
+-				goto memerror;
+-			}
+-			strncpy(type, ttl, strlen(ttl) + 1);
+-		}
+-	} else {
+-		if (-1 == ldns_bget_token(
+-				rr_buf, clas, "\t\n ", LDNS_SYNTAX_DATALEN)) {
+-
+-			status = LDNS_STATUS_SYNTAX_CLASS_ERR;
+-			goto error;
+-		}
+-		clas_val = ldns_get_rr_class_by_name(clas);
+-		/* class can be left out too, assume IN, current
+-		 * token must be type
+-		 */
+-		if (clas_val == 0) {
+-			clas_val = LDNS_RR_CLASS_IN;
+-			type = LDNS_XMALLOC(char, strlen(clas) + 1);
+-			if (!type) {
+-				goto memerror;
+-			}
+-			strncpy(type, clas, strlen(clas) + 1);
+-		}
+-	}
+-	/* the rest should still be waiting for us */
+-
+-	if (!type) {
+-		type = LDNS_XMALLOC(char, LDNS_SYNTAX_DATALEN);
+-		if (!type) {
+-			goto memerror;
+-		}
+-		if (-1 == ldns_bget_token(
+-				rr_buf, type, "\t\n ", LDNS_SYNTAX_DATALEN)) {
+-
+-			status = LDNS_STATUS_SYNTAX_TYPE_ERR;
+-			goto error;
+-		}
+-	}
+-
+-	if (ldns_bget_token(rr_buf, rdata, "\0", LDNS_MAX_PACKETLEN) == -1) {
+-		/* apparently we are done, and it's only a question RR
+-		 * so do not set status and go to ldnserror here
+-		 */
+-	}
+-	ldns_buffer_new_frm_data(rd_buf, rdata, strlen(rdata));
+-
+-	if (strlen(owner) <= 1 && strncmp(owner, "@", 1) == 0) {
+-		if (origin) {
+-			ldns_rr_set_owner(new, ldns_rdf_clone(origin));
+-		} else if (prev && *prev) {
+-			ldns_rr_set_owner(new, ldns_rdf_clone(*prev));
+-		} else {
+-			/* default to root */
+-			ldns_rr_set_owner(new, ldns_dname_new_frm_str("."));
+-		}
+-
+-		/* @ also overrides prev */
+-		if (prev) {
+-			ldns_rdf_deep_free(*prev);
+-			*prev = ldns_rdf_clone(ldns_rr_owner(new));
+-			if (!*prev) {
+-				goto memerror;
+-			}
+-		}
+-	} else {
+-		if (strlen(owner) == 0) {
+-			/* no ownername was given, try prev, if that fails
+-			 * origin, else default to root */
+-			if (prev && *prev) {
+-				ldns_rr_set_owner(new, ldns_rdf_clone(*prev));
+-			} else if (origin) {
+-				ldns_rr_set_owner(new, ldns_rdf_clone(origin));
+-			} else {
+-				ldns_rr_set_owner(new,
+-						ldns_dname_new_frm_str("."));
+-			}
+-			if(!ldns_rr_owner(new)) {
+-				goto memerror;
+-			}
+-		} else {
+-			owner_dname = ldns_dname_new_frm_str(owner);
+-			if (!owner_dname) {
+-				status = LDNS_STATUS_SYNTAX_ERR;
+-				goto error;
+-			}
+-
+-			ldns_rr_set_owner(new, owner_dname);
+-			if (!ldns_dname_str_absolute(owner) && origin) {
+-				if(ldns_dname_cat(ldns_rr_owner(new), origin)
+-						!= LDNS_STATUS_OK) {
+-
+-					status = LDNS_STATUS_SYNTAX_ERR;
+-					goto error;
+-				}
+-			}
+-			if (prev) {
+-				ldns_rdf_deep_free(*prev);
+-				*prev = ldns_rdf_clone(ldns_rr_owner(new));
+-				if (!*prev) {
+-					goto error;
+-				}
+-			}
+-		}
+-	}
+-	LDNS_FREE(owner);
+-
+-	ldns_rr_set_question(new, question);
+-
+-	ldns_rr_set_ttl(new, ttl_val);
+-	LDNS_FREE(ttl);
+-
+-	ldns_rr_set_class(new, clas_val);
+-	LDNS_FREE(clas);
+-
+-	rr_type = ldns_get_rr_type_by_name(type);
+-	LDNS_FREE(type);
+-
+-	desc = ldns_rr_descript((uint16_t)rr_type);
+-	ldns_rr_set_type(new, rr_type);
+-	if (desc) {
+-		/* only the rdata remains */
+-		r_max = ldns_rr_descriptor_maximum(desc);
+-		r_min = ldns_rr_descriptor_minimum(desc);
+-	} else {
+-		r_min = 0;
+-		r_max = 1;
+-	}
+-
+-	for (done = false, r_cnt = 0; !done && r_cnt < r_max; r_cnt++) {
+-		quoted = false;
+-
+-		switch (ldns_rr_descriptor_field_type(desc, r_cnt)) {
+-		case LDNS_RDF_TYPE_B64        :
+-		case LDNS_RDF_TYPE_HEX        : /* These rdf types may con- */
+-		case LDNS_RDF_TYPE_LOC        : /* tain whitespace, only if */
+-		case LDNS_RDF_TYPE_WKS        : /* it is the last rd field. */
+-		case LDNS_RDF_TYPE_IPSECKEY   :
+-		case LDNS_RDF_TYPE_NSEC       :	if (r_cnt == r_max - 1) {
+-							delimiters = "\n";
+-							break;
+-						}
+-		default                       :	delimiters = "\n\t "; 
+-		}
+-
+-		if (ldns_rdf_type_maybe_quoted(
+-				ldns_rr_descriptor_field_type(
+-				desc, r_cnt)) &&
+-				ldns_buffer_remaining(rd_buf) > 0){
+-
+-			/* skip spaces */
+-			while (*(ldns_buffer_current(rd_buf)) == ' ') {
+-				ldns_buffer_skip(rd_buf, 1);
+-			}
+-
+-			if (*(ldns_buffer_current(rd_buf)) == '\"') {
+-				delimiters = "\"\0";
+-				ldns_buffer_skip(rd_buf, 1);
+-				quoted = true;
+-			}
+-		}
+-
+-		/* because number of fields can be variable, we can't rely on
+-		 * _maximum() only
+-		 */
+-
+-		/* skip spaces */
+-		while (ldns_buffer_position(rd_buf) < ldns_buffer_limit(rd_buf)
+-				&& *(ldns_buffer_current(rd_buf)) == ' '
+-				&& !quoted) {
+-
+-			ldns_buffer_skip(rd_buf, 1);
+-		}
+-
+-		pre_data_pos = ldns_buffer_position(rd_buf);
+-		if (-1 == (c = ldns_bget_token(
+-				rd_buf, rd, delimiters, LDNS_MAX_RDFLEN))) {
+-
+-			done = true;
+-			break;
+-		}
+-		/* hmmz, rfc3597 specifies that any type can be represented 
+-		 * with \# method, which can contain spaces...
+-		 * it does specify size though...
+-		 */
+-		rd_strlen = strlen(rd);
+-
+-		/* unknown RR data */
+-		if (strncmp(rd, "\\#", 2) == 0 && !quoted &&
+-				(rd_strlen == 2 || rd[2]==' ')) {
+-
+-			was_unknown_rr_format = 1;
+-			/* go back to before \#
+-			 * and skip it while setting delimiters better
+-			 */
+-			ldns_buffer_set_position(rd_buf, pre_data_pos);
+-			delimiters = "\n\t ";
+-			(void)ldns_bget_token(rd_buf, rd,
+-					delimiters, LDNS_MAX_RDFLEN);
+-			/* read rdata octet length */
+-			c = ldns_bget_token(rd_buf, rd,
+-					delimiters, LDNS_MAX_RDFLEN);
+-			if (c == -1) {
+-				/* something goes very wrong here */
+-				status = LDNS_STATUS_SYNTAX_RDATA_ERR;
+-				goto error;
+-			}
+-			hex_data_size = (uint16_t) atoi(rd);
+-			/* copy hex chars into hex str (2 chars per byte) */
+-			hex_data_str = LDNS_XMALLOC(char, 2*hex_data_size + 1);
+-			if (!hex_data_str) {
+-				/* malloc error */
+-				goto memerror;
+-			}
+-			cur_hex_data_size = 0;
+-			while(cur_hex_data_size < 2 * hex_data_size) {
+-				c = ldns_bget_token(rd_buf, rd,
+-						delimiters, LDNS_MAX_RDFLEN);
+-				if (c != -1) {
+-					rd_strlen = strlen(rd);
+-				}
+-				if (c == -1 || 
+-				    (size_t)cur_hex_data_size + rd_strlen >
+-				    2 * (size_t)hex_data_size) {
+-
+-					status = LDNS_STATUS_SYNTAX_RDATA_ERR;
+-					goto error;
+-				}
+-				strncpy(hex_data_str + cur_hex_data_size, rd,
+-						rd_strlen);
+-
+-				cur_hex_data_size += rd_strlen;
+-			}
+-			hex_data_str[cur_hex_data_size] = '\0';
+-
+-			/* correct the rdf type */
+-			/* if *we* know the type, interpret it as wireformat */
+-			if (desc) {
+-				hex_pos = 0;
+-				hex_data =
+-					LDNS_XMALLOC(uint8_t, hex_data_size+2);
+-
+-				if (!hex_data) {
+-					goto memerror;
+-				}
+-				ldns_write_uint16(hex_data, hex_data_size);
+-				ldns_hexstring_to_data(
+-						hex_data + 2, hex_data_str);
+-				status = ldns_wire2rdf(new, hex_data,
+-						hex_data_size + 2, &hex_pos);
+-				if (status != LDNS_STATUS_OK) {
+-					goto error;
+-				}
+-				LDNS_FREE(hex_data);
+-			} else {
+-				r = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_HEX,
+-						hex_data_str);
+-				if (!r) {
+-					goto memerror;
+-				}
+-				ldns_rdf_set_type(r, LDNS_RDF_TYPE_UNKNOWN);
+-				if (!ldns_rr_push_rdf(new, r)) {
+-					goto memerror;
+-				}
+-			}
+-			LDNS_FREE(hex_data_str);
+-
+-		} else if(rd_strlen > 0 || quoted) {
+-			/* Normal RR */
+-			switch(ldns_rr_descriptor_field_type(desc, r_cnt)) {
+-
+-			case LDNS_RDF_TYPE_HEX:
+-			case LDNS_RDF_TYPE_B64:
+-				/* When this is the last rdata field, then the
+-				 * rest should be read in (cause then these
+-				 * rdf types may contain spaces).
+-				 */
+-				if (r_cnt == r_max - 1) {
+-					c = ldns_bget_token(rd_buf, xtok,
+-							"\n", LDNS_MAX_RDFLEN);
+-					if (c != -1) {
+-						(void) strncat(rd, xtok,
+-							LDNS_MAX_RDFLEN -
+-							strlen(rd) - 1);
+-					}
+-				}
+-				r = ldns_rdf_new_frm_str(
+-						ldns_rr_descriptor_field_type(
+-							desc, r_cnt), rd);
+-				break;
+-
+-			case LDNS_RDF_TYPE_HIP:
+-				/*
+-				 * In presentation format this RDATA type has
+-				 * three tokens: An algorithm byte, then a
+-				 * variable length HIT (in hexbytes) and then
+-				 * a variable length Public Key (in base64).
+-				 *
+-				 * We have just read the algorithm, so we need
+-				 * two more tokens: HIT and Public Key.
+-				 */
+-				do {
+-					/* Read and append HIT */
+-					if (ldns_bget_token(rd_buf,
+-							xtok, delimiters,
+-							LDNS_MAX_RDFLEN) == -1)
+-						break;
+-
+-					(void) strncat(rd, " ",
+-							LDNS_MAX_RDFLEN -
+-							strlen(rd) - 1);
+-					(void) strncat(rd, xtok,
+-							LDNS_MAX_RDFLEN -
+-							strlen(rd) - 1);
+-
+-					/* Read and append Public Key*/
+-					if (ldns_bget_token(rd_buf,
+-							xtok, delimiters,
+-							LDNS_MAX_RDFLEN) == -1)
+-						break;
+-
+-					(void) strncat(rd, " ",
+-							LDNS_MAX_RDFLEN -
+-							strlen(rd) - 1);
+-					(void) strncat(rd, xtok,
+-							LDNS_MAX_RDFLEN -
+-							strlen(rd) - 1);
+-				} while (false);
+-
+-				r = ldns_rdf_new_frm_str(
+-						ldns_rr_descriptor_field_type(
+-							desc, r_cnt), rd);
+-				break;
+-
+-			case LDNS_RDF_TYPE_DNAME:
+-				r = ldns_rdf_new_frm_str(
+-						ldns_rr_descriptor_field_type(
+-							desc, r_cnt), rd);
+-
+-				/* check if the origin should be used
+-				 * or concatenated
+-				 */
+-				if (r && ldns_rdf_size(r) > 1 &&
+-						ldns_rdf_data(r)[0] == 1 &&
+-						ldns_rdf_data(r)[1] == '@') {
+-
+-					ldns_rdf_deep_free(r);
+-
+-					r = origin ? ldns_rdf_clone(origin)
+-
+-					  : ( rr_type == LDNS_RR_TYPE_SOA ?
+-
+-					      ldns_rdf_clone(
+-						      ldns_rr_owner(new))
+-
+-					    : ldns_rdf_new_frm_str(
+-						    LDNS_RDF_TYPE_DNAME, ".")
+-					    );
+-
+-				} else if (r && rd_strlen >= 1 && origin &&
+-						!ldns_dname_str_absolute(rd)) {
+-
+-					status = ldns_dname_cat(r, origin);
+-					if (status != LDNS_STATUS_OK) {
+-						goto error;
+-					}
+-				}
+-				break;
+-			default:
+-				r = ldns_rdf_new_frm_str(
+-						ldns_rr_descriptor_field_type(
+-							desc, r_cnt), rd);
+-				break;
+-			}
+-			if (!r) {
+-				status = LDNS_STATUS_SYNTAX_RDATA_ERR;
+-				goto error;
+-			}
+-			ldns_rr_push_rdf(new, r);
+-		}
+-		if (quoted) {
+-			if (ldns_buffer_available(rd_buf, 1)) {
+-				ldns_buffer_skip(rd_buf, 1);
+-			} else {
+-				done = true;
+-			}
+-		}
+-
+-	} /* for (done = false, r_cnt = 0; !done && r_cnt < r_max; r_cnt++) */
+-	LDNS_FREE(rd);
+-	LDNS_FREE(xtok);
+-	ldns_buffer_free(rd_buf);
+-	ldns_buffer_free(rr_buf);
+-	LDNS_FREE(rdata);
+-
+-	if (!question && desc && !was_unknown_rr_format &&
+-			ldns_rr_rd_count(new) < r_min) {
+-
+-		ldns_rr_free(new);
+-		return LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR;
+-	}
+-
+-	if (newrr) {
+-		*newrr = new;
+-	} else {
+-		/* Maybe the caller just wanted to see if it would parse? */
+-		ldns_rr_free(new);
+-	}
+-	return LDNS_STATUS_OK;
+-
+-memerror:
+-	status = LDNS_STATUS_MEM_ERR;
+-error:
+-	if (rd_buf && rd_buf->_data) {
+-		ldns_buffer_free(rd_buf);
+-	} else {
+-		LDNS_FREE(rd_buf);
+-	}
+-	if (rr_buf && rr_buf->_data) {
+-		ldns_buffer_free(rr_buf);
+-	} else {
+-		LDNS_FREE(rr_buf);
+-	}
+-	LDNS_FREE(type);
+-	LDNS_FREE(owner);
+-	LDNS_FREE(ttl);
+-	LDNS_FREE(clas);
+-	LDNS_FREE(hex_data);
+-	LDNS_FREE(hex_data_str);
+-	LDNS_FREE(xtok);
+-	LDNS_FREE(rd);
+-	LDNS_FREE(rdata);
+-	ldns_rr_free(new);
+-	return status;
+-}
+-
+-ldns_status
+-ldns_rr_new_frm_str(ldns_rr **newrr, const char *str,
+-                    uint32_t default_ttl, ldns_rdf *origin,
+-		    ldns_rdf **prev)
+-{
+-	return ldns_rr_new_frm_str_internal(newrr,
+-	                                    str,
+-	                                    default_ttl,
+-	                                    origin,
+-	                                    prev,
+-	                                    false);
+-}
+-
+-ldns_status
+-ldns_rr_new_question_frm_str(ldns_rr **newrr, const char *str,
+-                             ldns_rdf *origin, ldns_rdf **prev)
+-{
+-	return ldns_rr_new_frm_str_internal(newrr,
+-	                                    str,
+-	                                    0,
+-	                                    origin,
+-	                                    prev,
+-	                                    true);
+-}
+-
+-/* Strip whitespace from the start and the end of <line>.  */
+-static char *
+-ldns_strip_ws(char *line)
+-{
+-	char *s = line, *e;
+-
+-	for (s = line; *s && isspace(*s); s++)
+-		;
+-
+-	for (e = strchr(s, 0); e > s+2 && isspace(e[-1]) && e[-2] != '\\'; e--)
+-		;
+-	*e = 0;
+-
+-	return s;
+-}
+-
+-ldns_status
+-ldns_rr_new_frm_fp(ldns_rr **newrr, FILE *fp, uint32_t *ttl, ldns_rdf **origin, ldns_rdf **prev)
+-{
+-	return ldns_rr_new_frm_fp_l(newrr, fp, ttl, origin, prev, NULL);
+-}
+-
+-ldns_status
+-ldns_rr_new_frm_fp_l(ldns_rr **newrr, FILE *fp, uint32_t *default_ttl, ldns_rdf **origin, ldns_rdf **prev, int *line_nr)
+-{
+-	char *line;
+-	const char *endptr;  /* unused */
+-	ldns_rr *rr;
+-	uint32_t ttl;
+-	ldns_rdf *tmp;
+-	ldns_status s;
+-	ssize_t size;
+-
+-	if (default_ttl) {
+-		ttl = *default_ttl;
+-	} else {
+-		ttl = 0;
+-	}
+-
+-	line = LDNS_XMALLOC(char, LDNS_MAX_LINELEN + 1);
+-	if (!line) {
+-		return LDNS_STATUS_MEM_ERR;
+-	}
+-
+-	/* read an entire line in from the file */
+-	if ((size = ldns_fget_token_l(fp, line, LDNS_PARSE_SKIP_SPACE, LDNS_MAX_LINELEN, line_nr)) == -1) {
+-		LDNS_FREE(line);
+-		/* if last line was empty, we are now at feof, which is not
+-		 * always a parse error (happens when for instance last line
+-		 * was a comment)
+-		 */
+-		return LDNS_STATUS_SYNTAX_ERR;
+-	}
+-
+-	/* we can have the situation, where we've read ok, but still got
+-	 * no bytes to play with, in this case size is 0
+-	 */
+-	if (size == 0) {
+-		LDNS_FREE(line);
+-		return LDNS_STATUS_SYNTAX_EMPTY;
+-	}
+-
+-	if (strncmp(line, "$ORIGIN", 7) == 0 && isspace(line[7])) {
+-		if (*origin) {
+-			ldns_rdf_deep_free(*origin);
+-			*origin = NULL;
+-		}
+-		tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME,
+-				ldns_strip_ws(line + 8));
+-		if (!tmp) {
+-			/* could not parse what next to $ORIGIN */
+-			LDNS_FREE(line);
+-			return LDNS_STATUS_SYNTAX_DNAME_ERR;
+-		}
+-		*origin = tmp;
+-		s = LDNS_STATUS_SYNTAX_ORIGIN;
+-	} else if (strncmp(line, "$TTL", 4) == 0 && isspace(line[4])) {
+-		if (default_ttl) {
+-			*default_ttl = ldns_str2period(
+-					ldns_strip_ws(line + 5), &endptr);
+-		}
+-		s = LDNS_STATUS_SYNTAX_TTL;
+-	} else if (strncmp(line, "$INCLUDE", 8) == 0) {
+-		s = LDNS_STATUS_SYNTAX_INCLUDE;
+-	} else if (!*ldns_strip_ws(line)) {
+-		LDNS_FREE(line);
+-		return LDNS_STATUS_SYNTAX_EMPTY;
+-	} else {
+-		if (origin && *origin) {
+-			s = ldns_rr_new_frm_str(&rr, (const char*) line, ttl, *origin, prev);
+-		} else {
+-			s = ldns_rr_new_frm_str(&rr, (const char*) line, ttl, NULL, prev);
+-		}
+-	}
+-	LDNS_FREE(line);
+-	if (s == LDNS_STATUS_OK) {
+-		if (newrr) {
+-			*newrr = rr;
+-		} else {
+-			/* Just testing if it would parse? */
+-			ldns_rr_free(rr);
+-		}
+-	}
+-	return s;
+-}
+-
+-void
+-ldns_rr_set_owner(ldns_rr *rr, ldns_rdf *owner)
+-{
+-	rr->_owner = owner;
+-}
+-
+-void
+-ldns_rr_set_question(ldns_rr *rr, bool question)
+-{
+-   rr->_rr_question = question;
+-}
+-
+-void
+-ldns_rr_set_ttl(ldns_rr *rr, uint32_t ttl)
+-{
+-	rr->_ttl = ttl;
+-}
+-
+-void
+-ldns_rr_set_rd_count(ldns_rr *rr, size_t count)
+-{
+-	rr->_rd_count = count;
+-}
+-
+-void
+-ldns_rr_set_type(ldns_rr *rr, ldns_rr_type rr_type)
+-{
+-	rr->_rr_type = rr_type;
+-}
+-
+-void
+-ldns_rr_set_class(ldns_rr *rr, ldns_rr_class rr_class)
+-{
+-	rr->_rr_class = rr_class;
+-}
+-
+-ldns_rdf *
+-ldns_rr_set_rdf(ldns_rr *rr, const ldns_rdf *f, size_t position)
+-{
+-	size_t rd_count;
+-	ldns_rdf *pop;
+-
+-	rd_count = ldns_rr_rd_count(rr);
+-	if (position < rd_count) {
+-		/* dicard the old one */
+-		pop = rr->_rdata_fields[position];
+-		rr->_rdata_fields[position] = (ldns_rdf*)f;
+-		return pop;
+-	} else {
+-		return NULL;
+-	}
+-}
+-
+-bool
+-ldns_rr_push_rdf(ldns_rr *rr, const ldns_rdf *f)
+-{
+-	size_t rd_count;
+-	ldns_rdf **rdata_fields;
+-
+-	rd_count = ldns_rr_rd_count(rr);
+-
+-	/* grow the array */
+-	rdata_fields = LDNS_XREALLOC(
+-		rr->_rdata_fields, ldns_rdf *, rd_count + 1);
+-	if (!rdata_fields) {
+-		return false;
+-	}
+-
+-	/* add the new member */
+-	rr->_rdata_fields = rdata_fields;
+-	rr->_rdata_fields[rd_count] = (ldns_rdf*)f;
+-
+-	ldns_rr_set_rd_count(rr, rd_count + 1);
+-	return true;
+-}
+-
+-ldns_rdf *
+-ldns_rr_pop_rdf(ldns_rr *rr)
+-{
+-	size_t rd_count;
+-	ldns_rdf *pop;
+-	ldns_rdf** newrd;
+-
+-	rd_count = ldns_rr_rd_count(rr);
+-
+-	if (rd_count == 0) {
+-		return NULL;
+-	}
+-
+-	pop = rr->_rdata_fields[rd_count - 1];
+-
+-	/* try to shrink the array */
+-	if(rd_count > 1) {
+-		newrd = LDNS_XREALLOC(
+-			rr->_rdata_fields, ldns_rdf *, rd_count - 1);
+-		if(newrd)
+-			rr->_rdata_fields = newrd;
+-	} else {
+-		LDNS_FREE(rr->_rdata_fields);
+-	}
+-
+-	ldns_rr_set_rd_count(rr, rd_count - 1);
+-	return pop;
+-}
+-
+-ldns_rdf *
+-ldns_rr_rdf(const ldns_rr *rr, size_t nr)
+-{
+-	if (rr && nr < ldns_rr_rd_count(rr)) {
+-		return rr->_rdata_fields[nr];
+-	} else {
+-		return NULL;
+-	}
+-}
+-
+-ldns_rdf *
+-ldns_rr_owner(const ldns_rr *rr)
+-{
+-	return rr->_owner;
+-}
+-
+-bool
+-ldns_rr_is_question(const ldns_rr *rr)
+-{
+-   return rr->_rr_question;
+-}
+-
+-uint32_t
+-ldns_rr_ttl(const ldns_rr *rr)
+-{
+-	return rr->_ttl;
+-}
+-
+-size_t
+-ldns_rr_rd_count(const ldns_rr *rr)
+-{
+-	return rr->_rd_count;
+-}
+-
+-ldns_rr_type
+-ldns_rr_get_type(const ldns_rr *rr)
+-{
+-        return rr->_rr_type;
+-}
+-
+-ldns_rr_class
+-ldns_rr_get_class(const ldns_rr *rr)
+-{
+-        return rr->_rr_class;
+-}
+-
+-/* rr_lists */
+-
+-size_t
+-ldns_rr_list_rr_count(const ldns_rr_list *rr_list)
+-{
+-	if (rr_list) {
+-		return rr_list->_rr_count;
+-	} else {
+-		return 0;
+-	}
+-}
+-
+-ldns_rr *
+-ldns_rr_list_set_rr(ldns_rr_list *rr_list, const ldns_rr *r, size_t count)
+-{
+-	ldns_rr *old;
+-
+-	if (count > ldns_rr_list_rr_count(rr_list)) {
+-		return NULL;
+-	}
+-
+-	old = ldns_rr_list_rr(rr_list, count);
+-
+-	/* overwrite old's pointer */
+-	rr_list->_rrs[count] = (ldns_rr*)r;
+-	return old;
+-}
+-
+-void
+-ldns_rr_list_set_rr_count(ldns_rr_list *rr_list, size_t count)
+-{
+-	assert(count <= rr_list->_rr_capacity);
+-	rr_list->_rr_count = count;
+-}
+-
+-ldns_rr *
+-ldns_rr_list_rr(const ldns_rr_list *rr_list, size_t nr)
+-{
+-	if (nr < ldns_rr_list_rr_count(rr_list)) {
+-		return rr_list->_rrs[nr];
+-	} else {
+-		return NULL;
+-	}
+-}
+-
+-ldns_rr_list *
+-ldns_rr_list_new(void)
+-{
+-	ldns_rr_list *rr_list = LDNS_MALLOC(ldns_rr_list);
+-        if(!rr_list) return NULL;
+-	rr_list->_rr_count = 0;
+-	rr_list->_rr_capacity = 0;
+-	rr_list->_rrs = NULL;
+-	return rr_list;
+-}
+-
+-void
+-ldns_rr_list_free(ldns_rr_list *rr_list)
+-{
+-	if (rr_list) {
+-		LDNS_FREE(rr_list->_rrs);
+-		LDNS_FREE(rr_list);
+-	}
+-}
+-
+-void
+-ldns_rr_list_deep_free(ldns_rr_list *rr_list)
+-{
+-	size_t i;
+-
+-	if (rr_list) {
+-		for (i=0; i < ldns_rr_list_rr_count(rr_list); i++) {
+-			ldns_rr_free(ldns_rr_list_rr(rr_list, i));
+-		}
+-		LDNS_FREE(rr_list->_rrs);
+-		LDNS_FREE(rr_list);
+-	}
+-}
+-
+-
+-/* add right to left. So we modify *left! */
+-bool
+-ldns_rr_list_cat(ldns_rr_list *left, ldns_rr_list *right)
+-{
+-	size_t r_rr_count;
+-	size_t i;
+-
+-	if (!left) {
+-		return false;
+-	}
+-
+-	if (right) {
+-		r_rr_count = ldns_rr_list_rr_count(right);
+-	} else {
+-		r_rr_count = 0;
+-	}
+-
+-	/* push right to left */
+-	for(i = 0; i < r_rr_count; i++) {
+-		ldns_rr_list_push_rr(left, ldns_rr_list_rr(right, i));
+-	}
+-	return true;
+-}
+-
+-ldns_rr_list *
+-ldns_rr_list_cat_clone(ldns_rr_list *left, ldns_rr_list *right)
+-{
+-	size_t l_rr_count;
+-	size_t r_rr_count;
+-	size_t i;
+-	ldns_rr_list *cat;
+-
+-	if (left) {
+-		l_rr_count = ldns_rr_list_rr_count(left);
+-	} else {
+-		return ldns_rr_list_clone(right);
+-	}
+-
+-	if (right) {
+-		r_rr_count = ldns_rr_list_rr_count(right);
+-	} else {
+-		r_rr_count = 0;
+-	}
+-
+-	cat = ldns_rr_list_new();
+-
+-	if (!cat) {
+-		return NULL;
+-	}
+-
+-	/* left */
+-	for(i = 0; i < l_rr_count; i++) {
+-		ldns_rr_list_push_rr(cat,
+-				ldns_rr_clone(ldns_rr_list_rr(left, i)));
+-	}
+-	/* right */
+-	for(i = 0; i < r_rr_count; i++) {
+-		ldns_rr_list_push_rr(cat,
+-				ldns_rr_clone(ldns_rr_list_rr(right, i)));
+-	}
+-	return cat;
+-}
+-
+-ldns_rr_list *
+-ldns_rr_list_subtype_by_rdf(ldns_rr_list *l, ldns_rdf *r, size_t pos)
+-{
+-	size_t i;
+-	ldns_rr_list *subtyped;
+-	ldns_rdf *list_rdf;
+-
+-	subtyped = ldns_rr_list_new();
+-
+-	for(i = 0; i < ldns_rr_list_rr_count(l); i++) {
+-		list_rdf = ldns_rr_rdf(
+-			ldns_rr_list_rr(l, i),
+-			pos);
+-		if (!list_rdf) {
+-			/* pos is too large or any other error */
+-			ldns_rr_list_deep_free(subtyped);
+-			return NULL;
+-		}
+-
+-		if (ldns_rdf_compare(list_rdf, r) == 0) {
+-			/* a match */
+-			ldns_rr_list_push_rr(subtyped,
+-					ldns_rr_clone(ldns_rr_list_rr(l, i)));
+-		}
+-	}
+-
+-	if (ldns_rr_list_rr_count(subtyped) > 0) {
+-		return subtyped;
+-	} else {
+-		ldns_rr_list_free(subtyped);
+-		return NULL;
+-	}
+-}
+-
+-bool
+-ldns_rr_list_push_rr(ldns_rr_list *rr_list, const ldns_rr *rr)
+-{
+-	size_t rr_count;
+-	size_t cap;
+-
+-	rr_count = ldns_rr_list_rr_count(rr_list);
+-	cap = rr_list->_rr_capacity;
+-
+-	/* grow the array */
+-	if(rr_count+1 > cap) {
+-		ldns_rr **rrs;
+-
+-		if(cap == 0)
+-			cap = LDNS_RRLIST_INIT;  /* initial list size */
+-		else	cap *= 2;
+-		rrs = LDNS_XREALLOC(rr_list->_rrs, ldns_rr *, cap);
+-		if (!rrs) {
+-			return false;
+-		}
+-		rr_list->_rrs = rrs;
+-		rr_list->_rr_capacity = cap;
+-	}
+-
+-	/* add the new member */
+-	rr_list->_rrs[rr_count] = (ldns_rr*)rr;
+-
+-	ldns_rr_list_set_rr_count(rr_list, rr_count + 1);
+-	return true;
+-}
+-
+-bool
+-ldns_rr_list_push_rr_list(ldns_rr_list *rr_list, const ldns_rr_list *push_list)
+-{
+-	size_t i;
+-
+-	for(i = 0; i < ldns_rr_list_rr_count(push_list); i++) {
+-		if (!ldns_rr_list_push_rr(rr_list,
+-				ldns_rr_list_rr(push_list, i))) {
+-			return false;
+-		}
+-	}
+-	return true;
+-}
+-
+-ldns_rr *
+-ldns_rr_list_pop_rr(ldns_rr_list *rr_list)
+-{
+-	size_t rr_count;
+-	size_t cap;
+-	ldns_rr *pop;
+-
+-	rr_count = ldns_rr_list_rr_count(rr_list);
+-
+-	if (rr_count == 0) {
+-		return NULL;
+-	}
+-
+-	cap = rr_list->_rr_capacity;
+-	pop = ldns_rr_list_rr(rr_list, rr_count - 1);
+-
+-	/* shrink the array */
+-	if(cap > LDNS_RRLIST_INIT && rr_count-1 <= cap/2) {
+-                ldns_rr** a;
+-		cap /= 2;
+-                a = LDNS_XREALLOC(rr_list->_rrs, ldns_rr *, cap);
+-                if(a) {
+-		        rr_list->_rrs = a;
+-		        rr_list->_rr_capacity = cap;
+-                }
+-	}
+-
+-	ldns_rr_list_set_rr_count(rr_list, rr_count - 1);
+-
+-	return pop;
+-}
+-
+-ldns_rr_list *
+-ldns_rr_list_pop_rr_list(ldns_rr_list *rr_list, size_t howmany)
+-{
+-	/* pop a number of rr's and put them in a rr_list */
+-	ldns_rr_list *popped;
+-	ldns_rr *p;
+-	size_t i = howmany;
+-
+-	popped = ldns_rr_list_new();
+-
+-	if (!popped) {
+-		return NULL;
+-	}
+-
+-
+-	while(i > 0 &&
+-			(p = ldns_rr_list_pop_rr(rr_list)) != NULL) {
+-		ldns_rr_list_push_rr(popped, p);
+-		i--;
+-	}
+-
+-	if (i == howmany) { /* so i <= 0 */
+-		ldns_rr_list_free(popped);
+-		return NULL;
+-	} else {
+-		return popped;
+-	}
+-}
+-
+-
+-bool
+-ldns_rr_list_contains_rr(const ldns_rr_list *rr_list, ldns_rr *rr)
+-{
+-	size_t i;
+-
+-	if (!rr_list || !rr || ldns_rr_list_rr_count(rr_list) == 0) {
+-		return false;
+-	}
+-
+-	for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
+-		if (rr == ldns_rr_list_rr(rr_list, i)) {
+-			return true;
+-		} else if (ldns_rr_compare(rr, ldns_rr_list_rr(rr_list, i)) == 0) {
+-			return true;
+-		}
+-	}
+-	return false;
+-}
+-
+-bool
+-ldns_is_rrset(ldns_rr_list *rr_list)
+-{
+-	ldns_rr_type t;
+-	ldns_rr_class c;
+-	ldns_rdf *o;
+-	ldns_rr *tmp;
+-	size_t i;
+-
+-	if (!rr_list || ldns_rr_list_rr_count(rr_list) == 0) {
+-		return false;
+-	}
+-
+-	tmp = ldns_rr_list_rr(rr_list, 0);
+-
+-	t = ldns_rr_get_type(tmp);
+-	c = ldns_rr_get_class(tmp);
+-	o = ldns_rr_owner(tmp);
+-
+-	/* compare these with the rest of the rr_list, start with 1 */
+-	for (i = 1; i < ldns_rr_list_rr_count(rr_list); i++) {
+-		tmp = ldns_rr_list_rr(rr_list, i);
+-		if (t != ldns_rr_get_type(tmp)) {
+-			return false;
+-		}
+-		if (c != ldns_rr_get_class(tmp)) {
+-			return false;
+-		}
+-		if (ldns_rdf_compare(o, ldns_rr_owner(tmp)) != 0) {
+-			return false;
+-		}
+-	}
+-	return true;
+-}
+-
+-bool
+-ldns_rr_set_push_rr(ldns_rr_list *rr_list, ldns_rr *rr)
+-{
+-	size_t rr_count;
+-	size_t i;
+-	ldns_rr *last;
+-
+-	assert(rr != NULL);
+-
+-	rr_count = ldns_rr_list_rr_count(rr_list);
+-
+-	if (rr_count == 0) {
+-		/* nothing there, so checking it is
+-		 * not needed */
+-		return ldns_rr_list_push_rr(rr_list, rr);
+-	} else {
+-		/* check with the final rr in the rr_list */
+-		last = ldns_rr_list_rr(rr_list, rr_count - 1);
+-
+-		if (ldns_rr_get_class(last) != ldns_rr_get_class(rr)) {
+-			return false;
+-		}
+-		if (ldns_rr_get_type(last) != ldns_rr_get_type(rr)) {
+-			return false;
+-		}
+-		/* only check if not equal to RRSIG */
+-		if (ldns_rr_get_type(rr) != LDNS_RR_TYPE_RRSIG) {
+-			if (ldns_rr_ttl(last) != ldns_rr_ttl(rr)) {
+-				return false;
+-			}
+-		}
+-		if (ldns_rdf_compare(ldns_rr_owner(last),
+-					ldns_rr_owner(rr)) != 0) {
+-			return false;
+-		}
+-		/* ok, still alive - check if the rr already
+-		 * exists - if so, dont' add it */
+-		for(i = 0; i < rr_count; i++) {
+-			if(ldns_rr_compare(
+-					ldns_rr_list_rr(rr_list, i), rr) == 0) {
+-				return false;
+-			}
+-		}
+-		/* it's safe, push it */
+-		return ldns_rr_list_push_rr(rr_list, rr);
+-	}
+-}
+-
+-ldns_rr *
+-ldns_rr_set_pop_rr(ldns_rr_list *rr_list)
+-{
+-	return ldns_rr_list_pop_rr(rr_list);
+-}
+-
+-ldns_rr_list *
+-ldns_rr_list_pop_rrset(ldns_rr_list *rr_list)
+-{
+-	ldns_rr_list *rrset;
+-	ldns_rr *last_rr = NULL;
+-	ldns_rr *next_rr;
+-
+-	if (!rr_list) {
+-		return NULL;
+-	}
+-
+-	rrset = ldns_rr_list_new();
+-	if (!last_rr) {
+-		last_rr = ldns_rr_list_pop_rr(rr_list);
+-		if (!last_rr) {
+-			ldns_rr_list_free(rrset);
+-			return NULL;
+-		} else {
+-			ldns_rr_list_push_rr(rrset, last_rr);
+-		}
+-	}
+-
+-	if (ldns_rr_list_rr_count(rr_list) > 0) {
+-		next_rr = ldns_rr_list_rr(rr_list, ldns_rr_list_rr_count(rr_list) - 1);
+-	} else {
+-		next_rr = NULL;
+-	}
+-
+-	while (next_rr) {
+-		if (
+-			ldns_rdf_compare(ldns_rr_owner(next_rr),
+-					 ldns_rr_owner(last_rr)) == 0
+-			&&
+-			ldns_rr_get_type(next_rr) == ldns_rr_get_type(last_rr)
+-			&&
+-			ldns_rr_get_class(next_rr) == ldns_rr_get_class(last_rr)
+-		   ) {
+-			ldns_rr_list_push_rr(rrset, ldns_rr_list_pop_rr(rr_list));
+-			if (ldns_rr_list_rr_count(rr_list) > 0) {
+-				last_rr = next_rr;
+-				next_rr = ldns_rr_list_rr(rr_list, ldns_rr_list_rr_count(rr_list) - 1);
+-			} else {
+-				next_rr = NULL;
+-			}
+-		} else {
+-			next_rr = NULL;
+-		}
+-	}
+-
+-	return rrset;
+-}
+-
+-ldns_rr *
+-ldns_rr_clone(const ldns_rr *rr)
+-{
+-	size_t i;
+-	ldns_rr *new_rr;
+-
+-	if (!rr) {
+-		return NULL;
+-	}
+-
+-	new_rr = ldns_rr_new();
+-	if (!new_rr) {
+-		return NULL;
+-	}
+-	if (ldns_rr_owner(rr)) {
+-		ldns_rr_set_owner(new_rr, ldns_rdf_clone(ldns_rr_owner(rr)));
+-  	}
+-	ldns_rr_set_ttl(new_rr, ldns_rr_ttl(rr));
+-	ldns_rr_set_type(new_rr, ldns_rr_get_type(rr));
+-	ldns_rr_set_class(new_rr, ldns_rr_get_class(rr));
+-	ldns_rr_set_question(new_rr, ldns_rr_is_question(rr));
+-
+-	for (i = 0; i < ldns_rr_rd_count(rr); i++) {
+-        	if (ldns_rr_rdf(rr,i)) {
+-        		ldns_rr_push_rdf(new_rr, ldns_rdf_clone(ldns_rr_rdf(rr, i)));
+-                }
+-	}
+-
+-	return new_rr;
+-}
+-
+-ldns_rr_list *
+-ldns_rr_list_clone(const ldns_rr_list *rrlist)
+-{
+-	size_t i;
+-	ldns_rr_list *new_list;
+-	ldns_rr *r;
+-
+-	if (!rrlist) {
+-		return NULL;
+-	}
+-
+-	new_list = ldns_rr_list_new();
+-	if (!new_list) {
+-		return NULL;
+-	}
+-	for (i = 0; i < ldns_rr_list_rr_count(rrlist); i++) {
+-		r = ldns_rr_clone(
+-			ldns_rr_list_rr(rrlist, i)
+-		    );
+-		if (!r) {
+-			/* huh, failure in cloning */
+-			ldns_rr_list_deep_free(new_list);
+-			return NULL;
+-		}
+-		ldns_rr_list_push_rr(new_list, r);
+-	}
+-	return new_list;
+-}
+-
+-
+-static int
+-qsort_schwartz_rr_compare(const void *a, const void *b)
+-{
+-	int result = 0;
+-	ldns_rr *rr1, *rr2;
+-	ldns_buffer *rr1_buf, *rr2_buf;
+-	struct ldns_schwartzian_compare_struct *sa = *(struct ldns_schwartzian_compare_struct **) a;
+-	struct ldns_schwartzian_compare_struct *sb = *(struct ldns_schwartzian_compare_struct **) b;
+-	/* if we are doing 2wire, we need to do lowercasing on the dname (and maybe on the rdata)
+-	 * this must be done for comparison only, so we need to have a temp var for both buffers,
+-	 * which is only used when the transformed object value isn't there yet
+-	 */
+-	ldns_rr *canonical_a, *canonical_b;
+-
+-	rr1 = (ldns_rr *) sa->original_object;
+-	rr2 = (ldns_rr *) sb->original_object;
+-
+-	result = ldns_rr_compare_no_rdata(rr1, rr2);
+-
+-	if (result == 0) {
+-		if (!sa->transformed_object) {
+-			canonical_a = ldns_rr_clone(sa->original_object);
+-			ldns_rr2canonical(canonical_a);
+-			sa->transformed_object = ldns_buffer_new(ldns_rr_uncompressed_size(canonical_a));
+-			if (ldns_rr2buffer_wire(sa->transformed_object, canonical_a, LDNS_SECTION_ANY) != LDNS_STATUS_OK) {
+-		                ldns_buffer_free((ldns_buffer *)sa->transformed_object);
+-                                sa->transformed_object = NULL;
+-				ldns_rr_free(canonical_a);
+-				return 0;
+-			}
+-			ldns_rr_free(canonical_a);
+-		}
+-		if (!sb->transformed_object) {
+-			canonical_b = ldns_rr_clone(sb->original_object);
+-			ldns_rr2canonical(canonical_b);
+-			sb->transformed_object = ldns_buffer_new(ldns_rr_uncompressed_size(canonical_b));
+-			if (ldns_rr2buffer_wire(sb->transformed_object, canonical_b, LDNS_SECTION_ANY) != LDNS_STATUS_OK) {
+-		                ldns_buffer_free((ldns_buffer *)sa->transformed_object);
+-		                ldns_buffer_free((ldns_buffer *)sb->transformed_object);
+-                                sa->transformed_object = NULL;
+-                                sb->transformed_object = NULL;
+-				ldns_rr_free(canonical_b);
+-				return 0;
+-			}
+-			ldns_rr_free(canonical_b);
+-		}
+-		rr1_buf = (ldns_buffer *) sa->transformed_object;
+-		rr2_buf = (ldns_buffer *) sb->transformed_object;
+-
+-		result = ldns_rr_compare_wire(rr1_buf, rr2_buf);
+-	}
+-
+-	return result;
+-}
+-
+-void
+-ldns_rr_list_sort(ldns_rr_list *unsorted)
+-{
+-	struct ldns_schwartzian_compare_struct **sortables;
+-	size_t item_count;
+-	size_t i;
+-
+-	if (unsorted) {
+-		item_count = ldns_rr_list_rr_count(unsorted);
+-
+-		sortables = LDNS_XMALLOC(struct ldns_schwartzian_compare_struct *,
+-					 item_count);
+-                if(!sortables) return; /* no way to return error */
+-		for (i = 0; i < item_count; i++) {
+-			sortables[i] = LDNS_XMALLOC(struct ldns_schwartzian_compare_struct, 1);
+-                        if(!sortables[i]) {
+-                                /* free the allocated parts */
+-                                while(i>0) {
+-                                        i--;
+-                                        LDNS_FREE(sortables[i]);
+-                                }
+-                                /* no way to return error */
+-				LDNS_FREE(sortables);
+-                                return;
+-                        }
+-			sortables[i]->original_object = ldns_rr_list_rr(unsorted, i);
+-			sortables[i]->transformed_object = NULL;
+-		}
+-		qsort(sortables,
+-		      item_count,
+-		      sizeof(struct ldns_schwartzian_compare_struct *),
+-		      qsort_schwartz_rr_compare);
+-		for (i = 0; i < item_count; i++) {
+-			unsorted->_rrs[i] = sortables[i]->original_object;
+-			if (sortables[i]->transformed_object) {
+-				ldns_buffer_free(sortables[i]->transformed_object);
+-			}
+-			LDNS_FREE(sortables[i]);
+-		}
+-		LDNS_FREE(sortables);
+-	}
+-}
+-
+-int
+-ldns_rr_compare_no_rdata(const ldns_rr *rr1, const ldns_rr *rr2)
+-{
+-	size_t rr1_len;
+-	size_t rr2_len;
+-        size_t offset;
+-
+-	assert(rr1 != NULL);
+-	assert(rr2 != NULL);
+-
+-	rr1_len = ldns_rr_uncompressed_size(rr1);
+-	rr2_len = ldns_rr_uncompressed_size(rr2);
+-
+-	if (ldns_dname_compare(ldns_rr_owner(rr1), ldns_rr_owner(rr2)) < 0) {
+-		return -1;
+-	} else if (ldns_dname_compare(ldns_rr_owner(rr1), ldns_rr_owner(rr2)) > 0) {
+-		return 1;
+-	}
+-
+-        /* should return -1 if rr1 comes before rr2, so need to do rr1 - rr2, not rr2 - rr1 */
+-        if (ldns_rr_get_class(rr1) != ldns_rr_get_class(rr2)) {
+-            return ldns_rr_get_class(rr1) - ldns_rr_get_class(rr2);
+-        }
+-
+-        /* should return -1 if rr1 comes before rr2, so need to do rr1 - rr2, not rr2 - rr1 */
+-        if (ldns_rr_get_type(rr1) != ldns_rr_get_type(rr2)) {
+-            return ldns_rr_get_type(rr1) - ldns_rr_get_type(rr2);
+-        }
+-
+-        /* offset is the owername length + ttl + type + class + rdlen == start of wire format rdata */
+-        offset = ldns_rdf_size(ldns_rr_owner(rr1)) + 4 + 2 + 2 + 2;
+-        /* if either record doesn't have any RDATA... */
+-        if (offset > rr1_len || offset > rr2_len) {
+-            if (rr1_len == rr2_len) {
+-              return 0;
+-            }
+-            return ((int) rr2_len - (int) rr1_len);
+-        }
+-
+-	return 0;
+-}
+-
+-int ldns_rr_compare_wire(ldns_buffer *rr1_buf, ldns_buffer *rr2_buf)
+-{
+-        size_t rr1_len, rr2_len, min_len, i, offset;
+-
+-        rr1_len = ldns_buffer_capacity(rr1_buf);
+-        rr2_len = ldns_buffer_capacity(rr2_buf);
+-
+-        /* jump past dname (checked in earlier part)
+-         * and especially past TTL */
+-        offset = 0;
+-        while (offset < rr1_len && *ldns_buffer_at(rr1_buf, offset) != 0) {
+-          offset += *ldns_buffer_at(rr1_buf, offset) + 1;
+-        }
+-        /* jump to rdata section (PAST the rdata length field, otherwise
+-           rrs with different lengths might be sorted erroneously */
+-        offset += 11;
+-	   min_len = (rr1_len < rr2_len) ? rr1_len : rr2_len;
+-        /* Compare RRs RDATA byte for byte. */
+-        for(i = offset; i < min_len; i++) {
+-                if (*ldns_buffer_at(rr1_buf,i) < *ldns_buffer_at(rr2_buf,i)) {
+-                        return -1;
+-                } else if (*ldns_buffer_at(rr1_buf,i) > *ldns_buffer_at(rr2_buf,i)) {
+-                        return +1;
+-                }
+-        }
+-
+-        /* If both RDATAs are the same up to min_len, then the shorter one sorts first. */
+-        if (rr1_len < rr2_len) {
+-                return -1;
+-        } else if (rr1_len > rr2_len) {
+-                return +1;
+-	}
+-        /* The RDATAs are equal. */
+-        return 0;
+-
+-}
+-
+-int
+-ldns_rr_compare(const ldns_rr *rr1, const ldns_rr *rr2)
+-{
+-	int result;
+-	size_t rr1_len, rr2_len;
+-
+-	ldns_buffer *rr1_buf;
+-	ldns_buffer *rr2_buf;
+-
+-	result = ldns_rr_compare_no_rdata(rr1, rr2);
+-	if (result == 0) {
+-		rr1_len = ldns_rr_uncompressed_size(rr1);
+-		rr2_len = ldns_rr_uncompressed_size(rr2);
+-
+-		rr1_buf = ldns_buffer_new(rr1_len);
+-		rr2_buf = ldns_buffer_new(rr2_len);
+-
+-		if (ldns_rr2buffer_wire_canonical(rr1_buf,
+-								    rr1,
+-								    LDNS_SECTION_ANY)
+-		    != LDNS_STATUS_OK) {
+-			ldns_buffer_free(rr1_buf);
+-			ldns_buffer_free(rr2_buf);
+-			return 0;
+-		}
+-		if (ldns_rr2buffer_wire_canonical(rr2_buf,
+-								    rr2,
+-								    LDNS_SECTION_ANY)
+-		    != LDNS_STATUS_OK) {
+-			ldns_buffer_free(rr1_buf);
+-			ldns_buffer_free(rr2_buf);
+-			return 0;
+-		}
+-
+-		result = ldns_rr_compare_wire(rr1_buf, rr2_buf);
+-
+-		ldns_buffer_free(rr1_buf);
+-		ldns_buffer_free(rr2_buf);
+-	}
+-
+-	return result;
+-}
+-
+-/* convert dnskey to a ds with the given algorithm,
+- * then compare the result with the given ds */
+-static int
+-ldns_rr_compare_ds_dnskey(ldns_rr *ds,
+-                          ldns_rr *dnskey)
+-{
+-	ldns_rr *ds_gen;
+-	bool result = false;
+-	ldns_hash algo;
+-
+-	if (!dnskey || !ds ||
+-	    ldns_rr_get_type(ds) != LDNS_RR_TYPE_DS ||
+-	    ldns_rr_get_type(dnskey) != LDNS_RR_TYPE_DNSKEY) {
+-		return false;
+-	}
+-
+-	if (ldns_rr_rdf(ds, 2) == NULL) {
+-		return false;
+-	}
+-	algo = ldns_rdf2native_int8(ldns_rr_rdf(ds, 2));
+-
+-	ds_gen = ldns_key_rr2ds(dnskey, algo);
+-	if (ds_gen) {
+-		result = ldns_rr_compare(ds, ds_gen) == 0;
+-		ldns_rr_free(ds_gen);
+-	}
+-	return result;
+-}
+-
+-bool
+-ldns_rr_compare_ds(const ldns_rr *orr1, const ldns_rr *orr2)
+-{
+-	bool result;
+-	ldns_rr *rr1 = ldns_rr_clone(orr1);
+-	ldns_rr *rr2 = ldns_rr_clone(orr2);
+-
+-	/* set ttls to zero */
+-	ldns_rr_set_ttl(rr1, 0);
+-	ldns_rr_set_ttl(rr2, 0);
+-
+-	if (ldns_rr_get_type(rr1) == LDNS_RR_TYPE_DS &&
+-	    ldns_rr_get_type(rr2) == LDNS_RR_TYPE_DNSKEY) {
+-		result = ldns_rr_compare_ds_dnskey(rr1, rr2);
+-	} else if (ldns_rr_get_type(rr1) == LDNS_RR_TYPE_DNSKEY &&
+-	    ldns_rr_get_type(rr2) == LDNS_RR_TYPE_DS) {
+-		result = ldns_rr_compare_ds_dnskey(rr2, rr1);
+-	} else {
+-		result = (ldns_rr_compare(rr1, rr2) == 0);
+-	}
+-
+-	ldns_rr_free(rr1);
+-	ldns_rr_free(rr2);
+-
+-	return result;
+-}
+-
+-int
+-ldns_rr_list_compare(const ldns_rr_list *rrl1, const ldns_rr_list *rrl2)
+-{
+-	size_t i = 0;
+-	int rr_cmp;
+-
+-	assert(rrl1 != NULL);
+-	assert(rrl2 != NULL);
+-
+-	for (i = 0; i < ldns_rr_list_rr_count(rrl1) && i < ldns_rr_list_rr_count(rrl2); i++) {
+-		rr_cmp = ldns_rr_compare(ldns_rr_list_rr(rrl1, i), ldns_rr_list_rr(rrl2, i));
+-		if (rr_cmp != 0) {
+-			return rr_cmp;
+-		}
+-	}
+-
+-	if (i == ldns_rr_list_rr_count(rrl1) &&
+-	    i != ldns_rr_list_rr_count(rrl2)) {
+-		return 1;
+-	} else if (i == ldns_rr_list_rr_count(rrl2) &&
+-	           i != ldns_rr_list_rr_count(rrl1)) {
+-		return -1;
+-	} else {
+-		return 0;
+-	}
+-}
+-
+-size_t
+-ldns_rr_uncompressed_size(const ldns_rr *r)
+-{
+-	size_t rrsize;
+-	size_t i;
+-
+-	rrsize = 0;
+-	/* add all the rdf sizes */
+-	for(i = 0; i < ldns_rr_rd_count(r); i++) {
+-		rrsize += ldns_rdf_size(ldns_rr_rdf(r, i));
+-	}
+-	/* ownername */
+-	rrsize += ldns_rdf_size(ldns_rr_owner(r));
+-	rrsize += LDNS_RR_OVERHEAD;
+-	return rrsize;
+-}
+-
+-void
+-ldns_rr2canonical(ldns_rr *rr)
+-{
+-	uint16_t i;
+-
+-	if (!rr) {
+-	  return;
+-        }
+-
+-        ldns_dname2canonical(ldns_rr_owner(rr));
+-
+-	/*
+-	 * lowercase the rdata dnames if the rr type is one
+-	 * of the list in chapter 7 of RFC3597
+-	 * Also added RRSIG, because a "Signer's Name" should be canonicalized
+-	 * too. See dnssec-bis-updates-16. We can add it to this list because
+-	 * the "Signer's Name"  is the only dname type rdata field in a RRSIG.
+-	 */
+-	switch(ldns_rr_get_type(rr)) {
+-        	case LDNS_RR_TYPE_NS:
+-        	case LDNS_RR_TYPE_MD:
+-        	case LDNS_RR_TYPE_MF:
+-        	case LDNS_RR_TYPE_CNAME:
+-        	case LDNS_RR_TYPE_SOA:
+-        	case LDNS_RR_TYPE_MB:
+-        	case LDNS_RR_TYPE_MG:
+-        	case LDNS_RR_TYPE_MR:
+-        	case LDNS_RR_TYPE_PTR:
+-        	case LDNS_RR_TYPE_MINFO:
+-        	case LDNS_RR_TYPE_MX:
+-        	case LDNS_RR_TYPE_RP:
+-        	case LDNS_RR_TYPE_AFSDB:
+-        	case LDNS_RR_TYPE_RT:
+-        	case LDNS_RR_TYPE_SIG:
+-        	case LDNS_RR_TYPE_PX:
+-        	case LDNS_RR_TYPE_NXT:
+-        	case LDNS_RR_TYPE_NAPTR:
+-        	case LDNS_RR_TYPE_KX:
+-        	case LDNS_RR_TYPE_SRV:
+-        	case LDNS_RR_TYPE_DNAME:
+-        	case LDNS_RR_TYPE_A6:
+-        	case LDNS_RR_TYPE_RRSIG:
+-			for (i = 0; i < ldns_rr_rd_count(rr); i++) {
+-				ldns_dname2canonical(ldns_rr_rdf(rr, i));
+-			}
+-			return;
+-		default:
+-			/* do nothing */
+-			return;
+-	}
+-}
+-
+-void
+-ldns_rr_list2canonical(ldns_rr_list *rr_list)
+-{
+-	size_t i;
+-	for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
+-		ldns_rr2canonical(ldns_rr_list_rr(rr_list, i));
+-	}
+-}
+-
+-uint8_t
+-ldns_rr_label_count(ldns_rr *rr)
+-{
+-	if (!rr) {
+-		return 0;
+-	}
+-	return ldns_dname_label_count(
+-			ldns_rr_owner(rr));
+-}
+-
+-/** \cond */
+-static const ldns_rdf_type type_0_wireformat[] = { LDNS_RDF_TYPE_UNKNOWN };
+-static const ldns_rdf_type type_a_wireformat[] = { LDNS_RDF_TYPE_A };
+-static const ldns_rdf_type type_ns_wireformat[] = { LDNS_RDF_TYPE_DNAME };
+-static const ldns_rdf_type type_md_wireformat[] = { LDNS_RDF_TYPE_DNAME };
+-static const ldns_rdf_type type_mf_wireformat[] = { LDNS_RDF_TYPE_DNAME };
+-static const ldns_rdf_type type_cname_wireformat[] = { LDNS_RDF_TYPE_DNAME };
+-static const ldns_rdf_type type_soa_wireformat[] = {
+-	LDNS_RDF_TYPE_DNAME, LDNS_RDF_TYPE_DNAME, LDNS_RDF_TYPE_INT32, 
+-	LDNS_RDF_TYPE_PERIOD, LDNS_RDF_TYPE_PERIOD, LDNS_RDF_TYPE_PERIOD,
+-	LDNS_RDF_TYPE_PERIOD
+-};
+-static const ldns_rdf_type type_mb_wireformat[] = { LDNS_RDF_TYPE_DNAME };
+-static const ldns_rdf_type type_mg_wireformat[] = { LDNS_RDF_TYPE_DNAME };
+-static const ldns_rdf_type type_mr_wireformat[] = { LDNS_RDF_TYPE_DNAME };
+-static const ldns_rdf_type type_wks_wireformat[] = {
+-	LDNS_RDF_TYPE_A, LDNS_RDF_TYPE_WKS
+-};
+-static const ldns_rdf_type type_ptr_wireformat[] = { LDNS_RDF_TYPE_DNAME };
+-static const ldns_rdf_type type_hinfo_wireformat[] = {
+-	LDNS_RDF_TYPE_STR, LDNS_RDF_TYPE_STR
+-};
+-static const ldns_rdf_type type_minfo_wireformat[] = {
+-	LDNS_RDF_TYPE_DNAME, LDNS_RDF_TYPE_DNAME
+-};
+-static const ldns_rdf_type type_mx_wireformat[] = {
+-	LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_DNAME
+-};
+-static const ldns_rdf_type type_rp_wireformat[] = {
+-	LDNS_RDF_TYPE_DNAME, LDNS_RDF_TYPE_DNAME
+-};
+-static const ldns_rdf_type type_afsdb_wireformat[] = {
+-	LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_DNAME
+-};
+-static const ldns_rdf_type type_x25_wireformat[] = { LDNS_RDF_TYPE_STR };
+-static const ldns_rdf_type type_isdn_wireformat[] = {
+-	LDNS_RDF_TYPE_STR, LDNS_RDF_TYPE_STR
+-};
+-static const ldns_rdf_type type_rt_wireformat[] = {
+-	LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_DNAME
+-};
+-static const ldns_rdf_type type_nsap_wireformat[] = {
+-	LDNS_RDF_TYPE_NSAP
+-};
+-static const ldns_rdf_type type_nsap_ptr_wireformat[] = {
+-	LDNS_RDF_TYPE_STR
+-};
+-static const ldns_rdf_type type_sig_wireformat[] = {
+-	LDNS_RDF_TYPE_TYPE, LDNS_RDF_TYPE_ALG, LDNS_RDF_TYPE_INT8, LDNS_RDF_TYPE_INT32,
+-	LDNS_RDF_TYPE_TIME, LDNS_RDF_TYPE_TIME, LDNS_RDF_TYPE_INT16,
+-	LDNS_RDF_TYPE_DNAME, LDNS_RDF_TYPE_B64
+-};
+-static const ldns_rdf_type type_key_wireformat[] = {
+-	LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_INT8, LDNS_RDF_TYPE_INT8, LDNS_RDF_TYPE_B64
+-};
+-static const ldns_rdf_type type_px_wireformat[] = {
+-	LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_DNAME, LDNS_RDF_TYPE_DNAME
+-};
+-static const ldns_rdf_type type_gpos_wireformat[] = {
+-	LDNS_RDF_TYPE_STR, LDNS_RDF_TYPE_STR, LDNS_RDF_TYPE_STR
+-};
+-static const ldns_rdf_type type_aaaa_wireformat[] = { LDNS_RDF_TYPE_AAAA };
+-static const ldns_rdf_type type_loc_wireformat[] = { LDNS_RDF_TYPE_LOC };
+-static const ldns_rdf_type type_nxt_wireformat[] = {
+-	LDNS_RDF_TYPE_DNAME, LDNS_RDF_TYPE_UNKNOWN
+-};
+-static const ldns_rdf_type type_eid_wireformat[] = {
+-	LDNS_RDF_TYPE_HEX
+-};
+-static const ldns_rdf_type type_nimloc_wireformat[] = {
+-	LDNS_RDF_TYPE_HEX
+-};
+-static const ldns_rdf_type type_srv_wireformat[] = {
+-	LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_DNAME
+-};
+-static const ldns_rdf_type type_atma_wireformat[] = {
+-	LDNS_RDF_TYPE_ATMA
+-};
+-static const ldns_rdf_type type_naptr_wireformat[] = {
+-	LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_STR, LDNS_RDF_TYPE_STR, LDNS_RDF_TYPE_STR, LDNS_RDF_TYPE_DNAME
+-};
+-static const ldns_rdf_type type_kx_wireformat[] = {
+-	LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_DNAME
+-};
+-static const ldns_rdf_type type_cert_wireformat[] = {
+-	 LDNS_RDF_TYPE_CERT_ALG, LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_ALG, LDNS_RDF_TYPE_B64
+-};
+-static const ldns_rdf_type type_a6_wireformat[] = { LDNS_RDF_TYPE_UNKNOWN };
+-static const ldns_rdf_type type_dname_wireformat[] = { LDNS_RDF_TYPE_DNAME };
+-static const ldns_rdf_type type_sink_wireformat[] = { LDNS_RDF_TYPE_INT8,
+-	LDNS_RDF_TYPE_INT8, LDNS_RDF_TYPE_INT8, LDNS_RDF_TYPE_B64
+-};
+-static const ldns_rdf_type type_apl_wireformat[] = {
+-	LDNS_RDF_TYPE_APL
+-};
+-static const ldns_rdf_type type_ds_wireformat[] = {
+-	LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_ALG, LDNS_RDF_TYPE_INT8, LDNS_RDF_TYPE_HEX
+-};
+-static const ldns_rdf_type type_sshfp_wireformat[] = {
+-	LDNS_RDF_TYPE_INT8, LDNS_RDF_TYPE_INT8, LDNS_RDF_TYPE_HEX
+-};
+-static const ldns_rdf_type type_ipseckey_wireformat[] = {
+-	LDNS_RDF_TYPE_IPSECKEY
+-};
+-static const ldns_rdf_type type_rrsig_wireformat[] = {
+-	LDNS_RDF_TYPE_TYPE, LDNS_RDF_TYPE_ALG, LDNS_RDF_TYPE_INT8, LDNS_RDF_TYPE_INT32,
+-	LDNS_RDF_TYPE_TIME, LDNS_RDF_TYPE_TIME, LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_DNAME, LDNS_RDF_TYPE_B64
+-};
+-static const ldns_rdf_type type_nsec_wireformat[] = {
+-	LDNS_RDF_TYPE_DNAME, LDNS_RDF_TYPE_NSEC
+-};
+-static const ldns_rdf_type type_dhcid_wireformat[] = {
+-	LDNS_RDF_TYPE_B64
+-};
+-static const ldns_rdf_type type_talink_wireformat[] = {
+-	LDNS_RDF_TYPE_DNAME, LDNS_RDF_TYPE_DNAME
+-};
+-/*@unused@*/ static const ldns_rdf_type type_openpgpkey_wireformat[] = {
+-	LDNS_RDF_TYPE_B64
+-};
+-/* nsec3 is some vars, followed by same type of data of nsec */
+-static const ldns_rdf_type type_nsec3_wireformat[] = {
+-/*	LDNS_RDF_TYPE_NSEC3_VARS, LDNS_RDF_TYPE_NSEC3_NEXT_OWNER, LDNS_RDF_TYPE_NSEC*/
+-	LDNS_RDF_TYPE_INT8, LDNS_RDF_TYPE_INT8, LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_NSEC3_SALT, LDNS_RDF_TYPE_NSEC3_NEXT_OWNER, LDNS_RDF_TYPE_NSEC
+-};
+-
+-static const ldns_rdf_type type_nsec3param_wireformat[] = {
+-/*	LDNS_RDF_TYPE_NSEC3_PARAMS_VARS*/
+-	LDNS_RDF_TYPE_INT8,
+-	LDNS_RDF_TYPE_INT8,
+-	LDNS_RDF_TYPE_INT16,
+-	LDNS_RDF_TYPE_NSEC3_SALT
+-};
+-
+-static const ldns_rdf_type type_dnskey_wireformat[] = {
+-	LDNS_RDF_TYPE_INT16,
+-	LDNS_RDF_TYPE_INT8,
+-	LDNS_RDF_TYPE_ALG,
+-	LDNS_RDF_TYPE_B64
+-};
+-static const ldns_rdf_type type_tkey_wireformat[] = {
+-	LDNS_RDF_TYPE_DNAME,
+-	LDNS_RDF_TYPE_TIME,
+-	LDNS_RDF_TYPE_TIME,
+-	LDNS_RDF_TYPE_INT16,
+-	LDNS_RDF_TYPE_INT16,
+-	LDNS_RDF_TYPE_INT16_DATA,
+-	LDNS_RDF_TYPE_INT16_DATA,
+-};
+-static const ldns_rdf_type type_tsig_wireformat[] = {
+-	LDNS_RDF_TYPE_DNAME,
+-	LDNS_RDF_TYPE_TSIGTIME,
+-	LDNS_RDF_TYPE_INT16,
+-	LDNS_RDF_TYPE_INT16_DATA,
+-	LDNS_RDF_TYPE_INT16,
+-	LDNS_RDF_TYPE_INT16,
+-	LDNS_RDF_TYPE_INT16_DATA
+-};
+-static const ldns_rdf_type type_tlsa_wireformat[] = {
+-	LDNS_RDF_TYPE_CERTIFICATE_USAGE,
+-	LDNS_RDF_TYPE_SELECTOR,
+-	LDNS_RDF_TYPE_MATCHING_TYPE,
+-	LDNS_RDF_TYPE_HEX
+-};
+-static const ldns_rdf_type type_hip_wireformat[] = {
+-	LDNS_RDF_TYPE_HIP
+-};
+-static const ldns_rdf_type type_nid_wireformat[] = {
+-	LDNS_RDF_TYPE_INT16,
+-	LDNS_RDF_TYPE_ILNP64
+-};
+-static const ldns_rdf_type type_l32_wireformat[] = {
+-	LDNS_RDF_TYPE_INT16,
+-	LDNS_RDF_TYPE_A
+-};
+-static const ldns_rdf_type type_l64_wireformat[] = {
+-	LDNS_RDF_TYPE_INT16,
+-	LDNS_RDF_TYPE_ILNP64
+-};
+-static const ldns_rdf_type type_lp_wireformat[] = {
+-	LDNS_RDF_TYPE_INT16,
+-	LDNS_RDF_TYPE_DNAME
+-};
+-static const ldns_rdf_type type_eui48_wireformat[] = {
+-	LDNS_RDF_TYPE_EUI48
+-};
+-static const ldns_rdf_type type_eui64_wireformat[] = {
+-	LDNS_RDF_TYPE_EUI64
+-};
+-#ifdef RRTYPE_URI
+-static const ldns_rdf_type type_uri_wireformat[] = {
+-	LDNS_RDF_TYPE_INT16,
+-	LDNS_RDF_TYPE_INT16,
+-	LDNS_RDF_TYPE_LONG_STR
+-};
+-#endif
+-static const ldns_rdf_type type_caa_wireformat[] = {
+-	LDNS_RDF_TYPE_INT8,
+-	LDNS_RDF_TYPE_TAG,
+-	LDNS_RDF_TYPE_LONG_STR
+-};
+-/** \endcond */
+-
+-/** \cond */
+-/* All RR's defined in 1035 are well known and can thus
+- * be compressed. See RFC3597. These RR's are:
+- * CNAME HINFO MB MD MF MG MINFO MR MX NULL NS PTR SOA TXT
+- */
+-static ldns_rr_descriptor rdata_field_descriptors[] = {
+-	/* 0 */
+-	{ 0, NULL, 0, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-	/* 1 */
+-	{LDNS_RR_TYPE_A, "A", 1, 1, type_a_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-	/* 2 */
+-	{LDNS_RR_TYPE_NS, "NS", 1, 1, type_ns_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_COMPRESS, 1 },
+-	/* 3 */
+-	{LDNS_RR_TYPE_MD, "MD", 1, 1, type_md_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_COMPRESS, 1 },
+-	/* 4 */
+-	{LDNS_RR_TYPE_MF, "MF", 1, 1, type_mf_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_COMPRESS, 1 },
+-	/* 5 */
+-	{LDNS_RR_TYPE_CNAME, "CNAME", 1, 1, type_cname_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_COMPRESS, 1 },
+-	/* 6 */
+-	{LDNS_RR_TYPE_SOA, "SOA", 7, 7, type_soa_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_COMPRESS, 2 },
+-	/* 7 */
+-	{LDNS_RR_TYPE_MB, "MB", 1, 1, type_mb_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_COMPRESS, 1 },
+-	/* 8 */
+-	{LDNS_RR_TYPE_MG, "MG", 1, 1, type_mg_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_COMPRESS, 1 },
+-	/* 9 */
+-	{LDNS_RR_TYPE_MR, "MR", 1, 1, type_mr_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_COMPRESS, 1 },
+-	/* 10 */
+-	{LDNS_RR_TYPE_NULL, "NULL", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-	/* 11 */
+-	{LDNS_RR_TYPE_WKS, "WKS", 2, 2, type_wks_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-	/* 12 */
+-	{LDNS_RR_TYPE_PTR, "PTR", 1, 1, type_ptr_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_COMPRESS, 1 },
+-	/* 13 */
+-	{LDNS_RR_TYPE_HINFO, "HINFO", 2, 2, type_hinfo_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-	/* 14 */
+-	{LDNS_RR_TYPE_MINFO, "MINFO", 2, 2, type_minfo_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_COMPRESS, 2 },
+-	/* 15 */
+-	{LDNS_RR_TYPE_MX, "MX", 2, 2, type_mx_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_COMPRESS, 1 },
+-	/* 16 */
+-	{LDNS_RR_TYPE_TXT, "TXT", 1, 0, NULL, LDNS_RDF_TYPE_STR, LDNS_RR_NO_COMPRESS, 0 },
+-	/* 17 */
+-	{LDNS_RR_TYPE_RP, "RP", 2, 2, type_rp_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 2 },
+-	/* 18 */
+-	{LDNS_RR_TYPE_AFSDB, "AFSDB", 2, 2, type_afsdb_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 1 },
+-	/* 19 */
+-	{LDNS_RR_TYPE_X25, "X25", 1, 1, type_x25_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-	/* 20 */
+-	{LDNS_RR_TYPE_ISDN, "ISDN", 1, 2, type_isdn_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-	/* 21 */
+-	{LDNS_RR_TYPE_RT, "RT", 2, 2, type_rt_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 1 },
+-	/* 22 */
+-	{LDNS_RR_TYPE_NSAP, "NSAP", 1, 1, type_nsap_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-	/* 23 */
+-	{LDNS_RR_TYPE_NSAP_PTR, "NSAP-PTR", 1, 1, type_nsap_ptr_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-	/* 24 */
+-	{LDNS_RR_TYPE_SIG, "SIG", 9, 9, type_sig_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 1 },
+-	/* 25 */
+-	{LDNS_RR_TYPE_KEY, "KEY", 4, 4, type_key_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-	/* 26 */
+-	{LDNS_RR_TYPE_PX, "PX", 3, 3, type_px_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 2 },
+-	/* 27 */
+-	{LDNS_RR_TYPE_GPOS, "GPOS", 3, 3, type_gpos_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-	/* 28 */
+-	{LDNS_RR_TYPE_AAAA, "AAAA", 1, 1, type_aaaa_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-	/* 29 */
+-	{LDNS_RR_TYPE_LOC, "LOC", 1, 1, type_loc_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-	/* 30 */
+-	{LDNS_RR_TYPE_NXT, "NXT", 2, 2, type_nxt_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 1 },
+-	/* 31 */
+-	{LDNS_RR_TYPE_EID, "EID", 1, 1, type_eid_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-	/* 32 */
+-	{LDNS_RR_TYPE_NIMLOC, "NIMLOC", 1, 1, type_nimloc_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-	/* 33 */
+-	{LDNS_RR_TYPE_SRV, "SRV", 4, 4, type_srv_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 1 },
+-	/* 34 */
+-	{LDNS_RR_TYPE_ATMA, "ATMA", 1, 1, type_atma_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-	/* 35 */
+-	{LDNS_RR_TYPE_NAPTR, "NAPTR", 6, 6, type_naptr_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 1 },
+-	/* 36 */
+-	{LDNS_RR_TYPE_KX, "KX", 2, 2, type_kx_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 1 },
+-	/* 37 */
+-	{LDNS_RR_TYPE_CERT, "CERT", 4, 4, type_cert_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-	/* 38 */
+-	{LDNS_RR_TYPE_A6, "A6", 1, 1, type_a6_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-	/* 39 */
+-	{LDNS_RR_TYPE_DNAME, "DNAME", 1, 1, type_dname_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 1 },
+-	/* 40 */
+-	{LDNS_RR_TYPE_SINK, "SINK", 1, 1, type_sink_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-	/* 41 */
+-	{LDNS_RR_TYPE_OPT, "OPT", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-	/* 42 */
+-	{LDNS_RR_TYPE_APL, "APL", 0, 0, type_apl_wireformat, LDNS_RDF_TYPE_APL, LDNS_RR_NO_COMPRESS, 0 },
+-	/* 43 */
+-	{LDNS_RR_TYPE_DS, "DS", 4, 4, type_ds_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-	/* 44 */
+-	{LDNS_RR_TYPE_SSHFP, "SSHFP", 3, 3, type_sshfp_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-	/* 45 */
+-	{LDNS_RR_TYPE_IPSECKEY, "IPSECKEY", 1, 1, type_ipseckey_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-	/* 46 */
+-	{LDNS_RR_TYPE_RRSIG, "RRSIG", 9, 9, type_rrsig_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 1 },
+-	/* 47 */
+-	{LDNS_RR_TYPE_NSEC, "NSEC", 1, 2, type_nsec_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 1 },
+-	/* 48 */
+-	{LDNS_RR_TYPE_DNSKEY, "DNSKEY", 4, 4, type_dnskey_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-	/* 49 */
+-	{LDNS_RR_TYPE_DHCID, "DHCID", 1, 1, type_dhcid_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-	/* 50 */
+-	{LDNS_RR_TYPE_NSEC3, "NSEC3", 5, 6, type_nsec3_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-	/* 51 */
+-	{LDNS_RR_TYPE_NSEC3PARAM, "NSEC3PARAM", 4, 4, type_nsec3param_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-	/* 52 */
+-	{LDNS_RR_TYPE_TLSA, "TLSA", 4, 4, type_tlsa_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-
+-{LDNS_RR_TYPE_NULL, "TYPE53", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE54", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-
+-	/* 55
+-	 * Hip ends with 0 or more Rendezvous Servers represented as dname's.
+-	 * Hence the LDNS_RDF_TYPE_DNAME _variable field and the _maximum field
+-	 * set to 0.
+-	 */
+-	{LDNS_RR_TYPE_HIP, "HIP", 1, 1, type_hip_wireformat, LDNS_RDF_TYPE_DNAME, LDNS_RR_NO_COMPRESS, 0 },
+-
+-#ifdef RRTYPE_NINFO
+-	/* 56 */
+-	{LDNS_RR_TYPE_NINFO, "NINFO", 1, 0, NULL, LDNS_RDF_TYPE_STR, LDNS_RR_NO_COMPRESS, 0 },
+-#else
+-{LDNS_RR_TYPE_NULL, "TYPE56", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-#endif
+-#ifdef RRTYPE_RKEY
+-	/* 57 */
+-	{LDNS_RR_TYPE_RKEY, "RKEY", 4, 4, type_key_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-#else
+-{LDNS_RR_TYPE_NULL, "TYPE57", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-#endif
+-	/* 58 */
+-	{LDNS_RR_TYPE_TALINK, "TALINK", 2, 2, type_talink_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 2 },
+-
+-	/* 59 */
+-	{LDNS_RR_TYPE_CDS, "CDS", 4, 4, type_ds_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-	/* 60 */
+-	{LDNS_RR_TYPE_CDNSKEY, "CDNSKEY", 4, 4, type_dnskey_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-
+-#ifdef RRTYPE_OPENPGPKEY
+-	/* 61 */
+-	{LDNS_RR_TYPE_OPENPGPKEY, "OPENPGPKEY", 1, 1, type_openpgpkey_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-#else
+-{LDNS_RR_TYPE_NULL, "TYPE61", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-#endif
+-
+-{LDNS_RR_TYPE_NULL, "TYPE62", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE63", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE64", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE65", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE66", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE67", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE68", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE69", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE70", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE71", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE72", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE73", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE74", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE75", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE76", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE77", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE78", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE79", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE80", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE81", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE82", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE83", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE84", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE85", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE86", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE87", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE88", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE89", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE90", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE91", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE92", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE93", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE94", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE95", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE96", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE97", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE98", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-
+-	/* 99 */
+-	{LDNS_RR_TYPE_SPF,  "SPF", 1, 0, NULL, LDNS_RDF_TYPE_STR, LDNS_RR_NO_COMPRESS, 0 },
+-
+-	/* UINFO  [IANA-Reserved] */
+-{LDNS_RR_TYPE_NULL, "TYPE100", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-	/* UID    [IANA-Reserved] */
+-{LDNS_RR_TYPE_NULL, "TYPE101", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-	/* GID    [IANA-Reserved] */
+-{LDNS_RR_TYPE_NULL, "TYPE102", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-	/* UNSPEC [IANA-Reserved] */
+-{LDNS_RR_TYPE_NULL, "TYPE103", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-
+-	/* 104 */
+-	{LDNS_RR_TYPE_NID, "NID", 2, 2, type_nid_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-	/* 105 */
+-	{LDNS_RR_TYPE_L32, "L32", 2, 2, type_l32_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-	/* 106 */
+-	{LDNS_RR_TYPE_L64, "L64", 2, 2, type_l64_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-	/* 107 */
+-	{LDNS_RR_TYPE_LP, "LP", 2, 2, type_lp_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 1 },
+-	/* 108 */
+-	{LDNS_RR_TYPE_EUI48, "EUI48", 1, 1, type_eui48_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-	/* 109 */
+-	{LDNS_RR_TYPE_EUI64, "EUI64", 1, 1, type_eui64_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-
+-{LDNS_RR_TYPE_NULL, "TYPE110", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE111", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE112", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE113", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE114", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE115", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE116", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE117", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE118", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE119", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE120", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE121", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE122", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE123", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE124", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE125", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE126", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE127", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE128", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE129", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE130", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE131", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE132", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE133", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE134", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE135", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE136", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE137", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE138", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE139", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE140", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE141", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE142", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE143", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE144", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE145", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE146", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE147", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE148", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE149", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE150", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE151", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE152", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE153", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE154", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE155", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE156", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE157", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE158", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE159", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE160", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE161", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE162", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE163", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE164", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE165", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE166", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE167", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE168", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE169", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE170", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE171", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE172", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE173", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE174", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE175", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE176", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE177", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE178", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE179", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE180", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE181", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE182", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE183", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE184", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE185", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE186", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE187", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE188", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE189", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE190", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE191", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE192", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE193", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE194", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE195", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE196", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE197", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE198", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE199", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE200", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE201", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE202", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE203", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE204", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE205", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE206", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE207", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE208", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE209", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE210", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE211", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE212", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE213", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE214", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE215", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE216", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE217", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE218", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE219", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE220", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE221", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE222", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE223", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE224", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE225", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE226", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE227", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE228", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE229", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE230", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE231", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE232", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE233", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE234", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE235", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE236", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE237", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE238", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE239", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE240", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE241", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE242", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE243", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE244", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE245", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE246", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE247", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-{LDNS_RR_TYPE_NULL, "TYPE248", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-
+-	/* LDNS_RDF_TYPE_INT16_DATA takes two fields (length and data) as one.
+-	 * So, unlike RFC 2930 spec, we have 7 min/max rdf's i.s.o. 8/9.
+-	 */
+-	/* 249 */
+-	{LDNS_RR_TYPE_TKEY, "TKEY", 7, 7, type_tkey_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 1 },
+-	/* LDNS_RDF_TYPE_INT16_DATA takes two fields (length and data) as one.
+-	 * So, unlike RFC 2930 spec, we have 7 min/max rdf's i.s.o. 8/9.
+-	 */
+-	/* 250 */
+-	{LDNS_RR_TYPE_TSIG, "TSIG", 7, 7, type_tsig_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 1 },
+-
+-	/* IXFR: A request for a transfer of an incremental zone transfer */
+-{LDNS_RR_TYPE_NULL, "TYPE251", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-	/* AXFR: A request for a transfer of an entire zone */
+-{LDNS_RR_TYPE_NULL, "TYPE252", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-	/* MAILB: A request for mailbox-related records (MB, MG or MR) */
+-{LDNS_RR_TYPE_NULL, "TYPE253", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-	/* MAILA: A request for mail agent RRs (Obsolete - see MX) */
+-{LDNS_RR_TYPE_NULL, "TYPE254", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-	/* ANY: A request for all (available) records */
+-{LDNS_RR_TYPE_NULL, "TYPE255", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-
+-#ifdef RRTYPE_URI
+-	/* 256 */
+-	{LDNS_RR_TYPE_URI, "URI", 3, 3, type_uri_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-#else
+-{LDNS_RR_TYPE_NULL, "TYPE256", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-#endif
+-	/* 257 */
+-	{LDNS_RR_TYPE_CAA, "CAA", 3, 3, type_caa_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-
+-/* split in array, no longer contiguous */
+-
+-#ifdef RRTYPE_TA
+-	/* 32768 */
+-	{LDNS_RR_TYPE_TA, "TA", 4, 4, type_ds_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-#else
+-{LDNS_RR_TYPE_NULL, "TYPE32768", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+-#endif
+-	/* 32769 */
+-	{LDNS_RR_TYPE_DLV, "DLV", 4, 4, type_ds_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }
+-};
+-/** \endcond */
+-
+-/**
+- * \def LDNS_RDATA_FIELD_DESCRIPTORS_COUNT
+- * computes the number of rdata fields
+- */
+-#define LDNS_RDATA_FIELD_DESCRIPTORS_COUNT \
+-	(sizeof(rdata_field_descriptors)/sizeof(rdata_field_descriptors[0]))
+-
+-
+-/*---------------------------------------------------------------------------*
+- * The functions below return an bitmap RDF with the space required to set
+- * or unset all known RR types. Arguably these functions are better situated
+- * in rdata.c, however for the space calculation it is necesarry to walk
+- * through rdata_field_descriptors which is not easily possible from anywhere
+- * other than rr.c where it is declared static.
+- *
+- * Alternatively rr.c could have provided an iterator for rr_type or 
+- * rdf_descriptors, but this seemed overkill for internal use only.
+- */
+-static ldns_rr_descriptor* rdata_field_descriptors_end =
+-	&rdata_field_descriptors[LDNS_RDATA_FIELD_DESCRIPTORS_COUNT];
+-
+-/* From RFC3845:
+- *
+- * 2.1.2.  The List of Type Bit Map(s) Field
+- * 
+- *    The RR type space is split into 256 window blocks, each representing
+- *    the low-order 8 bits of the 16-bit RR type space.  Each block that
+- *    has at least one active RR type is encoded using a single octet
+- *    window number (from 0 to 255), a single octet bitmap length (from 1
+- *    to 32) indicating the number of octets used for the window block's
+- *    bitmap, and up to 32 octets (256 bits) of bitmap.
+- * 
+- *    Window blocks are present in the NSEC RR RDATA in increasing
+- *    numerical order.
+- * 
+- *    "|" denotes concatenation
+- * 
+- *    Type Bit Map(s) Field = ( Window Block # | Bitmap Length | Bitmap ) +
+- * 
+- *    <cut>
+- * 
+- *    Blocks with no types present MUST NOT be included.  Trailing zero
+- *    octets in the bitmap MUST be omitted.  The length of each block's
+- *    bitmap is determined by the type code with the largest numerical
+- *    value within that block, among the set of RR types present at the
+- *    NSEC RR's owner name.  Trailing zero octets not specified MUST be
+- *    interpreted as zero octets.
+- */
+-static ldns_status
+-ldns_rdf_bitmap_known_rr_types_set(ldns_rdf** rdf, int value)
+-{
+-	uint8_t  window;		/*  most significant octet of type */
+-	uint8_t  subtype;		/* least significant octet of type */
+-	uint16_t windows[256]		/* Max subtype per window */
+-#ifndef S_SPLINT_S
+-	                      = { 0 }
+-#endif
+-	                             ;
+-	ldns_rr_descriptor* d;	/* used to traverse rdata_field_descriptors */
+-	size_t i;		/* used to traverse windows array */
+-
+-	size_t sz;			/* size needed for type bitmap rdf */
+-	uint8_t* data = NULL;		/* rdf data */
+-	uint8_t* dptr;			/* used to itraverse rdf data */
+-
+-	assert(rdf != NULL);
+-
+-	/* Which windows need to be in the bitmap rdf?
+-	 */
+-	for (d=rdata_field_descriptors; d < rdata_field_descriptors_end; d++) {
+-		window  = d->_type >> 8;
+-		subtype = d->_type & 0xff;
+-		if (windows[window] < subtype) {
+-			windows[window] = subtype;
+-		}
+-	}
+-
+-	/* How much space do we need in the rdf for those windows?
+-	 */
+-	sz = 0;
+-	for (i = 0; i < 256; i++) {
+-		if (windows[i]) {
+-			sz += windows[i] / 8 + 3;
+-		}
+-	}
+-	if (sz > 0) {
+-		/* Format rdf data according RFC3845 Section 2.1.2 (see above)
+-		 */
+-		dptr = data = LDNS_XMALLOC(uint8_t, sz);
+-		memset(data, value, sz);
+-		if (!data) {
+-			return LDNS_STATUS_MEM_ERR;
+-		}
+-		for (i = 0; i < 256; i++) {
+-			if (windows[i]) {
+-				*dptr++ = (uint8_t)i;
+-				*dptr++ = (uint8_t)(windows[i] / 8 + 1);
+-				dptr += dptr[-1];
+-			}
+-		}
+-	}
+-	/* Allocate and return rdf structure for the data
+-	 */
+-	*rdf = ldns_rdf_new(LDNS_RDF_TYPE_BITMAP, sz, data);
+-	if (!*rdf) {
+-		LDNS_FREE(data);
+-		return LDNS_STATUS_MEM_ERR;
+-	}
+-	return LDNS_STATUS_OK;
+-}
+-
+-ldns_status
+-ldns_rdf_bitmap_known_rr_types_space(ldns_rdf** rdf)
+-{
+-	return ldns_rdf_bitmap_known_rr_types_set(rdf, 0);
+-}
+-
+-ldns_status
+-ldns_rdf_bitmap_known_rr_types(ldns_rdf** rdf)
+-{
+-	return ldns_rdf_bitmap_known_rr_types_set(rdf, 255);
+-}
+-/* End of RDF bitmap functions
+- *---------------------------------------------------------------------------*/
+-
+-
+-const ldns_rr_descriptor *
+-ldns_rr_descript(uint16_t type)
+-{
+-	size_t i;
+-	if (type < LDNS_RDATA_FIELD_DESCRIPTORS_COMMON) {
+-		return &rdata_field_descriptors[type];
+-	} else {
+-		/* because not all array index equals type code */
+-		for (i = LDNS_RDATA_FIELD_DESCRIPTORS_COMMON;
+-		     i < LDNS_RDATA_FIELD_DESCRIPTORS_COUNT;
+-		     i++) {
+-		        if (rdata_field_descriptors[i]._type == type) {
+-		     		return &rdata_field_descriptors[i];
+-			}
+-		}
+-                return &rdata_field_descriptors[0];
+-	}
+-}
+-
+-size_t
+-ldns_rr_descriptor_minimum(const ldns_rr_descriptor *descriptor)
+-{
+-	if (descriptor) {
+-		return descriptor->_minimum;
+-	} else {
+-		return 0;
+-	}
+-}
+-
+-size_t
+-ldns_rr_descriptor_maximum(const ldns_rr_descriptor *descriptor)
+-{
+-	if (descriptor) {
+-		if (descriptor->_variable != LDNS_RDF_TYPE_NONE) {
+-			/* Should really be SIZE_MAX... bad FreeBSD.  */
+-			return UINT_MAX;
+-		} else {
+-			return descriptor->_maximum;
+-		}
+-	} else {
+-		return 0;
+-	}
+-}
+-
+-ldns_rdf_type
+-ldns_rr_descriptor_field_type(const ldns_rr_descriptor *descriptor,
+-                              size_t index)
+-{
+-	assert(descriptor != NULL);
+-	assert(index < descriptor->_maximum
+-	       || descriptor->_variable != LDNS_RDF_TYPE_NONE);
+-	if (index < descriptor->_maximum) {
+-		return descriptor->_wireformat[index];
+-	} else {
+-		return descriptor->_variable;
+-	}
+-}
+-
+-ldns_rr_type
+-ldns_get_rr_type_by_name(const char *name)
+-{
+-	unsigned int i;
+-	const char *desc_name;
+-	const ldns_rr_descriptor *desc;
+-
+-	/* TYPEXX representation */
+-	if (strlen(name) > 4 && strncasecmp(name, "TYPE", 4) == 0) {
+-		return atoi(name + 4);
+-	}
+-
+-	/* Normal types */
+-	for (i = 0; i < (unsigned int) LDNS_RDATA_FIELD_DESCRIPTORS_COUNT; i++) {
+-		desc = &rdata_field_descriptors[i];
+-		desc_name = desc->_name;
+-		if(desc_name &&
+-		   strlen(name) == strlen(desc_name) &&
+-		   strncasecmp(name, desc_name, strlen(desc_name)) == 0) {
+-			/* because not all array index equals type code */
+-			return desc->_type;
+-		}
+-	}
+-
+-	/* special cases for query types */
+-	if (strlen(name) == 4 && strncasecmp(name, "IXFR", 4) == 0) {
+-		return 251;
+-	} else if (strlen(name) == 4 && strncasecmp(name, "AXFR", 4) == 0) {
+-		return 252;
+-	} else if (strlen(name) == 5 && strncasecmp(name, "MAILB", 5) == 0) {
+-		return 253;
+-	} else if (strlen(name) == 5 && strncasecmp(name, "MAILA", 5) == 0) {
+-		return 254;
+-	} else if (strlen(name) == 3 && strncasecmp(name, "ANY", 3) == 0) {
+-		return 255;
+-	}
+-
+-	return 0;
+-}
+-
+-ldns_rr_class
+-ldns_get_rr_class_by_name(const char *name)
+-{
+-	ldns_lookup_table *lt;
+-
+-	/* CLASSXX representation */
+-	if (strlen(name) > 5 && strncasecmp(name, "CLASS", 5) == 0) {
+-		return atoi(name + 5);
+-	}
+-
+-	/* Normal types */
+-	lt = ldns_lookup_by_name(ldns_rr_classes, name);
+-
+-	if (lt) {
+-		return lt->id;
+-	}
+-	return 0;
+-}
+-
+-
+-ldns_rr_type
+-ldns_rdf2rr_type(const ldns_rdf *rd)
+-{
+-        ldns_rr_type r;
+-
+-        if (!rd) {
+-                return 0;
+-        }
+-
+-        if (ldns_rdf_get_type(rd) != LDNS_RDF_TYPE_TYPE) {
+-                return 0;
+-        }
+-
+-        r = (ldns_rr_type) ldns_rdf2native_int16(rd);
+-        return r;
+-}
+-
+-ldns_rr_type
+-ldns_rr_list_type(const ldns_rr_list *rr_list)
+-{
+-	if (rr_list && ldns_rr_list_rr_count(rr_list) > 0) {
+-		return ldns_rr_get_type(ldns_rr_list_rr(rr_list, 0));
+-	} else {
+-		return 0;
+-	}
+-}
+-
+-ldns_rdf *
+-ldns_rr_list_owner(const ldns_rr_list *rr_list)
+-{
+-	if (rr_list && ldns_rr_list_rr_count(rr_list) > 0) {
+-		return ldns_rr_owner(ldns_rr_list_rr(rr_list, 0));
+-	} else {
+-		return NULL;
+-	}
+-}
+diff --git a/src/ldns/rr_functions.c b/src/ldns/rr_functions.c
+deleted file mode 100644
+index b03751b..0000000
+--- a/src/ldns/rr_functions.c
++++ /dev/null
+@@ -1,419 +0,0 @@
+-/*
+- * rr_function.c
+- *
+- * function that operate on specific rr types
+- *
+- * (c) NLnet Labs, 2004-2006
+- * See the file LICENSE for the license
+- */
+-
+-/*
+- * These come strait from perldoc Net::DNS::RR::xxx
+- * first the read variant, then the write. This is
+- * not complete.
+- */
+-
+-#include <ldns/config.h>
+-
+-#include <ldns/ldns.h>
+-
+-#include <limits.h>
+-#include <strings.h>
+-
+-/**
+- * return a specific rdf
+- * \param[in] type type of RR
+- * \param[in] rr   the rr itself
+- * \param[in] pos  at which postion to get it
+- * \return the rdf sought
+- */
+-static ldns_rdf *
+-ldns_rr_function(ldns_rr_type type, const ldns_rr *rr, size_t pos)
+-{
+-        if (!rr || ldns_rr_get_type(rr) != type) {
+-                return NULL;
+-        }
+-        return ldns_rr_rdf(rr, pos);
+-}
+-
+-/**
+- * set a specific rdf
+- * \param[in] type type of RR
+- * \param[in] rr   the rr itself
+- * \param[in] rdf  the rdf to set
+- * \param[in] pos  at which postion to set it
+- * \return true or false
+- */
+-static bool
+-ldns_rr_set_function(ldns_rr_type type, ldns_rr *rr, ldns_rdf *rdf, size_t pos)
+-{
+-        ldns_rdf *pop;
+-        if (!rr || ldns_rr_get_type(rr) != type) {
+-                return false;
+-        }
+-        pop = ldns_rr_set_rdf(rr, rdf, pos);
+- 	ldns_rdf_deep_free(pop);
+-        return true;
+-}
+-
+-/* A/AAAA records */
+-ldns_rdf *
+-ldns_rr_a_address(const ldns_rr *r)
+-{
+-	/* 2 types to check, cannot use the macro */
+-	if (!r || (ldns_rr_get_type(r) != LDNS_RR_TYPE_A &&
+-			ldns_rr_get_type(r) != LDNS_RR_TYPE_AAAA)) {
+-		return NULL;
+-	}
+-	return ldns_rr_rdf(r, 0);
+-}
+-
+-bool
+-ldns_rr_a_set_address(ldns_rr *r, ldns_rdf *f)
+-{
+-	/* 2 types to check, cannot use the macro... */
+-	ldns_rdf *pop;
+-	if (!r || (ldns_rr_get_type(r) != LDNS_RR_TYPE_A &&
+-			ldns_rr_get_type(r) != LDNS_RR_TYPE_AAAA)) {
+-		return false;
+-	}
+-	pop = ldns_rr_set_rdf(r, f, 0);
+-	if (pop) {
+-		LDNS_FREE(pop);
+-		return true;
+-	} else {
+-		return false;
+-	}
+-}
+-
+-/* NS record */
+-ldns_rdf *
+-ldns_rr_ns_nsdname(const ldns_rr *r)
+-{
+-	return ldns_rr_function(LDNS_RR_TYPE_NS, r, 0);
+-}
+-
+-/* MX record */
+-ldns_rdf *
+-ldns_rr_mx_preference(const ldns_rr *r)
+-{
+-	return ldns_rr_function(LDNS_RR_TYPE_MX, r, 0);
+-}
+-
+-ldns_rdf *
+-ldns_rr_mx_exchange(const ldns_rr *r)
+-{
+-	return ldns_rr_function(LDNS_RR_TYPE_MX, r, 1);
+-}
+-
+-/* RRSIG record */
+-ldns_rdf *
+-ldns_rr_rrsig_typecovered(const ldns_rr *r)
+-{
+-	return ldns_rr_function(LDNS_RR_TYPE_RRSIG, r, 0);
+-}
+-
+-bool
+-ldns_rr_rrsig_set_typecovered(ldns_rr *r, ldns_rdf *f)
+-{
+-	return ldns_rr_set_function(LDNS_RR_TYPE_RRSIG, r, f, 0);
+-}
+-
+-ldns_rdf *
+-ldns_rr_rrsig_algorithm(const ldns_rr *r)
+-{
+-	return ldns_rr_function(LDNS_RR_TYPE_RRSIG, r, 1);
+-}
+-
+-bool
+-ldns_rr_rrsig_set_algorithm(ldns_rr *r, ldns_rdf *f)
+-{
+-	return ldns_rr_set_function(LDNS_RR_TYPE_RRSIG, r, f, 1);
+-}
+-
+-ldns_rdf *
+-ldns_rr_rrsig_labels(const ldns_rr *r)
+-{
+-	return ldns_rr_function(LDNS_RR_TYPE_RRSIG, r, 2);
+-}
+-
+-bool
+-ldns_rr_rrsig_set_labels(ldns_rr *r, ldns_rdf *f)
+-{
+-	return ldns_rr_set_function(LDNS_RR_TYPE_RRSIG, r, f, 2);
+-}
+-
+-ldns_rdf *
+-ldns_rr_rrsig_origttl(const ldns_rr *r)
+-{
+-	return ldns_rr_function(LDNS_RR_TYPE_RRSIG, r, 3);
+-}
+-
+-bool
+-ldns_rr_rrsig_set_origttl(ldns_rr *r, ldns_rdf *f)
+-{
+-	return ldns_rr_set_function(LDNS_RR_TYPE_RRSIG, r, f, 3);
+-}
+-
+-ldns_rdf *
+-ldns_rr_rrsig_expiration(const ldns_rr *r)
+-{
+-	return ldns_rr_function(LDNS_RR_TYPE_RRSIG, r, 4);
+-}
+-
+-bool
+-ldns_rr_rrsig_set_expiration(ldns_rr *r, ldns_rdf *f)
+-{
+-	return ldns_rr_set_function(LDNS_RR_TYPE_RRSIG, r, f, 4);
+-}
+-
+-ldns_rdf *
+-ldns_rr_rrsig_inception(const ldns_rr *r)
+-{
+-	return ldns_rr_function(LDNS_RR_TYPE_RRSIG, r, 5);
+-}
+-
+-bool
+-ldns_rr_rrsig_set_inception(ldns_rr *r, ldns_rdf *f)
+-{
+-	return ldns_rr_set_function(LDNS_RR_TYPE_RRSIG, r, f, 5);
+-}
+-
+-ldns_rdf *
+-ldns_rr_rrsig_keytag(const ldns_rr *r)
+-{
+-	return ldns_rr_function(LDNS_RR_TYPE_RRSIG, r, 6);
+-}
+-
+-bool
+-ldns_rr_rrsig_set_keytag(ldns_rr *r, ldns_rdf *f)
+-{
+-	return ldns_rr_set_function(LDNS_RR_TYPE_RRSIG, r, f, 6);
+-}
+-
+-ldns_rdf *
+-ldns_rr_rrsig_signame(const ldns_rr *r)
+-{
+-	return ldns_rr_function(LDNS_RR_TYPE_RRSIG, r, 7);
+-}
+-
+-bool
+-ldns_rr_rrsig_set_signame(ldns_rr *r, ldns_rdf *f)
+-{
+-	return ldns_rr_set_function(LDNS_RR_TYPE_RRSIG, r, f, 7);
+-}
+-
+-ldns_rdf *
+-ldns_rr_rrsig_sig(const ldns_rr *r)
+-{
+-	return ldns_rr_function(LDNS_RR_TYPE_RRSIG, r, 8);
+-}
+-
+-bool
+-ldns_rr_rrsig_set_sig(ldns_rr *r, ldns_rdf *f)
+-{
+-	return ldns_rr_set_function(LDNS_RR_TYPE_RRSIG, r, f, 8);
+-}
+-
+-/* DNSKEY record */
+-ldns_rdf *
+-ldns_rr_dnskey_flags(const ldns_rr *r)
+-{
+-	return ldns_rr_function(LDNS_RR_TYPE_DNSKEY, r, 0);
+-}
+-
+-bool
+-ldns_rr_dnskey_set_flags(ldns_rr *r, ldns_rdf *f)
+-{
+-	return ldns_rr_set_function(LDNS_RR_TYPE_DNSKEY, r, f, 0);
+-}
+-
+-ldns_rdf *
+-ldns_rr_dnskey_protocol(const ldns_rr *r)
+-{
+-	return ldns_rr_function(LDNS_RR_TYPE_DNSKEY, r, 1);
+-}
+-
+-bool
+-ldns_rr_dnskey_set_protocol(ldns_rr *r, ldns_rdf *f)
+-{
+-	return ldns_rr_set_function(LDNS_RR_TYPE_DNSKEY, r, f, 1);
+-}
+-
+-ldns_rdf *
+-ldns_rr_dnskey_algorithm(const ldns_rr *r)
+-{
+-	return ldns_rr_function(LDNS_RR_TYPE_DNSKEY, r, 2);
+-}
+-
+-bool
+-ldns_rr_dnskey_set_algorithm(ldns_rr *r, ldns_rdf *f)
+-{
+-	return ldns_rr_set_function(LDNS_RR_TYPE_DNSKEY, r, f, 2);
+-}
+-
+-ldns_rdf *
+-ldns_rr_dnskey_key(const ldns_rr *r)
+-{
+-	return ldns_rr_function(LDNS_RR_TYPE_DNSKEY, r, 3);
+-}
+-
+-bool
+-ldns_rr_dnskey_set_key(ldns_rr *r, ldns_rdf *f)
+-{
+-	return ldns_rr_set_function(LDNS_RR_TYPE_DNSKEY, r, f, 3);
+-}
+-
+-size_t
+-ldns_rr_dnskey_key_size_raw(const unsigned char* keydata,
+-                            const size_t len,
+-                            const ldns_algorithm alg)
+-{
+-	/* for DSA keys */
+-	uint8_t t;
+-	
+-	/* for RSA keys */
+-	uint16_t exp;
+-	uint16_t int16;
+-	
+-	switch ((ldns_signing_algorithm)alg) {
+-	case LDNS_SIGN_DSA:
+-	case LDNS_SIGN_DSA_NSEC3:
+-		if (len > 0) {
+-			t = keydata[0];
+-			return (64 + t*8)*8;
+-		} else {
+-			return 0;
+-		}
+-		break;
+-	case LDNS_SIGN_RSAMD5:
+-	case LDNS_SIGN_RSASHA1:
+-	case LDNS_SIGN_RSASHA1_NSEC3:
+-#ifdef USE_SHA2
+-	case LDNS_SIGN_RSASHA256:
+-	case LDNS_SIGN_RSASHA512:
+-#endif
+-		if (len > 0) {
+-			if (keydata[0] == 0) {
+-				/* big exponent */
+-				if (len > 3) {
+-					memmove(&int16, keydata + 1, 2);
+-					exp = ntohs(int16);
+-					return (len - exp - 3)*8;
+-				} else {
+-					return 0;
+-				}
+-			} else {
+-				exp = keydata[0];
+-				return (len-exp-1)*8;
+-			}
+-		} else {
+-			return 0;
+-		}
+-		break;
+-#ifdef USE_GOST
+-	case LDNS_SIGN_ECC_GOST:
+-		return 512;
+-#endif
+-#ifdef USE_ECDSA
+-        case LDNS_SIGN_ECDSAP256SHA256:
+-                return 256;
+-        case LDNS_SIGN_ECDSAP384SHA384:
+-                return 384;
+-#endif
+-	case LDNS_SIGN_HMACMD5:
+-		return len;
+-	default:
+-		return 0;
+-	}
+-}
+-
+-size_t 
+-ldns_rr_dnskey_key_size(const ldns_rr *key) 
+-{
+-	if (!key || !ldns_rr_dnskey_key(key) 
+-			|| !ldns_rr_dnskey_algorithm(key)) {
+-		return 0;
+-	}
+-	return ldns_rr_dnskey_key_size_raw((unsigned char*)ldns_rdf_data(ldns_rr_dnskey_key(key)),
+-	                                   ldns_rdf_size(ldns_rr_dnskey_key(key)),
+-	                                   ldns_rdf2native_int8(ldns_rr_dnskey_algorithm(key))
+-	                                  );
+-}
+-
+-uint32_t ldns_soa_serial_identity(uint32_t ATTR_UNUSED(unused), void *data)
+-{
+-	return (uint32_t) (intptr_t) data;
+-}
+-
+-uint32_t ldns_soa_serial_increment(uint32_t s, void *ATTR_UNUSED(unused))
+-{
+-	return ldns_soa_serial_increment_by(s, (void *)1);
+-}
+-
+-uint32_t ldns_soa_serial_increment_by(uint32_t s, void *data)
+-{
+-	return s + (intptr_t) data;
+-}
+-
+-uint32_t ldns_soa_serial_datecounter(uint32_t s, void *data)
+-{
+-	struct tm tm;
+-	char s_str[11];
+-	int32_t new_s;
+-	time_t t = data ? (time_t) (intptr_t) data : ldns_time(NULL);
+-
+-	(void) strftime(s_str, 11, "%Y%m%d00", localtime_r(&t, &tm));
+-	new_s = (int32_t) atoi(s_str);
+-	return new_s - ((int32_t) s) <= 0 ? s+1 : ((uint32_t) new_s);
+-}
+-
+-uint32_t ldns_soa_serial_unixtime(uint32_t s, void *data)
+-{
+-	int32_t new_s = data ? (int32_t) (intptr_t) data 
+-			     : (int32_t) ldns_time(NULL);
+-	return new_s - ((int32_t) s) <= 0 ? s+1 : ((uint32_t) new_s);
+-}
+-
+-void
+-ldns_rr_soa_increment(ldns_rr *soa)
+-{
+-	ldns_rr_soa_increment_func_data(soa, ldns_soa_serial_increment, NULL);
+-}
+-
+-void
+-ldns_rr_soa_increment_func(ldns_rr *soa, ldns_soa_serial_increment_func_t f)
+-{
+-	ldns_rr_soa_increment_func_data(soa, f, NULL);
+-}
+-
+-void
+-ldns_rr_soa_increment_func_data(ldns_rr *soa, 
+-		ldns_soa_serial_increment_func_t f, void *data)
+-{
+-	ldns_rdf *prev_soa_serial_rdf;
+-	if ( !soa || !f || ldns_rr_get_type(soa) != LDNS_RR_TYPE_SOA 
+-			|| !ldns_rr_rdf(soa, 2)) {
+-		return;
+-	}
+-	prev_soa_serial_rdf = ldns_rr_set_rdf(
+-		  soa
+-		, ldns_native2rdf_int32(
+-			  LDNS_RDF_TYPE_INT32
+-			, (*f)( ldns_rdf2native_int32(
+-					ldns_rr_rdf(soa, 2))
+-			      , data
+-			)
+-		)
+-		, 2
+-	);
+-	LDNS_FREE(prev_soa_serial_rdf);
+-}
+-
+-void
+-ldns_rr_soa_increment_func_int(ldns_rr *soa, 
+-		ldns_soa_serial_increment_func_t f, int data)
+-{
+-	ldns_rr_soa_increment_func_data(soa, f, (void *) (intptr_t) data);
+-}
+-
+diff --git a/src/ldns/sha1.c b/src/ldns/sha1.c
+deleted file mode 100644
+index 18a4dd2..0000000
+--- a/src/ldns/sha1.c
++++ /dev/null
+@@ -1,177 +0,0 @@
+-/*
+- * modified for ldns by Jelte Jansen, original taken from OpenBSD:
+- * 
+- * SHA-1 in C
+- * By Steve Reid <steve at edmweb.com>
+- * 100% Public Domain
+- * 
+- * Test Vectors (from FIPS PUB 180-1)
+- * "abc"
+- *   A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
+- * "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
+- *   84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
+- * A million repetitions of "a"
+- *   34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
+-*/
+-
+-/* #define LITTLE_ENDIAN * This should be #define'd already, if true. */
+-
+-#include <ldns/config.h>
+-#include <ldns/ldns.h>
+-#include <strings.h>
+-
+-#define SHA1HANDSOFF 1 /* Copies data before messing with it. */
+-#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
+-
+-/* blk0() and blk() perform the initial expand. */
+-/* I got the idea of expanding during the round function from SSLeay */
+-#if BYTE_ORDER == LITTLE_ENDIAN
+-#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
+-    |(rol(block->l[i],8)&0x00FF00FF))
+-#else
+-#define blk0(i) block->l[i]
+-#endif
+-#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
+-    ^block->l[(i+2)&15]^block->l[i&15],1))
+-
+-/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
+-#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
+-#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
+-#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
+-#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
+-#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
+-
+-/* Hash a single 512-bit block. This is the core of the algorithm. */
+-
+-void
+-ldns_sha1_transform(uint32_t state[5], const unsigned char buffer[LDNS_SHA1_BLOCK_LENGTH])
+-{
+-    uint32_t a, b, c, d, e;
+-    typedef union {
+-        unsigned char c[64];
+-        unsigned int l[16];
+-    } CHAR64LONG16;
+-    CHAR64LONG16* block;
+-#ifdef SHA1HANDSOFF
+-    unsigned char workspace[LDNS_SHA1_BLOCK_LENGTH];
+-
+-    block = (CHAR64LONG16 *)workspace;
+-    memmove(block, buffer, LDNS_SHA1_BLOCK_LENGTH);
+-#else
+-    block = (CHAR64LONG16 *)buffer;
+-#endif
+-    /* Copy context->state[] to working vars */
+-    a = state[0];
+-    b = state[1];
+-    c = state[2];
+-    d = state[3];
+-    e = state[4];
+-
+-    /* 4 rounds of 20 operations each. Loop unrolled. */
+-    R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
+-    R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
+-    R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
+-    R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
+-    R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
+-    R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
+-    R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
+-    R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
+-    R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
+-    R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
+-    R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
+-    R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
+-    R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
+-    R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
+-    R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
+-    R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
+-    R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
+-    R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
+-    R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
+-    R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
+-
+-    /* Add the working vars back into context.state[] */
+-    state[0] += a;
+-    state[1] += b;
+-    state[2] += c;
+-    state[3] += d;
+-    state[4] += e;
+-    /* Wipe variables */
+-    a = b = c = d = e = 0;
+-}
+-
+-
+-/* SHA1Init - Initialize new context */
+-
+-void
+-ldns_sha1_init(ldns_sha1_ctx *context)
+-{
+-    /* SHA1 initialization constants */
+-    context->count = 0;
+-    context->state[0] = 0x67452301;
+-    context->state[1] = 0xEFCDAB89;
+-    context->state[2] = 0x98BADCFE;
+-    context->state[3] = 0x10325476;
+-    context->state[4] = 0xC3D2E1F0;
+-}
+-
+-
+-/* Run your data through this. */
+-
+-void
+-ldns_sha1_update(ldns_sha1_ctx *context, const unsigned char *data, unsigned int len)
+-{
+-    unsigned int i;
+-    unsigned int j;
+-
+-    j = (unsigned)(uint32_t)((context->count >> 3) & 63);
+-    context->count += (len << 3);
+-    if ((j + len) > 63) {
+-        memmove(&context->buffer[j], data, (i = 64 - j));
+-        ldns_sha1_transform(context->state, context->buffer);
+-        for ( ; i + 63 < len; i += 64) {
+-            ldns_sha1_transform(context->state, &data[i]);
+-        }
+-        j = 0;
+-    }
+-    else i = 0;
+-    memmove(&context->buffer[j], &data[i], len - i);
+-}
+-
+-
+-/* Add padding and return the message digest. */
+-
+-void
+-ldns_sha1_final(unsigned char digest[LDNS_SHA1_DIGEST_LENGTH], ldns_sha1_ctx *context)
+-{
+-    unsigned int i;
+-    unsigned char finalcount[8];
+-
+-    for (i = 0; i < 8; i++) {
+-        finalcount[i] = (unsigned char)((context->count >>
+-            ((7 - (i & 7)) * 8)) & 255);  /* Endian independent */
+-    }
+-    ldns_sha1_update(context, (unsigned char *)"\200", 1);
+-    while ((context->count & 504) != 448) {
+-        ldns_sha1_update(context, (unsigned char *)"\0", 1);
+-    }
+-    ldns_sha1_update(context, finalcount, 8);  /* Should cause a SHA1Transform() */
+-
+-    if (digest != NULL)
+-        for (i = 0; i < LDNS_SHA1_DIGEST_LENGTH; i++) {
+-            digest[i] = (unsigned char)((context->state[i >> 2] >>
+-                ((3 - (i & 3)) * 8)) & 255);
+-      }
+-#ifdef SHA1HANDSOFF  /* make SHA1Transform overwrite its own static vars */
+-    ldns_sha1_transform(context->state, context->buffer);
+-#endif
+-}
+-
+-unsigned char *
+-ldns_sha1(unsigned char *data, unsigned int data_len, unsigned char *digest)
+-{
+-    ldns_sha1_ctx ctx;
+-    ldns_sha1_init(&ctx);
+-    ldns_sha1_update(&ctx, data, data_len);
+-    ldns_sha1_final(digest, &ctx);
+-    return digest;
+-}
+diff --git a/src/ldns/sha2.c b/src/ldns/sha2.c
+deleted file mode 100644
+index 9a27122..0000000
+--- a/src/ldns/sha2.c
++++ /dev/null
+@@ -1,991 +0,0 @@
+-/*
+- * FILE:	sha2.c
+- * AUTHOR:	Aaron D. Gifford - http://www.aarongifford.com/
+- * 
+- * Copyright (c) 2000-2001, Aaron D. Gifford
+- * All rights reserved.
+- *
+- * Modified by Jelte Jansen to fit in ldns, and not clash with any
+- * system-defined SHA code.
+- * Changes:
+- * - Renamed (external) functions and constants to fit ldns style
+- * - Removed _End and _Data functions
+- * - Added ldns_shaX(data, len, digest) convenience functions
+- * - Removed prototypes of _Transform functions and made those static
+- * 
+- * 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.
+- * 3. Neither the name of the copyright holder nor the names of contributors
+- *    may be used to endorse or promote products derived from this software
+- *    without specific prior written permission.
+- * 
+- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``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 OR CONTRIBUTOR(S) 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.
+- *
+- * $Id: sha2.c,v 1.1 2001/11/08 00:01:51 adg Exp adg $
+- */
+-
+-#include <ldns/config.h>
+-#include <string.h>	/* memcpy()/memset() or bcopy()/bzero() */
+-#include <assert.h>	/* assert() */
+-#include <ldns/sha2.h>
+-
+-/*
+- * ASSERT NOTE:
+- * Some sanity checking code is included using assert().  On my FreeBSD
+- * system, this additional code can be removed by compiling with NDEBUG
+- * defined.  Check your own systems manpage on assert() to see how to
+- * compile WITHOUT the sanity checking code on your system.
+- *
+- * UNROLLED TRANSFORM LOOP NOTE:
+- * You can define SHA2_UNROLL_TRANSFORM to use the unrolled transform
+- * loop version for the hash transform rounds (defined using macros
+- * later in this file).  Either define on the command line, for example:
+- *
+- *   cc -DSHA2_UNROLL_TRANSFORM -o sha2 sha2.c sha2prog.c
+- *
+- * or define below:
+- *
+- *   #define SHA2_UNROLL_TRANSFORM
+- *
+- */
+-
+-
+-/*** SHA-256/384/512 Machine Architecture Definitions *****************/
+-/*
+- * BYTE_ORDER NOTE:
+- *
+- * Please make sure that your system defines BYTE_ORDER.  If your
+- * architecture is little-endian, make sure it also defines
+- * LITTLE_ENDIAN and that the two (BYTE_ORDER and LITTLE_ENDIAN) are
+- * equivilent.
+- *
+- * If your system does not define the above, then you can do so by
+- * hand like this:
+- *
+- *   #define LITTLE_ENDIAN 1234
+- *   #define BIG_ENDIAN    4321
+- *
+- * And for little-endian machines, add:
+- *
+- *   #define BYTE_ORDER LITTLE_ENDIAN 
+- *
+- * Or for big-endian machines:
+- *
+- *   #define BYTE_ORDER BIG_ENDIAN
+- *
+- * The FreeBSD machine this was written on defines BYTE_ORDER
+- * appropriately by including <sys/types.h> (which in turn includes
+- * <machine/endian.h> where the appropriate definitions are actually
+- * made).
+- */
+-#if !defined(BYTE_ORDER) || (BYTE_ORDER != LITTLE_ENDIAN && BYTE_ORDER != BIG_ENDIAN)
+-#error Define BYTE_ORDER to be equal to either LITTLE_ENDIAN or BIG_ENDIAN
+-#endif
+-
+-typedef uint8_t  sha2_byte;	/* Exactly 1 byte */
+-typedef uint32_t sha2_word32;	/* Exactly 4 bytes */
+-#ifdef S_SPLINT_S
+-typedef unsigned long long sha2_word64; /* lint 8 bytes */
+-#else
+-typedef uint64_t sha2_word64;	/* Exactly 8 bytes */
+-#endif
+-
+-/*** SHA-256/384/512 Various Length Definitions ***********************/
+-/* NOTE: Most of these are in sha2.h */
+-#define ldns_sha256_SHORT_BLOCK_LENGTH	(LDNS_SHA256_BLOCK_LENGTH - 8)
+-#define ldns_sha384_SHORT_BLOCK_LENGTH	(LDNS_SHA384_BLOCK_LENGTH - 16)
+-#define ldns_sha512_SHORT_BLOCK_LENGTH	(LDNS_SHA512_BLOCK_LENGTH - 16)
+-
+-
+-/*** ENDIAN REVERSAL MACROS *******************************************/
+-#if BYTE_ORDER == LITTLE_ENDIAN
+-#define REVERSE32(w,x)	{ \
+-	sha2_word32 tmp = (w); \
+-	tmp = (tmp >> 16) | (tmp << 16); \
+-	(x) = ((tmp & 0xff00ff00UL) >> 8) | ((tmp & 0x00ff00ffUL) << 8); \
+-}
+-#ifndef S_SPLINT_S
+-#define REVERSE64(w,x)	{ \
+-	sha2_word64 tmp = (w); \
+-	tmp = (tmp >> 32) | (tmp << 32); \
+-	tmp = ((tmp & 0xff00ff00ff00ff00ULL) >> 8) | \
+-	      ((tmp & 0x00ff00ff00ff00ffULL) << 8); \
+-	(x) = ((tmp & 0xffff0000ffff0000ULL) >> 16) | \
+-	      ((tmp & 0x0000ffff0000ffffULL) << 16); \
+-}
+-#else /* splint */
+-#define REVERSE64(w,x) /* splint */
+-#endif /* splint */
+-#endif /* BYTE_ORDER == LITTLE_ENDIAN */
+-
+-/*
+- * Macro for incrementally adding the unsigned 64-bit integer n to the
+- * unsigned 128-bit integer (represented using a two-element array of
+- * 64-bit words):
+- */
+-#define ADDINC128(w,n)	{ \
+-	(w)[0] += (sha2_word64)(n); \
+-	if ((w)[0] < (n)) { \
+-		(w)[1]++; \
+-	} \
+-}
+-#ifdef S_SPLINT_S
+-#undef ADDINC128
+-#define ADDINC128(w,n) /* splint */
+-#endif
+-
+-/*
+- * Macros for copying blocks of memory and for zeroing out ranges
+- * of memory.  Using these macros makes it easy to switch from
+- * using memset()/memcpy() and using bzero()/bcopy().
+- *
+- * Please define either SHA2_USE_MEMSET_MEMCPY or define
+- * SHA2_USE_BZERO_BCOPY depending on which function set you
+- * choose to use:
+- */
+-#if !defined(SHA2_USE_MEMSET_MEMCPY) && !defined(SHA2_USE_BZERO_BCOPY)
+-/* Default to memset()/memcpy() if no option is specified */
+-#define	SHA2_USE_MEMSET_MEMCPY	1
+-#endif
+-#if defined(SHA2_USE_MEMSET_MEMCPY) && defined(SHA2_USE_BZERO_BCOPY)
+-/* Abort with an error if BOTH options are defined */
+-#error Define either SHA2_USE_MEMSET_MEMCPY or SHA2_USE_BZERO_BCOPY, not both!
+-#endif
+-
+-#ifdef SHA2_USE_MEMSET_MEMCPY
+-#define MEMSET_BZERO(p,l)	memset((p), 0, (l))
+-#define MEMCPY_BCOPY(d,s,l)	memcpy((d), (s), (l))
+-#endif
+-#ifdef SHA2_USE_BZERO_BCOPY
+-#define MEMSET_BZERO(p,l)	bzero((p), (l))
+-#define MEMCPY_BCOPY(d,s,l)	bcopy((s), (d), (l))
+-#endif
+-
+-
+-/*** THE SIX LOGICAL FUNCTIONS ****************************************/
+-/*
+- * Bit shifting and rotation (used by the six SHA-XYZ logical functions:
+- *
+- *   NOTE:  The naming of R and S appears backwards here (R is a SHIFT and
+- *   S is a ROTATION) because the SHA-256/384/512 description document
+- *   (see http://csrc.nist.gov/cryptval/shs/sha256-384-512.pdf) uses this
+- *   same "backwards" definition.
+- */
+-/* Shift-right (used in SHA-256, SHA-384, and SHA-512): */
+-#define R(b,x) 		((x) >> (b))
+-/* 32-bit Rotate-right (used in SHA-256): */
+-#define S32(b,x)	(((x) >> (b)) | ((x) << (32 - (b))))
+-/* 64-bit Rotate-right (used in SHA-384 and SHA-512): */
+-#define S64(b,x)	(((x) >> (b)) | ((x) << (64 - (b))))
+-
+-/* Two of six logical functions used in SHA-256, SHA-384, and SHA-512: */
+-#define Ch(x,y,z)	(((x) & (y)) ^ ((~(x)) & (z)))
+-#define Maj(x,y,z)	(((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
+-
+-/* Four of six logical functions used in SHA-256: */
+-#define Sigma0_256(x)	(S32(2,  (x)) ^ S32(13, (x)) ^ S32(22, (x)))
+-#define Sigma1_256(x)	(S32(6,  (x)) ^ S32(11, (x)) ^ S32(25, (x)))
+-#define sigma0_256(x)	(S32(7,  (x)) ^ S32(18, (x)) ^ R(3 ,   (x)))
+-#define sigma1_256(x)	(S32(17, (x)) ^ S32(19, (x)) ^ R(10,   (x)))
+-
+-/* Four of six logical functions used in SHA-384 and SHA-512: */
+-#define Sigma0_512(x)	(S64(28, (x)) ^ S64(34, (x)) ^ S64(39, (x)))
+-#define Sigma1_512(x)	(S64(14, (x)) ^ S64(18, (x)) ^ S64(41, (x)))
+-#define sigma0_512(x)	(S64( 1, (x)) ^ S64( 8, (x)) ^ R( 7,   (x)))
+-#define sigma1_512(x)	(S64(19, (x)) ^ S64(61, (x)) ^ R( 6,   (x)))
+-
+-/*** SHA-XYZ INITIAL HASH VALUES AND CONSTANTS ************************/
+-/* Hash constant words K for SHA-256: */
+-static const sha2_word32 K256[64] = {
+-	0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL,
+-	0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL,
+-	0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL,
+-	0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL,
+-	0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
+-	0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL,
+-	0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL,
+-	0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL,
+-	0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL,
+-	0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
+-	0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL,
+-	0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL,
+-	0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL,
+-	0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL,
+-	0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
+-	0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL
+-};
+-
+-/* initial hash value H for SHA-256: */
+-static const sha2_word32 ldns_sha256_initial_hash_value[8] = {
+-	0x6a09e667UL,
+-	0xbb67ae85UL,
+-	0x3c6ef372UL,
+-	0xa54ff53aUL,
+-	0x510e527fUL,
+-	0x9b05688cUL,
+-	0x1f83d9abUL,
+-	0x5be0cd19UL
+-};
+-
+-/* Hash constant words K for SHA-384 and SHA-512: */
+-static const sha2_word64 K512[80] = {
+-	0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL,
+-	0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,
+-	0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
+-	0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,
+-	0xd807aa98a3030242ULL, 0x12835b0145706fbeULL,
+-	0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
+-	0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL,
+-	0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,
+-	0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
+-	0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
+-	0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL,
+-	0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
+-	0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL,
+-	0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,
+-	0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
+-	0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,
+-	0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL,
+-	0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
+-	0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL,
+-	0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
+-	0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
+-	0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,
+-	0xd192e819d6ef5218ULL, 0xd69906245565a910ULL,
+-	0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
+-	0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL,
+-	0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,
+-	0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
+-	0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,
+-	0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL,
+-	0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
+-	0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL,
+-	0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,
+-	0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
+-	0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,
+-	0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL,
+-	0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
+-	0x28db77f523047d84ULL, 0x32caab7b40c72493ULL,
+-	0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,
+-	0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
+-	0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL
+-};
+-
+-/* initial hash value H for SHA-384 */
+-static const sha2_word64 sha384_initial_hash_value[8] = {
+-	0xcbbb9d5dc1059ed8ULL,
+-	0x629a292a367cd507ULL,
+-	0x9159015a3070dd17ULL,
+-	0x152fecd8f70e5939ULL,
+-	0x67332667ffc00b31ULL,
+-	0x8eb44a8768581511ULL,
+-	0xdb0c2e0d64f98fa7ULL,
+-	0x47b5481dbefa4fa4ULL
+-};
+-
+-/* initial hash value H for SHA-512 */
+-static const sha2_word64 sha512_initial_hash_value[8] = {
+-	0x6a09e667f3bcc908ULL,
+-	0xbb67ae8584caa73bULL,
+-	0x3c6ef372fe94f82bULL,
+-	0xa54ff53a5f1d36f1ULL,
+-	0x510e527fade682d1ULL,
+-	0x9b05688c2b3e6c1fULL,
+-	0x1f83d9abfb41bd6bULL,
+-	0x5be0cd19137e2179ULL
+-};
+-
+-/*** SHA-256: *********************************************************/
+-void ldns_sha256_init(ldns_sha256_CTX* context) {
+-	if (context == (ldns_sha256_CTX*)0) {
+-		return;
+-	}
+-	MEMCPY_BCOPY(context->state, ldns_sha256_initial_hash_value, LDNS_SHA256_DIGEST_LENGTH);
+-	MEMSET_BZERO(context->buffer, LDNS_SHA256_BLOCK_LENGTH);
+-	context->bitcount = 0;
+-}
+-
+-#ifdef SHA2_UNROLL_TRANSFORM
+-
+-/* Unrolled SHA-256 round macros: */
+-
+-#if BYTE_ORDER == LITTLE_ENDIAN
+-
+-#define ROUND256_0_TO_15(a,b,c,d,e,f,g,h)	\
+-	REVERSE32(*data++, W256[j]); \
+-	T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + \
+-             K256[j] + W256[j]; \
+-	(d) += T1; \
+-	(h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \
+-	j++
+-
+-
+-#else /* BYTE_ORDER == LITTLE_ENDIAN */
+-
+-#define ROUND256_0_TO_15(a,b,c,d,e,f,g,h)	\
+-	T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + \
+-	     K256[j] + (W256[j] = *data++); \
+-	(d) += T1; \
+-	(h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \
+-	j++
+-
+-#endif /* BYTE_ORDER == LITTLE_ENDIAN */
+-
+-#define ROUND256(a,b,c,d,e,f,g,h)	\
+-	s0 = W256[(j+1)&0x0f]; \
+-	s0 = sigma0_256(s0); \
+-	s1 = W256[(j+14)&0x0f]; \
+-	s1 = sigma1_256(s1); \
+-	T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + K256[j] + \
+-	     (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0); \
+-	(d) += T1; \
+-	(h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \
+-	j++
+-
+-static void ldns_sha256_Transform(ldns_sha256_CTX* context,
+-                                  const sha2_word32* data) {
+-	sha2_word32	a, b, c, d, e, f, g, h, s0, s1;
+-	sha2_word32	T1, *W256;
+-	int		j;
+-
+-	W256 = (sha2_word32*)context->buffer;
+-
+-	/* initialize registers with the prev. intermediate value */
+-	a = context->state[0];
+-	b = context->state[1];
+-	c = context->state[2];
+-	d = context->state[3];
+-	e = context->state[4];
+-	f = context->state[5];
+-	g = context->state[6];
+-	h = context->state[7];
+-
+-	j = 0;
+-	do {
+-		/* Rounds 0 to 15 (unrolled): */
+-		ROUND256_0_TO_15(a,b,c,d,e,f,g,h);
+-		ROUND256_0_TO_15(h,a,b,c,d,e,f,g);
+-		ROUND256_0_TO_15(g,h,a,b,c,d,e,f);
+-		ROUND256_0_TO_15(f,g,h,a,b,c,d,e);
+-		ROUND256_0_TO_15(e,f,g,h,a,b,c,d);
+-		ROUND256_0_TO_15(d,e,f,g,h,a,b,c);
+-		ROUND256_0_TO_15(c,d,e,f,g,h,a,b);
+-		ROUND256_0_TO_15(b,c,d,e,f,g,h,a);
+-	} while (j < 16);
+-
+-	/* Now for the remaining rounds to 64: */
+-	do {
+-		ROUND256(a,b,c,d,e,f,g,h);
+-		ROUND256(h,a,b,c,d,e,f,g);
+-		ROUND256(g,h,a,b,c,d,e,f);
+-		ROUND256(f,g,h,a,b,c,d,e);
+-		ROUND256(e,f,g,h,a,b,c,d);
+-		ROUND256(d,e,f,g,h,a,b,c);
+-		ROUND256(c,d,e,f,g,h,a,b);
+-		ROUND256(b,c,d,e,f,g,h,a);
+-	} while (j < 64);
+-
+-	/* Compute the current intermediate hash value */
+-	context->state[0] += a;
+-	context->state[1] += b;
+-	context->state[2] += c;
+-	context->state[3] += d;
+-	context->state[4] += e;
+-	context->state[5] += f;
+-	context->state[6] += g;
+-	context->state[7] += h;
+-
+-	/* Clean up */
+-	a = b = c = d = e = f = g = h = T1 = 0;
+-}
+-
+-#else /* SHA2_UNROLL_TRANSFORM */
+-
+-static void ldns_sha256_Transform(ldns_sha256_CTX* context,
+-                                  const sha2_word32* data) {
+-	sha2_word32	a, b, c, d, e, f, g, h, s0, s1;
+-	sha2_word32	T1, T2, *W256;
+-	int		j;
+-
+-	W256 = (sha2_word32*)context->buffer;
+-
+-	/* initialize registers with the prev. intermediate value */
+-	a = context->state[0];
+-	b = context->state[1];
+-	c = context->state[2];
+-	d = context->state[3];
+-	e = context->state[4];
+-	f = context->state[5];
+-	g = context->state[6];
+-	h = context->state[7];
+-
+-	j = 0;
+-	do {
+-#if BYTE_ORDER == LITTLE_ENDIAN
+-		/* Copy data while converting to host byte order */
+-		REVERSE32(*data++,W256[j]);
+-		/* Apply the SHA-256 compression function to update a..h */
+-		T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + W256[j];
+-#else /* BYTE_ORDER == LITTLE_ENDIAN */
+-		/* Apply the SHA-256 compression function to update a..h with copy */
+-		T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + (W256[j] = *data++);
+-#endif /* BYTE_ORDER == LITTLE_ENDIAN */
+-		T2 = Sigma0_256(a) + Maj(a, b, c);
+-		h = g;
+-		g = f;
+-		f = e;
+-		e = d + T1;
+-		d = c;
+-		c = b;
+-		b = a;
+-		a = T1 + T2;
+-
+-		j++;
+-	} while (j < 16);
+-
+-	do {
+-		/* Part of the message block expansion: */
+-		s0 = W256[(j+1)&0x0f];
+-		s0 = sigma0_256(s0);
+-		s1 = W256[(j+14)&0x0f];	
+-		s1 = sigma1_256(s1);
+-
+-		/* Apply the SHA-256 compression function to update a..h */
+-		T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + 
+-		     (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0);
+-		T2 = Sigma0_256(a) + Maj(a, b, c);
+-		h = g;
+-		g = f;
+-		f = e;
+-		e = d + T1;
+-		d = c;
+-		c = b;
+-		b = a;
+-		a = T1 + T2;
+-
+-		j++;
+-	} while (j < 64);
+-
+-	/* Compute the current intermediate hash value */
+-	context->state[0] += a;
+-	context->state[1] += b;
+-	context->state[2] += c;
+-	context->state[3] += d;
+-	context->state[4] += e;
+-	context->state[5] += f;
+-	context->state[6] += g;
+-	context->state[7] += h;
+-
+-	/* Clean up */
+-	a = b = c = d = e = f = g = h = T1 = T2 = 0;
+-}
+-
+-#endif /* SHA2_UNROLL_TRANSFORM */
+-
+-void ldns_sha256_update(ldns_sha256_CTX* context, const sha2_byte *data, size_t len) {
+-	size_t freespace, usedspace;
+-
+-	if (len == 0) {
+-		/* Calling with no data is valid - we do nothing */
+-		return;
+-	}
+-
+-	/* Sanity check: */
+-	assert(context != (ldns_sha256_CTX*)0 && data != (sha2_byte*)0);
+-
+-	usedspace = (context->bitcount >> 3) % LDNS_SHA256_BLOCK_LENGTH;
+-	if (usedspace > 0) {
+-		/* Calculate how much free space is available in the buffer */
+-		freespace = LDNS_SHA256_BLOCK_LENGTH - usedspace;
+-
+-		if (len >= freespace) {
+-			/* Fill the buffer completely and process it */
+-			MEMCPY_BCOPY(&context->buffer[usedspace], data, freespace);
+-			context->bitcount += freespace << 3;
+-			len -= freespace;
+-			data += freespace;
+-			ldns_sha256_Transform(context, (sha2_word32*)context->buffer);
+-		} else {
+-			/* The buffer is not yet full */
+-			MEMCPY_BCOPY(&context->buffer[usedspace], data, len);
+-			context->bitcount += len << 3;
+-			/* Clean up: */
+-			usedspace = freespace = 0;
+-			return;
+-		}
+-	}
+-	while (len >= LDNS_SHA256_BLOCK_LENGTH) {
+-		/* Process as many complete blocks as we can */
+-		ldns_sha256_Transform(context, (sha2_word32*)data);
+-		context->bitcount += LDNS_SHA256_BLOCK_LENGTH << 3;
+-		len -= LDNS_SHA256_BLOCK_LENGTH;
+-		data += LDNS_SHA256_BLOCK_LENGTH;
+-	}
+-	if (len > 0) {
+-		/* There's left-overs, so save 'em */
+-		MEMCPY_BCOPY(context->buffer, data, len);
+-		context->bitcount += len << 3;
+-	}
+-	/* Clean up: */
+-	usedspace = freespace = 0;
+-}
+-
+-typedef union _ldns_sha2_buffer_union {
+-        uint8_t*  theChars;
+-        uint64_t* theLongs;
+-} ldns_sha2_buffer_union;
+-
+-void ldns_sha256_final(sha2_byte digest[], ldns_sha256_CTX* context) {
+-	sha2_word32	*d = (sha2_word32*)digest;
+-	size_t usedspace;
+-	ldns_sha2_buffer_union cast_var;
+-
+-	/* Sanity check: */
+-	assert(context != (ldns_sha256_CTX*)0);
+-
+-	/* If no digest buffer is passed, we don't bother doing this: */
+-	if (digest != (sha2_byte*)0) {
+-		usedspace = (context->bitcount >> 3) % LDNS_SHA256_BLOCK_LENGTH;
+-#if BYTE_ORDER == LITTLE_ENDIAN
+-		/* Convert FROM host byte order */
+-		REVERSE64(context->bitcount,context->bitcount);
+-#endif
+-		if (usedspace > 0) {
+-			/* Begin padding with a 1 bit: */
+-			context->buffer[usedspace++] = 0x80;
+-
+-			if (usedspace <= ldns_sha256_SHORT_BLOCK_LENGTH) {
+-				/* Set-up for the last transform: */
+-				MEMSET_BZERO(&context->buffer[usedspace], ldns_sha256_SHORT_BLOCK_LENGTH - usedspace);
+-			} else {
+-				if (usedspace < LDNS_SHA256_BLOCK_LENGTH) {
+-					MEMSET_BZERO(&context->buffer[usedspace], LDNS_SHA256_BLOCK_LENGTH - usedspace);
+-				}
+-				/* Do second-to-last transform: */
+-				ldns_sha256_Transform(context, (sha2_word32*)context->buffer);
+-
+-				/* And set-up for the last transform: */
+-				MEMSET_BZERO(context->buffer, ldns_sha256_SHORT_BLOCK_LENGTH);
+-			}
+-		} else {
+-			/* Set-up for the last transform: */
+-			MEMSET_BZERO(context->buffer, ldns_sha256_SHORT_BLOCK_LENGTH);
+-
+-			/* Begin padding with a 1 bit: */
+-			*context->buffer = 0x80;
+-		}
+-		/* Set the bit count: */
+-		cast_var.theChars = context->buffer;
+-		cast_var.theLongs[ldns_sha256_SHORT_BLOCK_LENGTH / 8] = context->bitcount;
+-
+-		/* final transform: */
+-		ldns_sha256_Transform(context, (sha2_word32*)context->buffer);
+-
+-#if BYTE_ORDER == LITTLE_ENDIAN
+-		{
+-			/* Convert TO host byte order */
+-			int	j;
+-			for (j = 0; j < 8; j++) {
+-				REVERSE32(context->state[j],context->state[j]);
+-				*d++ = context->state[j];
+-			}
+-		}
+-#else
+-		MEMCPY_BCOPY(d, context->state, LDNS_SHA256_DIGEST_LENGTH);
+-#endif
+-	}
+-
+-	/* Clean up state data: */
+-	MEMSET_BZERO(context, sizeof(ldns_sha256_CTX));
+-	usedspace = 0;
+-}
+-
+-unsigned char *
+-ldns_sha256(unsigned char *data, unsigned int data_len, unsigned char *digest)
+-{
+-    ldns_sha256_CTX ctx;
+-    ldns_sha256_init(&ctx);
+-    ldns_sha256_update(&ctx, data, data_len);
+-    ldns_sha256_final(digest, &ctx);
+-    return digest;
+-}
+-
+-/*** SHA-512: *********************************************************/
+-void ldns_sha512_init(ldns_sha512_CTX* context) {
+-	if (context == (ldns_sha512_CTX*)0) {
+-		return;
+-	}
+-	MEMCPY_BCOPY(context->state, sha512_initial_hash_value, LDNS_SHA512_DIGEST_LENGTH);
+-	MEMSET_BZERO(context->buffer, LDNS_SHA512_BLOCK_LENGTH);
+-	context->bitcount[0] = context->bitcount[1] =  0;
+-}
+-
+-#ifdef SHA2_UNROLL_TRANSFORM
+-
+-/* Unrolled SHA-512 round macros: */
+-#if BYTE_ORDER == LITTLE_ENDIAN
+-
+-#define ROUND512_0_TO_15(a,b,c,d,e,f,g,h)	\
+-	REVERSE64(*data++, W512[j]); \
+-	T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + \
+-             K512[j] + W512[j]; \
+-	(d) += T1, \
+-	(h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)), \
+-	j++
+-
+-
+-#else /* BYTE_ORDER == LITTLE_ENDIAN */
+-
+-#define ROUND512_0_TO_15(a,b,c,d,e,f,g,h)	\
+-	T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + \
+-             K512[j] + (W512[j] = *data++); \
+-	(d) += T1; \
+-	(h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)); \
+-	j++
+-
+-#endif /* BYTE_ORDER == LITTLE_ENDIAN */
+-
+-#define ROUND512(a,b,c,d,e,f,g,h)	\
+-	s0 = W512[(j+1)&0x0f]; \
+-	s0 = sigma0_512(s0); \
+-	s1 = W512[(j+14)&0x0f]; \
+-	s1 = sigma1_512(s1); \
+-	T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + K512[j] + \
+-             (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0); \
+-	(d) += T1; \
+-	(h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)); \
+-	j++
+-
+-static void ldns_sha512_Transform(ldns_sha512_CTX* context,
+-                                  const sha2_word64* data) {
+-	sha2_word64	a, b, c, d, e, f, g, h, s0, s1;
+-	sha2_word64	T1, *W512 = (sha2_word64*)context->buffer;
+-	int		j;
+-
+-	/* initialize registers with the prev. intermediate value */
+-	a = context->state[0];
+-	b = context->state[1];
+-	c = context->state[2];
+-	d = context->state[3];
+-	e = context->state[4];
+-	f = context->state[5];
+-	g = context->state[6];
+-	h = context->state[7];
+-
+-	j = 0;
+-	do {
+-		ROUND512_0_TO_15(a,b,c,d,e,f,g,h);
+-		ROUND512_0_TO_15(h,a,b,c,d,e,f,g);
+-		ROUND512_0_TO_15(g,h,a,b,c,d,e,f);
+-		ROUND512_0_TO_15(f,g,h,a,b,c,d,e);
+-		ROUND512_0_TO_15(e,f,g,h,a,b,c,d);
+-		ROUND512_0_TO_15(d,e,f,g,h,a,b,c);
+-		ROUND512_0_TO_15(c,d,e,f,g,h,a,b);
+-		ROUND512_0_TO_15(b,c,d,e,f,g,h,a);
+-	} while (j < 16);
+-
+-	/* Now for the remaining rounds up to 79: */
+-	do {
+-		ROUND512(a,b,c,d,e,f,g,h);
+-		ROUND512(h,a,b,c,d,e,f,g);
+-		ROUND512(g,h,a,b,c,d,e,f);
+-		ROUND512(f,g,h,a,b,c,d,e);
+-		ROUND512(e,f,g,h,a,b,c,d);
+-		ROUND512(d,e,f,g,h,a,b,c);
+-		ROUND512(c,d,e,f,g,h,a,b);
+-		ROUND512(b,c,d,e,f,g,h,a);
+-	} while (j < 80);
+-
+-	/* Compute the current intermediate hash value */
+-	context->state[0] += a;
+-	context->state[1] += b;
+-	context->state[2] += c;
+-	context->state[3] += d;
+-	context->state[4] += e;
+-	context->state[5] += f;
+-	context->state[6] += g;
+-	context->state[7] += h;
+-
+-	/* Clean up */
+-	a = b = c = d = e = f = g = h = T1 = 0;
+-}
+-
+-#else /* SHA2_UNROLL_TRANSFORM */
+-
+-static void ldns_sha512_Transform(ldns_sha512_CTX* context,
+-                                  const sha2_word64* data) {
+-	sha2_word64	a, b, c, d, e, f, g, h, s0, s1;
+-	sha2_word64	T1, T2, *W512 = (sha2_word64*)context->buffer;
+-	int		j;
+-
+-	/* initialize registers with the prev. intermediate value */
+-	a = context->state[0];
+-	b = context->state[1];
+-	c = context->state[2];
+-	d = context->state[3];
+-	e = context->state[4];
+-	f = context->state[5];
+-	g = context->state[6];
+-	h = context->state[7];
+-
+-	j = 0;
+-	do {
+-#if BYTE_ORDER == LITTLE_ENDIAN
+-		/* Convert TO host byte order */
+-		REVERSE64(*data++, W512[j]);
+-		/* Apply the SHA-512 compression function to update a..h */
+-		T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + W512[j];
+-#else /* BYTE_ORDER == LITTLE_ENDIAN */
+-		/* Apply the SHA-512 compression function to update a..h with copy */
+-		T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + (W512[j] = *data++);
+-#endif /* BYTE_ORDER == LITTLE_ENDIAN */
+-		T2 = Sigma0_512(a) + Maj(a, b, c);
+-		h = g;
+-		g = f;
+-		f = e;
+-		e = d + T1;
+-		d = c;
+-		c = b;
+-		b = a;
+-		a = T1 + T2;
+-
+-		j++;
+-	} while (j < 16);
+-
+-	do {
+-		/* Part of the message block expansion: */
+-		s0 = W512[(j+1)&0x0f];
+-		s0 = sigma0_512(s0);
+-		s1 = W512[(j+14)&0x0f];
+-		s1 =  sigma1_512(s1);
+-
+-		/* Apply the SHA-512 compression function to update a..h */
+-		T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] +
+-		     (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0);
+-		T2 = Sigma0_512(a) + Maj(a, b, c);
+-		h = g;
+-		g = f;
+-		f = e;
+-		e = d + T1;
+-		d = c;
+-		c = b;
+-		b = a;
+-		a = T1 + T2;
+-
+-		j++;
+-	} while (j < 80);
+-
+-	/* Compute the current intermediate hash value */
+-	context->state[0] += a;
+-	context->state[1] += b;
+-	context->state[2] += c;
+-	context->state[3] += d;
+-	context->state[4] += e;
+-	context->state[5] += f;
+-	context->state[6] += g;
+-	context->state[7] += h;
+-
+-	/* Clean up */
+-	a = b = c = d = e = f = g = h = T1 = T2 = 0;
+-}
+-
+-#endif /* SHA2_UNROLL_TRANSFORM */
+-
+-void ldns_sha512_update(ldns_sha512_CTX* context, const sha2_byte *data, size_t len) {
+-	size_t freespace, usedspace;
+-
+-	if (len == 0) {
+-		/* Calling with no data is valid - we do nothing */
+-		return;
+-	}
+-
+-	/* Sanity check: */
+-	assert(context != (ldns_sha512_CTX*)0 && data != (sha2_byte*)0);
+-
+-	usedspace = (context->bitcount[0] >> 3) % LDNS_SHA512_BLOCK_LENGTH;
+-	if (usedspace > 0) {
+-		/* Calculate how much free space is available in the buffer */
+-		freespace = LDNS_SHA512_BLOCK_LENGTH - usedspace;
+-
+-		if (len >= freespace) {
+-			/* Fill the buffer completely and process it */
+-			MEMCPY_BCOPY(&context->buffer[usedspace], data, freespace);
+-			ADDINC128(context->bitcount, freespace << 3);
+-			len -= freespace;
+-			data += freespace;
+-			ldns_sha512_Transform(context, (sha2_word64*)context->buffer);
+-		} else {
+-			/* The buffer is not yet full */
+-			MEMCPY_BCOPY(&context->buffer[usedspace], data, len);
+-			ADDINC128(context->bitcount, len << 3);
+-			/* Clean up: */
+-			usedspace = freespace = 0;
+-			return;
+-		}
+-	}
+-	while (len >= LDNS_SHA512_BLOCK_LENGTH) {
+-		/* Process as many complete blocks as we can */
+-		ldns_sha512_Transform(context, (sha2_word64*)data);
+-		ADDINC128(context->bitcount, LDNS_SHA512_BLOCK_LENGTH << 3);
+-		len -= LDNS_SHA512_BLOCK_LENGTH;
+-		data += LDNS_SHA512_BLOCK_LENGTH;
+-	}
+-	if (len > 0) {
+-		/* There's left-overs, so save 'em */
+-		MEMCPY_BCOPY(context->buffer, data, len);
+-		ADDINC128(context->bitcount, len << 3);
+-	}
+-	/* Clean up: */
+-	usedspace = freespace = 0;
+-}
+-
+-static void ldns_sha512_Last(ldns_sha512_CTX* context) {
+-	size_t usedspace;
+-	ldns_sha2_buffer_union cast_var;
+-
+-	usedspace = (context->bitcount[0] >> 3) % LDNS_SHA512_BLOCK_LENGTH;
+-#if BYTE_ORDER == LITTLE_ENDIAN
+-	/* Convert FROM host byte order */
+-	REVERSE64(context->bitcount[0],context->bitcount[0]);
+-	REVERSE64(context->bitcount[1],context->bitcount[1]);
+-#endif
+-	if (usedspace > 0) {
+-		/* Begin padding with a 1 bit: */
+-		context->buffer[usedspace++] = 0x80;
+-
+-		if (usedspace <= ldns_sha512_SHORT_BLOCK_LENGTH) {
+-			/* Set-up for the last transform: */
+-			MEMSET_BZERO(&context->buffer[usedspace], ldns_sha512_SHORT_BLOCK_LENGTH - usedspace);
+-		} else {
+-			if (usedspace < LDNS_SHA512_BLOCK_LENGTH) {
+-				MEMSET_BZERO(&context->buffer[usedspace], LDNS_SHA512_BLOCK_LENGTH - usedspace);
+-			}
+-			/* Do second-to-last transform: */
+-			ldns_sha512_Transform(context, (sha2_word64*)context->buffer);
+-
+-			/* And set-up for the last transform: */
+-			MEMSET_BZERO(context->buffer, LDNS_SHA512_BLOCK_LENGTH - 2);
+-		}
+-	} else {
+-		/* Prepare for final transform: */
+-		MEMSET_BZERO(context->buffer, ldns_sha512_SHORT_BLOCK_LENGTH);
+-
+-		/* Begin padding with a 1 bit: */
+-		*context->buffer = 0x80;
+-	}
+-	/* Store the length of input data (in bits): */
+-	cast_var.theChars = context->buffer;
+-	cast_var.theLongs[ldns_sha512_SHORT_BLOCK_LENGTH / 8] = context->bitcount[1];
+-	cast_var.theLongs[ldns_sha512_SHORT_BLOCK_LENGTH / 8 + 1] = context->bitcount[0];
+-
+-	/* final transform: */
+-	ldns_sha512_Transform(context, (sha2_word64*)context->buffer);
+-}
+-
+-void ldns_sha512_final(sha2_byte digest[], ldns_sha512_CTX* context) {
+-	sha2_word64	*d = (sha2_word64*)digest;
+-
+-	/* Sanity check: */
+-	assert(context != (ldns_sha512_CTX*)0);
+-
+-	/* If no digest buffer is passed, we don't bother doing this: */
+-	if (digest != (sha2_byte*)0) {
+-		ldns_sha512_Last(context);
+-
+-		/* Save the hash data for output: */
+-#if BYTE_ORDER == LITTLE_ENDIAN
+-		{
+-			/* Convert TO host byte order */
+-			int	j;
+-			for (j = 0; j < 8; j++) {
+-				REVERSE64(context->state[j],context->state[j]);
+-				*d++ = context->state[j];
+-			}
+-		}
+-#else
+-		MEMCPY_BCOPY(d, context->state, LDNS_SHA512_DIGEST_LENGTH);
+-#endif
+-	}
+-
+-	/* Zero out state data */
+-	MEMSET_BZERO(context, sizeof(ldns_sha512_CTX));
+-}
+-
+-unsigned char *
+-ldns_sha512(unsigned char *data, unsigned int data_len, unsigned char *digest)
+-{
+-    ldns_sha512_CTX ctx;
+-    ldns_sha512_init(&ctx);
+-    ldns_sha512_update(&ctx, data, data_len);
+-    ldns_sha512_final(digest, &ctx);
+-    return digest;
+-}
+-
+-/*** SHA-384: *********************************************************/
+-void ldns_sha384_init(ldns_sha384_CTX* context) {
+-	if (context == (ldns_sha384_CTX*)0) {
+-		return;
+-	}
+-	MEMCPY_BCOPY(context->state, sha384_initial_hash_value, LDNS_SHA512_DIGEST_LENGTH);
+-	MEMSET_BZERO(context->buffer, LDNS_SHA384_BLOCK_LENGTH);
+-	context->bitcount[0] = context->bitcount[1] = 0;
+-}
+-
+-void ldns_sha384_update(ldns_sha384_CTX* context, const sha2_byte* data, size_t len) {
+-	ldns_sha512_update((ldns_sha512_CTX*)context, data, len);
+-}
+-
+-void ldns_sha384_final(sha2_byte digest[], ldns_sha384_CTX* context) {
+-	sha2_word64	*d = (sha2_word64*)digest;
+-
+-	/* Sanity check: */
+-	assert(context != (ldns_sha384_CTX*)0);
+-
+-	/* If no digest buffer is passed, we don't bother doing this: */
+-	if (digest != (sha2_byte*)0) {
+-		ldns_sha512_Last((ldns_sha512_CTX*)context);
+-
+-		/* Save the hash data for output: */
+-#if BYTE_ORDER == LITTLE_ENDIAN
+-		{
+-			/* Convert TO host byte order */
+-			int	j;
+-			for (j = 0; j < 6; j++) {
+-				REVERSE64(context->state[j],context->state[j]);
+-				*d++ = context->state[j];
+-			}
+-		}
+-#else
+-		MEMCPY_BCOPY(d, context->state, LDNS_SHA384_DIGEST_LENGTH);
+-#endif
+-	}
+-
+-	/* Zero out state data */
+-	MEMSET_BZERO(context, sizeof(ldns_sha384_CTX));
+-}
+-
+-unsigned char *
+-ldns_sha384(unsigned char *data, unsigned int data_len, unsigned char *digest)
+-{
+-    ldns_sha384_CTX ctx;
+-    ldns_sha384_init(&ctx);
+-    ldns_sha384_update(&ctx, data, data_len);
+-    ldns_sha384_final(digest, &ctx);
+-    return digest;
+-}
+diff --git a/src/ldns/str2host.c b/src/ldns/str2host.c
+deleted file mode 100644
+index cd07c89..0000000
+--- a/src/ldns/str2host.c
++++ /dev/null
+@@ -1,1604 +0,0 @@
+-/*
+- * str2host.c
+- *
+- * conversion routines from the presentation format
+- * to the host format
+- *
+- * a Net::DNS like library for C
+- *
+- * (c) NLnet Labs, 2004-2006
+- *
+- * See the file LICENSE for the license
+- */
+-#include <ldns/config.h>
+-
+-#include <ldns/ldns.h>
+-
+-#ifdef HAVE_SYS_SOCKET_H
+-#include <sys/socket.h>
+-#endif
+-#ifdef HAVE_ARPA_INET_H
+-#include <arpa/inet.h>
+-#endif
+-#include <time.h>
+-
+-#include <errno.h>
+-#ifdef HAVE_NETDB_H
+-#include <netdb.h>
+-#endif
+-
+-#include <limits.h>
+-#ifdef HAVE_SYS_PARAM_H
+-#include <sys/param.h>
+-#endif
+-
+-ldns_status
+-ldns_str2rdf_int16(ldns_rdf **rd, const char *shortstr)
+-{
+-	char *end = NULL;
+-	uint16_t *r;
+-	r = LDNS_MALLOC(uint16_t);
+-        if(!r) return LDNS_STATUS_MEM_ERR;
+-
+-	*r = htons((uint16_t)strtol((char *)shortstr, &end, 10));
+-
+-	if(*end != 0) {
+-		LDNS_FREE(r);
+-		return LDNS_STATUS_INVALID_INT;
+-	} else {
+-		*rd = ldns_rdf_new_frm_data(
+-			LDNS_RDF_TYPE_INT16, sizeof(uint16_t), r);
+-		LDNS_FREE(r);
+-		return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
+-	}
+-}
+-
+-ldns_status
+-ldns_str2rdf_time(ldns_rdf **rd, const char *time)
+-{
+-	/* convert a time YYYYDDMMHHMMSS to wireformat */
+-	uint16_t *r = NULL;
+-	struct tm tm;
+-	uint32_t l;
+-	char *end;
+-
+-	/* Try to scan the time... */
+-	r = (uint16_t*)LDNS_MALLOC(uint32_t);
+-        if(!r) return LDNS_STATUS_MEM_ERR;
+-
+-	memset(&tm, 0, sizeof(tm));
+-
+-	if (strlen(time) == 14 &&
+-	    sscanf(time, "%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 values */
+-		if (tm.tm_year < 70) {
+-			goto bad_format;
+-		}
+-		if (tm.tm_mon < 0 || tm.tm_mon > 11) {
+-			goto bad_format;
+-		}
+-		if (tm.tm_mday < 1 || tm.tm_mday > 31) {
+-			goto bad_format;
+-		}
+-
+-		if (tm.tm_hour < 0 || tm.tm_hour > 23) {
+-			goto bad_format;
+-		}
+-
+-		if (tm.tm_min < 0 || tm.tm_min > 59) {
+-			goto bad_format;
+-		}
+-
+-		if (tm.tm_sec < 0 || tm.tm_sec > 59) {
+-			goto bad_format;
+-		}
+-
+-		l = htonl(ldns_mktime_from_utc(&tm));
+-		memcpy(r, &l, sizeof(uint32_t));
+-		*rd = ldns_rdf_new_frm_data(
+-			LDNS_RDF_TYPE_TIME, sizeof(uint32_t), r);
+-		LDNS_FREE(r);
+-		return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
+-	} else {
+-		/* handle it as 32 bits timestamp */
+-		l = htonl((uint32_t)strtol((char*)time, &end, 10));
+-		if(*end != 0) {
+-			LDNS_FREE(r);
+-			return LDNS_STATUS_ERR;
+-		} else {
+-			memcpy(r, &l, sizeof(uint32_t));
+-			*rd = ldns_rdf_new_frm_data(
+-				LDNS_RDF_TYPE_INT32, sizeof(uint32_t), r);
+-			LDNS_FREE(r);
+-		        return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
+-		}
+-	}
+-
+-	bad_format:
+-	LDNS_FREE(r);
+-	return LDNS_STATUS_INVALID_TIME;
+-}
+-
+-ldns_status
+-ldns_str2rdf_nsec3_salt(ldns_rdf **rd, const char *salt_str)
+-{
+-	uint8_t salt_length;
+-	int c;
+-	int salt_length_str;
+-
+-	uint8_t *salt;
+-	uint8_t *data;
+-	if(rd == NULL) {
+-		return LDNS_STATUS_NULL;
+-	}
+-
+-	salt_length_str = (int)strlen(salt_str);
+-	if (salt_length_str == 1 && salt_str[0] == '-') {
+-		salt_length_str = 0;
+-	} else if (salt_length_str % 2 != 0) {
+-		return LDNS_STATUS_INVALID_HEX;
+-	}
+-	if (salt_length_str > 512) {
+-		return LDNS_STATUS_INVALID_HEX;
+-	}
+-
+-	salt = LDNS_XMALLOC(uint8_t, salt_length_str / 2);
+-        if(!salt) {
+-                return LDNS_STATUS_MEM_ERR;
+-        }
+-	for (c = 0; c < salt_length_str; c += 2) {
+-		if (isxdigit((int) salt_str[c]) && isxdigit((int) salt_str[c+1])) {
+-			salt[c/2] = (uint8_t) ldns_hexdigit_to_int(salt_str[c]) * 16 +
+-					  ldns_hexdigit_to_int(salt_str[c+1]);
+-		} else {
+-			LDNS_FREE(salt);
+-			return LDNS_STATUS_INVALID_HEX;
+-		}
+-	}
+-	salt_length = (uint8_t) (salt_length_str / 2);
+-
+-	data = LDNS_XMALLOC(uint8_t, 1 + salt_length);
+-        if(!data) {
+-	        LDNS_FREE(salt);
+-                return LDNS_STATUS_MEM_ERR;
+-        }
+-	data[0] = salt_length;
+-	memcpy(&data[1], salt, salt_length);
+-	*rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_NSEC3_SALT, 1 + salt_length, data);
+-	LDNS_FREE(data);
+-	LDNS_FREE(salt);
+-
+-	return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
+-}
+-
+-ldns_status
+-ldns_str2rdf_period(ldns_rdf **rd,const char *period)
+-{
+-        uint32_t p;
+-        const char *end;
+-
+-        /* Allocate required space... */
+-        p = ldns_str2period(period, &end);
+-
+-        if (*end != 0) {
+-		return LDNS_STATUS_ERR;
+-        } else {
+-                p = (uint32_t) htonl(p);
+-		*rd = ldns_rdf_new_frm_data(
+-			LDNS_RDF_TYPE_PERIOD, sizeof(uint32_t), &p);
+-        }
+-	return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
+-}
+-
+-ldns_status
+-ldns_str2rdf_int32(ldns_rdf **rd, const char *longstr)
+-{
+-	char *end;
+-	uint16_t *r = NULL;
+-	uint32_t l;
+-
+-	r = (uint16_t*)LDNS_MALLOC(uint32_t);
+-        if(!r) return LDNS_STATUS_MEM_ERR;
+-	errno = 0; /* must set to zero before call,
+-			note race condition on errno */
+-	if(*longstr == '-')
+-		l = htonl((uint32_t)strtol((char*)longstr, &end, 10));
+-	else	l = htonl((uint32_t)strtoul((char*)longstr, &end, 10));
+-
+-	if(*end != 0) {
+-		LDNS_FREE(r);
+-		return LDNS_STATUS_ERR;
+-     } else {
+-		if (errno == ERANGE) {
+-			LDNS_FREE(r);
+-			return LDNS_STATUS_SYNTAX_INTEGER_OVERFLOW;
+-		}
+-		memcpy(r, &l, sizeof(uint32_t));
+-		*rd = ldns_rdf_new_frm_data(
+-			LDNS_RDF_TYPE_INT32, sizeof(uint32_t), r);
+-		LDNS_FREE(r);
+-	        return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
+-	}
+-}
+-
+-ldns_status
+-ldns_str2rdf_int8(ldns_rdf **rd, const char *bytestr)
+-{
+-	char *end;
+-	uint8_t *r = NULL;
+-
+-	r = LDNS_MALLOC(uint8_t);
+-        if(!r) return LDNS_STATUS_MEM_ERR;
+-
+-	*r = (uint8_t)strtol((char*)bytestr, &end, 10);
+-
+-        if(*end != 0) {
+-		LDNS_FREE(r);
+-		return LDNS_STATUS_ERR;
+-        } else {
+-		*rd = ldns_rdf_new_frm_data(
+-			LDNS_RDF_TYPE_INT8, sizeof(uint8_t), r);
+-		LDNS_FREE(r);
+-	        return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
+-        }
+-}
+-
+-
+-/*
+- * Checks whether the escaped value at **s is an decimal value or
+- * a 'normally' escaped character (and not eos)
+- *
+- * The string pointer at *s is increased by either 0 (on error), 1 (on
+- * normal escapes), or 3 (on decimals)
+- *
+- * Returns the number of bytes read from the escaped string, or
+- * 0 on error
+- */
+-INLINE bool
+-parse_escape(uint8_t *ch_p, const char** str_p)
+-{
+-	uint16_t val;
+-
+-	if ((*str_p)[0] && isdigit((*str_p)[0])  &&
+-	    (*str_p)[1] && isdigit((*str_p)[1])  &&
+-	    (*str_p)[2] && isdigit((*str_p)[2]))  {
+-
+-		val = (uint16_t)(((*str_p)[0] - '0') * 100 +
+-				 ((*str_p)[1] - '0') *  10 +
+-				 ((*str_p)[2] - '0'));
+-
+-		if (val > 255) {
+-			goto error;
+-		}
+-		*ch_p = (uint8_t)val;
+-		*str_p += 3;
+-		return true;
+-
+-	} else if ((*str_p)[0] && !isdigit((*str_p)[0])) {
+-
+-		*ch_p = (uint8_t)*(*str_p)++;
+-		return true;
+-	}
+-error:
+-	*str_p = NULL;
+-	return false; /* LDNS_STATUS_SYNTAX_BAD_ESCAPE */
+-}
+-
+-INLINE bool
+-parse_char(uint8_t *ch_p, const char** str_p)
+-{
+-	switch (**str_p) {
+-
+-	case '\0':	return false;
+-
+-	case '\\':	*str_p += 1;
+-			return parse_escape(ch_p, str_p);
+-
+-	default:	*ch_p = (uint8_t)*(*str_p)++;
+-			return true;
+-	}
+-}
+-
+-/*
+- * No special care is taken, all dots are translated into
+- * label seperators.
+- * Could be made more efficient....we do 3 memcpy's in total...
+- */
+-ldns_status
+-ldns_str2rdf_dname(ldns_rdf **d, const char *str)
+-{
+-	size_t len;
+-
+-	const char *s;
+-	uint8_t *q, *pq, label_len;
+-	uint8_t buf[LDNS_MAX_DOMAINLEN + 1];
+-	*d = NULL;
+-
+-	len = strlen((char*)str);
+-	/* octet representation can make strings a lot longer than actual length */
+-	if (len > LDNS_MAX_DOMAINLEN * 4) {
+-		return LDNS_STATUS_DOMAINNAME_OVERFLOW;
+-	}
+-	if (0 == len) {
+-		return LDNS_STATUS_DOMAINNAME_UNDERFLOW;
+-	}
+-
+-	/* root label */
+-	if (1 == len && *str == '.') {
+-		*d = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_DNAME, 1, "\0");
+-		return LDNS_STATUS_OK;
+-	}
+-
+-	/* get on with the rest */
+-
+-	/* s is on the current character in the string
+-         * pq points to where the labellength is going to go
+-         * label_len keeps track of the current label's length
+-	 * q builds the dname inside the buf array
+-	 */
+-	len = 0;
+-	q = buf+1;
+-	pq = buf;
+-	label_len = 0;
+-	for (s = str; *s; s++, q++) {
+-		if (q > buf + LDNS_MAX_DOMAINLEN) {
+-			return LDNS_STATUS_DOMAINNAME_OVERFLOW;
+-		}
+-		*q = 0;
+-		switch (*s) {
+-		case '.':
+-			if (label_len > LDNS_MAX_LABELLEN) {
+-				return LDNS_STATUS_LABEL_OVERFLOW;
+-			}
+-			if (label_len == 0) {
+-				return LDNS_STATUS_EMPTY_LABEL;
+-			}
+-			len += label_len + 1;
+-			*pq = label_len;
+-			label_len = 0;
+-			pq = q;
+-			break;
+-		case '\\':
+-			/* octet value or literal char */
+-			s += 1;
+-			if (! parse_escape(q, &s)) {
+-				return LDNS_STATUS_SYNTAX_BAD_ESCAPE;
+-			}
+-			s -= 1;
+-			label_len++;
+-			break;
+-		default:
+-			*q = (uint8_t)*s;
+-			label_len++;
+-		}
+-	}
+-
+-	/* add root label if last char was not '.' */
+-	if (!ldns_dname_str_absolute(str)) {
+-		if (q > buf + LDNS_MAX_DOMAINLEN) {
+-			return LDNS_STATUS_DOMAINNAME_OVERFLOW;
+-		}
+-                if (label_len > LDNS_MAX_LABELLEN) {
+-                        return LDNS_STATUS_LABEL_OVERFLOW;
+-                }
+-                if (label_len == 0) { /* label_len 0 but not . at end? */
+-                        return LDNS_STATUS_EMPTY_LABEL;
+-                }
+-		len += label_len + 1;
+-		*pq = label_len;
+-		*q = 0;
+-	}
+-	len++;
+-
+-	*d = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_DNAME, len, buf);
+-	return LDNS_STATUS_OK;
+-}
+-
+-ldns_status
+-ldns_str2rdf_a(ldns_rdf **rd, const char *str)
+-{
+-	in_addr_t address;
+-        if (inet_pton(AF_INET, (char*)str, &address) != 1) {
+-                return LDNS_STATUS_INVALID_IP4;
+-        } else {
+-		*rd = ldns_rdf_new_frm_data(
+-			LDNS_RDF_TYPE_A, sizeof(address), &address);
+-        }
+-	return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
+-}
+-
+-ldns_status
+-ldns_str2rdf_aaaa(ldns_rdf **rd, const char *str)
+-{
+-	uint8_t address[LDNS_IP6ADDRLEN + 1];
+-
+-	if (inet_pton(AF_INET6, (char*)str, address) != 1) {
+-		return LDNS_STATUS_INVALID_IP6;
+-	} else {
+-		*rd = ldns_rdf_new_frm_data(
+-			LDNS_RDF_TYPE_AAAA, sizeof(address) - 1, &address);
+-	}
+-	return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
+-}
+-
+-ldns_status
+-ldns_str2rdf_str(ldns_rdf **rd, const char *str)
+-{
+-	uint8_t *data, *dp, ch = 0;
+-	size_t length;
+-
+-	/* Worst case space requirement. We'll realloc to actual size later. */
+-	dp = data = LDNS_XMALLOC(uint8_t, strlen(str) > 255 ? 256 : (strlen(str) + 1));
+-	if (! data) {
+-		return LDNS_STATUS_MEM_ERR;
+-	}
+-
+-	/* Fill data (up to 255 characters) */
+-	while (parse_char(&ch, &str)) {
+-		if (dp - data >= 255) {
+-			LDNS_FREE(data);
+-			return LDNS_STATUS_INVALID_STR;
+-		}
+-		*++dp = ch;
+-	}
+-	if (! str) {
+-		return LDNS_STATUS_SYNTAX_BAD_ESCAPE;
+-	}
+-	length = (size_t)(dp - data);
+-	/* Fix last length byte */
+-	data[0] = (uint8_t)length;
+-
+-	/* Lose the overmeasure */
+-	data = LDNS_XREALLOC(dp = data, uint8_t, length + 1);
+-	if (! data) {
+-		LDNS_FREE(dp);
+-		return LDNS_STATUS_MEM_ERR;
+-	}
+-
+-	/* Create rdf */
+-	*rd = ldns_rdf_new(LDNS_RDF_TYPE_STR, length + 1, data);
+-	if (! *rd) {
+-		LDNS_FREE(data);
+-		return LDNS_STATUS_MEM_ERR;
+-	}
+-	return LDNS_STATUS_OK;
+-}
+-
+-ldns_status
+-ldns_str2rdf_apl(ldns_rdf **rd, const char *str)
+-{
+-	const char *my_str = str;
+-
+-	char *my_ip_str;
+-	size_t ip_str_len;
+-
+-	uint16_t family;
+-	bool negation;
+-	uint8_t afdlength = 0;
+-	uint8_t *afdpart;
+-	uint8_t prefix;
+-
+-	uint8_t *data;
+-
+-	size_t i = 0;
+-
+-	/* [!]afi:address/prefix */
+-	if (strlen(my_str) < 2
+-			|| strchr(my_str, ':') == NULL
+-			|| strchr(my_str, '/') == NULL
+-			|| strchr(my_str, ':') > strchr(my_str, '/')) {
+-		return LDNS_STATUS_INVALID_STR;
+-	}
+-
+-	if (my_str[0] == '!') {
+-		negation = true;
+-		my_str += 1;
+-	} else {
+-		negation = false;
+-	}
+-
+-	family = (uint16_t) atoi(my_str);
+-
+-	my_str = strchr(my_str, ':') + 1;
+-
+-	/* need ip addr and only ip addr for inet_pton */
+-	ip_str_len = (size_t) (strchr(my_str, '/') - my_str);
+-	my_ip_str = LDNS_XMALLOC(char, ip_str_len + 1);
+-        if(!my_ip_str) return LDNS_STATUS_MEM_ERR;
+-	strncpy(my_ip_str, my_str, ip_str_len + 1);
+-	my_ip_str[ip_str_len] = '\0';
+-
+-	if (family == 1) {
+-		/* ipv4 */
+-		afdpart = LDNS_XMALLOC(uint8_t, 4);
+-                if(!afdpart) {
+-                        LDNS_FREE(my_ip_str);
+-                        return LDNS_STATUS_MEM_ERR;
+-                }
+-		if (inet_pton(AF_INET, my_ip_str, afdpart) == 0) {
+-                        LDNS_FREE(my_ip_str);
+-                        LDNS_FREE(afdpart);
+-			return LDNS_STATUS_INVALID_STR;
+-		}
+-		for (i = 0; i < 4; i++) {
+-			if (afdpart[i] != 0) {
+-				afdlength = i + 1;
+-			}
+-		}
+-	} else if (family == 2) {
+-		/* ipv6 */
+-		afdpart = LDNS_XMALLOC(uint8_t, 16);
+-                if(!afdpart) {
+-                        LDNS_FREE(my_ip_str);
+-                        return LDNS_STATUS_MEM_ERR;
+-                }
+-		if (inet_pton(AF_INET6, my_ip_str, afdpart) == 0) {
+-                        LDNS_FREE(my_ip_str);
+-                        LDNS_FREE(afdpart);
+-			return LDNS_STATUS_INVALID_STR;
+-		}
+-		for (i = 0; i < 16; i++) {
+-			if (afdpart[i] != 0) {
+-				afdlength = i + 1;
+-			}
+-		}
+-	} else {
+-		/* unknown family */
+-		LDNS_FREE(my_ip_str);
+-		return LDNS_STATUS_INVALID_STR;
+-	}
+-
+-	my_str = strchr(my_str, '/') + 1;
+-	prefix = (uint8_t) atoi(my_str);
+-
+-	data = LDNS_XMALLOC(uint8_t, 4 + afdlength);
+-        if(!data) {
+-		LDNS_FREE(afdpart);
+-		LDNS_FREE(my_ip_str);
+-		return LDNS_STATUS_INVALID_STR;
+-        }
+-	ldns_write_uint16(data, family);
+-	data[2] = prefix;
+-	data[3] = afdlength;
+-	if (negation) {
+-		/* set bit 1 of byte 3 */
+-		data[3] = data[3] | 0x80;
+-	}
+-
+-	memcpy(data + 4, afdpart, afdlength);
+-
+-	*rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_APL, afdlength + 4, data);
+-	LDNS_FREE(afdpart);
+-	LDNS_FREE(data);
+-	LDNS_FREE(my_ip_str);
+-
+-	return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
+-}
+-
+-ldns_status
+-ldns_str2rdf_b64(ldns_rdf **rd, const char *str)
+-{
+-	uint8_t *buffer;
+-	int16_t i;
+-
+-	buffer = LDNS_XMALLOC(uint8_t, ldns_b64_ntop_calculate_size(strlen(str)));
+-        if(!buffer) {
+-                return LDNS_STATUS_MEM_ERR;
+-        }
+-
+-	i = (uint16_t)ldns_b64_pton((const char*)str, buffer,
+-						   ldns_b64_ntop_calculate_size(strlen(str)));
+-	if (-1 == i) {
+-		LDNS_FREE(buffer);
+-		return LDNS_STATUS_INVALID_B64;
+-	} else {
+-		*rd = ldns_rdf_new_frm_data(
+-			LDNS_RDF_TYPE_B64, (uint16_t) i, buffer);
+-	}
+-	LDNS_FREE(buffer);
+-
+-	return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
+-}
+-
+-ldns_status
+-ldns_str2rdf_b32_ext(ldns_rdf **rd, const char *str)
+-{
+-	uint8_t *buffer;
+-	int i;
+-	/* first byte contains length of actual b32 data */
+-	uint8_t len = ldns_b32_pton_calculate_size(strlen(str));
+-	buffer = LDNS_XMALLOC(uint8_t, len + 1);
+-        if(!buffer) {
+-                return LDNS_STATUS_MEM_ERR;
+-        }
+-	buffer[0] = len;
+-
+-	i = ldns_b32_pton_extended_hex((const char*)str, strlen(str), buffer + 1,
+-							 ldns_b32_ntop_calculate_size(strlen(str)));
+-	if (i < 0) {
+-                LDNS_FREE(buffer);
+-		return LDNS_STATUS_INVALID_B32_EXT;
+-	} else {
+-		*rd = ldns_rdf_new_frm_data(
+-			LDNS_RDF_TYPE_B32_EXT, (uint16_t) i + 1, buffer);
+-	}
+-	LDNS_FREE(buffer);
+-
+-	return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
+-}
+-
+-ldns_status
+-ldns_str2rdf_hex(ldns_rdf **rd, const char *str)
+-{
+-	uint8_t *t, *t_orig;
+-	int i;
+-	size_t len;
+-
+-	len = strlen(str);
+-
+-	if (len > LDNS_MAX_RDFLEN * 2) {
+-		return LDNS_STATUS_LABEL_OVERFLOW;
+-	} else {
+-		t = LDNS_XMALLOC(uint8_t, (len / 2) + 1);
+-                if(!t) {
+-                        return LDNS_STATUS_MEM_ERR;
+-                }
+-		t_orig = t;
+-		/* Now process octet by octet... */
+-		while (*str) {
+-			*t = 0;
+-			if (isspace((int) *str)) {
+-				str++;
+-			} else {
+-				for (i = 16; i >= 1; i -= 15) {
+-					while (*str && isspace((int) *str)) { str++; }
+-					if (*str) {
+-						if (isxdigit((int) *str)) {
+-							*t += ldns_hexdigit_to_int(*str) * i;
+-						} else {
+-                                                        LDNS_FREE(t_orig);
+-							return LDNS_STATUS_ERR;
+-						}
+-						++str;
+-					}
+-				}
+-				++t;
+-			}
+-		}
+-		*rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_HEX,
+-		                            (size_t) (t - t_orig),
+-		                            t_orig);
+-		LDNS_FREE(t_orig);
+-	}
+-	return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
+-}
+-
+-ldns_status
+-ldns_str2rdf_nsec(ldns_rdf **rd, const char *str)
+-{
+-	const char *delimiters = "\n\t ";
+-	char *token = LDNS_XMALLOC(char, LDNS_MAX_RDFLEN);
+-	ldns_buffer *str_buf;
+-	ssize_t c;
+-	uint16_t cur_type;
+-	size_t type_count = 0;
+-	ldns_rr_type type_list[65536];
+-	if(!token) return LDNS_STATUS_MEM_ERR;
+-	if(rd == NULL) {
+-		LDNS_FREE(token);
+-		return LDNS_STATUS_NULL;
+-	}
+-
+-	str_buf = LDNS_MALLOC(ldns_buffer);
+-	if(!str_buf) {
+-		LDNS_FREE(token);
+-		return LDNS_STATUS_MEM_ERR;
+-	}
+-	ldns_buffer_new_frm_data(str_buf, (char *)str, strlen(str));
+-	if(ldns_buffer_status(str_buf) != LDNS_STATUS_OK) {
+-		LDNS_FREE(str_buf);
+-		LDNS_FREE(token);
+-		return LDNS_STATUS_MEM_ERR;
+-	}
+-
+-	while ((c = ldns_bget_token(str_buf, token, delimiters, LDNS_MAX_RDFLEN)) != -1 && c != 0) {
+-                if(type_count >= sizeof(type_list)) {
+-		        LDNS_FREE(str_buf);
+-		        LDNS_FREE(token);
+-                        return LDNS_STATUS_ERR;
+-                }
+-		cur_type = ldns_get_rr_type_by_name(token);
+-		type_list[type_count] = cur_type;
+-		type_count++;
+-	}
+-
+-	*rd = ldns_dnssec_create_nsec_bitmap(type_list,
+-	                                     type_count,
+-	                                     LDNS_RR_TYPE_NSEC);
+-
+-	LDNS_FREE(token);
+-	ldns_buffer_free(str_buf);
+-	return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
+-}
+-
+-ldns_status
+-ldns_str2rdf_type(ldns_rdf **rd, const char *str)
+-{
+-	uint16_t type;
+-	type = htons(ldns_get_rr_type_by_name(str));
+-	/* ldns_rr_type is a 16 bit value */
+-	*rd = ldns_rdf_new_frm_data(
+-		LDNS_RDF_TYPE_TYPE, sizeof(uint16_t), &type);
+-	return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
+-}
+-
+-ldns_status
+-ldns_str2rdf_class(ldns_rdf **rd, const char *str)
+-{
+-	uint16_t klass;
+-	klass = htons(ldns_get_rr_class_by_name(str));
+-	/* class is 16 bit */
+-	*rd = ldns_rdf_new_frm_data(
+-		LDNS_RDF_TYPE_CLASS, sizeof(uint16_t), &klass);
+-	return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
+-}
+-
+-/* An certificate alg field can either be specified as a 8 bits number
+- * or by its symbolic name. Handle both
+- */
+-ldns_status
+-ldns_str2rdf_cert_alg(ldns_rdf **rd, const char *str)
+-{
+-	ldns_lookup_table *lt;
+-	ldns_status st;
+-	uint8_t idd[2];
+-	lt = ldns_lookup_by_name(ldns_cert_algorithms, str);
+-	st = LDNS_STATUS_OK;
+-
+-	if (lt) {
+-		ldns_write_uint16(idd, (uint16_t) lt->id);
+-		*rd = ldns_rdf_new_frm_data(
+-			LDNS_RDF_TYPE_INT16, sizeof(uint16_t), idd);
+-		if (!*rd) {
+-			st = LDNS_STATUS_ERR;
+-		}
+-	} else {
+-		/* try as-is (a number) */
+-		st = ldns_str2rdf_int16(rd, str);
+-		if (st == LDNS_STATUS_OK &&
+-		    ldns_rdf2native_int16(*rd) == 0) {
+-			st = LDNS_STATUS_CERT_BAD_ALGORITHM;
+-		}
+-	}
+-
+-	return st;
+-}
+-
+-static ldns_lookup_table ldns_tlsa_certificate_usages[] = {
+-	{ LDNS_TLSA_USAGE_PKIX_TA		, "PKIX-TA"  },
+-	{ LDNS_TLSA_USAGE_PKIX_EE		, "PKIX-EE"  },
+-	{ LDNS_TLSA_USAGE_DANE_TA		, "DANE-TA"  },
+-	{ LDNS_TLSA_USAGE_DANE_EE		, "DANE-EE"  },
+-	{ LDNS_TLSA_USAGE_PRIVCERT		, "PrivCert" }
+-};
+-
+-static ldns_lookup_table ldns_tlsa_selectors[] = {
+-	{ LDNS_TLSA_SELECTOR_CERT		, "Cert" },
+-	{ LDNS_TLSA_SELECTOR_SPKI		, "SPKI" },
+-	{ LDNS_TLSA_SELECTOR_PRIVSEL		, "PrivSel" }
+-};
+-
+-static ldns_lookup_table ldns_tlsa_matching_types[] = {
+-	{ LDNS_TLSA_MATCHING_TYPE_FULL		, "Full"      },
+-	{ LDNS_TLSA_MATCHING_TYPE_SHA2_256	, "SHA2-256"  },
+-	{ LDNS_TLSA_MATCHING_TYPE_SHA2_512	, "SHA2-512"  },
+-	{ LDNS_TLSA_MATCHING_TYPE_PRIVMATCH	, "PrivMatch" }
+-};
+-
+-static ldns_status
+-ldns_str2rdf_mnemonic4int8(ldns_lookup_table *lt,
+-		ldns_rdf **rd, const char *str)
+-{
+-	if ((lt = ldns_lookup_by_name(lt, str))) {
+-		/* it was given as a integer */
+-		*rd = ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8, (uint8_t) lt->id);
+-		if (!*rd)
+-			return LDNS_STATUS_ERR;
+-		else
+-			return LDNS_STATUS_OK;
+-	}
+-	return ldns_str2rdf_int8(rd, str);
+-}
+-
+-/* An alg field can either be specified as a 8 bits number
+- * or by its symbolic name. Handle both
+- */
+-ldns_status
+-ldns_str2rdf_alg(ldns_rdf **rd, const char *str)
+-{
+-	return ldns_str2rdf_mnemonic4int8(ldns_algorithms, rd, str);
+-}
+-
+-ldns_status
+-ldns_str2rdf_certificate_usage(ldns_rdf **rd, const char *str)
+-{
+-	return ldns_str2rdf_mnemonic4int8(
+-			ldns_tlsa_certificate_usages, rd, str);
+-}
+-
+-ldns_status
+-ldns_str2rdf_selector(ldns_rdf **rd, const char *str)
+-{
+-	return ldns_str2rdf_mnemonic4int8(ldns_tlsa_selectors, rd, str);
+-}
+-
+-ldns_status
+-ldns_str2rdf_matching_type(ldns_rdf **rd, const char *str)
+-{
+-	return ldns_str2rdf_mnemonic4int8(ldns_tlsa_matching_types, rd, str);
+-}
+-
+-ldns_status
+-ldns_str2rdf_unknown( ATTR_UNUSED(ldns_rdf **rd)
+-		    , ATTR_UNUSED(const char *str)
+-		    )
+-{
+-	/* this should be caught in an earlier time (general str2host for
+-	   rr's */
+-	return LDNS_STATUS_NOT_IMPL;
+-}
+-
+-ldns_status
+-ldns_str2rdf_service( ATTR_UNUSED(ldns_rdf **rd)
+-		    , ATTR_UNUSED(const char *str)
+-		    )
+-{
+-	/* is this used? is this actually WKS? or SRV? */
+-	return LDNS_STATUS_NOT_IMPL;
+-}
+-
+-static int
+-loc_parse_cm(char* my_str, char** endstr, uint8_t* m, uint8_t* e)
+-{
+-	/* read <digits>[.<digits>][mM] */
+-	/* into mantissa exponent format for LOC type */
+-	uint32_t meters = 0, cm = 0, val;
+-	while (isblank(*my_str)) {
+-		my_str++;
+-	}
+-	meters = (uint32_t)strtol(my_str, &my_str, 10);
+-	if (*my_str == '.') {
+-		my_str++;
+-		cm = (uint32_t)strtol(my_str, &my_str, 10);
+-	}
+-	if (meters >= 1) {
+-		*e = 2;
+-		val = meters;
+-	} else	{
+-		*e = 0;
+-		val = cm;
+-	}
+-	while(val >= 10) {
+-		(*e)++;
+-		val /= 10;
+-	}
+-	*m = (uint8_t)val;
+-
+-	if (*e > 9)
+-		return 0;
+-	if (*my_str == 'm' || *my_str == 'M') {
+-		my_str++;
+-	}
+-	*endstr = my_str;
+-	return 1;
+-}
+-
+-ldns_status
+-ldns_str2rdf_loc(ldns_rdf **rd, const char *str)
+-{
+-	uint32_t latitude = 0;
+-	uint32_t longitude = 0;
+-	uint32_t altitude = 0;
+-
+-	uint8_t *data;
+-	uint32_t equator = (uint32_t) ldns_power(2, 31);
+-
+-	uint32_t h = 0;
+-	uint32_t m = 0;
+-	uint8_t size_b = 1, size_e = 2;
+-	uint8_t horiz_pre_b = 1, horiz_pre_e = 6;
+-	uint8_t vert_pre_b = 1, vert_pre_e = 3;
+-
+-	double s = 0.0;
+-	bool northerness;
+-	bool easterness;
+-
+-	char *my_str = (char *) str;
+-
+-	/* only support version 0 */
+-	if (isdigit((int) *my_str)) {
+-		h = (uint32_t) strtol(my_str, &my_str, 10);
+-	} else {
+-		return LDNS_STATUS_INVALID_STR;
+-	}
+-
+-	while (isblank((int) *my_str)) {
+-		my_str++;
+-	}
+-
+-	if (isdigit((int) *my_str)) {
+-		m = (uint32_t) strtol(my_str, &my_str, 10);
+-	} else if (*my_str == 'N' || *my_str == 'S') {
+-		goto north;
+-	} else {
+-		return LDNS_STATUS_INVALID_STR;
+-	}
+-
+-	while (isblank((int) *my_str)) {
+-		my_str++;
+-	}
+-
+-	if (isdigit((int) *my_str)) {
+-		s = strtod(my_str, &my_str);
+-	}
+-north:
+-	while (isblank((int) *my_str)) {
+-		my_str++;
+-	}
+-
+-	if (*my_str == 'N') {
+-		northerness = true;
+-	} else if (*my_str == 'S') {
+-		northerness = false;
+-	} else {
+-		return LDNS_STATUS_INVALID_STR;
+-	}
+-
+-	my_str++;
+-
+-	/* store number */
+-	s = 1000.0 * s;
+-	/* add a little to make floor in conversion a round */
+-	s += 0.0005;
+-	latitude = (uint32_t) s;
+-	latitude += 1000 * 60 * m;
+-	latitude += 1000 * 60 * 60 * h;
+-	if (northerness) {
+-		latitude = equator + latitude;
+-	} else {
+-		latitude = equator - latitude;
+-	}
+-	while (isblank(*my_str)) {
+-		my_str++;
+-	}
+-
+-	if (isdigit((int) *my_str)) {
+-		h = (uint32_t) strtol(my_str, &my_str, 10);
+-	} else {
+-		return LDNS_STATUS_INVALID_STR;
+-	}
+-
+-	while (isblank((int) *my_str)) {
+-		my_str++;
+-	}
+-
+-	if (isdigit((int) *my_str)) {
+-		m = (uint32_t) strtol(my_str, &my_str, 10);
+-	} else if (*my_str == 'E' || *my_str == 'W') {
+-		goto east;
+-	} else {
+-		return LDNS_STATUS_INVALID_STR;
+-	}
+-
+-	while (isblank(*my_str)) {
+-		my_str++;
+-	}
+-
+-	if (isdigit((int) *my_str)) {
+-		s = strtod(my_str, &my_str);
+-	}
+-
+-east:
+-	while (isblank(*my_str)) {
+-		my_str++;
+-	}
+-
+-	if (*my_str == 'E') {
+-		easterness = true;
+-	} else if (*my_str == 'W') {
+-		easterness = false;
+-	} else {
+-		return LDNS_STATUS_INVALID_STR;
+-	}
+-
+-	my_str++;
+-
+-	/* store number */
+-	s *= 1000.0;
+-	/* add a little to make floor in conversion a round */
+-	s += 0.0005;
+-	longitude = (uint32_t) s;
+-	longitude += 1000 * 60 * m;
+-	longitude += 1000 * 60 * 60 * h;
+-
+-	if (easterness) {
+-		longitude += equator;
+-	} else {
+-		longitude = equator - longitude;
+-	}
+-
+-	altitude = (uint32_t)(strtod(my_str, &my_str)*100.0 +
+-		10000000.0 + 0.5);
+-	if (*my_str == 'm' || *my_str == 'M') {
+-		my_str++;
+-	}
+-
+-	if (strlen(my_str) > 0) {
+-		if(!loc_parse_cm(my_str, &my_str, &size_b, &size_e))
+-			return LDNS_STATUS_INVALID_STR;
+-	}
+-
+-	if (strlen(my_str) > 0) {
+-		if(!loc_parse_cm(my_str, &my_str, &horiz_pre_b, &horiz_pre_e))
+-			return LDNS_STATUS_INVALID_STR;
+-	}
+-
+-	if (strlen(my_str) > 0) {
+-		if(!loc_parse_cm(my_str, &my_str, &vert_pre_b, &vert_pre_e))
+-			return LDNS_STATUS_INVALID_STR;
+-	}
+-
+-	data = LDNS_XMALLOC(uint8_t, 16);
+-        if(!data) {
+-                return LDNS_STATUS_MEM_ERR;
+-        }
+-	data[0] = 0;
+-	data[1] = 0;
+-	data[1] = ((size_b << 4) & 0xf0) | (size_e & 0x0f);
+-	data[2] = ((horiz_pre_b << 4) & 0xf0) | (horiz_pre_e & 0x0f);
+-	data[3] = ((vert_pre_b << 4) & 0xf0) | (vert_pre_e & 0x0f);
+-	ldns_write_uint32(data + 4, latitude);
+-	ldns_write_uint32(data + 8, longitude);
+-	ldns_write_uint32(data + 12, altitude);
+-
+-	*rd = ldns_rdf_new_frm_data(
+-		LDNS_RDF_TYPE_LOC, 16, data);
+-
+-	LDNS_FREE(data);
+-	return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR;
+-}
+-
+-ldns_status
+-ldns_str2rdf_wks(ldns_rdf **rd, const char *str)
+-{
+-	uint8_t *bitmap = NULL;
+-	uint8_t *data;
+-	int bm_len = 0;
+-
+-	struct protoent *proto = NULL;
+-	struct servent *serv = NULL;
+-	int serv_port;
+-
+-	ldns_buffer *str_buf;
+-
+-	char *proto_str = NULL;
+-	char *token;
+-	if(strlen(str) == 0)
+-		token = LDNS_XMALLOC(char, 50);
+-	else 	token = LDNS_XMALLOC(char, strlen(str)+2);
+-	if(!token) return LDNS_STATUS_MEM_ERR;
+-
+-	str_buf = LDNS_MALLOC(ldns_buffer);
+-	if(!str_buf) {LDNS_FREE(token); return LDNS_STATUS_MEM_ERR;}
+-	ldns_buffer_new_frm_data(str_buf, (char *)str, strlen(str));
+-	if(ldns_buffer_status(str_buf) != LDNS_STATUS_OK) {
+-		LDNS_FREE(str_buf);
+-		LDNS_FREE(token);
+-		return LDNS_STATUS_MEM_ERR;
+-	}
+-
+-	while(ldns_bget_token(str_buf, token, "\t\n ", strlen(str)) > 0) {
+-		if (!proto_str) {
+-			proto_str = strdup(token);
+-			if (!proto_str) {
+-				LDNS_FREE(bitmap);
+-				LDNS_FREE(token);
+-	                        ldns_buffer_free(str_buf);
+-				return LDNS_STATUS_INVALID_STR;
+-			}
+-		} else {
+-			serv = getservbyname(token, proto_str);
+-			if (serv) {
+-				serv_port = (int) ntohs((uint16_t) serv->s_port);
+-			} else {
+-				serv_port = atoi(token);
+-			}
+-			if (serv_port / 8 >= bm_len) {
+-				uint8_t *b2 = LDNS_XREALLOC(bitmap, uint8_t, (serv_port / 8) + 1);
+-                                if(!b2) {
+-					LDNS_FREE(bitmap);
+-				        LDNS_FREE(token);
+-	                                ldns_buffer_free(str_buf);
+-				        free(proto_str);
+-				        return LDNS_STATUS_INVALID_STR;
+-                                }
+-				bitmap = b2;
+-				/* set to zero to be sure */
+-				for (; bm_len <= serv_port / 8; bm_len++) {
+-					bitmap[bm_len] = 0;
+-				}
+-			}
+-			ldns_set_bit(bitmap + (serv_port / 8), 7 - (serv_port % 8), true);
+-		}
+-	}
+-
+-	if (!proto_str || !bitmap) {
+-		LDNS_FREE(bitmap);
+-		LDNS_FREE(token);
+-	        ldns_buffer_free(str_buf);
+-	        free(proto_str);
+-		return LDNS_STATUS_INVALID_STR;
+-	}
+-
+-	data = LDNS_XMALLOC(uint8_t, bm_len + 1);
+-        if(!data) {
+-	        LDNS_FREE(token);
+-	        ldns_buffer_free(str_buf);
+-	        LDNS_FREE(bitmap);
+-	        free(proto_str);
+-	        return LDNS_STATUS_INVALID_STR;
+-        }
+-    if (proto_str)
+-		proto = getprotobyname(proto_str);
+-	if (proto) {
+-		data[0] = (uint8_t) proto->p_proto;
+-	} else if (proto_str) {
+-		data[0] = (uint8_t) atoi(proto_str);
+-	}
+-	memcpy(data + 1, bitmap, (size_t) bm_len);
+-
+-	*rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_WKS, (uint16_t) (bm_len + 1), data);
+-
+-	LDNS_FREE(data);
+-	LDNS_FREE(token);
+-	ldns_buffer_free(str_buf);
+-	LDNS_FREE(bitmap);
+-	free(proto_str);
+-#ifdef HAVE_ENDSERVENT
+-	endservent();
+-#endif
+-#ifdef HAVE_ENDPROTOENT
+-	endprotoent();
+-#endif
+-
+-	if(!*rd) return LDNS_STATUS_MEM_ERR;
+-
+-	return LDNS_STATUS_OK;
+-}
+-
+-ldns_status
+-ldns_str2rdf_nsap(ldns_rdf **rd, const char *str)
+-{
+-    size_t len, i;
+-    char* nsap_str = (char*) str;
+-
+-	/* just a hex string with optional dots? */
+-	if (str[0] != '0' || str[1] != 'x') {
+-		return LDNS_STATUS_INVALID_STR;
+-	} else {
+-		len = strlen(str);
+-		for (i=0; i < len; i++) {
+-			if (nsap_str[i] == '.')
+-				nsap_str[i] = ' ';
+-        }
+-		return ldns_str2rdf_hex(rd, str+2);
+-	}
+-}
+-
+-ldns_status
+-ldns_str2rdf_atma(ldns_rdf **rd, const char *str)
+-{
+-    size_t len, i;
+-    char* atma_str = (char*) str;
+-	ldns_status status;
+-
+-	/* just a hex string with optional dots? */
+-	len = strlen(str);
+-	for (i=0; i < len; i++) {
+-		if (atma_str[i] == '.')
+-			atma_str[i] = ' ';
+-	}
+-	status = ldns_str2rdf_hex(rd, str);
+-    if (status != LDNS_STATUS_OK) {
+-		; /* probably in e.164 format than */
+-	}
+-	return status;
+-}
+-
+-ldns_status
+-ldns_str2rdf_ipseckey(ldns_rdf **rd, const char *str)
+-{
+-	uint8_t precedence = 0;
+-	uint8_t gateway_type = 0;
+-	uint8_t algorithm = 0;
+-	char* gateway = NULL;
+-	char* publickey = NULL;
+-	uint8_t *data;
+-	ldns_buffer *str_buf;
+-	char *token;
+-	int token_count = 0;
+-	int ipseckey_len = 0;
+-	ldns_rdf* gateway_rdf = NULL;
+-	ldns_rdf* publickey_rdf = NULL;
+-	ldns_status status = LDNS_STATUS_OK;
+-	
+-	if(strlen(str) == 0)
+-		token = LDNS_XMALLOC(char, 256);
+-	else	token = LDNS_XMALLOC(char, strlen(str)+2);
+-	if(!token) return LDNS_STATUS_MEM_ERR;
+-
+-	str_buf = LDNS_MALLOC(ldns_buffer);
+-	if(!str_buf) {LDNS_FREE(token); return LDNS_STATUS_MEM_ERR;}
+-	ldns_buffer_new_frm_data(str_buf, (char *)str, strlen(str));
+-	if(ldns_buffer_status(str_buf) != LDNS_STATUS_OK) {
+-		LDNS_FREE(str_buf);
+-		LDNS_FREE(token);
+-		return LDNS_STATUS_MEM_ERR;
+-	}
+-	while(ldns_bget_token(str_buf, token, "\t\n ", strlen(str)) > 0) {
+-		switch (token_count) {
+-				case 0:
+-					precedence = (uint8_t)atoi(token);
+-					break;
+-				case 1:
+-					gateway_type = (uint8_t)atoi(token);
+-					break;
+-				case 2:
+-					algorithm = (uint8_t)atoi(token);
+-					break;
+-				case 3:
+-					gateway = strdup(token);
+-					if (!gateway || (gateway_type == 0 &&
+-							(token[0] != '.' || token[1] != '\0'))) {
+-						LDNS_FREE(gateway);
+-						LDNS_FREE(token);
+-						ldns_buffer_free(str_buf);
+-						return LDNS_STATUS_INVALID_STR;
+-					}
+-					break;
+-				case 4:
+-					publickey = strdup(token);
+-					break;
+-				default:
+-					LDNS_FREE(token);
+-					ldns_buffer_free(str_buf);
+-					return LDNS_STATUS_INVALID_STR;
+-					break;
+-		}
+-		token_count++;
+-	}
+-
+-	if (!gateway || !publickey) {
+-		if (gateway)
+-			LDNS_FREE(gateway);
+-		if (publickey)
+-			LDNS_FREE(publickey);
+-		LDNS_FREE(token);
+-		ldns_buffer_free(str_buf);
+-		return LDNS_STATUS_INVALID_STR;
+-	}
+-
+-	if (gateway_type == 1) {
+-		status = ldns_str2rdf_a(&gateway_rdf, gateway);
+-	} else if (gateway_type == 2) {
+-		status = ldns_str2rdf_aaaa(&gateway_rdf, gateway);
+-	} else if (gateway_type == 3) {
+-		status = ldns_str2rdf_dname(&gateway_rdf, gateway);
+-	}
+-
+-	if (status != LDNS_STATUS_OK) {
+-		if (gateway)
+-			LDNS_FREE(gateway);
+-		if (publickey)
+-			LDNS_FREE(publickey);
+-		LDNS_FREE(token);
+-		ldns_buffer_free(str_buf);
+-		return LDNS_STATUS_INVALID_STR;
+-	}
+-
+-	status = ldns_str2rdf_b64(&publickey_rdf, publickey);
+-
+-	if (status != LDNS_STATUS_OK) {
+-		if (gateway)
+-			LDNS_FREE(gateway);
+-		if (publickey)
+-			LDNS_FREE(publickey);
+-		LDNS_FREE(token);
+-		ldns_buffer_free(str_buf);
+-		if (gateway_rdf) ldns_rdf_free(gateway_rdf);
+-		return LDNS_STATUS_INVALID_STR;
+-	}
+-
+-	/* now copy all into one ipseckey rdf */
+-	if (gateway_type)
+-		ipseckey_len = 3 + (int)ldns_rdf_size(gateway_rdf) + (int)ldns_rdf_size(publickey_rdf);
+-	else
+-		ipseckey_len = 3 + (int)ldns_rdf_size(publickey_rdf);
+-
+-	data = LDNS_XMALLOC(uint8_t, ipseckey_len);
+-	if(!data) {
+-		if (gateway)
+-			LDNS_FREE(gateway);
+-		if (publickey)
+-			LDNS_FREE(publickey);
+-		LDNS_FREE(token);
+-		ldns_buffer_free(str_buf);
+-		if (gateway_rdf) ldns_rdf_free(gateway_rdf);
+-		if (publickey_rdf) ldns_rdf_free(publickey_rdf);
+-		return LDNS_STATUS_MEM_ERR;
+-	}
+-
+-	data[0] = precedence;
+-	data[1] = gateway_type;
+-	data[2] = algorithm;
+-
+-	if (gateway_type) {
+-		memcpy(data + 3,
+-			ldns_rdf_data(gateway_rdf), ldns_rdf_size(gateway_rdf));
+-		memcpy(data + 3 + ldns_rdf_size(gateway_rdf),
+-			ldns_rdf_data(publickey_rdf), ldns_rdf_size(publickey_rdf));
+-	} else {
+-		memcpy(data + 3,
+-			ldns_rdf_data(publickey_rdf), ldns_rdf_size(publickey_rdf));
+-	}
+-
+-	*rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_IPSECKEY, (uint16_t) ipseckey_len, data);
+-
+-	if (gateway)
+-		LDNS_FREE(gateway);
+-	if (publickey)
+-		LDNS_FREE(publickey);
+-	LDNS_FREE(token);
+-	ldns_buffer_free(str_buf);
+-	ldns_rdf_free(gateway_rdf);
+-	ldns_rdf_free(publickey_rdf);
+-	LDNS_FREE(data);
+-	if(!*rd) return LDNS_STATUS_MEM_ERR;
+-	return LDNS_STATUS_OK;
+-}
+-
+-ldns_status
+-ldns_str2rdf_ilnp64(ldns_rdf **rd, const char *str)
+-{
+-	unsigned int a, b, c, d;
+-	uint16_t shorts[4];
+-	int l;
+-
+-	if (sscanf(str, "%4x:%4x:%4x:%4x%n", &a, &b, &c, &d, &l) != 4 ||
+-			l != (int)strlen(str) || /* more data to read */
+-			strpbrk(str, "+-")       /* signed hexes */
+-			) {
+-		return LDNS_STATUS_INVALID_ILNP64;
+-	} else {
+-		shorts[0] = htons(a);
+-		shorts[1] = htons(b);
+-		shorts[2] = htons(c);
+-		shorts[3] = htons(d);
+-		*rd = ldns_rdf_new_frm_data(
+-			LDNS_RDF_TYPE_ILNP64, 4 * sizeof(uint16_t), &shorts);
+-	}
+-	return *rd ? LDNS_STATUS_OK : LDNS_STATUS_MEM_ERR;
+-}
+-
+-ldns_status
+-ldns_str2rdf_eui48(ldns_rdf **rd, const char *str)
+-{
+-	unsigned int a, b, c, d, e, f;
+-	uint8_t bytes[6];
+-	int l;
+-
+-	if (sscanf(str, "%2x-%2x-%2x-%2x-%2x-%2x%n",
+-			&a, &b, &c, &d, &e, &f, &l) != 6 ||
+-			l != (int)strlen(str)) {
+-		return LDNS_STATUS_INVALID_EUI48;
+-	} else {
+-		bytes[0] = a;
+-		bytes[1] = b;
+-		bytes[2] = c;
+-		bytes[3] = d;
+-		bytes[4] = e;
+-		bytes[5] = f;
+-		*rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_EUI48, 6, &bytes);
+-	}
+-	return *rd ? LDNS_STATUS_OK : LDNS_STATUS_MEM_ERR;
+-}
+-
+-ldns_status
+-ldns_str2rdf_eui64(ldns_rdf **rd, const char *str)
+-{
+-	unsigned int a, b, c, d, e, f, g, h;
+-	uint8_t bytes[8];
+-	int l;
+-
+-	if (sscanf(str, "%2x-%2x-%2x-%2x-%2x-%2x-%2x-%2x%n",
+-			&a, &b, &c, &d, &e, &f, &g, &h, &l) != 8 ||
+-			l != (int)strlen(str)) {
+-		return LDNS_STATUS_INVALID_EUI64;
+-	} else {
+-		bytes[0] = a;
+-		bytes[1] = b;
+-		bytes[2] = c;
+-		bytes[3] = d;
+-		bytes[4] = e;
+-		bytes[5] = f;
+-		bytes[6] = g;
+-		bytes[7] = h;
+-		*rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_EUI64, 8, &bytes);
+-	}
+-	return *rd ? LDNS_STATUS_OK : LDNS_STATUS_MEM_ERR;
+-}
+-
+-ldns_status
+-ldns_str2rdf_tag(ldns_rdf **rd, const char *str)
+-{
+-	uint8_t *data;
+-	const char* ptr;
+-
+-	if (strlen(str) > 255) {
+-		return LDNS_STATUS_INVALID_TAG;
+-	}
+-	for (ptr = str; *ptr; ptr++) {
+-		if (! isalnum(*ptr)) {
+-			return LDNS_STATUS_INVALID_TAG;
+-		}
+-	}
+-	data = LDNS_XMALLOC(uint8_t, strlen(str) + 1);
+-        if (!data) {
+-		return LDNS_STATUS_MEM_ERR;
+-	}
+-	data[0] = strlen(str);
+-	memcpy(data + 1, str, strlen(str));
+-
+-	*rd = ldns_rdf_new(LDNS_RDF_TYPE_TAG, strlen(str) + 1, data);
+-	if (!*rd) {
+-		LDNS_FREE(data);
+-		return LDNS_STATUS_MEM_ERR;
+-	}
+-	return LDNS_STATUS_OK;
+-}
+-
+-ldns_status
+-ldns_str2rdf_long_str(ldns_rdf **rd, const char *str)
+-{
+-	uint8_t *data, *dp, ch = 0;
+-	size_t length;
+-
+-	/* Worst case space requirement. We'll realloc to actual size later. */
+-	dp = data = LDNS_XMALLOC(uint8_t, strlen(str));
+-        if (! data) {
+-		return LDNS_STATUS_MEM_ERR;
+-	}
+-
+-	/* Fill data with parsed bytes */
+-	while (parse_char(&ch, &str)) {
+-		*dp++ = ch;
+-		if (dp - data > LDNS_MAX_RDFLEN) {
+-			LDNS_FREE(data);
+-			return LDNS_STATUS_INVALID_STR;
+-		}
+-	}
+-	if (! str) {
+-		return LDNS_STATUS_SYNTAX_BAD_ESCAPE;
+-	}
+-	length = (size_t)(dp - data);
+-
+-	/* Lose the overmeasure */
+-	data = LDNS_XREALLOC(dp = data, uint8_t, length);
+-	if (! data) {
+-		LDNS_FREE(dp);
+-		return LDNS_STATUS_MEM_ERR;
+-	}
+-
+-	/* Create rdf */
+-	*rd = ldns_rdf_new(LDNS_RDF_TYPE_LONG_STR, length, data);
+-	if (! *rd) {
+-		LDNS_FREE(data);
+-		return LDNS_STATUS_MEM_ERR;
+-	}
+-	return LDNS_STATUS_OK;
+-}
+-
+-ldns_status
+-ldns_str2rdf_hip(ldns_rdf **rd, const char *str)
+-{
+-	const char *hit = strchr(str, ' ') + 1;
+-	const char *pk  = hit == NULL ? NULL : strchr(hit, ' ') + 1;
+-	size_t hit_size = hit == NULL ? 0
+-	                : pk  == NULL ? strlen(hit) : (size_t) (pk - hit) - 1;
+-	size_t  pk_size = pk  == NULL ? 0 : strlen(pk);
+-	size_t hit_wire_size = (hit_size + 1) / 2;
+-	size_t  pk_wire_size = ldns_b64_pton_calculate_size(pk_size);
+-	size_t rdf_size = 4 + hit_wire_size + pk_wire_size;
+-
+-	char *endptr; /* utility var for strtol usage */
+-	int algorithm = strtol(str, &endptr, 10);
+-
+-	uint8_t *data, *dp;
+-	int hi, lo, written;
+-
+-	if (hit_size == 0 || pk_size == 0 || (hit_size + 1) / 2 > 255
+-			|| rdf_size > LDNS_MAX_RDFLEN
+-			|| algorithm < 0 || algorithm > 255
+-			|| (errno != 0 && algorithm == 0) /* out of range */
+-			|| endptr == str                  /* no digits    */) {
+-
+-		return LDNS_STATUS_SYNTAX_ERR;
+-	}
+-	if ((data = LDNS_XMALLOC(uint8_t, rdf_size)) == NULL) {
+-
+-		return LDNS_STATUS_MEM_ERR;
+-	}
+-	/* From RFC 5205 section 5. HIP RR Storage Format:
+-	 *************************************************
+-
+-	0                   1                   2                   3
+-	0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-	+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+-	|  HIT length   | PK algorithm  |          PK length            |
+-	+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+-	|                                                               |
+-	~                           HIT                                 ~
+-	|                                                               |
+-	+                     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+-	|                     |                                         |
+-	+-+-+-+-+-+-+-+-+-+-+-+                                         +
+-	|                           Public Key                          |
+-	~                                                               ~
+-	|                                                               |
+-	+                               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+-	|                               |                               |
+-	+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               +
+-	|                                                               |
+-	~                       Rendezvous Servers                      ~
+-	|                                                               |
+-	+             +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+-	|             |
+-	+-+-+-+-+-+-+-+                                                    */
+-
+-	data[0] = (uint8_t) hit_wire_size;
+-	data[1] = (uint8_t) algorithm;
+-
+-	for (dp = data + 4; *hit && *hit != ' '; dp++) {
+-
+-		if ((hi = ldns_hexdigit_to_int(*hit++)) == -1 ||
+-		    (lo = ldns_hexdigit_to_int(*hit++)) == -1) {
+-
+-			LDNS_FREE(data);
+-			return LDNS_STATUS_INVALID_HEX;
+-		}
+-		*dp = (uint8_t) hi << 4 | lo;
+-	}
+-	if ((written = ldns_b64_pton(pk, dp, pk_wire_size)) <= 0) {
+-
+-		LDNS_FREE(data);
+-		return LDNS_STATUS_INVALID_B64;
+-	}
+-
+-	/* Because ldns_b64_pton_calculate_size isn't always correct:
+-	 * (we have to fix it at some point)
+-	 */
+-	pk_wire_size = (uint16_t) written;
+-	ldns_write_uint16(data + 2, pk_wire_size);
+-	rdf_size = 4 + hit_wire_size + pk_wire_size;
+-
+-	/* Create rdf */
+-	if (! (*rd = ldns_rdf_new(LDNS_RDF_TYPE_HIP, rdf_size, data))) {
+-
+-		LDNS_FREE(data);
+-		return LDNS_STATUS_MEM_ERR;
+-	}
+-	return LDNS_STATUS_OK;
+-}
+diff --git a/src/ldns/tsig.c b/src/ldns/tsig.c
+deleted file mode 100644
+index 53aa85e..0000000
+--- a/src/ldns/tsig.c
++++ /dev/null
+@@ -1,470 +0,0 @@
+-/*
+- * tsig.c
+- *
+- * contains the functions needed for TSIG [RFC2845]
+- *
+- * (c) 2005-2006 NLnet Labs
+- * See the file LICENSE for the license
+- */
+-
+-#include <ldns/config.h>
+-
+-#include <ldns/ldns.h>
+-
+-#include <strings.h>
+-
+-#ifdef HAVE_SSL
+-#include <openssl/hmac.h>
+-#include <openssl/md5.h>
+-#endif /* HAVE_SSL */
+-
+-char *
+-ldns_tsig_algorithm(ldns_tsig_credentials *tc)
+-{
+-	return tc->algorithm;
+-}
+-
+-char *
+-ldns_tsig_keyname(ldns_tsig_credentials *tc)
+-{
+-	return tc->keyname;
+-}
+-
+-char *
+-ldns_tsig_keydata(ldns_tsig_credentials *tc)
+-{
+-	return tc->keydata;
+-}
+-
+-char *
+-ldns_tsig_keyname_clone(ldns_tsig_credentials *tc)
+-{
+-	return strdup(tc->keyname);
+-}
+-
+-char *
+-ldns_tsig_keydata_clone(ldns_tsig_credentials *tc)
+-{
+-	return strdup(tc->keydata);
+-}
+-
+-/*
+- *  Makes an exact copy of the wire, but with the tsig rr removed
+- */
+-static uint8_t *
+-ldns_tsig_prepare_pkt_wire(uint8_t *wire, size_t wire_len, size_t *result_len)
+-{
+-	uint8_t *wire2 = NULL;
+-	uint16_t qd_count;
+-	uint16_t an_count;
+-	uint16_t ns_count;
+-	uint16_t ar_count;
+-	ldns_rr *rr;
+-
+-	size_t pos;
+-	uint16_t i;
+-
+-	ldns_status status;
+-
+-	if(wire_len < LDNS_HEADER_SIZE) {
+-		return NULL;
+-	}
+-	/* fake parse the wire */
+-	qd_count = LDNS_QDCOUNT(wire);
+-	an_count = LDNS_ANCOUNT(wire);
+-	ns_count = LDNS_NSCOUNT(wire);
+-	ar_count = LDNS_ARCOUNT(wire);
+-
+-	if (ar_count > 0) {
+-		ar_count--;
+-	} else {
+-		return NULL;
+-	}
+-
+-	pos = LDNS_HEADER_SIZE;
+-
+-	for (i = 0; i < qd_count; i++) {
+-		status = ldns_wire2rr(&rr, wire, wire_len, &pos, LDNS_SECTION_QUESTION);
+-		if (status != LDNS_STATUS_OK) {
+-			return NULL;
+-		}
+-		ldns_rr_free(rr);
+-	}
+-
+-	for (i = 0; i < an_count; i++) {
+-		status = ldns_wire2rr(&rr, wire, wire_len, &pos, LDNS_SECTION_ANSWER);
+-		if (status != LDNS_STATUS_OK) {
+-			return NULL;
+-		}
+-		ldns_rr_free(rr);
+-	}
+-
+-	for (i = 0; i < ns_count; i++) {
+-		status = ldns_wire2rr(&rr, wire, wire_len, &pos, LDNS_SECTION_AUTHORITY);
+-		if (status != LDNS_STATUS_OK) {
+-			return NULL;
+-		}
+-		ldns_rr_free(rr);
+-	}
+-
+-	for (i = 0; i < ar_count; i++) {
+-		status = ldns_wire2rr(&rr, wire, wire_len, &pos,
+-				LDNS_SECTION_ADDITIONAL);
+-		if (status != LDNS_STATUS_OK) {
+-			return NULL;
+-		}
+-		ldns_rr_free(rr);
+-	}
+-
+-	*result_len = pos;
+-	wire2 = LDNS_XMALLOC(uint8_t, *result_len);
+-	if(!wire2) {
+-		return NULL;
+-	}
+-	memcpy(wire2, wire, *result_len);
+-
+-	ldns_write_uint16(wire2 + LDNS_ARCOUNT_OFF, ar_count);
+-
+-	return wire2;
+-}
+-
+-#ifdef HAVE_SSL
+-static const EVP_MD *
+-ldns_digest_function(char *name)
+-{
+-	/* these are the mandatory algorithms from RFC4635 */
+-	/* The optional algorithms are not yet implemented */
+-	if (strcasecmp(name, "hmac-sha256.") == 0) {
+-#ifdef HAVE_EVP_SHA256
+-		return EVP_sha256();
+-#else
+-		return NULL;
+-#endif
+-	} else if (strcasecmp(name, "hmac-sha1.") == 0) {
+-		return EVP_sha1();
+-	} else if (strcasecmp(name, "hmac-md5.sig-alg.reg.int.") == 0) {
+-		return EVP_md5();
+-	} else {
+-		return NULL;
+-	}
+-}
+-#endif
+-
+-#ifdef HAVE_SSL
+-static ldns_status
+-ldns_tsig_mac_new(ldns_rdf **tsig_mac, uint8_t *pkt_wire, size_t pkt_wire_size,
+-		const char *key_data, ldns_rdf *key_name_rdf, ldns_rdf *fudge_rdf,
+-		ldns_rdf *algorithm_rdf, ldns_rdf *time_signed_rdf, ldns_rdf *error_rdf,
+-		ldns_rdf *other_data_rdf, ldns_rdf *orig_mac_rdf, int tsig_timers_only)
+-{
+-	ldns_status status;
+-	char *wireformat;
+-	int wiresize;
+-	unsigned char *mac_bytes = NULL;
+-	unsigned char *key_bytes = NULL;
+-	int key_size;
+-	const EVP_MD *digester;
+-	char *algorithm_name = NULL;
+-	unsigned int md_len = EVP_MAX_MD_SIZE;
+-	ldns_rdf *result = NULL;
+-	ldns_buffer *data_buffer = NULL;
+-	ldns_rdf *canonical_key_name_rdf = NULL;
+-	ldns_rdf *canonical_algorithm_rdf = NULL;
+-	
+-	if (key_name_rdf == NULL || algorithm_rdf == NULL) {
+-		return LDNS_STATUS_NULL;
+-	}
+-	canonical_key_name_rdf  = ldns_rdf_clone(key_name_rdf);
+-	if (canonical_key_name_rdf == NULL) {
+-		return LDNS_STATUS_MEM_ERR;
+-	}
+-	canonical_algorithm_rdf = ldns_rdf_clone(algorithm_rdf);
+-	if (canonical_algorithm_rdf == NULL) {
+-		ldns_rdf_deep_free(canonical_key_name_rdf);
+-		return LDNS_STATUS_MEM_ERR;
+-	}
+-	/*
+-	 * prepare the digestable information
+-	 */
+-	data_buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN);
+-	if (!data_buffer) {
+-		status = LDNS_STATUS_MEM_ERR;
+-		goto clean;
+-	}
+-	/* if orig_mac is not NULL, add it too */
+-	if (orig_mac_rdf) {
+-		(void) ldns_rdf2buffer_wire(data_buffer, orig_mac_rdf);
+- 	}
+-	ldns_buffer_write(data_buffer, pkt_wire, pkt_wire_size);
+-	if (!tsig_timers_only) {
+-		ldns_dname2canonical(canonical_key_name_rdf);
+-		(void)ldns_rdf2buffer_wire(data_buffer, 
+-				canonical_key_name_rdf);
+-		ldns_buffer_write_u16(data_buffer, LDNS_RR_CLASS_ANY);
+-		ldns_buffer_write_u32(data_buffer, 0);
+-		ldns_dname2canonical(canonical_algorithm_rdf);
+-		(void)ldns_rdf2buffer_wire(data_buffer, 
+-				canonical_algorithm_rdf);
+-	}
+-	(void)ldns_rdf2buffer_wire(data_buffer, time_signed_rdf);
+-	(void)ldns_rdf2buffer_wire(data_buffer, fudge_rdf);
+-	if (!tsig_timers_only) {
+-		(void)ldns_rdf2buffer_wire(data_buffer, error_rdf);
+-		(void)ldns_rdf2buffer_wire(data_buffer, other_data_rdf);
+-	}
+-
+-	wireformat = (char *) data_buffer->_data;
+-	wiresize = (int) ldns_buffer_position(data_buffer);
+-
+-	algorithm_name = ldns_rdf2str(algorithm_rdf);
+-	if(!algorithm_name) {
+-		status = LDNS_STATUS_MEM_ERR;
+-		goto clean;
+-	}
+-
+-	/* prepare the key */
+-	key_bytes = LDNS_XMALLOC(unsigned char,
+-			ldns_b64_pton_calculate_size(strlen(key_data)));
+-	if(!key_bytes) {
+-		status = LDNS_STATUS_MEM_ERR;
+-		goto clean;
+-	}
+-	key_size = ldns_b64_pton(key_data, key_bytes,
+-	ldns_b64_pton_calculate_size(strlen(key_data)));
+-	if (key_size < 0) {
+-		status = LDNS_STATUS_INVALID_B64;
+-		goto clean;
+-	}
+-	/* hmac it */
+-	/* 2 spare bytes for the length */
+-	mac_bytes = LDNS_XMALLOC(unsigned char, md_len+2);
+-	if(!mac_bytes) {
+-		status = LDNS_STATUS_MEM_ERR;
+-		goto clean;
+-	}
+-	memset(mac_bytes, 0, md_len+2);
+-
+-	digester = ldns_digest_function(algorithm_name);
+-
+-	if (digester) {
+-		(void) HMAC(digester, key_bytes, key_size, (void *)wireformat,
+-		            (size_t) wiresize, mac_bytes + 2, &md_len);
+-
+-		ldns_write_uint16(mac_bytes, md_len);
+-		result = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_INT16_DATA, md_len + 2,
+-				mac_bytes);
+-	} else {
+-		status = LDNS_STATUS_CRYPTO_UNKNOWN_ALGO;
+-		goto clean;
+-	}
+-	*tsig_mac = result;
+-	status = LDNS_STATUS_OK;
+-  clean:
+-	LDNS_FREE(mac_bytes);
+-	LDNS_FREE(key_bytes);
+-	LDNS_FREE(algorithm_name);
+-	ldns_buffer_free(data_buffer);
+-	ldns_rdf_deep_free(canonical_algorithm_rdf);
+-	ldns_rdf_deep_free(canonical_key_name_rdf);
+-	return status;
+-}
+-#endif /*  HAVE_SSL */
+-
+-
+-#ifdef HAVE_SSL
+-bool
+-ldns_pkt_tsig_verify(ldns_pkt *pkt, uint8_t *wire, size_t wirelen, const char *key_name,
+-	const char *key_data, ldns_rdf *orig_mac_rdf)
+-{
+-	return ldns_pkt_tsig_verify_next(pkt, wire, wirelen, key_name, key_data, orig_mac_rdf, 0);
+-}
+-
+-bool
+-ldns_pkt_tsig_verify_next(ldns_pkt *pkt, uint8_t *wire, size_t wirelen, const char* key_name,
+-	const char *key_data, ldns_rdf *orig_mac_rdf, int tsig_timers_only)
+-{
+-	ldns_rdf *fudge_rdf;
+-	ldns_rdf *algorithm_rdf;
+-	ldns_rdf *time_signed_rdf;
+-	ldns_rdf *orig_id_rdf;
+-	ldns_rdf *error_rdf;
+-	ldns_rdf *other_data_rdf;
+-	ldns_rdf *pkt_mac_rdf;
+-	ldns_rdf *my_mac_rdf;
+-	ldns_rdf *key_name_rdf = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, key_name);
+-	uint16_t pkt_id, orig_pkt_id;
+-	ldns_status status;
+-
+-	uint8_t *prepared_wire = NULL;
+-	size_t prepared_wire_size = 0;
+-
+-	ldns_rr *orig_tsig = ldns_pkt_tsig(pkt);
+-
+-	if (!orig_tsig || ldns_rr_rd_count(orig_tsig) <= 6) {
+-		ldns_rdf_deep_free(key_name_rdf);
+-		return false;
+-	}
+-	algorithm_rdf = ldns_rr_rdf(orig_tsig, 0);
+-	time_signed_rdf = ldns_rr_rdf(orig_tsig, 1);
+-	fudge_rdf = ldns_rr_rdf(orig_tsig, 2);
+-	pkt_mac_rdf = ldns_rr_rdf(orig_tsig, 3);
+-	orig_id_rdf = ldns_rr_rdf(orig_tsig, 4);
+-	error_rdf = ldns_rr_rdf(orig_tsig, 5);
+-	other_data_rdf = ldns_rr_rdf(orig_tsig, 6);
+-
+-	/* remove temporarily */
+-	ldns_pkt_set_tsig(pkt, NULL);
+-	/* temporarily change the id to the original id */
+-	pkt_id = ldns_pkt_id(pkt);
+-	orig_pkt_id = ldns_rdf2native_int16(orig_id_rdf);
+-	ldns_pkt_set_id(pkt, orig_pkt_id);
+-
+-	prepared_wire = ldns_tsig_prepare_pkt_wire(wire, wirelen, &prepared_wire_size);
+-
+-	status = ldns_tsig_mac_new(&my_mac_rdf, prepared_wire, prepared_wire_size,
+-			key_data, key_name_rdf, fudge_rdf, algorithm_rdf,
+-			time_signed_rdf, error_rdf, other_data_rdf, orig_mac_rdf, tsig_timers_only);
+-
+-	LDNS_FREE(prepared_wire);
+-
+-	if (status != LDNS_STATUS_OK) {
+-		ldns_rdf_deep_free(key_name_rdf);
+-		return false;
+-	}
+-	/* Put back the values */
+-	ldns_pkt_set_tsig(pkt, orig_tsig);
+-	ldns_pkt_set_id(pkt, pkt_id);
+-
+-	ldns_rdf_deep_free(key_name_rdf);
+-
+-	if (ldns_rdf_compare(pkt_mac_rdf, my_mac_rdf) == 0) {
+-		ldns_rdf_deep_free(my_mac_rdf);
+-		return true;
+-	} else {
+-		ldns_rdf_deep_free(my_mac_rdf);
+-		return false;
+-	}
+-}
+-#endif /* HAVE_SSL */
+-
+-#ifdef HAVE_SSL
+-ldns_status
+-ldns_pkt_tsig_sign(ldns_pkt *pkt, const char *key_name, const char *key_data,
+-	uint16_t fudge, const char *algorithm_name, ldns_rdf *query_mac)
+-{
+-	return ldns_pkt_tsig_sign_next(pkt, key_name, key_data, fudge, algorithm_name, query_mac, 0);
+-}
+-
+-ldns_status
+-ldns_pkt_tsig_sign_next(ldns_pkt *pkt, const char *key_name, const char *key_data,
+-	uint16_t fudge, const char *algorithm_name, ldns_rdf *query_mac, int tsig_timers_only)
+-{
+-	ldns_rr *tsig_rr;
+-	ldns_rdf *key_name_rdf = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, key_name);
+-	ldns_rdf *fudge_rdf = NULL;
+-	ldns_rdf *orig_id_rdf = NULL;
+-	ldns_rdf *algorithm_rdf;
+-	ldns_rdf *error_rdf = NULL;
+-	ldns_rdf *mac_rdf = NULL;
+-	ldns_rdf *other_data_rdf = NULL;
+-
+-	ldns_status status = LDNS_STATUS_OK;
+-
+-	uint8_t *pkt_wire = NULL;
+-	size_t pkt_wire_len;
+-
+-	struct timeval tv_time_signed;
+-	uint8_t *time_signed = NULL;
+-	ldns_rdf *time_signed_rdf = NULL;
+-
+-	algorithm_rdf = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, algorithm_name);
+-	if(!key_name_rdf || !algorithm_rdf) {
+-		status = LDNS_STATUS_MEM_ERR;
+-		goto clean;
+-	}
+-
+-	/* eww don't have create tsigtime rdf yet :( */
+-	/* bleh :p */
+-	if (gettimeofday(&tv_time_signed, NULL) == 0) {
+-		time_signed = LDNS_XMALLOC(uint8_t, 6);
+-		if(!time_signed) {
+-			status = LDNS_STATUS_MEM_ERR;
+-			goto clean;
+-		}
+-		ldns_write_uint64_as_uint48(time_signed,
+-				(uint64_t)tv_time_signed.tv_sec);
+-	} else {
+-		status = LDNS_STATUS_INTERNAL_ERR;
+-		goto clean;
+-	}
+-
+-	time_signed_rdf = ldns_rdf_new(LDNS_RDF_TYPE_TSIGTIME, 6, time_signed);
+-	if(!time_signed_rdf) {
+-		LDNS_FREE(time_signed);
+-		status = LDNS_STATUS_MEM_ERR;
+-		goto clean;
+-	}
+-
+-	fudge_rdf = ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16, fudge);
+-
+-	orig_id_rdf = ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16, ldns_pkt_id(pkt));
+-
+-	error_rdf = ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16, 0);
+-
+-	other_data_rdf = ldns_native2rdf_int16_data(0, NULL);
+-
+-	if(!fudge_rdf || !orig_id_rdf || !error_rdf || !other_data_rdf) {
+-		status = LDNS_STATUS_MEM_ERR;
+-		goto clean;
+-	}
+-
+-	if (ldns_pkt2wire(&pkt_wire, pkt, &pkt_wire_len) != LDNS_STATUS_OK) {
+-		status = LDNS_STATUS_ERR;
+-		goto clean;
+-	}
+-
+-	status = ldns_tsig_mac_new(&mac_rdf, pkt_wire, pkt_wire_len,
+-			key_data, key_name_rdf, fudge_rdf, algorithm_rdf,
+-			time_signed_rdf, error_rdf, other_data_rdf, query_mac, tsig_timers_only);
+-
+-	if (!mac_rdf) {
+-		goto clean;
+-	}
+-
+-	LDNS_FREE(pkt_wire);
+-
+-	/* Create the TSIG RR */
+-	tsig_rr = ldns_rr_new();
+-	if(!tsig_rr) {
+-		status = LDNS_STATUS_MEM_ERR;
+-		goto clean;
+-	}
+-	ldns_rr_set_owner(tsig_rr, key_name_rdf);
+-	ldns_rr_set_class(tsig_rr, LDNS_RR_CLASS_ANY);
+-	ldns_rr_set_type(tsig_rr, LDNS_RR_TYPE_TSIG);
+-	ldns_rr_set_ttl(tsig_rr, 0);
+-
+-	ldns_rr_push_rdf(tsig_rr, algorithm_rdf);
+-	ldns_rr_push_rdf(tsig_rr, time_signed_rdf);
+-	ldns_rr_push_rdf(tsig_rr, fudge_rdf);
+-	ldns_rr_push_rdf(tsig_rr, mac_rdf);
+-	ldns_rr_push_rdf(tsig_rr, orig_id_rdf);
+-	ldns_rr_push_rdf(tsig_rr, error_rdf);
+-	ldns_rr_push_rdf(tsig_rr, other_data_rdf);
+-
+-	ldns_pkt_set_tsig(pkt, tsig_rr);
+-
+-	return status;
+-
+-  clean:
+-	LDNS_FREE(pkt_wire);
+-	ldns_rdf_free(key_name_rdf);
+-	ldns_rdf_free(algorithm_rdf);
+-	ldns_rdf_free(time_signed_rdf);
+-	ldns_rdf_free(fudge_rdf);
+-	ldns_rdf_free(orig_id_rdf);
+-	ldns_rdf_free(error_rdf);
+-	ldns_rdf_free(other_data_rdf);
+-	return status;
+-}
+-#endif /* HAVE_SSL */
+diff --git a/src/ldns/update.c b/src/ldns/update.c
+deleted file mode 100644
+index 74e9d19..0000000
+--- a/src/ldns/update.c
++++ /dev/null
+@@ -1,325 +0,0 @@
+-/* update.c
+- *
+- * Functions for RFC 2136 Dynamic Update
+- *
+- * Copyright (c) 2005-2008, NLnet Labs. All rights reserved.
+- *
+- * See LICENSE for the license.
+- */
+-
+-#include <ldns/config.h>
+-
+-#include <ldns/ldns.h>
+-
+-#include <strings.h>
+-#include <stdlib.h>
+-#include <limits.h>
+-
+-/*
+- * RFC 2136 sections mapped to RFC 1035:
+- *              zone/ZO -- QD/question
+- *     prerequisites/PR -- AN/answers
+- *           updates/UP -- NS/authority records
+- *   additional data/AD -- AR/additional records
+- */
+-
+-ldns_pkt *
+-ldns_update_pkt_new(ldns_rdf *zone_rdf, ldns_rr_class c,
+-    ldns_rr_list *pr_rrlist, ldns_rr_list *up_rrlist, ldns_rr_list *ad_rrlist)
+-{
+-	ldns_pkt *p;
+-
+-	if (!zone_rdf || !up_rrlist) {
+-		return NULL;
+-	}
+-
+-	if (c == 0) { 
+-		c = LDNS_RR_CLASS_IN;
+-	}
+-
+-	/* Create packet, fill in Zone Section. */
+-	p = ldns_pkt_query_new(zone_rdf, LDNS_RR_TYPE_SOA, c, LDNS_RD);
+-	if (!p) {
+-		return NULL;
+-	}
+-	zone_rdf = NULL; /* No longer safe to use. */
+-
+-	ldns_pkt_set_opcode(p, LDNS_PACKET_UPDATE);
+-
+-	ldns_rr_list_deep_free(p->_authority);
+-
+-	ldns_pkt_set_authority(p, ldns_rr_list_clone(up_rrlist));
+-
+-	ldns_update_set_upcount(p, ldns_rr_list_rr_count(up_rrlist));
+-
+-	if (pr_rrlist) {
+-		ldns_rr_list_deep_free(p->_answer); /*XXX access function */
+-		ldns_pkt_set_answer(p, ldns_rr_list_clone(pr_rrlist));
+-		ldns_update_set_prcount(p, ldns_rr_list_rr_count(pr_rrlist));
+-	}
+-
+-	if (ad_rrlist) {
+-		ldns_rr_list_deep_free(p->_additional);
+-		ldns_pkt_set_additional(p, ldns_rr_list_clone(ad_rrlist));
+-		ldns_update_set_adcount(p, ldns_rr_list_rr_count(ad_rrlist));
+-	}
+-	return p;
+-}
+-
+-ldns_status
+-ldns_update_pkt_tsig_add(ldns_pkt *p, ldns_resolver *r)
+-{
+-#ifdef HAVE_SSL
+-	uint16_t fudge = 300; /* Recommended fudge. [RFC2845 6.4]  */
+-	if (ldns_resolver_tsig_keyname(r) && ldns_resolver_tsig_keydata(r))
+-		return ldns_pkt_tsig_sign(p, ldns_resolver_tsig_keyname(r),
+-		    ldns_resolver_tsig_keydata(r), fudge,
+-		    ldns_resolver_tsig_algorithm(r), NULL);
+-#else
+-	/* do nothing */
+-	(void)p;
+-	(void)r;
+-#endif /* HAVE_SSL */
+-	/* No TSIG to do. */
+-	return LDNS_STATUS_OK;
+-}
+-
+-/* Move to higher.c or similar? */
+-/* XXX doc */
+-ldns_status
+-ldns_update_soa_mname(ldns_rdf *zone, ldns_resolver *r,
+-    ldns_rr_class c, ldns_rdf **mname)
+-{
+-	ldns_rr		*soa_rr;
+-	ldns_pkt	*query, *resp;
+-
+-	/* Nondestructive, so clone 'zone' here */
+-	query = ldns_pkt_query_new(ldns_rdf_clone(zone), LDNS_RR_TYPE_SOA,
+-	    c, LDNS_RD);
+-	if (!query) {
+-		return LDNS_STATUS_ERR;
+-	}
+-
+-	ldns_pkt_set_random_id(query);
+-	if (ldns_resolver_send_pkt(&resp, r, query) != LDNS_STATUS_OK) {
+-		ldns_pkt_free(query);
+-		return LDNS_STATUS_ERR;
+-	}
+-	ldns_pkt_free(query);
+-	if (!resp) {
+-		return LDNS_STATUS_ERR;
+-	}
+-
+-	/* Expect a SOA answer. */
+-	*mname = NULL;
+-	while ((soa_rr = ldns_rr_list_pop_rr(ldns_pkt_answer(resp)))) {
+-		if (ldns_rr_get_type(soa_rr) != LDNS_RR_TYPE_SOA
+-				|| ldns_rr_rdf(soa_rr, 0) == NULL)
+-			continue;
+-		/* [RFC1035 3.3.13] */
+-		*mname = ldns_rdf_clone(ldns_rr_rdf(soa_rr, 0));
+-		break;
+-	}
+-	ldns_pkt_free(resp);
+-
+-	return *mname ? LDNS_STATUS_OK : LDNS_STATUS_ERR;
+-}
+-
+-/* Try to get zone and MNAME from SOA queries. */
+-ldns_status
+-ldns_update_soa_zone_mname(const char *fqdn, ldns_resolver *r,
+-    ldns_rr_class c, ldns_rdf **zone_rdf, ldns_rdf **mname_rdf)
+-{
+-	ldns_rr		*soa_rr, *rr;
+-	ldns_rdf	*soa_zone = NULL, *soa_mname = NULL;
+-	ldns_rdf	*ipaddr, *fqdn_rdf, *tmp;
+-	ldns_rdf	**nslist;
+-	ldns_pkt	*query, *resp;
+-	ldns_resolver   *tmp_r;
+-	size_t		i;
+-
+-	/* 
+-	 * XXX Ok, this cannot be the best way to find this...?
+-	 * XXX (I run into weird cache-related stuff here)
+-	 */
+-
+-	/* Step 1 - first find a nameserver that should know *something* */
+-	fqdn_rdf = ldns_dname_new_frm_str(fqdn);
+-	query = ldns_pkt_query_new(fqdn_rdf, LDNS_RR_TYPE_SOA, c, LDNS_RD);
+-	if (!query) {
+-		return LDNS_STATUS_ERR;
+-	}
+-	fqdn_rdf = NULL;
+-
+-	ldns_pkt_set_random_id(query);
+-	if (ldns_resolver_send_pkt(&resp, r, query) != LDNS_STATUS_OK) {
+-		ldns_pkt_free(query);
+-		return LDNS_STATUS_ERR;
+-	}
+-	ldns_pkt_free(query);
+-	if (!resp) {
+-		return LDNS_STATUS_ERR;
+-	}
+-
+-	/* XXX Is it safe to only look in authority section here? */
+-	while ((soa_rr = ldns_rr_list_pop_rr(ldns_pkt_authority(resp)))) {
+-		if (ldns_rr_get_type(soa_rr) != LDNS_RR_TYPE_SOA
+-				|| ldns_rr_rdf(soa_rr, 0) == NULL)
+-			continue;
+-		/* [RFC1035 3.3.13] */
+-		soa_mname = ldns_rdf_clone(ldns_rr_rdf(soa_rr, 0));
+-		break;
+-	}
+-	ldns_pkt_free(resp);
+-	if (!soa_rr) {
+-		return LDNS_STATUS_ERR;
+-	}
+-
+-	/* Step 2 - find SOA MNAME IP address, add to resolver */
+-	query = ldns_pkt_query_new(soa_mname, LDNS_RR_TYPE_A, c, LDNS_RD);
+-	if (!query) {
+-		return LDNS_STATUS_ERR;
+-	}
+-	soa_mname = NULL;
+-
+-	ldns_pkt_set_random_id(query);
+-	if (ldns_resolver_send_pkt(&resp, r, query) != LDNS_STATUS_OK) {
+-		ldns_pkt_free(query);
+-		return LDNS_STATUS_ERR;
+-	}
+-	ldns_pkt_free(query);
+-	if (!resp) {
+-		return LDNS_STATUS_ERR;
+-	}
+-
+-	if (ldns_pkt_ancount(resp) == 0) {
+-		ldns_pkt_free(resp);
+-		return LDNS_STATUS_ERR;
+-	}
+-
+-	/* XXX There may be more than one answer RR here. */
+-	rr = ldns_rr_list_pop_rr(ldns_pkt_answer(resp));
+-	ipaddr = ldns_rr_rdf(rr, 0);
+-
+-	/* Put the SOA mname IP first in the nameserver list. */
+-	if (!(tmp_r = ldns_resolver_clone(r))) {
+-		return LDNS_STATUS_MEM_ERR;
+-	}
+-	nslist = ldns_resolver_nameservers(tmp_r);
+-	for (i = 0; i < ldns_resolver_nameserver_count(tmp_r); i++) {
+-		if (ldns_rdf_compare(ipaddr, nslist[i]) == 0) {
+-			if (i) {
+-				tmp = nslist[0];
+-				nslist[0] = nslist[i];
+-				nslist[i] = tmp;
+-			}
+-			break;
+-		}
+-	}
+-	if (i >= ldns_resolver_nameserver_count(tmp_r)) {
+-		/* SOA mname was not part of the resolver so add it first. */
+-		(void) ldns_resolver_push_nameserver(tmp_r, ipaddr);
+-		nslist = ldns_resolver_nameservers(tmp_r);
+-		i = ldns_resolver_nameserver_count(tmp_r) - 1;
+-		tmp = nslist[0];
+-		nslist[0] = nslist[i];
+-		nslist[i] = tmp;
+-	}
+-	ldns_pkt_free(resp);
+-
+-	/* Make sure to ask the first in the list, i.e SOA mname */
+-	ldns_resolver_set_random(tmp_r, false);
+-
+-	/* Step 3 - Redo SOA query, sending to SOA MNAME directly. */
+-	fqdn_rdf = ldns_dname_new_frm_str(fqdn);
+-	query = ldns_pkt_query_new(fqdn_rdf, LDNS_RR_TYPE_SOA, c, LDNS_RD);
+-	if (!query) {
+-		ldns_resolver_free(tmp_r);
+-		return LDNS_STATUS_ERR;
+-	}
+-	fqdn_rdf = NULL;
+-
+-	ldns_pkt_set_random_id(query);
+-	if (ldns_resolver_send_pkt(&resp, tmp_r, query) != LDNS_STATUS_OK) {
+-		ldns_pkt_free(query);
+-		ldns_resolver_free(tmp_r);
+-		return LDNS_STATUS_ERR;
+-	}
+-	ldns_resolver_free(tmp_r);
+-	ldns_pkt_free(query);
+-	if (!resp) {
+-		return LDNS_STATUS_ERR;
+-	}
+-
+-	/* XXX Is it safe to only look in authority section here, too? */
+-	while ((soa_rr = ldns_rr_list_pop_rr(ldns_pkt_authority(resp)))) {
+-		if (ldns_rr_get_type(soa_rr) != LDNS_RR_TYPE_SOA
+-				|| ldns_rr_rdf(soa_rr, 0) == NULL)
+-			continue;
+-		/* [RFC1035 3.3.13] */
+-		soa_mname = ldns_rdf_clone(ldns_rr_rdf(soa_rr, 0));
+-		soa_zone = ldns_rdf_clone(ldns_rr_owner(soa_rr));
+-		break;
+-	}
+-	ldns_pkt_free(resp);
+-	if (!soa_rr) {
+-		return LDNS_STATUS_ERR;
+-	}
+-
+-	/* That seems to have worked, pass results to caller. */
+-	*zone_rdf = soa_zone;
+-	*mname_rdf = soa_mname;
+-	return LDNS_STATUS_OK;
+-}	
+-
+-/*
+- * ldns_update_{get,set}_{zo,pr,up,ad}count
+- */
+-
+-uint16_t
+-ldns_update_zocount(const ldns_pkt *p)
+-{
+-	return ldns_pkt_qdcount(p);
+-}
+-
+-uint16_t
+-ldns_update_prcount(const ldns_pkt *p)
+-{
+-	return ldns_pkt_ancount(p);
+-}
+-
+-uint16_t
+-ldns_update_upcount(const ldns_pkt *p)
+-{
+-	return ldns_pkt_nscount(p);
+-}
+-
+-uint16_t
+-ldns_update_ad(const ldns_pkt *p)
+-{
+-	return ldns_pkt_arcount(p);
+-}
+-
+-void
+-ldns_update_set_zo(ldns_pkt *p, uint16_t v)
+-{
+-	ldns_pkt_set_qdcount(p, v);
+-}
+-
+-void
+-ldns_update_set_prcount(ldns_pkt *p, uint16_t v)
+-{
+-	ldns_pkt_set_ancount(p, v);
+-}
+-
+-void
+-ldns_update_set_upcount(ldns_pkt *p, uint16_t v)
+-{
+-	ldns_pkt_set_nscount(p, v);
+-}
+-
+-void
+-ldns_update_set_adcount(ldns_pkt *p, uint16_t v)
+-{
+-	ldns_pkt_set_arcount(p, v);
+-}
+diff --git a/src/ldns/util.c b/src/ldns/util.c
+deleted file mode 100644
+index 33060d9..0000000
+--- a/src/ldns/util.c
++++ /dev/null
+@@ -1,773 +0,0 @@
+-/*
+- * util.c
+- *
+- * some general memory functions
+- *
+- * a Net::DNS like library for C
+- *
+- * (c) NLnet Labs, 2004-2006
+- *
+- * See the file LICENSE for the license
+- */
+-
+-#include <ldns/config.h>
+-
+-#include <ldns/rdata.h>
+-#include <ldns/rr.h>
+-#include <ldns/util.h>
+-#include <strings.h>
+-#include <stdlib.h>
+-#include <stdio.h>
+-#include <sys/time.h>
+-#include <time.h>
+-#include <ctype.h>
+-
+-#ifdef HAVE_SSL
+-#include <openssl/rand.h>
+-#endif
+-
+-ldns_lookup_table *
+-ldns_lookup_by_name(ldns_lookup_table *table, const char *name)
+-{
+-	while (table->name != NULL) {
+-		if (strcasecmp(name, table->name) == 0)
+-			return table;
+-		table++;
+-	}
+-	return NULL;
+-}
+-
+-ldns_lookup_table *
+-ldns_lookup_by_id(ldns_lookup_table *table, int id)
+-{
+-	while (table->name != NULL) {
+-		if (table->id == id)
+-			return table;
+-		table++;
+-	}
+-	return NULL;
+-}
+-
+-int
+-ldns_get_bit(uint8_t bits[], size_t index)
+-{
+-	/*
+-	 * The bits are counted from left to right, so bit #0 is the
+-	 * left most bit.
+-	 */
+-	return (int) (bits[index / 8] & (1 << (7 - index % 8)));
+-}
+-
+-int
+-ldns_get_bit_r(uint8_t bits[], size_t index)
+-{
+-	/*
+-	 * The bits are counted from right to left, so bit #0 is the
+-	 * right most bit.
+-	 */
+-	return (int) bits[index / 8] & (1 << (index % 8));
+-}
+-
+-void
+-ldns_set_bit(uint8_t *byte, int bit_nr, bool value)
+-{
+-	/*
+-	 * The bits are counted from right to left, so bit #0 is the
+-	 * right most bit.
+-	 */
+-	if (bit_nr >= 0 && bit_nr < 8) {
+-		if (value) {
+-			*byte = *byte | (0x01 << bit_nr);
+-		} else {
+-			*byte = *byte & ~(0x01 << bit_nr);
+-		}
+-	}
+-}
+-
+-int
+-ldns_hexdigit_to_int(char ch)
+-{
+-	switch (ch) {
+-	case '0': return 0;
+-	case '1': return 1;
+-	case '2': return 2;
+-	case '3': return 3;
+-	case '4': return 4;
+-	case '5': return 5;
+-	case '6': return 6;
+-	case '7': return 7;
+-	case '8': return 8;
+-	case '9': return 9;
+-	case 'a': case 'A': return 10;
+-	case 'b': case 'B': return 11;
+-	case 'c': case 'C': return 12;
+-	case 'd': case 'D': return 13;
+-	case 'e': case 'E': return 14;
+-	case 'f': case 'F': return 15;
+-	default:
+-		return -1;
+-	}
+-}
+-
+-char
+-ldns_int_to_hexdigit(int i)
+-{
+-	switch (i) {
+-	case 0: return '0';
+-	case 1: return '1';
+-	case 2: return '2';
+-	case 3: return '3';
+-	case 4: return '4';
+-	case 5: return '5';
+-	case 6: return '6';
+-	case 7: return '7';
+-	case 8: return '8';
+-	case 9: return '9';
+-	case 10: return 'a';
+-	case 11: return 'b';
+-	case 12: return 'c';
+-	case 13: return 'd';
+-	case 14: return 'e';
+-	case 15: return 'f';
+-	default:
+-		abort();
+-	}
+-}
+-
+-int
+-ldns_hexstring_to_data(uint8_t *data, const char *str)
+-{
+-	size_t i;
+-
+-	if (!str || !data) {
+-		return -1;
+-	}
+-
+-	if (strlen(str) % 2 != 0) {
+-		return -2;
+-	}
+-
+-	for (i = 0; i < strlen(str) / 2; i++) {
+-		data[i] =
+-			16 * (uint8_t) ldns_hexdigit_to_int(str[i*2]) +
+-			(uint8_t) ldns_hexdigit_to_int(str[i*2 + 1]);
+-	}
+-
+-	return (int) i;
+-}
+-
+-const char *
+-ldns_version(void)
+-{
+-	return (char*)LDNS_VERSION;
+-}
+-
+-/* 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
+-};
+-
+-#define LDNS_MOD(x,y) (((x) % (y) < 0) ? ((x) % (y) + (y)) : ((x) % (y)))
+-#define LDNS_DIV(x,y) (((x) % (y) < 0) ? ((x) / (y) -  1 ) : ((x) / (y)))
+-
+-static int
+-is_leap_year(int year)
+-{
+-	return LDNS_MOD(year,   4) == 0 && (LDNS_MOD(year, 100) != 0 
+-	    || LDNS_MOD(year, 400) == 0);
+-}
+-
+-static int
+-leap_days(int y1, int y2)
+-{
+-	--y1;
+-	--y2;
+-	return (LDNS_DIV(y2,   4) - LDNS_DIV(y1,   4)) - 
+-	       (LDNS_DIV(y2, 100) - LDNS_DIV(y1, 100)) +
+-	       (LDNS_DIV(y2, 400) - LDNS_DIV(y1, 400));
+-}
+-
+-/*
+- * Code adapted from Python 2.4.1 sources (Lib/calendar.py).
+- */
+-time_t
+-ldns_mktime_from_utc(const struct tm *tm)
+-{
+-	int year = 1900 + tm->tm_year;
+-	time_t days = 365 * ((time_t) 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;
+-}
+-
+-time_t
+-mktime_from_utc(const struct tm *tm)
+-{
+-	return ldns_mktime_from_utc(tm);
+-}
+-
+-#if SIZEOF_TIME_T <= 4
+-
+-static void
+-ldns_year_and_yday_from_days_since_epoch(int64_t days, struct tm *result)
+-{
+-	int year = 1970;
+-	int new_year;
+-
+-	while (days < 0 || days >= (int64_t) (is_leap_year(year) ? 366 : 365)) {
+-		new_year = year + (int) LDNS_DIV(days, 365);
+-		days -= (new_year - year) * 365;
+-		days -= leap_days(year, new_year);
+-		year  = new_year;
+-	}
+-	result->tm_year = year;
+-	result->tm_yday = (int) days;
+-}
+-
+-/* Number of days per month in a leap year. */
+-static const int leap_year_mdays[] = {
+-	31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+-};
+-
+-static void
+-ldns_mon_and_mday_from_year_and_yday(struct tm *result)
+-{
+-	int idays = result->tm_yday;
+-	const int *mon_lengths = is_leap_year(result->tm_year) ? 
+-					leap_year_mdays : mdays;
+-
+-	result->tm_mon = 0;
+-	while  (idays >= mon_lengths[result->tm_mon]) {
+-		idays -= mon_lengths[result->tm_mon++];
+-	}
+-	result->tm_mday = idays + 1;
+-}
+-
+-static void
+-ldns_wday_from_year_and_yday(struct tm *result)
+-{
+-	result->tm_wday = 4 /* 1-1-1970 was a thursday */
+-			+ LDNS_MOD((result->tm_year - 1970), 7) * LDNS_MOD(365, 7)
+-			+ leap_days(1970, result->tm_year)
+-			+ result->tm_yday;
+-	result->tm_wday = LDNS_MOD(result->tm_wday, 7);
+-	if (result->tm_wday < 0) {
+-		result->tm_wday += 7;
+-	}
+-}
+-
+-static struct tm *
+-ldns_gmtime64_r(int64_t clock, struct tm *result)
+-{
+-	result->tm_isdst = 0;
+-	result->tm_sec   = (int) LDNS_MOD(clock, 60);
+-	clock            =       LDNS_DIV(clock, 60);
+-	result->tm_min   = (int) LDNS_MOD(clock, 60);
+-	clock            =       LDNS_DIV(clock, 60);
+-	result->tm_hour  = (int) LDNS_MOD(clock, 24);
+-	clock            =       LDNS_DIV(clock, 24);
+-
+-	ldns_year_and_yday_from_days_since_epoch(clock, result);
+-	ldns_mon_and_mday_from_year_and_yday(result);
+-	ldns_wday_from_year_and_yday(result);
+-	result->tm_year -= 1900;
+-
+-	return result;
+-}
+-
+-#endif /* SIZEOF_TIME_T <= 4 */
+-
+-static int64_t
+-ldns_serial_arithmitics_time(int32_t time, time_t now)
+-{
+-	int32_t offset = time - (int32_t) now;
+-	return (int64_t) now + offset;
+-}
+-
+-
+-struct tm *
+-ldns_serial_arithmitics_gmtime_r(int32_t time, time_t now, struct tm *result)
+-{
+-#if SIZEOF_TIME_T <= 4
+-	int64_t secs_since_epoch = ldns_serial_arithmitics_time(time, now);
+-	return  ldns_gmtime64_r(secs_since_epoch, result);
+-#else
+-	time_t  secs_since_epoch = ldns_serial_arithmitics_time(time, now);
+-	return  gmtime_r(&secs_since_epoch, result);
+-#endif
+-}
+-
+-/**
+- * Init the random source
+- * applications should call this if they need entropy data within ldns
+- * If openSSL is available, it is automatically seeded from /dev/urandom
+- * or /dev/random
+- *
+- * If you need more entropy, or have no openssl available, this function
+- * MUST be called at the start of the program
+- *
+- * If openssl *is* available, this function just adds more entropy
+- **/
+-int
+-ldns_init_random(FILE *fd, unsigned int size)
+-{
+-	/* if fp is given, seed srandom with data from file
+-	   otherwise use /dev/urandom */
+-	FILE *rand_f;
+-	uint8_t *seed;
+-	size_t read = 0;
+-	unsigned int seed_i;
+-	struct timeval tv;
+-
+-	/* we'll need at least sizeof(unsigned int) bytes for the
+-	   standard prng seed */
+-	if (size < (unsigned int) sizeof(seed_i)){
+-		size = (unsigned int) sizeof(seed_i);
+-	}
+-
+-	seed = LDNS_XMALLOC(uint8_t, size);
+-        if(!seed) {
+-		return 1;
+-        }
+-
+-	if (!fd) {
+-		if ((rand_f = fopen("/dev/urandom", "r")) == NULL) {
+-			/* no readable /dev/urandom, try /dev/random */
+-			if ((rand_f = fopen("/dev/random", "r")) == NULL) {
+-				/* no readable /dev/random either, and no entropy
+-				   source given. we'll have to improvise */
+-				for (read = 0; read < size; read++) {
+-					gettimeofday(&tv, NULL);
+-					seed[read] = (uint8_t) (tv.tv_usec % 256);
+-				}
+-			} else {
+-				read = fread(seed, 1, size, rand_f);
+-			}
+-		} else {
+-			read = fread(seed, 1, size, rand_f);
+-		}
+-	} else {
+-		rand_f = fd;
+-		read = fread(seed, 1, size, rand_f);
+-	}
+-
+-	if (read < size) {
+-		LDNS_FREE(seed);
+-		if (!fd) fclose(rand_f);
+-		return 1;
+-	} else {
+-#ifdef HAVE_SSL
+-		/* Seed the OpenSSL prng (most systems have it seeded
+-		   automatically, in that case this call just adds entropy */
+-		RAND_seed(seed, (int) size);
+-#else
+-		/* Seed the standard prng, only uses the first
+-		 * unsigned sizeof(unsiged int) bytes found in the entropy pool
+-		 */
+-		memcpy(&seed_i, seed, sizeof(seed_i));
+-		srandom(seed_i);
+-#endif
+-		LDNS_FREE(seed);
+-	}
+-
+-	if (!fd) {
+-                if (rand_f) fclose(rand_f);
+-	}
+-
+-	return 0;
+-}
+-
+-/**
+- * Get random number.
+- *
+- */
+-uint16_t
+-ldns_get_random(void)
+-{
+-        uint16_t rid = 0;
+-#ifdef HAVE_SSL
+-        if (RAND_bytes((unsigned char*)&rid, 2) != 1) {
+-                rid = (uint16_t) random();
+-        }
+-#else
+-        rid = (uint16_t) random();
+-#endif
+-	return rid;
+-}
+-
+-/*
+- * BubbleBabble code taken from OpenSSH
+- * Copyright (c) 2001 Carsten Raskgaard.  All rights reserved.
+- */
+-char *
+-ldns_bubblebabble(uint8_t *data, size_t len)
+-{
+-	char vowels[] = { 'a', 'e', 'i', 'o', 'u', 'y' };
+-	char consonants[] = { 'b', 'c', 'd', 'f', 'g', 'h', 'k', 'l', 'm',
+-	    'n', 'p', 'r', 's', 't', 'v', 'z', 'x' };
+-	size_t i, j = 0, rounds, seed = 1;
+-	char *retval;
+-
+-	rounds = (len / 2) + 1;
+-	retval = LDNS_XMALLOC(char, rounds * 6);
+-	if(!retval) return NULL;
+-	retval[j++] = 'x';
+-	for (i = 0; i < rounds; i++) {
+-		size_t idx0, idx1, idx2, idx3, idx4;
+-		if ((i + 1 < rounds) || (len % 2 != 0)) {
+-			idx0 = (((((size_t)(data[2 * i])) >> 6) & 3) +
+-			    seed) % 6;
+-			idx1 = (((size_t)(data[2 * i])) >> 2) & 15;
+-			idx2 = ((((size_t)(data[2 * i])) & 3) +
+-			    (seed / 6)) % 6;
+-			retval[j++] = vowels[idx0];
+-			retval[j++] = consonants[idx1];
+-			retval[j++] = vowels[idx2];
+-			if ((i + 1) < rounds) {
+-				idx3 = (((size_t)(data[(2 * i) + 1])) >> 4) & 15;
+-				idx4 = (((size_t)(data[(2 * i) + 1]))) & 15;
+-				retval[j++] = consonants[idx3];
+-				retval[j++] = '-';
+-				retval[j++] = consonants[idx4];
+-				seed = ((seed * 5) +
+-				    ((((size_t)(data[2 * i])) * 7) +
+-				    ((size_t)(data[(2 * i) + 1])))) % 36;
+-			}
+-		} else {
+-			idx0 = seed % 6;
+-			idx1 = 16;
+-			idx2 = seed / 6;
+-			retval[j++] = vowels[idx0];
+-			retval[j++] = consonants[idx1];
+-			retval[j++] = vowels[idx2];
+-		}
+-	}
+-	retval[j++] = 'x';
+-	retval[j++] = '\0';
+-	return retval;
+-}
+-
+-/*
+- * For backwards compatibility, because we have always exported this symbol.
+- */
+-#ifdef HAVE_B64_NTOP
+-int ldns_b64_ntop(const uint8_t* src, size_t srclength,
+-		char *target, size_t targsize);
+-{
+-	return b64_ntop(src, srclength, target, targsize);
+-}
+-#endif
+-
+-/*
+- * For backwards compatibility, because we have always exported this symbol.
+- */
+-#ifdef HAVE_B64_PTON
+-int ldns_b64_pton(const char* src, uint8_t *target, size_t targsize)
+-{
+-	return b64_pton(src, target, targsize);
+-}
+-#endif
+-
+-
+-static int
+-ldns_b32_ntop_base(const uint8_t* src, size_t src_sz,
+-		char* dst, size_t dst_sz,
+-		bool extended_hex, bool add_padding)
+-{
+-	size_t ret_sz;
+-	const char* b32 = extended_hex ? "0123456789abcdefghijklmnopqrstuv"
+-	                               : "abcdefghijklmnopqrstuvwxyz234567";
+-
+-	size_t c = 0; /* c is used to carry partial base32 character over 
+-	               * byte boundaries for sizes with a remainder.
+-		       * (i.e. src_sz % 5 != 0)
+-		       */
+-
+-	ret_sz = add_padding ? ldns_b32_ntop_calculate_size(src_sz)
+-	                     : ldns_b32_ntop_calculate_size_no_padding(src_sz);
+-	
+-	/* Do we have enough space? */
+-	if (dst_sz < ret_sz + 1)
+-		return -1;
+-
+-	/* We know the size; terminate the string */
+-	dst[ret_sz] = '\0';
+-
+-	/* First process all chunks of five */
+-	while (src_sz >= 5) {
+-		/* 00000... ........ ........ ........ ........ */
+-		dst[0] = b32[(src[0]       ) >> 3];
+-
+-		/* .....111 11...... ........ ........ ........ */
+-		dst[1] = b32[(src[0] & 0x07) << 2 | src[1] >> 6];
+-
+-		/* ........ ..22222. ........ ........ ........ */
+-		dst[2] = b32[(src[1] & 0x3e) >> 1];
+-
+-		/* ........ .......3 3333.... ........ ........ */
+-		dst[3] = b32[(src[1] & 0x01) << 4 | src[2] >> 4];
+-
+-		/* ........ ........ ....4444 4....... ........ */
+-		dst[4] = b32[(src[2] & 0x0f) << 1 | src[3] >> 7];
+-
+-		/* ........ ........ ........ .55555.. ........ */
+-		dst[5] = b32[(src[3] & 0x7c) >> 2];
+-
+-		/* ........ ........ ........ ......66 666..... */
+-		dst[6] = b32[(src[3] & 0x03) << 3 | src[4] >> 5];
+-
+-		/* ........ ........ ........ ........ ...77777 */
+-		dst[7] = b32[(src[4] & 0x1f)     ];
+-
+-		src_sz -= 5;
+-		src    += 5;
+-		dst    += 8;
+-	}
+-	/* Process what remains */
+-	switch (src_sz) {
+-	case 4: /* ........ ........ ........ ......66 666..... */
+-		dst[6] = b32[(src[3] & 0x03) << 3];
+-
+-		/* ........ ........ ........ .55555.. ........ */
+-		dst[5] = b32[(src[3] & 0x7c) >> 2];
+-
+-		/* ........ ........ ....4444 4....... ........ */
+-		         c =  src[3]         >> 7 ;
+-	case 3: dst[4] = b32[(src[2] & 0x0f) << 1 | c];
+-
+-		/* ........ .......3 3333.... ........ ........ */
+-			 c =  src[2]         >> 4 ;
+-	case 2:	dst[3] = b32[(src[1] & 0x01) << 4 | c];
+-
+-		/* ........ ..22222. ........ ........ ........ */
+-		dst[2] = b32[(src[1] & 0x3e) >> 1];
+-
+-		/* .....111 11...... ........ ........ ........ */
+-	                 c =  src[1]         >> 6 ;
+-	case 1:	dst[1] = b32[(src[0] & 0x07) << 2 | c];
+-
+-		/* 00000... ........ ........ ........ ........ */
+-		dst[0] = b32[ src[0]         >> 3];
+-	}
+-	/* Add padding */
+-	if (add_padding) {
+-		switch (src_sz) {
+-			case 1: dst[2] = '=';
+-				dst[3] = '=';
+-			case 2: dst[4] = '=';
+-			case 3: dst[5] = '=';
+-				dst[6] = '=';
+-			case 4: dst[7] = '=';
+-		}
+-	}
+-	return (int)ret_sz;
+-}
+-
+-int 
+-ldns_b32_ntop(const uint8_t* src, size_t src_sz, char* dst, size_t dst_sz)
+-{
+-	return ldns_b32_ntop_base(src, src_sz, dst, dst_sz, false, true);
+-}
+-
+-int 
+-ldns_b32_ntop_extended_hex(const uint8_t* src, size_t src_sz,
+-		char* dst, size_t dst_sz)
+-{
+-	return ldns_b32_ntop_base(src, src_sz, dst, dst_sz, true, true);
+-}
+-
+-#ifndef HAVE_B32_NTOP
+-
+-int 
+-b32_ntop(const uint8_t* src, size_t src_sz, char* dst, size_t dst_sz)
+-{
+-	return ldns_b32_ntop_base(src, src_sz, dst, dst_sz, false, true);
+-}
+-
+-int 
+-b32_ntop_extended_hex(const uint8_t* src, size_t src_sz,
+-		char* dst, size_t dst_sz)
+-{
+-	return ldns_b32_ntop_base(src, src_sz, dst, dst_sz, true, true);
+-}
+-
+-#endif /* ! HAVE_B32_NTOP */
+-
+-static int
+-ldns_b32_pton_base(const char* src, size_t src_sz,
+-		uint8_t* dst, size_t dst_sz,
+-		bool extended_hex, bool check_padding)
+-{
+-	size_t i = 0;
+-	char ch = '\0';
+-	uint8_t buf[8];
+-	uint8_t* start = dst;
+-
+-	while (src_sz) {
+-		/* Collect 8 characters in buf (if possible) */
+-		for (i = 0; i < 8; i++) {
+-
+-			do {
+-				ch = *src++;
+-				--src_sz;
+-
+-			} while (isspace(ch) && src_sz > 0);
+-
+-			if (ch == '=' || ch == '\0')
+-				break;
+-
+-			else if (extended_hex)
+-
+-				if (ch >= '0' && ch <= '9')
+-					buf[i] = (uint8_t)ch - '0';
+-				else if (ch >= 'a' && ch <= 'v')
+-					buf[i] = (uint8_t)ch - 'a' + 10;
+-				else if (ch >= 'A' && ch <= 'V')
+-					buf[i] = (uint8_t)ch - 'A' + 10;
+-				else
+-					return -1;
+-
+-			else if (ch >= 'a' && ch <= 'z')
+-				buf[i] = (uint8_t)ch - 'a';
+-			else if (ch >= 'A' && ch <= 'Z')
+-				buf[i] = (uint8_t)ch - 'A';
+-			else if (ch >= '2' && ch <= '7')
+-				buf[i] = (uint8_t)ch - '2' + 26;
+-			else
+-				return -1;
+-		}
+-		/* Less that 8 characters. We're done. */
+-		if (i < 8)
+-			break;
+-
+-		/* Enough space available at the destination? */
+-		if (dst_sz < 5)
+-			return -1;
+-
+-		/* 00000... ........ ........ ........ ........ */
+-		/* .....111 11...... ........ ........ ........ */
+-		dst[0] = buf[0] << 3 | buf[1] >> 2;
+-
+-		/* .....111 11...... ........ ........ ........ */
+-		/* ........ ..22222. ........ ........ ........ */
+-		/* ........ .......3 3333.... ........ ........ */
+-		dst[1] = buf[1] << 6 | buf[2] << 1 | buf[3] >> 4;
+-
+-		/* ........ .......3 3333.... ........ ........ */
+-		/* ........ ........ ....4444 4....... ........ */
+-		dst[2] = buf[3] << 4 | buf[4] >> 1;
+-
+-		/* ........ ........ ....4444 4....... ........ */
+-		/* ........ ........ ........ .55555.. ........ */
+-		/* ........ ........ ........ ......66 666..... */
+-		dst[3] = buf[4] << 7 | buf[5] << 2 | buf[6] >> 3;
+-
+-		/* ........ ........ ........ ......66 666..... */
+-		/* ........ ........ ........ ........ ...77777 */
+-		dst[4] = buf[6] << 5 | buf[7];
+-
+-		dst += 5;
+-		dst_sz -= 5;
+-	}
+-	/* Not ending on a eight byte boundary? */
+-	if (i > 0 && i < 8) {
+-
+-		/* Enough space available at the destination? */
+-		if (dst_sz < (i + 1) / 2)
+-			return -1;
+-
+-		switch (i) {
+-		case 7: /* ........ ........ ........ ......66 666..... */
+-			/* ........ ........ ........ .55555.. ........ */
+-			/* ........ ........ ....4444 4....... ........ */
+-			dst[3] = buf[4] << 7 | buf[5] << 2 | buf[6] >> 3;
+-
+-		case 5: /* ........ ........ ....4444 4....... ........ */
+-			/* ........ .......3 3333.... ........ ........ */
+-			dst[2] = buf[3] << 4 | buf[4] >> 1;
+-
+-		case 4: /* ........ .......3 3333.... ........ ........ */
+-			/* ........ ..22222. ........ ........ ........ */
+-			/* .....111 11...... ........ ........ ........ */
+-			dst[1] = buf[1] << 6 | buf[2] << 1 | buf[3] >> 4;
+-
+-		case 2: /* .....111 11...... ........ ........ ........ */
+-			/* 00000... ........ ........ ........ ........ */
+-			dst[0] = buf[0] << 3 | buf[1] >> 2;
+-
+-			break;
+-
+-		default:
+-			return -1;
+-		}
+-		dst += (i + 1) / 2;
+-
+-		if (check_padding) {
+-			/* Check remaining padding characters */
+-			if (ch != '=')
+-				return -1;
+-
+-			/* One down, 8 - i - 1 more to come... */
+-			for (i = 8 - i - 1; i > 0; i--) {
+-
+-				do {
+-					if (src_sz == 0)
+-						return -1;
+-					ch = *src++;
+-					src_sz--;
+-
+-				} while (isspace(ch));
+-
+-				if (ch != '=')
+-					return -1;
+-			}
+-		}
+-	}
+-	return dst - start;
+-}
+-
+-int
+-ldns_b32_pton(const char* src, size_t src_sz, uint8_t* dst, size_t dst_sz)
+-{
+-	return ldns_b32_pton_base(src, src_sz, dst, dst_sz, false, true);
+-}
+-
+-int
+-ldns_b32_pton_extended_hex(const char* src, size_t src_sz, 
+-		uint8_t* dst, size_t dst_sz)
+-{
+-	return ldns_b32_pton_base(src, src_sz, dst, dst_sz, true, true);
+-}
+-
+-#ifndef HAVE_B32_PTON
+-
+-int
+-b32_pton(const char* src, size_t src_sz, uint8_t* dst, size_t dst_sz)
+-{
+-	return ldns_b32_pton_base(src, src_sz, dst, dst_sz, false, true);
+-}
+-
+-int
+-b32_pton_extended_hex(const char* src, size_t src_sz, 
+-		uint8_t* dst, size_t dst_sz)
+-{
+-	return ldns_b32_pton_base(src, src_sz, dst, dst_sz, true, true);
+-}
+-
+-#endif /* ! HAVE_B32_PTON */
+-
+diff --git a/src/ldns/wire2host.c b/src/ldns/wire2host.c
+deleted file mode 100644
+index e492215..0000000
+--- a/src/ldns/wire2host.c
++++ /dev/null
+@@ -1,491 +0,0 @@
+-/*
+- * wire2host.c
+- *
+- * conversion routines from the wire to the host
+- * format.
+- * This will usually just a re-ordering of the
+- * data (as we store it in network format)
+- *
+- * a Net::DNS like library for C
+- *
+- * (c) NLnet Labs, 2004-2006
+- *
+- * See the file LICENSE for the license
+- */
+-
+-
+-#include <ldns/config.h>
+-
+-#include <ldns/ldns.h>
+-/*#include <ldns/wire2host.h>*/
+-
+-#include <strings.h>
+-#include <limits.h>
+-
+-
+-
+-/*
+- * Set of macro's to deal with the dns message header as specified
+- * in RFC1035 in portable way.
+- *
+- */
+-
+-/*
+- *
+- *                                    1  1  1  1  1  1
+- *      0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
+- *    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+- *    |                      ID                       |
+- *    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+- *    |QR|   Opcode  |AA|TC|RD|RA| Z|AD|CD|   RCODE   |
+- *    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+- *    |                    QDCOUNT                    |
+- *    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+- *    |                    ANCOUNT                    |
+- *    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+- *    |                    NSCOUNT                    |
+- *    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+- *    |                    ARCOUNT                    |
+- *    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+- *
+- */
+-
+-
+-/* allocates memory to *dname! */
+-ldns_status
+-ldns_wire2dname(ldns_rdf **dname, const uint8_t *wire, size_t max, size_t *pos)
+-{
+-	uint8_t label_size;
+-	uint16_t pointer_target;
+-	uint8_t pointer_target_buf[2];
+-	size_t dname_pos = 0;
+-	size_t uncompressed_length = 0;
+-	size_t compression_pos = 0;
+-	uint8_t tmp_dname[LDNS_MAX_DOMAINLEN];
+-	unsigned int pointer_count = 0;
+-
+-	if (pos == NULL) {
+-		return LDNS_STATUS_WIRE_RDATA_ERR;
+-	}
+-	if (*pos >= max) {
+-		return LDNS_STATUS_PACKET_OVERFLOW;
+-	}
+-	label_size = wire[*pos];
+-	while (label_size > 0) {
+-		/* compression */
+-		while (label_size >= 192) {
+-			if (compression_pos == 0) {
+-				compression_pos = *pos + 2;
+-			}
+-
+-			pointer_count++;
+-
+-			/* remove first two bits */
+-			if (*pos + 2 > max) {
+-				return LDNS_STATUS_PACKET_OVERFLOW;
+-			}
+-			pointer_target_buf[0] = wire[*pos] & 63;
+-			pointer_target_buf[1] = wire[*pos + 1];
+-			pointer_target = ldns_read_uint16(pointer_target_buf);
+-
+-			if (pointer_target == 0) {
+-				return LDNS_STATUS_INVALID_POINTER;
+-			} else if (pointer_target >= max) {
+-				return LDNS_STATUS_INVALID_POINTER;
+-			} else if (pointer_count > LDNS_MAX_POINTERS) {
+-				return LDNS_STATUS_INVALID_POINTER;
+-			}
+-			*pos = pointer_target;
+-			label_size = wire[*pos];
+-		}
+-		if(label_size == 0)
+-			break; /* break from pointer to 0 byte */
+-		if (label_size > LDNS_MAX_LABELLEN) {
+-			return LDNS_STATUS_LABEL_OVERFLOW;
+-		}
+-		if (*pos + 1 + label_size > max) {
+-			return LDNS_STATUS_LABEL_OVERFLOW;
+-		}
+-
+-		/* check space for labelcount itself */
+-		if (dname_pos + 1 > LDNS_MAX_DOMAINLEN) {
+-			return LDNS_STATUS_DOMAINNAME_OVERFLOW;
+-		}
+-		tmp_dname[dname_pos] = label_size;
+-		if (label_size > 0) {
+-			dname_pos++;
+-		}
+-		*pos = *pos + 1;
+-		if (dname_pos + label_size > LDNS_MAX_DOMAINLEN) {
+-			return LDNS_STATUS_DOMAINNAME_OVERFLOW;
+-		}
+-		memcpy(&tmp_dname[dname_pos], &wire[*pos], label_size);
+-		uncompressed_length += label_size + 1;
+-		dname_pos += label_size;
+-		*pos = *pos + label_size;
+-
+-		if (*pos < max) {
+-			label_size = wire[*pos];
+-		}
+-	}
+-
+-	if (compression_pos > 0) {
+-		*pos = compression_pos;
+-	} else {
+-		*pos = *pos + 1;
+-	}
+-
+-	if (dname_pos >= LDNS_MAX_DOMAINLEN) {
+-		return LDNS_STATUS_DOMAINNAME_OVERFLOW;
+-	}
+-
+-	tmp_dname[dname_pos] = 0;
+-	dname_pos++;
+-
+-	*dname = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_DNAME,
+-			(uint16_t) dname_pos, tmp_dname);
+-	if (!*dname) {
+-		return LDNS_STATUS_MEM_ERR;
+-	}
+-	return LDNS_STATUS_OK;
+-}
+-
+-/* maybe make this a goto error so data can be freed or something/ */
+-#define LDNS_STATUS_CHECK_RETURN(st) {if (st != LDNS_STATUS_OK) { return st; }}
+-#define LDNS_STATUS_CHECK_GOTO(st, label) {if (st != LDNS_STATUS_OK) { /*printf("STG %s:%d: status code %d\n", __FILE__, __LINE__, st);*/  goto label; }}
+-
+-ldns_status
+-ldns_wire2rdf(ldns_rr *rr, const uint8_t *wire, size_t max, size_t *pos)
+-{
+-	size_t end;
+-	size_t cur_rdf_length;
+-	uint8_t rdf_index;
+-	uint8_t *data;
+-	uint16_t rd_length;
+-	ldns_rdf *cur_rdf = NULL;
+-	ldns_rdf_type cur_rdf_type;
+-	const ldns_rr_descriptor *descriptor;
+-	ldns_status status;
+-
+-	assert(rr != NULL);
+-
+-	descriptor = ldns_rr_descript(ldns_rr_get_type(rr));
+-
+-	if (*pos + 2 > max) {
+-		return LDNS_STATUS_PACKET_OVERFLOW;
+-	}
+-
+-	rd_length = ldns_read_uint16(&wire[*pos]);
+-	*pos = *pos + 2;
+-
+-	if (*pos + rd_length > max) {
+-		return LDNS_STATUS_PACKET_OVERFLOW;
+-	}
+-
+-	end = *pos + (size_t) rd_length;
+-
+-	rdf_index = 0;
+-	while (*pos < end &&
+-			rdf_index < ldns_rr_descriptor_maximum(descriptor)) {
+-
+-		cur_rdf_length = 0;
+-
+-		cur_rdf_type = ldns_rr_descriptor_field_type(
+-				descriptor, rdf_index);
+-
+-		/* handle special cases immediately, set length
+-		   for fixed length rdata and do them below */
+-		switch (cur_rdf_type) {
+-		case LDNS_RDF_TYPE_DNAME:
+-			status = ldns_wire2dname(&cur_rdf, wire, max, pos);
+-			LDNS_STATUS_CHECK_RETURN(status);
+-			break;
+-		case LDNS_RDF_TYPE_CLASS:
+-		case LDNS_RDF_TYPE_ALG:
+-		case LDNS_RDF_TYPE_CERTIFICATE_USAGE:
+-		case LDNS_RDF_TYPE_SELECTOR:
+-		case LDNS_RDF_TYPE_MATCHING_TYPE:
+-		case LDNS_RDF_TYPE_INT8:
+-			cur_rdf_length = LDNS_RDF_SIZE_BYTE;
+-			break;
+-		case LDNS_RDF_TYPE_TYPE:
+-		case LDNS_RDF_TYPE_INT16:
+-		case LDNS_RDF_TYPE_CERT_ALG:
+-			cur_rdf_length = LDNS_RDF_SIZE_WORD;
+-			break;
+-		case LDNS_RDF_TYPE_TIME:
+-		case LDNS_RDF_TYPE_INT32:
+-		case LDNS_RDF_TYPE_A:
+-		case LDNS_RDF_TYPE_PERIOD:
+-			cur_rdf_length = LDNS_RDF_SIZE_DOUBLEWORD;
+-			break;
+-		case LDNS_RDF_TYPE_TSIGTIME:
+-		case LDNS_RDF_TYPE_EUI48:
+-			cur_rdf_length = LDNS_RDF_SIZE_6BYTES;
+-			break;
+-		case LDNS_RDF_TYPE_ILNP64:
+-		case LDNS_RDF_TYPE_EUI64:
+-			cur_rdf_length = LDNS_RDF_SIZE_8BYTES;
+-			break;
+-		case LDNS_RDF_TYPE_AAAA:
+-			cur_rdf_length = LDNS_RDF_SIZE_16BYTES;
+-			break;
+-		case LDNS_RDF_TYPE_STR:
+-		case LDNS_RDF_TYPE_NSEC3_SALT:
+-		case LDNS_RDF_TYPE_TAG:
+-			/* len is stored in first byte
+-			 * it should be in the rdf too, so just
+-			 * copy len+1 from this position
+-			 */
+-			cur_rdf_length = ((size_t) wire[*pos]) + 1;
+-			break;
+-
+-		case LDNS_RDF_TYPE_INT16_DATA:
+-			if (*pos + 2 > end) {
+-				return LDNS_STATUS_PACKET_OVERFLOW;
+-			}
+-			cur_rdf_length =
+-				(size_t) ldns_read_uint16(&wire[*pos]) + 2;
+-			break;
+-		case LDNS_RDF_TYPE_HIP:
+-			if (*pos + 4 > end) {
+-				return LDNS_STATUS_PACKET_OVERFLOW;
+-			}
+-			cur_rdf_length =
+-				(size_t) wire[*pos] + 
+-				(size_t) ldns_read_uint16(&wire[*pos + 2]) + 4;
+-			break;
+-		case LDNS_RDF_TYPE_B32_EXT:
+-		case LDNS_RDF_TYPE_NSEC3_NEXT_OWNER:
+-			/* length is stored in first byte */
+-			cur_rdf_length = ((size_t) wire[*pos]) + 1;
+-			break;
+-		case LDNS_RDF_TYPE_APL:
+-		case LDNS_RDF_TYPE_B64:
+-		case LDNS_RDF_TYPE_HEX:
+-		case LDNS_RDF_TYPE_NSEC:
+-		case LDNS_RDF_TYPE_UNKNOWN:
+-		case LDNS_RDF_TYPE_SERVICE:
+-		case LDNS_RDF_TYPE_LOC:
+-		case LDNS_RDF_TYPE_WKS:
+-		case LDNS_RDF_TYPE_NSAP:
+-		case LDNS_RDF_TYPE_ATMA:
+-		case LDNS_RDF_TYPE_IPSECKEY:
+-		case LDNS_RDF_TYPE_LONG_STR:
+-		case LDNS_RDF_TYPE_NONE:
+-			/*
+-			 * Read to end of rr rdata
+-			 */
+-			cur_rdf_length = end - *pos;
+-			break;
+-		}
+-
+-		/* fixed length rdata */
+-		if (cur_rdf_length > 0) {
+-			if (cur_rdf_length + *pos > end) {
+-				return LDNS_STATUS_PACKET_OVERFLOW;
+-			}
+-			data = LDNS_XMALLOC(uint8_t, rd_length);
+-			if (!data) {
+-				return LDNS_STATUS_MEM_ERR;
+-			}
+-			memcpy(data, &wire[*pos], cur_rdf_length);
+-
+-			cur_rdf = ldns_rdf_new(cur_rdf_type,
+-					cur_rdf_length, data);
+-			*pos = *pos + cur_rdf_length;
+-		}
+-
+-		if (cur_rdf) {
+-			ldns_rr_push_rdf(rr, cur_rdf);
+-			cur_rdf = NULL;
+-		}
+-
+-		rdf_index++;
+-
+-	} /* while (rdf_index < ldns_rr_descriptor_maximum(descriptor)) */
+-
+-
+-	return LDNS_STATUS_OK;
+-}
+-
+-
+-/* TODO:
+-         can *pos be incremented at READ_INT? or maybe use something like
+-         RR_CLASS(wire)?
+-	 uhhm Jelte??
+-*/
+-ldns_status
+-ldns_wire2rr(ldns_rr **rr_p, const uint8_t *wire, size_t max,
+-             size_t *pos, ldns_pkt_section section)
+-{
+-	ldns_rdf *owner = NULL;
+-	ldns_rr *rr = ldns_rr_new();
+-	ldns_status status;
+-
+-	status = ldns_wire2dname(&owner, wire, max, pos);
+-	LDNS_STATUS_CHECK_GOTO(status, status_error);
+-
+-	ldns_rr_set_owner(rr, owner);
+-
+-	if (*pos + 4 > max) {
+-		status = LDNS_STATUS_PACKET_OVERFLOW;
+-		goto status_error;
+-	}
+-
+-	ldns_rr_set_type(rr, ldns_read_uint16(&wire[*pos]));
+-	*pos = *pos + 2;
+-
+-	ldns_rr_set_class(rr, ldns_read_uint16(&wire[*pos]));
+-	*pos = *pos + 2;
+-
+-	if (section != LDNS_SECTION_QUESTION) {
+-		if (*pos + 4 > max) {
+-			status = LDNS_STATUS_PACKET_OVERFLOW;
+-			goto status_error;
+-		}
+-		ldns_rr_set_ttl(rr, ldns_read_uint32(&wire[*pos]));
+-
+-		*pos = *pos + 4;
+-		status = ldns_wire2rdf(rr, wire, max, pos);
+-
+-		LDNS_STATUS_CHECK_GOTO(status, status_error);
+-        ldns_rr_set_question(rr, false);
+-	} else {
+-        ldns_rr_set_question(rr, true);
+-    }
+-
+-	*rr_p = rr;
+-	return LDNS_STATUS_OK;
+-
+-status_error:
+-	ldns_rr_free(rr);
+-	return status;
+-}
+-
+-static ldns_status
+-ldns_wire2pkt_hdr(ldns_pkt *packet, const uint8_t *wire, size_t max, size_t *pos)
+-{
+-	if (*pos + LDNS_HEADER_SIZE > max) {
+-		return LDNS_STATUS_WIRE_INCOMPLETE_HEADER;
+-	} else {
+-		ldns_pkt_set_id(packet, LDNS_ID_WIRE(wire));
+-		ldns_pkt_set_qr(packet, LDNS_QR_WIRE(wire));
+-		ldns_pkt_set_opcode(packet, LDNS_OPCODE_WIRE(wire));
+-		ldns_pkt_set_aa(packet, LDNS_AA_WIRE(wire));
+-		ldns_pkt_set_tc(packet, LDNS_TC_WIRE(wire));
+-		ldns_pkt_set_rd(packet, LDNS_RD_WIRE(wire));
+-		ldns_pkt_set_ra(packet, LDNS_RA_WIRE(wire));
+-		ldns_pkt_set_ad(packet, LDNS_AD_WIRE(wire));
+-		ldns_pkt_set_cd(packet, LDNS_CD_WIRE(wire));
+-		ldns_pkt_set_rcode(packet, LDNS_RCODE_WIRE(wire));
+-
+-		ldns_pkt_set_qdcount(packet, LDNS_QDCOUNT(wire));
+-		ldns_pkt_set_ancount(packet, LDNS_ANCOUNT(wire));
+-		ldns_pkt_set_nscount(packet, LDNS_NSCOUNT(wire));
+-		ldns_pkt_set_arcount(packet, LDNS_ARCOUNT(wire));
+-
+-		*pos += LDNS_HEADER_SIZE;
+-
+-		return LDNS_STATUS_OK;
+-	}
+-}
+-
+-ldns_status
+-ldns_buffer2pkt_wire(ldns_pkt **packet, ldns_buffer *buffer)
+-{
+-	/* lazy */
+-	return ldns_wire2pkt(packet, ldns_buffer_begin(buffer),
+-				ldns_buffer_limit(buffer));
+-
+-}
+-
+-ldns_status
+-ldns_wire2pkt(ldns_pkt **packet_p, const uint8_t *wire, size_t max)
+-{
+-	size_t pos = 0;
+-	uint16_t i;
+-	ldns_rr *rr;
+-	ldns_pkt *packet = ldns_pkt_new();
+-	ldns_status status = LDNS_STATUS_OK;
+-	uint8_t have_edns = 0;
+-
+-	uint8_t data[4];
+-
+-	status = ldns_wire2pkt_hdr(packet, wire, max, &pos);
+-	LDNS_STATUS_CHECK_GOTO(status, status_error);
+-
+-	for (i = 0; i < ldns_pkt_qdcount(packet); i++) {
+-
+-		status = ldns_wire2rr(&rr, wire, max, &pos, LDNS_SECTION_QUESTION);
+-		if (status == LDNS_STATUS_PACKET_OVERFLOW) {
+-			status = LDNS_STATUS_WIRE_INCOMPLETE_QUESTION;
+-		}
+-		LDNS_STATUS_CHECK_GOTO(status, status_error);
+-		if (!ldns_rr_list_push_rr(ldns_pkt_question(packet), rr)) {
+-			ldns_pkt_free(packet);
+-			return LDNS_STATUS_INTERNAL_ERR;
+-		}
+-	}
+-	for (i = 0; i < ldns_pkt_ancount(packet); i++) {
+-		status = ldns_wire2rr(&rr, wire, max, &pos, LDNS_SECTION_ANSWER);
+-		if (status == LDNS_STATUS_PACKET_OVERFLOW) {
+-			status = LDNS_STATUS_WIRE_INCOMPLETE_ANSWER;
+-		}
+-		LDNS_STATUS_CHECK_GOTO(status, status_error);
+-		if (!ldns_rr_list_push_rr(ldns_pkt_answer(packet), rr)) {
+-			ldns_pkt_free(packet);
+-			return LDNS_STATUS_INTERNAL_ERR;
+-		}
+-	}
+-	for (i = 0; i < ldns_pkt_nscount(packet); i++) {
+-		status = ldns_wire2rr(&rr, wire, max, &pos, LDNS_SECTION_AUTHORITY);
+-		if (status == LDNS_STATUS_PACKET_OVERFLOW) {
+-			status = LDNS_STATUS_WIRE_INCOMPLETE_AUTHORITY;
+-		}
+-		LDNS_STATUS_CHECK_GOTO(status, status_error);
+-		if (!ldns_rr_list_push_rr(ldns_pkt_authority(packet), rr)) {
+-			ldns_pkt_free(packet);
+-			return LDNS_STATUS_INTERNAL_ERR;
+-		}
+-	}
+-	for (i = 0; i < ldns_pkt_arcount(packet); i++) {
+-		status = ldns_wire2rr(&rr, wire, max, &pos, LDNS_SECTION_ADDITIONAL);
+-		if (status == LDNS_STATUS_PACKET_OVERFLOW) {
+-			status = LDNS_STATUS_WIRE_INCOMPLETE_ADDITIONAL;
+-		}
+-		LDNS_STATUS_CHECK_GOTO(status, status_error);
+-
+-		if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_OPT) {
+-			ldns_pkt_set_edns_udp_size(packet, ldns_rr_get_class(rr));
+-			ldns_write_uint32(data, ldns_rr_ttl(rr));
+-			ldns_pkt_set_edns_extended_rcode(packet, data[0]);
+-			ldns_pkt_set_edns_version(packet, data[1]);
+-			ldns_pkt_set_edns_z(packet, ldns_read_uint16(&data[2]));
+-			/* edns might not have rdfs */
+-			if (ldns_rr_rdf(rr, 0)) {
+-				ldns_pkt_set_edns_data(packet, ldns_rdf_clone(ldns_rr_rdf(rr, 0)));
+-			}
+-			ldns_rr_free(rr);
+-			have_edns += 1;
+-		} else if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_TSIG) {
+-			ldns_pkt_set_tsig(packet, rr);
+-			ldns_pkt_set_arcount(packet, ldns_pkt_arcount(packet) - 1);
+-		} else if (!ldns_rr_list_push_rr(ldns_pkt_additional(packet), rr)) {
+-			ldns_pkt_free(packet);
+-			return LDNS_STATUS_INTERNAL_ERR;
+-		}
+-	}
+-	ldns_pkt_set_size(packet, max);
+-	if(have_edns)
+-		ldns_pkt_set_arcount(packet, ldns_pkt_arcount(packet)
+-                        - have_edns);
+-        packet->_edns_present = have_edns;
+-
+-	*packet_p = packet;
+-	return status;
+-
+-status_error:
+-	ldns_pkt_free(packet);
+-	return status;
+-}
+diff --git a/src/ldns/zone.c b/src/ldns/zone.c
+deleted file mode 100644
+index d97a81e..0000000
+--- a/src/ldns/zone.c
++++ /dev/null
+@@ -1,318 +0,0 @@
+-/* zone.c
+- *
+- * Functions for ldns_zone structure
+- * a Net::DNS like library for C
+- *
+- * (c) NLnet Labs, 2005-2006
+- * See the file LICENSE for the license
+- */
+-#include <ldns/config.h>
+-
+-#include <ldns/ldns.h>
+-
+-#include <strings.h>
+-#include <limits.h>
+-
+-ldns_rr *
+-ldns_zone_soa(const ldns_zone *z)
+-{
+-        return z->_soa;
+-}
+-
+-size_t
+-ldns_zone_rr_count(const ldns_zone *z)
+-{
+-	return ldns_rr_list_rr_count(z->_rrs);
+-}
+-
+-void
+-ldns_zone_set_soa(ldns_zone *z, ldns_rr *soa)
+-{
+-	z->_soa = soa;
+-}
+-
+-ldns_rr_list *
+-ldns_zone_rrs(const ldns_zone *z)
+-{
+-	return z->_rrs;
+-}
+-
+-void
+-ldns_zone_set_rrs(ldns_zone *z, ldns_rr_list *rrlist)
+-{
+-	z->_rrs = rrlist;
+-}
+-
+-bool
+-ldns_zone_push_rr_list(ldns_zone *z, ldns_rr_list *list)
+-{
+-	return ldns_rr_list_cat(ldns_zone_rrs(z), list);
+-
+-}
+-
+-bool
+-ldns_zone_push_rr(ldns_zone *z, ldns_rr *rr)
+-{
+-	return ldns_rr_list_push_rr( ldns_zone_rrs(z), rr);
+-}
+-
+-
+-/*
+- * Get the list of glue records in a zone
+- * XXX: there should be a way for this to return error, other than NULL, 
+- *      since NULL is a valid return
+- */
+-ldns_rr_list *
+-ldns_zone_glue_rr_list(const ldns_zone *z)
+-{
+-	/* when do we find glue? It means we find an IP address
+-	 * (AAAA/A) for a nameserver listed in the zone
+-	 *
+-	 * Alg used here:
+-	 * first find all the zonecuts (NS records)
+-	 * find all the AAAA or A records (can be done it the 
+-	 * above loop).
+-	 *
+-	 * Check if the aaaa/a list are subdomains under the
+-	 * NS domains.
+-	 * If yes -> glue, if no -> not glue
+-	 */
+-
+-	ldns_rr_list *zone_cuts;
+-	ldns_rr_list *addr;
+-	ldns_rr_list *glue;
+-	ldns_rr *r, *ns, *a;
+-	ldns_rdf *dname_a, *ns_owner;
+-	size_t i,j;
+-
+-	zone_cuts = NULL;
+-	addr = NULL;
+-	glue = NULL;
+-
+-	/* we cannot determine glue in a 'zone' without a SOA */
+-	if (!ldns_zone_soa(z)) {
+-		return NULL;
+-	}
+-
+-	zone_cuts = ldns_rr_list_new();
+-	if (!zone_cuts) goto memory_error;
+-	addr = ldns_rr_list_new();
+-	if (!addr) goto memory_error;
+-	glue = ldns_rr_list_new();
+-	if (!glue) goto memory_error;
+-
+-	for(i = 0; i < ldns_zone_rr_count(z); i++) {
+-		r = ldns_rr_list_rr(ldns_zone_rrs(z), i);
+-		if (ldns_rr_get_type(r) == LDNS_RR_TYPE_A ||
+-				ldns_rr_get_type(r) == LDNS_RR_TYPE_AAAA) {
+-			/* possibly glue */
+-			if (!ldns_rr_list_push_rr(addr, r)) goto memory_error;
+-			continue;
+-		}
+-		if (ldns_rr_get_type(r) == LDNS_RR_TYPE_NS) {
+-			/* multiple zones will end up here -
+-			 * for now; not a problem
+-			 */
+-			/* don't add NS records for the current zone itself */
+-			if (ldns_rdf_compare(ldns_rr_owner(r), 
+-						ldns_rr_owner(ldns_zone_soa(z))) != 0) {
+-				if (!ldns_rr_list_push_rr(zone_cuts, r)) goto memory_error;
+-			}
+-			continue;
+-		}
+-	}
+-
+-	/* will sorting make it quicker ?? */
+-	for(i = 0; i < ldns_rr_list_rr_count(zone_cuts); i++) {
+-		ns = ldns_rr_list_rr(zone_cuts, i);
+-		ns_owner = ldns_rr_owner(ns);
+-
+-		for(j = 0; j < ldns_rr_list_rr_count(addr); j++) {
+-			a = ldns_rr_list_rr(addr, j);
+-			dname_a = ldns_rr_owner(a);
+-
+-			if (ldns_dname_is_subdomain(dname_a, ns_owner) ||
+-				ldns_dname_compare(dname_a, ns_owner) == 0) {
+-				/* GLUE! */
+-				if (!ldns_rr_list_push_rr(glue, a)) goto memory_error;
+-			}
+-		}
+-	}
+-	
+-	ldns_rr_list_free(addr);
+-	ldns_rr_list_free(zone_cuts);
+-
+-	if (ldns_rr_list_rr_count(glue) == 0) {
+-		ldns_rr_list_free(glue);
+-		return NULL;
+-	} else {
+-		return glue;
+-	}
+-
+-memory_error:
+-	if (zone_cuts) {
+-		LDNS_FREE(zone_cuts);
+-	}
+-	if (addr) {
+-		ldns_rr_list_free(addr);
+-	}
+-	if (glue) {
+-		ldns_rr_list_free(glue);
+-	}
+-	return NULL;
+-}
+-
+-ldns_zone *
+-ldns_zone_new(void)
+-{
+-	ldns_zone *z;
+-
+-	z = LDNS_MALLOC(ldns_zone);
+-	if (!z) {
+-		return NULL;
+-	}
+-
+-	z->_rrs = ldns_rr_list_new();
+-	if (!z->_rrs) {
+-		LDNS_FREE(z);
+-		return NULL;
+-	}
+-	ldns_zone_set_soa(z, NULL);
+-	return z;
+-}
+-
+-/* we regocnize:
+- * $TTL, $ORIGIN
+- */
+-ldns_status
+-ldns_zone_new_frm_fp(ldns_zone **z, FILE *fp, ldns_rdf *origin, uint32_t ttl, ldns_rr_class c)
+-{
+-	return ldns_zone_new_frm_fp_l(z, fp, origin, ttl, c, NULL);
+-}
+-
+-/* XXX: class is never used */
+-ldns_status
+-ldns_zone_new_frm_fp_l(ldns_zone **z, FILE *fp, ldns_rdf *origin, uint32_t ttl, 
+-        ldns_rr_class ATTR_UNUSED(c), int *line_nr)
+-{
+-	ldns_zone *newzone;
+-	ldns_rr *rr;
+-	uint32_t my_ttl;
+-	ldns_rdf *my_origin;
+-	ldns_rdf *my_prev;
+-	bool soa_seen = false; 	/* 2 soa are an error */
+-	ldns_status s;
+-	ldns_status ret;
+-
+-	/* most cases of error are memory problems */
+-	ret = LDNS_STATUS_MEM_ERR;
+-
+-	newzone = NULL;
+-	my_origin = NULL;
+-	my_prev = NULL;
+-
+-	my_ttl    = ttl;
+-	
+-	if (origin) {
+-		my_origin = ldns_rdf_clone(origin);
+-		if (!my_origin) goto error;
+-		/* also set the prev */
+-		my_prev   = ldns_rdf_clone(origin);
+-		if (!my_prev) goto error;
+-	}
+-
+-	newzone = ldns_zone_new();
+-	if (!newzone) goto error;
+-
+-	while(!feof(fp)) {
+-		s = ldns_rr_new_frm_fp_l(&rr, fp, &my_ttl, &my_origin, &my_prev, line_nr);
+-		switch (s) {
+-		case LDNS_STATUS_OK:
+-			if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_SOA) {
+-				if (soa_seen) {
+-					/* second SOA 
+-					 * just skip, maybe we want to say
+-					 * something??? */
+-					ldns_rr_free(rr);
+-					continue;
+-				}
+-				soa_seen = true;
+-				ldns_zone_set_soa(newzone, rr);
+-				/* set origin to soa if not specified */
+-				if (!my_origin) {
+-					my_origin = ldns_rdf_clone(ldns_rr_owner(rr));
+-				}
+-				continue;
+-			}
+-			
+-			/* a normal RR - as sofar the DNS is normal */
+-			if (!ldns_zone_push_rr(newzone, rr)) goto error;
+-
+-		case LDNS_STATUS_SYNTAX_EMPTY:
+-			/* empty line was seen */
+-		case LDNS_STATUS_SYNTAX_TTL:
+-			/* the function set the ttl */
+-			break;
+-		case LDNS_STATUS_SYNTAX_ORIGIN:
+-			/* the function set the origin */
+-			break;
+-		case LDNS_STATUS_SYNTAX_INCLUDE:
+-			ret = LDNS_STATUS_SYNTAX_INCLUDE_ERR_NOTIMPL;
+-			break;
+-		default:
+-			ret = s;
+-			goto error;
+-		}
+-	}
+-
+-	if (my_origin) {
+-		ldns_rdf_deep_free(my_origin);
+-	}
+-	if (my_prev) {
+-		ldns_rdf_deep_free(my_prev);
+-	}
+-	if (z) {
+-		*z = newzone;
+-	} else {
+-		ldns_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_zone_free(newzone);
+-	}
+-	return ret;
+-}
+-
+-void
+-ldns_zone_sort(ldns_zone *zone)
+-{
+-	ldns_rr_list *zrr;
+-	assert(zone != NULL);
+-
+-	zrr = ldns_zone_rrs(zone);
+-	ldns_rr_list_sort(zrr);
+-}
+-
+-void
+-ldns_zone_free(ldns_zone *zone) 
+-{
+-	ldns_rr_list_free(zone->_rrs);
+-	LDNS_FREE(zone);
+-}
+-
+-void
+-ldns_zone_deep_free(ldns_zone *zone) 
+-{
+-	ldns_rr_free(zone->_soa);
+-	ldns_rr_list_deep_free(zone->_rrs);
+-	LDNS_FREE(zone);
+-}
diff --git a/debian/patches/series b/debian/patches/series
new file mode 100644
index 0000000..cd64c59
--- /dev/null
+++ b/debian/patches/series
@@ -0,0 +1 @@
+0001-Use-system-ldns-library-for-compilation.patch

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-perl/packages/libnet-ldns-perl.git



More information about the Pkg-perl-cvs-commits mailing list