summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOndřej Surý <ondrej@sury.org>2016-06-28 12:36:34 +0200
committerOndřej Surý <ondrej@sury.org>2016-06-28 14:01:17 +0200
commitce5878439913bf2c0c57c356c694eeaf883f6542 (patch)
treea3f5b389b90fd6af9248efacf4de56aae82c72e1
parentc78c7ccf0e8c5a1af42c9b5812eedc91ea403a73 (diff)
Use system ldns library for compilation
-rw-r--r--debian/control2
-rw-r--r--debian/patches/0001-Use-system-ldns-library-for-compilation.patch86155
-rw-r--r--debian/patches/series1
3 files changed, 86157 insertions, 1 deletions
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@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@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@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 &lt;space&gt; TTL &lt;space&gt; CLASS &lt;space&gt;
+- * TYPE &lt;space&gt; 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@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 &lt;space&gt; TTL &lt;space&gt; CLASS &lt;space&gt;
++ * TYPE &lt;space&gt; 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@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@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@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@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