diff options
author | Ondřej Surý <ondrej@sury.org> | 2016-06-28 12:36:34 +0200 |
---|---|---|
committer | Ondřej Surý <ondrej@sury.org> | 2016-06-28 14:01:17 +0200 |
commit | ce5878439913bf2c0c57c356c694eeaf883f6542 (patch) | |
tree | a3f5b389b90fd6af9248efacf4de56aae82c72e1 | |
parent | c78c7ccf0e8c5a1af42c9b5812eedc91ea403a73 (diff) |
Use system ldns library for compilation
-rw-r--r-- | debian/control | 2 | ||||
-rw-r--r-- | debian/patches/0001-Use-system-ldns-library-for-compilation.patch | 86155 | ||||
-rw-r--r-- | debian/patches/series | 1 |
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 <space> TTL <space> CLASS <space> +- * TYPE <space> RDATA. +- * \param[out] n the rr to return +- * \param[in] str the string to convert +- * \param[in] default_ttl default ttl value for the rr. +- * If 0 DEF_TTL will be used +- * \param[in] origin when the owner is relative add this. +- * The caller must ldns_rdf_deep_free it. +- * \param[out] prev the previous ownername. if this value is not NULL, +- * the function overwrites this with the ownername found in this +- * string. The caller must then ldns_rdf_deep_free it. +- * \return a status msg describing an error or LDNS_STATUS_OK +- */ +-ldns_status ldns_rr_new_frm_str(ldns_rr **n, const char *str, +- uint32_t default_ttl, ldns_rdf *origin, +- ldns_rdf **prev); +- +-/** +- * creates an rr for the question section from a string, i.e. +- * without RDATA fields +- * Origin and previous RR functionality are the same as in +- * ldns_rr_new_frm_str() +- * \param[out] n the rr to return +- * \param[in] str the string to convert +- * \param[in] origin when the owner is relative add this. +- * The caller must ldns_rdf_deep_free it. +- * \param prev the previous ownername. the function overwrite this with +- * the current found ownername. The caller must ldns_rdf_deep_free it. +- * \return a status msg describing an error or LDNS_STATUS_OK +- */ +-ldns_status ldns_rr_new_question_frm_str(ldns_rr **n, const char *str, +- ldns_rdf *origin, ldns_rdf **prev); +- +-/** +- * creates a new rr from a file containing a string. +- * \param[out] rr the new rr +- * \param[in] fp the file pointer to use +- * \param[in] default_ttl pointer to a default ttl for the rr. If NULL DEF_TTL will be used +- * the pointer will be updated if the file contains a $TTL directive +- * \param[in] origin when the owner is relative add this +- * the pointer will be updated if the file contains a $ORIGIN directive +- * The caller must ldns_rdf_deep_free it. +- * \param[in] prev when the owner is whitespaces use this as the * ownername +- * the pointer will be updated after the call +- * The caller must ldns_rdf_deep_free it. +- * \return a ldns_status with an error or LDNS_STATUS_OK +- */ +-ldns_status ldns_rr_new_frm_fp(ldns_rr **rr, FILE *fp, uint32_t *default_ttl, ldns_rdf **origin, ldns_rdf **prev); +- +-/** +- * creates a new rr from a file containing a string. +- * \param[out] rr the new rr +- * \param[in] fp the file pointer to use +- * \param[in] default_ttl a default ttl for the rr. If NULL DEF_TTL will be used +- * the pointer will be updated if the file contains a $TTL directive +- * \param[in] origin when the owner is relative add this +- * the pointer will be updated if the file contains a $ORIGIN directive +- * The caller must ldns_rdf_deep_free it. +- * \param[in] line_nr pointer to an integer containing the current line number (for debugging purposes) +- * \param[in] prev when the owner is whitespaces use this as the * ownername +- * the pointer will be updated after the call +- * The caller must ldns_rdf_deep_free it. +- * \return a ldns_status with an error or LDNS_STATUS_OK +- */ +-ldns_status ldns_rr_new_frm_fp_l(ldns_rr **rr, FILE *fp, uint32_t *default_ttl, ldns_rdf **origin, ldns_rdf **prev, int *line_nr); +- +-/** +- * sets the owner in the rr structure. +- * \param[in] *rr rr to operate on +- * \param[in] *owner set to this owner +- * \return void +- */ +-void ldns_rr_set_owner(ldns_rr *rr, ldns_rdf *owner); +- +-/** +- * sets the question flag in the rr structure. +- * \param[in] *rr rr to operate on +- * \param[in] question question flag +- * \return void +- */ +-void ldns_rr_set_question(ldns_rr *rr, bool question); +- +-/** +- * sets the ttl in the rr structure. +- * \param[in] *rr rr to operate on +- * \param[in] ttl set to this ttl +- * \return void +- */ +-void ldns_rr_set_ttl(ldns_rr *rr, uint32_t ttl); +- +-/** +- * sets the rd_count in the rr. +- * \param[in] *rr rr to operate on +- * \param[in] count set to this count +- * \return void +- */ +-void ldns_rr_set_rd_count(ldns_rr *rr, size_t count); +- +-/** +- * sets the type in the rr. +- * \param[in] *rr rr to operate on +- * \param[in] rr_type set to this type +- * \return void +- */ +-void ldns_rr_set_type(ldns_rr *rr, ldns_rr_type rr_type); +- +-/** +- * sets the class in the rr. +- * \param[in] *rr rr to operate on +- * \param[in] rr_class set to this class +- * \return void +- */ +-void ldns_rr_set_class(ldns_rr *rr, ldns_rr_class rr_class); +- +-/** +- * sets a rdf member, it will be set on the +- * position given. The old value is returned, like pop. +- * \param[in] *rr the rr to operate on +- * \param[in] *f the rdf to set +- * \param[in] position the position the set the rdf +- * \return the old value in the rr, NULL on failyre +- */ +-ldns_rdf* ldns_rr_set_rdf(ldns_rr *rr, const ldns_rdf *f, size_t position); +- +-/** +- * sets rd_field member, it will be +- * placed in the next available spot. +- * \param[in] *rr rr to operate on +- * \param[in] *f the data field member to set +- * \return bool +- */ +-bool ldns_rr_push_rdf(ldns_rr *rr, const ldns_rdf *f); +- +-/** +- * removes a rd_field member, it will be +- * popped from the last position. +- * \param[in] *rr rr to operate on +- * \return rdf which was popped (null if nothing) +- */ +-ldns_rdf* ldns_rr_pop_rdf(ldns_rr *rr); +- +-/** +- * returns the rdata field member counter. +- * \param[in] *rr rr to operate on +- * \param[in] nr the number of the rdf to return +- * \return ldns_rdf * +- */ +-ldns_rdf* ldns_rr_rdf(const ldns_rr *rr, size_t nr); +- +-/** +- * returns the owner name of an rr structure. +- * \param[in] *rr rr to operate on +- * \return ldns_rdf * +- */ +-ldns_rdf* ldns_rr_owner(const ldns_rr *rr); +- +-/** +- * returns the question flag of an rr structure. +- * \param[in] *rr rr to operate on +- * \return bool true if question +- */ +-bool ldns_rr_is_question(const ldns_rr *rr); +- +-/** +- * returns the ttl of an rr structure. +- * \param[in] *rr the rr to read from +- * \return the ttl of the rr +- */ +-uint32_t ldns_rr_ttl(const ldns_rr *rr); +- +-/** +- * returns the rd_count of an rr structure. +- * \param[in] *rr the rr to read from +- * \return the rd count of the rr +- */ +-size_t ldns_rr_rd_count(const ldns_rr *rr); +- +-/** +- * returns the type of the rr. +- * \param[in] *rr the rr to read from +- * \return the type of the rr +- */ +-ldns_rr_type ldns_rr_get_type(const ldns_rr *rr); +- +-/** +- * returns the class of the rr. +- * \param[in] *rr the rr to read from +- * \return the class of the rr +- */ +-ldns_rr_class ldns_rr_get_class(const ldns_rr *rr); +- +-/* rr_lists */ +- +-/** +- * returns the number of rr's in an rr_list. +- * \param[in] rr_list the rr_list to read from +- * \return the number of rr's +- */ +-size_t ldns_rr_list_rr_count(const ldns_rr_list *rr_list); +- +-/** +- * sets the number of rr's in an rr_list. +- * \param[in] rr_list the rr_list to set the count on +- * \param[in] count the number of rr in this list +- * \return void +- */ +-void ldns_rr_list_set_rr_count(ldns_rr_list *rr_list, size_t count); +- +-/** +- * set a rr on a specific index in a ldns_rr_list +- * \param[in] rr_list the rr_list to use +- * \param[in] r the rr to set +- * \param[in] count index into the rr_list +- * \return the old rr which was stored in the rr_list, or +- * NULL is the index was too large +- * set a specific rr */ +-ldns_rr * ldns_rr_list_set_rr(ldns_rr_list *rr_list, const ldns_rr *r, size_t count); +- +-/** +- * returns a specific rr of an rrlist. +- * \param[in] rr_list the rr_list to read from +- * \param[in] nr return this rr +- * \return the rr at position nr +- */ +-ldns_rr* ldns_rr_list_rr(const ldns_rr_list *rr_list, size_t nr); +- +-/** +- * creates a new rr_list structure. +- * \return a new rr_list structure +- */ +-ldns_rr_list* ldns_rr_list_new(void); +- +-/** +- * frees an rr_list structure. +- * \param[in] rr_list the list to free +- */ +-void ldns_rr_list_free(ldns_rr_list *rr_list); +- +-/** +- * frees an rr_list structure and all rrs contained therein. +- * \param[in] rr_list the list to free +- */ +-void ldns_rr_list_deep_free(ldns_rr_list *rr_list); +- +-/** +- * concatenates two ldns_rr_lists together. This modifies +- * *left (to extend it and add the pointers from *right). +- * \param[in] left the leftside +- * \param[in] right the rightside +- * \return a left with right concatenated to it +- */ +-bool ldns_rr_list_cat(ldns_rr_list *left, ldns_rr_list *right); +- +-/** +- * concatenates two ldns_rr_lists together, but makes clones of the rr's +- * (instead of pointer copying). +- * \param[in] left the leftside +- * \param[in] right the rightside +- * \return a new rr_list with leftside/rightside concatenated +- */ +-ldns_rr_list* ldns_rr_list_cat_clone(ldns_rr_list *left, ldns_rr_list *right); +- +-/** +- * pushes an rr to an rrlist. +- * \param[in] rr_list the rr_list to push to +- * \param[in] rr the rr to push +- * \return false on error, otherwise true +- */ +-bool ldns_rr_list_push_rr(ldns_rr_list *rr_list, const ldns_rr *rr); +- +-/** +- * pushes an rr_list to an rrlist. +- * \param[in] rr_list the rr_list to push to +- * \param[in] push_list the rr_list to push +- * \return false on error, otherwise true +- */ +-bool ldns_rr_list_push_rr_list(ldns_rr_list *rr_list, const ldns_rr_list *push_list); +- +-/** +- * pops the last rr from an rrlist. +- * \param[in] rr_list the rr_list to pop from +- * \return NULL if nothing to pop. Otherwise the popped RR +- */ +-ldns_rr* ldns_rr_list_pop_rr(ldns_rr_list *rr_list); +- +-/** +- * pops an rr_list of size s from an rrlist. +- * \param[in] rr_list the rr_list to pop from +- * \param[in] size the number of rr's to pop +- * \return NULL if nothing to pop. Otherwise the popped rr_list +- */ +-ldns_rr_list* ldns_rr_list_pop_rr_list(ldns_rr_list *rr_list, size_t size); +- +-/** +- * returns true if the given rr is one of the rrs in the +- * list, or if it is equal to one +- * \param[in] rr_list the rr_list to check +- * \param[in] rr the rr to check +- * \return true if rr_list contains rr, false otherwise +- */ +-bool ldns_rr_list_contains_rr(const ldns_rr_list *rr_list, ldns_rr *rr); +- +-/** +- * checks if an rr_list is a rrset. +- * \param[in] rr_list the rr_list to check +- * \return true if it is an rrset otherwise false +- */ +-bool ldns_is_rrset(ldns_rr_list *rr_list); +- +-/** +- * pushes an rr to an rrset (which really are rr_list's). +- * \param[in] *rr_list the rrset to push the rr to +- * \param[in] *rr the rr to push +- * \return true if the push succeeded otherwise false +- */ +-bool ldns_rr_set_push_rr(ldns_rr_list *rr_list, ldns_rr *rr); +- +-/** +- * pops the last rr from an rrset. This function is there only +- * for the symmetry. +- * \param[in] rr_list the rr_list to pop from +- * \return NULL if nothing to pop. Otherwise the popped RR +- * +- */ +-ldns_rr* ldns_rr_set_pop_rr(ldns_rr_list *rr_list); +- +-/** +- * pops the first rrset from the list, +- * the list must be sorted, so that all rr's from each rrset +- * are next to each other +- */ +-ldns_rr_list *ldns_rr_list_pop_rrset(ldns_rr_list *rr_list); +- +- +-/** +- * retrieves a rrtype by looking up its name. +- * \param[in] name a string with the name +- * \return the type which corresponds with the name +- */ +-ldns_rr_type ldns_get_rr_type_by_name(const char *name); +- +-/** +- * retrieves a class by looking up its name. +- * \param[in] name string with the name +- * \return the cass which corresponds with the name +- */ +-ldns_rr_class ldns_get_rr_class_by_name(const char *name); +- +-/** +- * clones a rr and all its data +- * \param[in] rr the rr to clone +- * \return the new rr or NULL on failure +- */ +-ldns_rr* ldns_rr_clone(const ldns_rr *rr); +- +-/** +- * clones an rrlist. +- * \param[in] rrlist the rrlist to clone +- * \return the cloned rr list +- */ +-ldns_rr_list* ldns_rr_list_clone(const ldns_rr_list *rrlist); +- +-/** +- * sorts an rr_list (canonical wire format). the sorting is done inband. +- * \param[in] unsorted the rr_list to be sorted +- * \return void +- */ +-void ldns_rr_list_sort(ldns_rr_list *unsorted); +- +-/** +- * compares two rrs. The TTL is not looked at. +- * \param[in] rr1 the first one +- * \param[in] rr2 the second one +- * \return 0 if equal +- * -1 if rr1 comes before rr2 +- * +1 if rr2 comes before rr1 +- */ +-int ldns_rr_compare(const ldns_rr *rr1, const ldns_rr *rr2); +- +-/** +- * compares two rrs, up to the rdata. +- * \param[in] rr1 the first one +- * \param[in] rr2 the second one +- * \return 0 if equal +- * -1 if rr1 comes before rr2 +- * +1 if rr2 comes before rr1 +- */ +-int ldns_rr_compare_no_rdata(const ldns_rr *rr1, const ldns_rr *rr2); +- +-/** +- * compares the wireformat of two rrs, contained in the given buffers. +- * \param[in] rr1_buf the first one +- * \param[in] rr2_buf the second one +- * \return 0 if equal +- * -1 if rr1_buf comes before rr2_buf +- * +1 if rr2_buf comes before rr1_buf +- */ +-int ldns_rr_compare_wire(ldns_buffer *rr1_buf, ldns_buffer *rr2_buf); +- +-/** +- * returns true of the given rr's are equal. +- * Also returns true if one record is a DS that represents the +- * same DNSKEY record as the other record +- * \param[in] rr1 the first rr +- * \param[in] rr2 the second rr +- * \return true if equal otherwise false +- */ +-bool ldns_rr_compare_ds(const ldns_rr *rr1, const ldns_rr *rr2); +- +-/** +- * compares two rr listss. +- * \param[in] rrl1 the first one +- * \param[in] rrl2 the second one +- * \return 0 if equal +- * -1 if rrl1 comes before rrl2 +- * +1 if rrl2 comes before rrl1 +- */ +-int ldns_rr_list_compare(const ldns_rr_list *rrl1, const ldns_rr_list *rrl2); +- +-/** +- * calculates the uncompressed size of an RR. +- * \param[in] r the rr to operate on +- * \return size of the rr +- */ +-size_t ldns_rr_uncompressed_size(const ldns_rr *r); +- +-/** +- * converts each dname in a rr to its canonical form. +- * \param[in] rr the rr to work on +- * \return void +- */ +-void ldns_rr2canonical(ldns_rr *rr); +- +-/** +- * converts each dname in each rr in a rr_list to its canonical form. +- * \param[in] rr_list the rr_list to work on +- * \return void +- */ +-void ldns_rr_list2canonical(ldns_rr_list *rr_list); +- +-/** +- * counts the number of labels of the ownername. +- * \param[in] rr count the labels of this rr +- * \return the number of labels +- */ +-uint8_t ldns_rr_label_count(ldns_rr *rr); +- +-/** +- * returns the resource record descriptor for the given rr type. +- * +- * \param[in] type the type value of the rr type +- *\return the ldns_rr_descriptor for this type +- */ +-const ldns_rr_descriptor *ldns_rr_descript(uint16_t type); +- +-/** +- * returns the minimum number of rdata fields of the rr type this descriptor describes. +- * +- * \param[in] descriptor for an rr type +- * \return the minimum number of rdata fields +- */ +-size_t ldns_rr_descriptor_minimum(const ldns_rr_descriptor *descriptor); +- +-/** +- * returns the maximum number of rdata fields of the rr type this descriptor describes. +- * +- * \param[in] descriptor for an rr type +- * \return the maximum number of rdata fields +- */ +-size_t ldns_rr_descriptor_maximum(const ldns_rr_descriptor *descriptor); +- +-/** +- * returns the rdf type for the given rdata field number of the rr type for the given descriptor. +- * +- * \param[in] descriptor for an rr type +- * \param[in] field the field number +- * \return the rdf type for the field +- */ +-ldns_rdf_type ldns_rr_descriptor_field_type(const ldns_rr_descriptor *descriptor, size_t field); +- +-/** +- * Return the rr_list which matches the rdf at position field. Think +- * type-covered stuff for RRSIG +- * +- * \param[in] l the rr_list to look in +- * \param[in] r the rdf to use for the comparison +- * \param[in] pos at which position can we find the rdf +- * +- * \return a new rr list with only the RRs that match +- * +- */ +-ldns_rr_list *ldns_rr_list_subtype_by_rdf(ldns_rr_list *l, ldns_rdf *r, size_t pos); +- +-/** +- * convert an rdf of type LDNS_RDF_TYPE_TYPE to an actual +- * LDNS_RR_TYPE. This is usefull in the case when inspecting +- * the rrtype covered field of an RRSIG. +- * \param[in] rd the rdf to look at +- * \return a ldns_rr_type with equivalent LDNS_RR_TYPE +- * +- */ +-ldns_rr_type ldns_rdf2rr_type(const ldns_rdf *rd); +- +-/** +- * Returns the type of the first element of the RR +- * If there are no elements present, 0 is returned +- * +- * \param[in] rr_list The rr list +- * \return rr_type of the first element, or 0 if the list is empty +- */ +-ldns_rr_type +-ldns_rr_list_type(const ldns_rr_list *rr_list); +- +-/** +- * Returns the owner domain name rdf of the first element of the RR +- * If there are no elements present, NULL is returned +- * +- * \param[in] rr_list The rr list +- * \return dname of the first element, or NULL if the list is empty +- */ +-ldns_rdf * +-ldns_rr_list_owner(const ldns_rr_list *rr_list); +- +-#ifdef __cplusplus +-} +-#endif +- +-#endif /* LDNS_RR_H */ +diff --git a/include/ldns/rr_functions.h b/include/ldns/rr_functions.h +deleted file mode 100644 +index 09a28dd..0000000 +--- a/include/ldns/rr_functions.h ++++ /dev/null +@@ -1,363 +0,0 @@ +-/* +- * rr_functions.h +- * +- * the .h file with defs for the per rr +- * functions +- * +- * a Net::DNS like library for C +- * +- * (c) NLnet Labs, 2005-2006 +- * +- * See the file LICENSE for the license +- */ +-#ifndef LDNS_RR_FUNCTIONS_H +-#define LDNS_RR_FUNCTIONS_H +- +-#ifdef __cplusplus +-extern "C" { +-#endif +- +-/** +- * \file +- * +- * Defines some extra convenience functions for ldns_rr structures +- */ +- +-/* A / AAAA */ +-/** +- * returns the address of a LDNS_RR_TYPE_A rr +- * \param[in] r the resource record +- * \return a ldns_rdf* with the address or NULL on failure +- */ +-ldns_rdf* ldns_rr_a_address(const ldns_rr *r); +- +-/** +- * sets the address of a LDNS_RR_TYPE_A rr +- * \param[in] r the rr to use +- * \param[in] f the address to set +- * \return true on success, false otherwise +- */ +-bool ldns_rr_a_set_address(ldns_rr *r, ldns_rdf *f); +- +-/* NS */ +-/** +- * returns the name of a LDNS_RR_TYPE_NS rr +- * \param[in] r the resource record +- * \return a ldns_rdf* with the name or NULL on failure +- */ +-ldns_rdf* ldns_rr_ns_nsdname(const ldns_rr *r); +- +-/* MX */ +-/** +- * returns the mx pref. of a LDNS_RR_TYPE_MX rr +- * \param[in] r the resource record +- * \return a ldns_rdf* with the preference or NULL on failure +- */ +-ldns_rdf* ldns_rr_mx_preference(const ldns_rr *r); +-/** +- * returns the mx host of a LDNS_RR_TYPE_MX rr +- * \param[in] r the resource record +- * \return a ldns_rdf* with the name of the MX host or NULL on failure +- */ +-ldns_rdf* ldns_rr_mx_exchange(const ldns_rr *r); +- +-/* RRSIG */ +-/** +- * returns the type covered of a LDNS_RR_TYPE_RRSIG rr +- * \param[in] r the resource record +- * \return a ldns_rdf* with the type covered or NULL on failure +- */ +-ldns_rdf* ldns_rr_rrsig_typecovered(const ldns_rr *r); +-/** +- * sets the typecovered of a LDNS_RR_TYPE_RRSIG rr +- * \param[in] r the rr to use +- * \param[in] f the typecovered to set +- * \return true on success, false otherwise +- */ +-bool ldns_rr_rrsig_set_typecovered(ldns_rr *r, ldns_rdf *f); +-/** +- * returns the algorithm of a LDNS_RR_TYPE_RRSIG RR +- * \param[in] r the resource record +- * \return a ldns_rdf* with the algorithm or NULL on failure +- */ +-ldns_rdf* ldns_rr_rrsig_algorithm(const ldns_rr *r); +-/** +- * sets the algorithm of a LDNS_RR_TYPE_RRSIG rr +- * \param[in] r the rr to use +- * \param[in] f the algorithm to set +- * \return true on success, false otherwise +- */ +-bool ldns_rr_rrsig_set_algorithm(ldns_rr *r, ldns_rdf *f); +-/** +- * returns the number of labels of a LDNS_RR_TYPE_RRSIG RR +- * \param[in] r the resource record +- * \return a ldns_rdf* with the number of labels or NULL on failure +- */ +-ldns_rdf *ldns_rr_rrsig_labels(const ldns_rr *r); +-/** +- * sets the number of labels of a LDNS_RR_TYPE_RRSIG rr +- * \param[in] r the rr to use +- * \param[in] f the number of labels to set +- * \return true on success, false otherwise +- */ +-bool ldns_rr_rrsig_set_labels(ldns_rr *r, ldns_rdf *f); +-/** +- * returns the original TTL of a LDNS_RR_TYPE_RRSIG RR +- * \param[in] r the resource record +- * \return a ldns_rdf* with the original TTL or NULL on failure +- */ +-ldns_rdf* ldns_rr_rrsig_origttl(const ldns_rr *r); +-/** +- * sets the original TTL of a LDNS_RR_TYPE_RRSIG rr +- * \param[in] r the rr to use +- * \param[in] f the original TTL to set +- * \return true on success, false otherwise +- */ +-bool ldns_rr_rrsig_set_origttl(ldns_rr *r, ldns_rdf *f); +-/** +- * returns the expiration time of a LDNS_RR_TYPE_RRSIG RR +- * \param[in] r the resource record +- * \return a ldns_rdf* with the expiration time or NULL on failure +- */ +-ldns_rdf* ldns_rr_rrsig_expiration(const ldns_rr *r); +-/** +- * sets the expireation date of a LDNS_RR_TYPE_RRSIG rr +- * \param[in] r the rr to use +- * \param[in] f the expireation date to set +- * \return true on success, false otherwise +- */ +-bool ldns_rr_rrsig_set_expiration(ldns_rr *r, ldns_rdf *f); +-/** +- * returns the inception time of a LDNS_RR_TYPE_RRSIG RR +- * \param[in] r the resource record +- * \return a ldns_rdf* with the inception time or NULL on failure +- */ +-ldns_rdf* ldns_rr_rrsig_inception(const ldns_rr *r); +-/** +- * sets the inception date of a LDNS_RR_TYPE_RRSIG rr +- * \param[in] r the rr to use +- * \param[in] f the inception date to set +- * \return true on success, false otherwise +- */ +-bool ldns_rr_rrsig_set_inception(ldns_rr *r, ldns_rdf *f); +-/** +- * returns the keytag of a LDNS_RR_TYPE_RRSIG RR +- * \param[in] r the resource record +- * \return a ldns_rdf* with the keytag or NULL on failure +- */ +-ldns_rdf* ldns_rr_rrsig_keytag(const ldns_rr *r); +-/** +- * sets the keytag of a LDNS_RR_TYPE_RRSIG rr +- * \param[in] r the rr to use +- * \param[in] f the keytag to set +- * \return true on success, false otherwise +- */ +-bool ldns_rr_rrsig_set_keytag(ldns_rr *r, ldns_rdf *f); +-/** +- * returns the signers name of a LDNS_RR_TYPE_RRSIG RR +- * \param[in] r the resource record +- * \return a ldns_rdf* with the signers name or NULL on failure +- */ +-ldns_rdf* ldns_rr_rrsig_signame(const ldns_rr *r); +-/** +- * sets the signers name of a LDNS_RR_TYPE_RRSIG rr +- * \param[in] r the rr to use +- * \param[in] f the signers name to set +- * \return true on success, false otherwise +- */ +-bool ldns_rr_rrsig_set_signame(ldns_rr *r, ldns_rdf *f); +-/** +- * returns the signature data of a LDNS_RR_TYPE_RRSIG RR +- * \param[in] r the resource record +- * \return a ldns_rdf* with the signature data or NULL on failure +- */ +-ldns_rdf* ldns_rr_rrsig_sig(const ldns_rr *r); +-/** +- * sets the signature data of a LDNS_RR_TYPE_RRSIG rr +- * \param[in] r the rr to use +- * \param[in] f the signature data to set +- * \return true on success, false otherwise +- */ +-bool ldns_rr_rrsig_set_sig(ldns_rr *r, ldns_rdf *f); +- +-/* DNSKEY */ +-/** +- * returns the flags of a LDNS_RR_TYPE_DNSKEY rr +- * \param[in] r the resource record +- * \return a ldns_rdf* with the flags or NULL on failure +- */ +-ldns_rdf* ldns_rr_dnskey_flags(const ldns_rr *r); +-/** +- * sets the flags of a LDNS_RR_TYPE_DNSKEY rr +- * \param[in] r the rr to use +- * \param[in] f the flags to set +- * \return true on success, false otherwise +- */ +-bool ldns_rr_dnskey_set_flags(ldns_rr *r, ldns_rdf *f); +-/** +- * returns the protocol of a LDNS_RR_TYPE_DNSKEY rr +- * \param[in] r the resource record +- * \return a ldns_rdf* with the protocol or NULL on failure +- */ +-ldns_rdf* ldns_rr_dnskey_protocol(const ldns_rr *r); +-/** +- * sets the protocol of a LDNS_RR_TYPE_DNSKEY rr +- * \param[in] r the rr to use +- * \param[in] f the protocol to set +- * \return true on success, false otherwise +- */ +-bool ldns_rr_dnskey_set_protocol(ldns_rr *r, ldns_rdf *f); +-/** +- * returns the algorithm of a LDNS_RR_TYPE_DNSKEY rr +- * \param[in] r the resource record +- * \return a ldns_rdf* with the algorithm or NULL on failure +- */ +-ldns_rdf* ldns_rr_dnskey_algorithm(const ldns_rr *r); +-/** +- * sets the algorithm of a LDNS_RR_TYPE_DNSKEY rr +- * \param[in] r the rr to use +- * \param[in] f the algorithm to set +- * \return true on success, false otherwise +- */ +-bool ldns_rr_dnskey_set_algorithm(ldns_rr *r, ldns_rdf *f); +-/** +- * returns the key data of a LDNS_RR_TYPE_DNSKEY rr +- * \param[in] r the resource record +- * \return a ldns_rdf* with the key data or NULL on failure +- */ +-ldns_rdf* ldns_rr_dnskey_key(const ldns_rr *r); +-/** +- * sets the key data of a LDNS_RR_TYPE_DNSKEY rr +- * \param[in] r the rr to use +- * \param[in] f the key data to set +- * \return true on success, false otherwise +- */ +-bool ldns_rr_dnskey_set_key(ldns_rr *r, ldns_rdf *f); +- +-/** +- * get the length of the keydata in bits +- * \param[in] keydata the raw key data +- * \param[in] len the length of the keydata +- * \param[in] alg the cryptographic algorithm this is a key for +- * \return the keysize in bits, or 0 on error +- */ +-size_t ldns_rr_dnskey_key_size_raw(const unsigned char *keydata, +- const size_t len, +- const ldns_algorithm alg); +- +-/** +- * get the length of the keydata in bits +- * \param[in] key the key rr to use +- * \return the keysize in bits +- */ +-size_t ldns_rr_dnskey_key_size(const ldns_rr *key); +- +-/** +- * The type of function to be passed to ldns_rr_soa_increment_func, +- * ldns_rr_soa_increment_func_data or ldns_rr_soa_increment_int. +- * The function will be called with as the first argument the current serial +- * number of the SOA RR to be updated, and as the second argument a value +- * given when calling ldns_rr_soa_increment_func_data or +- * ldns_rr_soa_increment_int. With ldns_rr_soa_increment_int the pointer +- * value holds the integer value passed to ldns_rr_soa_increment_int, +- * and it should be cast to intptr_t to be used as an integer by the +- * serial modifying function. +- */ +-typedef uint32_t (*ldns_soa_serial_increment_func_t)(uint32_t, void*); +- +-/** +- * Function to be used with dns_rr_soa_increment_func_int, to set the soa +- * serial number. +- * \param[in] unused the (unused) current serial number. +- * \param[in] data the serial number to be set. +- */ +-uint32_t ldns_soa_serial_identity(uint32_t unused, void *data); +- +-/** +- * Function to be used with dns_rr_soa_increment_func, to increment the soa +- * serial number with one. +- * \param[in] s the current serial number. +- * \param[in] unused unused. +- */ +-uint32_t ldns_soa_serial_increment(uint32_t s, void *unused); +- +-/** +- * Function to be used with dns_rr_soa_increment_func_int, to increment the soa +- * serial number with a certain amount. +- * \param[in] s the current serial number. +- * \param[in] data the amount to add to the current serial number. +- */ +-uint32_t ldns_soa_serial_increment_by(uint32_t s, void *data); +- +-/** +- * Function to be used with ldns_rr_soa_increment_func or +- * ldns_rr_soa_increment_func_int to set the soa serial to the number of +- * seconds since unix epoch (1-1-1970 00:00). +- * When data is given (i.e. the function is called via +- * ldns_rr_soa_increment_func_int), it is used as the current time. +- * When the resulting serial number is smaller than the current serial number, +- * the current serial number is increased by one. +- * \param[in] s the current serial number. +- * \param[in] data the time in seconds since 1-1-1970 00:00 +- */ +-uint32_t ldns_soa_serial_unixtime(uint32_t s, void *data); +- +-/** +- * Function to be used with ldns_rr_soa_increment_func or +- * ldns_rr_soa_increment_func_int to set the soa serial to the current date +- * succeeded by a two digit iteration (datecounter). +- * When data is given (i.e. the function is called via +- * ldns_rr_soa_increment_func_int), it is used as the current time. +- * When the resulting serial number is smaller than the current serial number, +- * the current serial number is increased by one. +- * \param[in] s the current serial number. +- * \param[in] data the time in seconds since 1-1-1970 00:00 +- */ +-uint32_t ldns_soa_serial_datecounter(uint32_t s, void *data); +- +-/** +- * Increment the serial number of the given SOA by one. +- * \param[in] soa The soa rr to be incremented +- */ +-void ldns_rr_soa_increment( +- ldns_rr *soa); +- +-/** +- * Increment the serial number of the given SOA with the given function. +- * Included functions to be used here are: ldns_rr_soa_increment, +- * ldns_soa_serial_unixtime and ldns_soa_serial_datecounter. +- * \param[in] soa The soa rr to be incremented +- * \param[in] f the function to use to increment the soa rr. +- */ +-void ldns_rr_soa_increment_func( +- ldns_rr *soa, ldns_soa_serial_increment_func_t f); +- +-/** +- * Increment the serial number of the given SOA with the given function +- * passing it the given data argument. +- * \param[in] soa The soa rr to be incremented +- * \param[in] f the function to use to increment the soa rr. +- * \param[in] data this argument will be passed to f as the second argument. +- */ +-void ldns_rr_soa_increment_func_data( +- ldns_rr *soa, ldns_soa_serial_increment_func_t f, void *data); +- +-/** +- * Increment the serial number of the given SOA with the given function +- * using data as an argument for the function. +- * Included functions to be used here are: ldns_soa_serial_identity, +- * ldns_rr_soa_increment_by, ldns_soa_serial_unixtime and +- * ldns_soa_serial_datecounter. +- * \param[in] soa The soa rr to be incremented +- * \param[in] f the function to use to increment the soa rr. +- * \param[in] data this argument will be passed to f as the second argument +- * (by casting it to void*). +- */ +-void ldns_rr_soa_increment_func_int( +- ldns_rr *soa, ldns_soa_serial_increment_func_t f, int data); +- +-#ifdef __cplusplus +-} +-#endif +- +-#endif /* LDNS_RR_FUNCTIONS_H */ +diff --git a/include/ldns/sha1.h b/include/ldns/sha1.h +deleted file mode 100644 +index d5b1082..0000000 +--- a/include/ldns/sha1.h ++++ /dev/null +@@ -1,38 +0,0 @@ +-#ifndef LDNS_SHA1_H +-#define LDNS_SHA1_H +- +-#ifdef __cplusplus +-extern "C" { +-#endif +- +-#define LDNS_SHA1_BLOCK_LENGTH 64 +-#define LDNS_SHA1_DIGEST_LENGTH 20 +- +-typedef struct { +- uint32_t state[5]; +- uint64_t count; +- unsigned char buffer[LDNS_SHA1_BLOCK_LENGTH]; +-} ldns_sha1_ctx; +- +-void ldns_sha1_init(ldns_sha1_ctx * context); +-void ldns_sha1_transform(uint32_t state[5], const unsigned char buffer[LDNS_SHA1_BLOCK_LENGTH]); +-void ldns_sha1_update(ldns_sha1_ctx *context, const unsigned char *data, unsigned int len); +-void ldns_sha1_final(unsigned char digest[LDNS_SHA1_DIGEST_LENGTH], ldns_sha1_ctx *context); +- +-/** +- * Convenience function to digest a fixed block of data at once. +- * +- * \param[in] data the data to digest +- * \param[in] data_len the length of data in bytes +- * \param[out] digest the length of data in bytes +- * This pointer MUST have LDNS_SHA1_DIGEST_LENGTH bytes +- * available +- * \return the SHA1 digest of the given data +- */ +-unsigned char *ldns_sha1(unsigned char *data, unsigned int data_len, unsigned char *digest); +- +-#ifdef __cplusplus +-} +-#endif +- +-#endif /* LDNS_SHA1_H */ +diff --git a/include/ldns/sha2.h b/include/ldns/sha2.h +deleted file mode 100644 +index 238767a..0000000 +--- a/include/ldns/sha2.h ++++ /dev/null +@@ -1,149 +0,0 @@ +-/* +- * FILE: sha2.h +- * AUTHOR: Aaron D. Gifford - http://www.aarongifford.com/ +- * +- * Copyright (c) 2000-2001, Aaron D. Gifford +- * All rights reserved. +- * +- * Modified by Jelte Jansen to fit in ldns, and not clash with any +- * system-defined SHA code. +- * Changes: +- * - Renamed (external) functions and constants to fit ldns style +- * - Removed uintXX vs. u_intXX smartness, since ldns needs uintXX +- * anyway +- * - BYTE ORDER check replaced by simple ifdef as defined or not by +- * configure.ac +- * - Removed _End and _Data functions +- * - Added ldns_shaX(data, len, digest) functions +- * +- * Redistribution and use in source and binary forms, with or without +- * modification, are permitted provided that the following conditions +- * are met: +- * 1. Redistributions of source code must retain the above copyright +- * notice, this list of conditions and the following disclaimer. +- * 2. Redistributions in binary form must reproduce the above copyright +- * notice, this list of conditions and the following disclaimer in the +- * documentation and/or other materials provided with the distribution. +- * 3. Neither the name of the copyright holder nor the names of contributors +- * may be used to endorse or promote products derived from this software +- * without specific prior written permission. +- * +- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``AS IS'' AND +- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTOR(S) BE LIABLE +- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +- * SUCH DAMAGE. +- * +- * $Id: sha2.h,v 1.1 2001/11/08 00:02:01 adg Exp adg $ +- */ +- +-#ifndef __LDNS_SHA2_H__ +-#define __LDNS_SHA2_H__ +- +-#ifdef __cplusplus +-extern "C" { +-#endif +- +- +-/* +- * Import u_intXX_t size_t type definitions from system headers. You +- * may need to change this, or define these things yourself in this +- * file. +- */ +-#include <sys/types.h> +- +-#if LDNS_BUILD_CONFIG_HAVE_INTTYPES_H +- +-#include <inttypes.h> +- +-#endif /* LDNS_BUILD_CONFIG_HAVE_INTTYPES_H */ +- +- +-/*** SHA-256/384/512 Various Length Definitions ***********************/ +-#define LDNS_SHA256_BLOCK_LENGTH 64 +-#define LDNS_SHA256_DIGEST_LENGTH 32 +-#define LDNS_SHA256_DIGEST_STRING_LENGTH (LDNS_SHA256_DIGEST_LENGTH * 2 + 1) +-#define LDNS_SHA384_BLOCK_LENGTH 128 +-#define LDNS_SHA384_DIGEST_LENGTH 48 +-#define LDNS_SHA384_DIGEST_STRING_LENGTH (LDNS_SHA384_DIGEST_LENGTH * 2 + 1) +-#define LDNS_SHA512_BLOCK_LENGTH 128 +-#define LDNS_SHA512_DIGEST_LENGTH 64 +-#define LDNS_SHA512_DIGEST_STRING_LENGTH (LDNS_SHA512_DIGEST_LENGTH * 2 + 1) +- +- +-/*** SHA-256/384/512 Context Structures *******************************/ +- +-typedef struct _ldns_sha256_CTX { +- uint32_t state[8]; +- uint64_t bitcount; +- uint8_t buffer[LDNS_SHA256_BLOCK_LENGTH]; +-} ldns_sha256_CTX; +-typedef struct _ldns_sha512_CTX { +- uint64_t state[8]; +- uint64_t bitcount[2]; +- uint8_t buffer[LDNS_SHA512_BLOCK_LENGTH]; +-} ldns_sha512_CTX; +- +-typedef ldns_sha512_CTX ldns_sha384_CTX; +- +- +-/*** SHA-256/384/512 Function Prototypes ******************************/ +-void ldns_sha256_init(ldns_sha256_CTX *); +-void ldns_sha256_update(ldns_sha256_CTX*, const uint8_t*, size_t); +-void ldns_sha256_final(uint8_t[LDNS_SHA256_DIGEST_LENGTH], ldns_sha256_CTX*); +- +-void ldns_sha384_init(ldns_sha384_CTX*); +-void ldns_sha384_update(ldns_sha384_CTX*, const uint8_t*, size_t); +-void ldns_sha384_final(uint8_t[LDNS_SHA384_DIGEST_LENGTH], ldns_sha384_CTX*); +- +-void ldns_sha512_init(ldns_sha512_CTX*); +-void ldns_sha512_update(ldns_sha512_CTX*, const uint8_t*, size_t); +-void ldns_sha512_final(uint8_t[LDNS_SHA512_DIGEST_LENGTH], ldns_sha512_CTX*); +- +-/** +- * Convenience function to digest a fixed block of data at once. +- * +- * \param[in] data the data to digest +- * \param[in] data_len the length of data in bytes +- * \param[out] digest the length of data in bytes +- * This pointer MUST have LDNS_SHA256_DIGEST_LENGTH bytes +- * available +- * \return the SHA1 digest of the given data +- */ +-unsigned char *ldns_sha256(unsigned char *data, unsigned int data_len, unsigned char *digest); +- +-/** +- * Convenience function to digest a fixed block of data at once. +- * +- * \param[in] data the data to digest +- * \param[in] data_len the length of data in bytes +- * \param[out] digest the length of data in bytes +- * This pointer MUST have LDNS_SHA384_DIGEST_LENGTH bytes +- * available +- * \return the SHA1 digest of the given data +- */ +-unsigned char *ldns_sha384(unsigned char *data, unsigned int data_len, unsigned char *digest); +- +-/** +- * Convenience function to digest a fixed block of data at once. +- * +- * \param[in] data the data to digest +- * \param[in] data_len the length of data in bytes +- * \param[out] digest the length of data in bytes +- * This pointer MUST have LDNS_SHA512_DIGEST_LENGTH bytes +- * available +- * \return the SHA1 digest of the given data +- */ +-unsigned char *ldns_sha512(unsigned char *data, unsigned int data_len, unsigned char *digest); +- +-#ifdef __cplusplus +-} +-#endif /* __cplusplus */ +- +-#endif /* __LDNS_SHA2_H__ */ +diff --git a/include/ldns/str2host.h b/include/ldns/str2host.h +deleted file mode 100644 +index d639970..0000000 +--- a/include/ldns/str2host.h ++++ /dev/null +@@ -1,319 +0,0 @@ +-/** +- * str2host.h - conversion from str to the host fmt +- * +- * a Net::DNS like library for C +- * +- * (c) NLnet Labs, 2005-2006 +- * +- * See the file LICENSE for the license +- */ +- +-#ifndef LDNS_2HOST_H +-#define LDNS_2HOST_H +- +-#include <ldns/common.h> +-#include <ldns/error.h> +-#include <ldns/rr.h> +-#include <ldns/rdata.h> +-#include <ldns/packet.h> +-#include <ldns/buffer.h> +-#include <ctype.h> +- +-#ifdef __cplusplus +-extern "C" { +-#endif +- +-/** +- * \file +- * +- * Defines functions to convert dns data in presentation format or text files +- * to internal structures. +- */ +- +-/** +- * convert a byte into wireformat +- * \param[in] rd the rdf where to put the data +- * \param[in] bytestr the string to be converted +- * \return ldns_status +- */ +-ldns_status ldns_str2rdf_int8(ldns_rdf **rd, const char *bytestr); +- +-/** +- * convert a string to a int16 in wireformat +- * \param[in] rd the rdf where to put the data +- * \param[in] shortstr the string to be converted +- * \return ldns_status +- */ +-ldns_status ldns_str2rdf_int16(ldns_rdf **rd, const char *shortstr); +- +-/** +- * convert a strings into a 4 byte int in wireformat +- * \param[in] rd the rdf where to put the data +- * \param[in] longstr the string to be converted +- * \return ldns_status +- */ +-ldns_status ldns_str2rdf_int32(ldns_rdf **rd, const char *longstr); +- +-/** +- * convert a time string to a time value in wireformat +- * \param[in] rd the rdf where to put the data +- * \param[in] time the string to be converted +- * \return ldns_status +- */ +-ldns_status ldns_str2rdf_time(ldns_rdf **rd, const char *time); +- +-/* convert string with NSEC3 salt to wireformat) +- * \param[in] rd the rdf where to put the data +- * \param[in] str the string to be converted +- * return ldns_status +- */ +-ldns_status ldns_str2rdf_nsec3_salt(ldns_rdf **rd, const char *nsec3_salt); +- +-/* convert a time period (think TTL's) to wireformat) +- * \param[in] rd the rdf where to put the data +- * \param[in] str the string to be converted +- * return ldns_status +- */ +-ldns_status ldns_str2rdf_period(ldns_rdf **rd, const char *str); +- +-/** +- * convert str with an A record into wireformat +- * \param[in] rd the rdf where to put the data +- * \param[in] str the string to be converted +- * \return ldns_status +- */ +-ldns_status ldns_str2rdf_a(ldns_rdf **rd, const char *str); +- +-/** +- * convert the str with an AAAA record into wireformat +- * \param[in] rd the rdf where to put the data +- * \param[in] str the string to be converted +- * \return ldns_status +- */ +-ldns_status ldns_str2rdf_aaaa(ldns_rdf **rd, const char *str); +- +-/** +- * convert a string into wireformat (think txt record) +- * \param[in] rd the rdf where to put the data +- * \param[in] str the string to be converted (NULL terminated) +- * \return ldns_status +- */ +-ldns_status ldns_str2rdf_str(ldns_rdf **rd, const char *str); +- +-/** +- * convert str with the apl record into wireformat +- * \param[in] rd the rdf where to put the data +- * \param[in] str the string to be converted +- * \return ldns_status +- */ +-ldns_status ldns_str2rdf_apl(ldns_rdf **rd, const char *str); +- +-/** +- * convert the string with the b64 data into wireformat +- * \param[in] rd the rdf where to put the data +- * \param[in] str the string to be converted +- * \return ldns_status +- */ +-ldns_status ldns_str2rdf_b64(ldns_rdf **rd, const char *str); +- +-/** +- * convert the string with the b32 ext hex data into wireformat +- * \param[in] rd the rdf where to put the data +- * \param[in] str the string to be converted +- * \return ldns_status +- */ +-ldns_status ldns_str2rdf_b32_ext(ldns_rdf **rd, const char *str); +- +-/** +- * convert a hex value into wireformat +- * \param[in] rd the rdf where to put the data +- * \param[in] str the string to be converted +- * \return ldns_status +- */ +-ldns_status ldns_str2rdf_hex(ldns_rdf **rd, const char *str); +- +-/** +- * convert string with nsec into wireformat +- * \param[in] rd the rdf where to put the data +- * \param[in] str the string to be converted +- * \return ldns_status +- */ +-ldns_status ldns_str2rdf_nsec(ldns_rdf **rd, const char *str); +- +-/** +- * convert a rrtype into wireformat +- * \param[in] rd the rdf where to put the data +- * \param[in] str the string to be converted +- * \return ldns_status +- */ +-ldns_status ldns_str2rdf_type(ldns_rdf **rd, const char *str); +- +-/** +- * convert string with a classname into wireformat +- * \param[in] rd the rdf where to put the data +- * \param[in] str the string to be converted +- * \return ldns_status +- */ +-ldns_status ldns_str2rdf_class(ldns_rdf **rd, const char *str); +- +-/** +- * convert an certificate algorithm value into wireformat +- * \param[in] rd the rdf where to put the data +- * \param[in] str the string to be converted +- * \return ldns_status +- */ +-ldns_status ldns_str2rdf_cert_alg(ldns_rdf **rd, const char *str); +- +-/** +- * convert an algorithm value into wireformat +- * \param[in] rd the rdf where to put the data +- * \param[in] str the string to be converted +- * \return ldns_status +- */ +-ldns_status ldns_str2rdf_alg(ldns_rdf **rd, const char *str); +- +-/** +- * convert a tlsa certificate usage value into wireformat +- * \param[in] rd the rdf where to put the data +- * \param[in] str the string to be converted +- * \return ldns_status +- */ +-ldns_status ldns_str2rdf_certificate_usage(ldns_rdf **rd, const char *str); +- +-/** +- * convert a tlsa selector value into wireformat +- * \param[in] rd the rdf where to put the data +- * \param[in] str the string to be converted +- * \return ldns_status +- */ +-ldns_status ldns_str2rdf_selector(ldns_rdf **rd, const char *str); +- +-/** +- * convert a tlsa matching type value into wireformat +- * \param[in] rd the rdf where to put the data +- * \param[in] str the string to be converted +- * \return ldns_status +- */ +-ldns_status ldns_str2rdf_matching_type(ldns_rdf **rd, const char *str); +- +-/** +- * convert a string with a unknown RR into wireformat +- * \param[in] rd the rdf where to put the data +- * \param[in] str the string to be converted +- * \return ldns_status +- */ +-ldns_status ldns_str2rdf_unknown(ldns_rdf **rd, const char *str); +- +-/** +- * convert string with a protocol service into wireformat +- * \param[in] rd the rdf where to put the data +- * \param[in] str the string to be converted +- * \return ldns_status +- */ +-ldns_status ldns_str2rdf_service(ldns_rdf **rd, const char *str); +- +-/** +- * convert a string with a LOC RR into wireformat +- * \param[in] rd the rdf where to put the data +- * \param[in] str the string to be converted +- * \return ldns_status +- */ +-ldns_status ldns_str2rdf_loc(ldns_rdf **rd, const char *str); +- +-/** +- * convert string with a WKS RR into wireformat +- * \param[in] rd the rdf where to put the data +- * \param[in] str the string to be converted +- * \return ldns_status +- */ +-ldns_status ldns_str2rdf_wks(ldns_rdf **rd, const char *str); +- +-/** +- * convert a str with a NSAP RR into wireformat +- * \param[in] rd the rdf where to put the data +- * \param[in] str the string to be converted +- * \return ldns_status +- */ +-ldns_status ldns_str2rdf_nsap(ldns_rdf **rd, const char *str); +- +-/** +- * convert a str with a ATMA RR into wireformat +- * \param[in] rd the rdf where to put the data +- * \param[in] str the string to be converted +- * \return ldns_status +- */ +-ldns_status ldns_str2rdf_atma(ldns_rdf **rd, const char *str); +- +-/** +- * convert a str with a IPSECKEY RR into wireformat +- * \param[in] rd the rdf where to put the data +- * \param[in] str the string to be converted +- * \return ldns_status +- */ +-ldns_status ldns_str2rdf_ipseckey(ldns_rdf **rd, const char *str); +- +-/** +- * convert a dname string into wireformat +- * \param[in] rd the rdf where to put the data +- * \param[in] str the string to be converted +- * \return ldns_status +- */ +-ldns_status ldns_str2rdf_dname(ldns_rdf **rd, const char *str); +- +-/** +- * convert 4 * 16bit hex separated by colons into wireformat +- * \param[in] rd the rdf where to put the data +- * \param[in] str the string to be converted +- * \return ldns_status +- */ +-ldns_status ldns_str2rdf_ilnp64(ldns_rdf **rd, const char *str); +- +-/** +- * convert 6 hex bytes separated by dashes into wireformat +- * \param[in] rd the rdf where to put the data +- * \param[in] str the string to be converted +- * \return ldns_status +- */ +-ldns_status ldns_str2rdf_eui48(ldns_rdf **rd, const char *str); +- +-/** +- * convert 8 hex bytes separated by dashes into wireformat +- * \param[in] rd the rdf where to put the data +- * \param[in] str the string to be converted +- * \return ldns_status +- */ +-ldns_status ldns_str2rdf_eui64(ldns_rdf **rd, const char *str); +- +-/** +- * Convert a non-zero sequence of US-ASCII letters and numbers into wireformat +- * \param[in] rd the rdf where to put the data +- * \param[in] str the string to be converted +- * \return ldns_status +- */ +-ldns_status ldns_str2rdf_tag(ldns_rdf **rd, const char *str); +- +-/** +- * Convert a <character-string> encoding of the value field as specified +- * [RFC1035], Section 5.1., encoded as one bug chunk of data. +- * \param[in] rd the rdf where to put the data +- * \param[in] str the string to be converted +- * \return ldns_status +- */ +-ldns_status ldns_str2rdf_long_str(ldns_rdf **rd, const char *str); +- +-/** +- * Convert a "<algorithm> <hit> <pk>" encoding of the value field as specified +- * in Section 6. of [RFC5205], encoded as wireformat as specified in Section 5. +- * of [RFC5205]. +- * \param[in] rd the rdf where to put the data +- * \param[in] str the string to be converted +- * \return ldns_status +- */ +-ldns_status ldns_str2rdf_hip(ldns_rdf **rd, const char *str); +- +- +-#ifdef __cplusplus +-} +-#endif +- +-#endif /* LDNS_2HOST_H */ +diff --git a/include/ldns/tsig.h b/include/ldns/tsig.h +deleted file mode 100644 +index 676045f..0000000 +--- a/include/ldns/tsig.h ++++ /dev/null +@@ -1,101 +0,0 @@ +-/* +- * tsig.h -- defines for TSIG [RFC2845] +- * +- * Copyright (c) 2005-2008, NLnet Labs. All rights reserved. +- * +- * See LICENSE for the license. +- */ +- +-#ifndef LDNS_TSIG_H +-#define LDNS_TSIG_H +- +-#ifdef __cplusplus +-extern "C" { +-#endif +- +-/** +- * \file +- * +- * Defines functions for TSIG usage +- */ +- +- +-/** +- * Contains credentials for TSIG +-*/ +-typedef struct ldns_tsig_credentials_struct +-{ +- char *algorithm; +- char *keyname; +- char *keydata; +- /* XXX More eventually. */ +-} ldns_tsig_credentials; +- +-char *ldns_tsig_algorithm(ldns_tsig_credentials *); +-char *ldns_tsig_keyname(ldns_tsig_credentials *); +-char *ldns_tsig_keydata(ldns_tsig_credentials *); +-char *ldns_tsig_keyname_clone(ldns_tsig_credentials *); +-char *ldns_tsig_keydata_clone(ldns_tsig_credentials *); +- +-/** +- * verifies the tsig rr for the given packet and key. +- * The wire must be given too because tsig does not sign normalized packets. +- * \param[in] pkt the packet to verify +- * \param[in] wire needed to verify the mac +- * \param[in] wire_size size of wire +- * \param[in] key_name the name of the shared key +- * \param[in] key_data the key in base 64 format +- * \param[in] mac original mac +- * \return true if tsig is correct, false if not, or if tsig is not set +- */ +-bool ldns_pkt_tsig_verify(ldns_pkt *pkt, uint8_t *wire, size_t wire_size, const char *key_name, const char *key_data, ldns_rdf *mac); +- +-/** +- * verifies the tsig rr for the given packet and key. +- * The wire must be given too because tsig does not sign normalized packets. +- * \param[in] pkt the packet to verify +- * \param[in] wire needed to verify the mac +- * \param[in] wire_size size of wire +- * \param[in] key_name the name of the shared key +- * \param[in] key_data the key in base 64 format +- * \param[in] mac original mac +- * \param[in] tsig_timers_only must be zero for the first packet and positive for subsequent packets. If zero, all digest +- components are used to verify the _mac. If non-zero, only the TSIG timers are used to verify the mac. +- * \return true if tsig is correct, false if not, or if tsig is not set +- */ +-bool ldns_pkt_tsig_verify_next(ldns_pkt *pkt, uint8_t *wire, size_t wire_size, const char *key_name, const char *key_data, ldns_rdf *mac, +- int tsig_timers_only); +- +-/** +- * creates a tsig rr for the given packet and key. +- * \param[in] pkt the packet to sign +- * \param[in] key_name the name of the shared key +- * \param[in] key_data the key in base 64 format +- * \param[in] fudge seconds of error permitted in time signed +- * \param[in] algorithm_name the name of the algorithm used +- * \param[in] query_mac is added to the digest if not NULL (so NULL is for signing queries, not NULL is for signing answers) +- * \return status (OK if success) +- */ +-ldns_status ldns_pkt_tsig_sign(ldns_pkt *pkt, const char *key_name, const char *key_data, uint16_t fudge, +- const char *algorithm_name, ldns_rdf *query_mac); +- +-/** +- * creates a tsig rr for the given packet and key. +- * \param[in] pkt the packet to sign +- * \param[in] key_name the name of the shared key +- * \param[in] key_data the key in base 64 format +- * \param[in] fudge seconds of error permitted in time signed +- * \param[in] algorithm_name the name of the algorithm used +- * \param[in] query_mac is added to the digest if not NULL (so NULL is for signing queries, not NULL is for signing answers) +- * \param[in] tsig_timers_only must be zero for the first packet and positive for subsequent packets. If zero, all digest +- components are used to create the query_mac. If non-zero, only the TSIG timers are used to create the query_mac. +- * \return status (OK if success) +- */ +-ldns_status ldns_pkt_tsig_sign_next(ldns_pkt *pkt, const char *key_name, const char *key_data, uint16_t fudge, +- const char *algorithm_name, ldns_rdf *query_mac, int tsig_timers_only); +- +-#ifdef __cplusplus +-} +-#endif +- +-#endif /* LDNS_TSIG_H */ +diff --git a/include/ldns/update.h b/include/ldns/update.h +deleted file mode 100644 +index d3459d3..0000000 +--- a/include/ldns/update.h ++++ /dev/null +@@ -1,115 +0,0 @@ +-/* +- * update.h +- * +- * Functions for RFC 2136 Dynamic Update +- * +- * Copyright (c) 2005-2008, NLnet Labs. All rights reserved. +- * +- * See LICENSE for the license. +- */ +- +-/** +- * \file +- * +- * Defines functions to perform UPDATE queries +- */ +- +- +-#ifndef LDNS_UPDATE_H +-#define LDNS_UPDATE_H +- +-#include <ldns/resolver.h> +- +-#ifdef __cplusplus +-extern "C" { +-#endif +- +-/** +- * create an update packet from zone name, class and the rr lists +- * \param[in] zone_rdf name of the zone +- * \param[in] clas zone class +- * \param[in] pr_rrlist list of Prerequisite Section RRs +- * \param[in] up_rrlist list of Updates Section RRs +- * \param[in] ad_rrlist list of Additional Data Section RRs (currently unused) +- * \return the new packet +- */ +-ldns_pkt *ldns_update_pkt_new(ldns_rdf *zone_rdf, ldns_rr_class clas, ldns_rr_list *pr_rrlist, ldns_rr_list *up_rrlist, ldns_rr_list *ad_rrlist); +- +-/** +- * add tsig credentials to +- * a packet from a resolver +- * \param[in] p packet to copy to +- * \param[in] r resolver to copy from +- * +- * \return status wether successfull or not +- */ +-ldns_status ldns_update_pkt_tsig_add(ldns_pkt *p, ldns_resolver *r); +- +-/* access functions */ +- +-/** +- * Get the zo count +- * \param[in] p the packet +- * \return the zo count +- */ +-uint16_t ldns_update_zocount(const ldns_pkt *p); +-/** +- * Get the zo count +- * \param[in] p the packet +- * \return the pr count +- */ +-uint16_t ldns_update_prcount(const ldns_pkt *p); +-/** +- * Get the zo count +- * \param[in] p the packet +- * \return the up count +- */ +-uint16_t ldns_update_upcount(const ldns_pkt *p); +-/** +- * Get the zo count +- * \param[in] p the packet +- * \return the ad count +- */ +-uint16_t ldns_update_ad(const ldns_pkt *p); +-/** +- * Set the zo count +- * \param[in] p the packet +- * \param[in] c the zo count to set +- */ +-void ldns_update_set_zo(ldns_pkt *p, uint16_t c); +-/** +- * Set the pr count +- * \param[in] p the packet +- * \param[in] c the pr count to set +- */ +-void ldns_update_set_prcount(ldns_pkt *p, uint16_t c); +-/** +- * Set the up count +- * \param[in] p the packet +- * \param[in] c the up count to set +- */ +-void ldns_update_set_upcount(ldns_pkt *p, uint16_t c); +-/** +- * Set the ad count +- * \param[in] p the packet +- * \param[in] c the ad count to set +- */ +-void ldns_update_set_adcount(ldns_pkt *p, uint16_t c); +- +-/* soa functions that need to be configured */ +-/* +- * Not sure if we want to keep these like this, therefore +- * not documented +- */ +-ldns_status ldns_update_soa_mname(ldns_rdf *zone, ldns_resolver *r, ldns_rr_class c, ldns_rdf **mname); +-/* +- * Not sure if we want to keep these like this, therefore +- * not documented +- */ +-ldns_status ldns_update_soa_zone_mname(const char *fqdn, ldns_resolver *r, ldns_rr_class c, ldns_rdf **zone_rdf, ldns_rdf **mname_rdf); +- +-#ifdef __cplusplus +-} +-#endif +- +-#endif /* LDNS_UPDATE_H */ +diff --git a/include/ldns/util.h b/include/ldns/util.h +deleted file mode 100644 +index 86848eb..0000000 +--- a/include/ldns/util.h ++++ /dev/null +@@ -1,392 +0,0 @@ +-/* +- * util.h +- * +- * helper function header file +- * +- * a Net::DNS like library for C +- * +- * (c) NLnet Labs, 2004 +- * +- * See the file LICENSE for the license +- */ +- +-#ifndef _UTIL_H +-#define _UTIL_H +- +-#include "EXTERN.h" +-#include "perl.h" +-#include <ldns/common.h> +-#include <time.h> +-#include <stdio.h> +- +-#ifdef __cplusplus +-extern "C" { +-#endif +- +-#define dprintf(X,Y) fprintf(stderr, (X), (Y)) +-/* #define dprintf(X, Y) */ +- +-#define LDNS_VERSION "1.6.18" +-#define LDNS_REVISION ((1<<16)|(6<<8)|(18)) +- +-/** +- * splint static inline workaround +- */ +-#ifdef S_SPLINT_S +-# define INLINE +-#else +-# ifdef SWIG +-# define INLINE static +-# else +-# define INLINE static inline +-# endif +-#endif +- +-/** +- * Memory management macros +- */ +-#define LDNS_MALLOC(type) LDNS_XMALLOC(type, 1) +- +-#define LDNS_XMALLOC(type, count) ((type *) malloc((count) * sizeof(type))) +- +-#define LDNS_CALLOC(type, count) ((type *) calloc((count), sizeof(type))) +- +-#define LDNS_REALLOC(ptr, type) LDNS_XREALLOC((ptr), type, 1) +- +-#define LDNS_XREALLOC(ptr, type, count) \ +- ((type *) realloc((ptr), (count) * sizeof(type))) +- +-#define LDNS_FREE(ptr) \ +- do { free((ptr)); (ptr) = NULL; } while (0) +- +-#define LDNS_DEP printf("DEPRECATED FUNCTION!\n"); +- +-/* +- * Copy data allowing for unaligned accesses in network byte order +- * (big endian). +- */ +-INLINE uint16_t +-ldns_read_uint16(const void *src) +-{ +-#ifdef ALLOW_UNALIGNED_ACCESSES +- return ntohs(*(const uint16_t *) src); +-#else +- const uint8_t *p = (const uint8_t *) src; +- return ((uint16_t) p[0] << 8) | (uint16_t) p[1]; +-#endif +-} +- +-INLINE uint32_t +-ldns_read_uint32(const void *src) +-{ +-#ifdef ALLOW_UNALIGNED_ACCESSES +- return ntohl(*(const uint32_t *) src); +-#else +- const uint8_t *p = (const uint8_t *) src; +- return ( ((uint32_t) p[0] << 24) +- | ((uint32_t) p[1] << 16) +- | ((uint32_t) p[2] << 8) +- | (uint32_t) p[3]); +-#endif +-} +- +-/* +- * Copy data allowing for unaligned accesses in network byte order +- * (big endian). +- */ +-INLINE void +-ldns_write_uint16(void *dst, uint16_t data) +-{ +-#ifdef ALLOW_UNALIGNED_ACCESSES +- * (uint16_t *) dst = htons(data); +-#else +- uint8_t *p = (uint8_t *) dst; +- p[0] = (uint8_t) ((data >> 8) & 0xff); +- p[1] = (uint8_t) (data & 0xff); +-#endif +-} +- +-INLINE void +-ldns_write_uint32(void *dst, uint32_t data) +-{ +-#ifdef ALLOW_UNALIGNED_ACCESSES +- * (uint32_t *) dst = htonl(data); +-#else +- uint8_t *p = (uint8_t *) dst; +- p[0] = (uint8_t) ((data >> 24) & 0xff); +- p[1] = (uint8_t) ((data >> 16) & 0xff); +- p[2] = (uint8_t) ((data >> 8) & 0xff); +- p[3] = (uint8_t) (data & 0xff); +-#endif +-} +- +-/* warning. */ +-INLINE void +-ldns_write_uint64_as_uint48(void *dst, uint64_t data) +-{ +- uint8_t *p = (uint8_t *) dst; +- p[0] = (uint8_t) ((data >> 40) & 0xff); +- p[1] = (uint8_t) ((data >> 32) & 0xff); +- p[2] = (uint8_t) ((data >> 24) & 0xff); +- p[3] = (uint8_t) ((data >> 16) & 0xff); +- p[4] = (uint8_t) ((data >> 8) & 0xff); +- p[5] = (uint8_t) (data & 0xff); +-} +- +- +-/** +- * Structure to do a Schwartzian-like transformation, for instance when +- * sorting. If you need a transformation on the objects that are sorted, +- * you can sue this to store the transformed values, so you do not +- * need to do the transformation again for each comparison +- */ +-struct ldns_schwartzian_compare_struct { +- void *original_object; +- void *transformed_object; +-}; +- +-/** A general purpose lookup table +- * +- * Lookup tables are arrays of (id, name) pairs, +- * So you can for instance lookup the RCODE 3, which is "NXDOMAIN", +- * and vice versa. The lookup tables themselves are defined wherever needed, +- * for instance in \ref host2str.c +- */ +-struct ldns_struct_lookup_table { +- int id; +- const char *name; +-}; +-typedef struct ldns_struct_lookup_table ldns_lookup_table; +- +-/** +- * Looks up the table entry by name, returns NULL if not found. +- * \param[in] table the lookup table to search in +- * \param[in] name what to search for +- * \return the item found +- */ +-ldns_lookup_table *ldns_lookup_by_name(ldns_lookup_table table[], +- const char *name); +- +-/** +- * Looks up the table entry by id, returns NULL if not found. +- * \param[in] table the lookup table to search in +- * \param[in] id what to search for +- * \return the item found +- */ +-ldns_lookup_table *ldns_lookup_by_id(ldns_lookup_table table[], int id); +- +-/** +- * Returns the value of the specified bit +- * The bits are counted from left to right, so bit #0 is the +- * left most bit. +- * \param[in] bits array holding the bits +- * \param[in] index to the wanted bit +- * \return +- */ +-int ldns_get_bit(uint8_t bits[], size_t index); +- +- +-/** +- * Returns the value of the specified bit +- * The bits are counted from right to left, so bit #0 is the +- * right most bit. +- * \param[in] bits array holding the bits +- * \param[in] index to the wanted bit +- * \return 1 or 0 depending no the bit state +- */ +-int ldns_get_bit_r(uint8_t bits[], size_t index); +- +-/** +- * sets the specified bit in the specified byte to +- * 1 if value is true, 0 if false +- * The bits are counted from right to left, so bit #0 is the +- * right most bit. +- * \param[in] byte the bit to set the bit in +- * \param[in] bit_nr the bit to set (0 <= n <= 7) +- * \param[in] value whether to set the bit to 1 or 0 +- * \return 1 or 0 depending no the bit state +- */ +-void ldns_set_bit(uint8_t *byte, int bit_nr, bool value); +- +-/** +- * Returns the value of a to the power of b +- * (or 1 of b < 1) +- */ +-/*@unused@*/ +-INLINE long +-ldns_power(long a, long b) { +- long result = 1; +- while (b > 0) { +- if (b & 1) { +- result *= a; +- if (b == 1) { +- return result; +- } +- } +- a *= a; +- b /= 2; +- } +- return result; +-} +- +-/** +- * Returns the int value of the given (hex) digit +- * \param[in] ch the hex char to convert +- * \return the converted decimal value +- */ +-int ldns_hexdigit_to_int(char ch); +- +-/** +- * Returns the char (hex) representation of the given int +- * \param[in] ch the int to convert +- * \return the converted hex char +- */ +-char ldns_int_to_hexdigit(int ch); +- +-/** +- * Converts a hex string to binary data +- * +- * \param[out] data The binary result is placed here. +- * At least strlen(str)/2 bytes should be allocated +- * \param[in] str The hex string to convert. +- * This string should not contain spaces +- * \return The number of bytes of converted data, or -1 if one of the arguments * is NULL, or -2 if the string length is not an even number +- */ +-int +-ldns_hexstring_to_data(uint8_t *data, const char *str); +- +-/** +- * Show the internal library version +- * \return a string with the version in it +- */ +-const char * ldns_version(void); +- +-/** +- * Convert TM to seconds since epoch (midnight, January 1st, 1970). +- * Like timegm(3), which is not always available. +- * \param[in] tm a struct tm* with the date +- * \return the seconds since epoch +- */ +-time_t ldns_mktime_from_utc(const struct tm *tm); +- +-time_t mktime_from_utc(const struct tm *tm); +- +-/** +- * The function interprets time as the number of seconds since epoch +- * with respect to now using serial arithmitics (rfc1982). +- * That number of seconds is then converted to broken-out time information. +- * This is especially usefull when converting the inception and expiration +- * fields of RRSIG records. +- * +- * \param[in] time number of seconds since epoch (midnight, January 1st, 1970) +- * to be intepreted as a serial arithmitics number relative to now. +- * \param[in] now number of seconds since epoch (midnight, January 1st, 1970) +- * to which the time value is compared to determine the final value. +- * \param[out] result the struct with the broken-out time information +- * \return result on success or NULL on error +- */ +-struct tm * ldns_serial_arithmitics_gmtime_r(int32_t time, time_t now, struct tm *result); +- +-/** +- * Seed the random function. +- * If the file descriptor is specified, the random generator is seeded with +- * data from that file. If not, /dev/urandom is used. +- * +- * applications should call this if they need entropy data within ldns +- * If openSSL is available, it is automatically seeded from /dev/urandom +- * or /dev/random. +- * +- * If you need more entropy, or have no openssl available, this function +- * MUST be called at the start of the program +- * +- * If openssl *is* available, this function just adds more entropy +- * +- * \param[in] fd a file providing entropy data for the seed +- * \param[in] size the number of bytes to use as entropy data. If this is 0, +- * only the minimal amount is taken (usually 4 bytes) +- * \return 0 if seeding succeeds, 1 if it fails +- */ +-int ldns_init_random(FILE *fd, unsigned int size); +- +-/** +- * Get random number. +- * \return random number. +- * +- */ +-uint16_t ldns_get_random(void); +- +-/** +- * Encode data as BubbleBabble +- * +- * \param[in] data a pointer to data to be encoded +- * \param[in] len size the number of bytes of data +- * \return a string of BubbleBabble +- */ +-char *ldns_bubblebabble(uint8_t *data, size_t len); +- +- +-INLINE time_t ldns_time(time_t *t) { return time(t); } +- +- +-/** +- * calculates the size needed to store the result of b32_ntop +- */ +-/*@unused@*/ +-INLINE size_t ldns_b32_ntop_calculate_size(size_t src_data_length) +-{ +- return src_data_length == 0 ? 0 : ((src_data_length - 1) / 5 + 1) * 8; +-} +- +-INLINE size_t ldns_b32_ntop_calculate_size_no_padding(size_t src_data_length) +-{ +- return ((src_data_length + 3) * 8 / 5) - 4; +-} +- +-int ldns_b32_ntop(const uint8_t* src_data, size_t src_data_length, +- char* target_text_buffer, size_t target_text_buffer_size); +- +-int ldns_b32_ntop_extended_hex(const uint8_t* src_data, size_t src_data_length, +- char* target_text_buffer, size_t target_text_buffer_size); +- +-#if ! LDNS_BUILD_CONFIG_HAVE_B32_NTOP +- +-int b32_ntop(const uint8_t* src_data, size_t src_data_length, +- char* target_text_buffer, size_t target_text_buffer_size); +- +-int b32_ntop_extended_hex(const uint8_t* src_data, size_t src_data_length, +- char* target_text_buffer, size_t target_text_buffer_size); +- +-#endif /* ! LDNS_BUILD_CONFIG_HAVE_B32_NTOP */ +- +- +-/** +- * calculates the size needed to store the result of b32_pton +- */ +-/*@unused@*/ +-INLINE size_t ldns_b32_pton_calculate_size(size_t src_text_length) +-{ +- return src_text_length * 5 / 8; +-} +- +-int ldns_b32_pton(const char* src_text, size_t src_text_length, +- uint8_t* target_data_buffer, size_t target_data_buffer_size); +- +-int ldns_b32_pton_extended_hex(const char* src_text, size_t src_text_length, +- uint8_t* target_data_buffer, size_t target_data_buffer_size); +- +-#if ! LDNS_BUILD_CONFIG_HAVE_B32_PTON +- +-int b32_pton(const char* src_text, size_t src_text_length, +- uint8_t* target_data_buffer, size_t target_data_buffer_size); +- +-int b32_pton_extended_hex(const char* src_text, size_t src_text_length, +- uint8_t* target_data_buffer, size_t target_data_buffer_size); +- +-#endif /* ! LDNS_BUILD_CONFIG_HAVE_B32_PTON */ +- +- +-#ifdef __cplusplus +-} +-#endif +- +-#endif /* !_UTIL_H */ +diff --git a/include/ldns/wire2host.h b/include/ldns/wire2host.h +deleted file mode 100644 +index 53155b3..0000000 +--- a/include/ldns/wire2host.h ++++ /dev/null +@@ -1,197 +0,0 @@ +-/* +- * wire2host.h - from wire conversion routines +- * +- * a Net::DNS like library for C +- * +- * (c) NLnet Labs, 2005-2006 +- * +- * See the file LICENSE for the license +- */ +- +-/** +- * \file +- * +- * Contains functions that translate dns data from the wire format (as sent +- * by servers and clients) to the internal structures. +- */ +- +-#ifndef LDNS_WIRE2HOST_H +-#define LDNS_WIRE2HOST_H +- +-#include <ldns/rdata.h> +-#include <ldns/common.h> +-#include <ldns/error.h> +-#include <ldns/rr.h> +-#include <ldns/packet.h> +- +-#ifdef __cplusplus +-extern "C" { +-#endif +- +-/* The length of the header */ +-#define LDNS_HEADER_SIZE 12 +- +-/* First octet of flags */ +-#define LDNS_RD_MASK 0x01U +-#define LDNS_RD_SHIFT 0 +-#define LDNS_RD_WIRE(wirebuf) (*(wirebuf+2) & LDNS_RD_MASK) +-#define LDNS_RD_SET(wirebuf) (*(wirebuf+2) |= LDNS_RD_MASK) +-#define LDNS_RD_CLR(wirebuf) (*(wirebuf+2) &= ~LDNS_RD_MASK) +- +-#define LDNS_TC_MASK 0x02U +-#define LDNS_TC_SHIFT 1 +-#define LDNS_TC_WIRE(wirebuf) (*(wirebuf+2) & LDNS_TC_MASK) +-#define LDNS_TC_SET(wirebuf) (*(wirebuf+2) |= LDNS_TC_MASK) +-#define LDNS_TC_CLR(wirebuf) (*(wirebuf+2) &= ~LDNS_TC_MASK) +- +-#define LDNS_AA_MASK 0x04U +-#define LDNS_AA_SHIFT 2 +-#define LDNS_AA_WIRE(wirebuf) (*(wirebuf+2) & LDNS_AA_MASK) +-#define LDNS_AA_SET(wirebuf) (*(wirebuf+2) |= LDNS_AA_MASK) +-#define LDNS_AA_CLR(wirebuf) (*(wirebuf+2) &= ~LDNS_AA_MASK) +- +-#define LDNS_OPCODE_MASK 0x78U +-#define LDNS_OPCODE_SHIFT 3 +-#define LDNS_OPCODE_WIRE(wirebuf) ((*(wirebuf+2) & LDNS_OPCODE_MASK) >> LDNS_OPCODE_SHIFT) +-#define LDNS_OPCODE_SET(wirebuf, opcode) \ +- (*(wirebuf+2) = ((*(wirebuf+2)) & ~LDNS_OPCODE_MASK) | ((opcode) << LDNS_OPCODE_SHIFT)) +- +-#define LDNS_QR_MASK 0x80U +-#define LDNS_QR_SHIFT 7 +-#define LDNS_QR_WIRE(wirebuf) (*(wirebuf+2) & LDNS_QR_MASK) +-#define LDNS_QR_SET(wirebuf) (*(wirebuf+2) |= LDNS_QR_MASK) +-#define LDNS_QR_CLR(wirebuf) (*(wirebuf+2) &= ~LDNS_QR_MASK) +- +-/* Second octet of flags */ +-#define LDNS_RCODE_MASK 0x0fU +-#define LDNS_RCODE_SHIFT 0 +-#define LDNS_RCODE_WIRE(wirebuf) (*(wirebuf+3) & LDNS_RCODE_MASK) +-#define LDNS_RCODE_SET(wirebuf, rcode) \ +- (*(wirebuf+3) = ((*(wirebuf+3)) & ~LDNS_RCODE_MASK) | (rcode)) +- +-#define LDNS_CD_MASK 0x10U +-#define LDNS_CD_SHIFT 4 +-#define LDNS_CD_WIRE(wirebuf) (*(wirebuf+3) & LDNS_CD_MASK) +-#define LDNS_CD_SET(wirebuf) (*(wirebuf+3) |= LDNS_CD_MASK) +-#define LDNS_CD_CLR(wirebuf) (*(wirebuf+3) &= ~LDNS_CD_MASK) +- +-#define LDNS_AD_MASK 0x20U +-#define LDNS_AD_SHIFT 5 +-#define LDNS_AD_WIRE(wirebuf) (*(wirebuf+3) & LDNS_AD_MASK) +-#define LDNS_AD_SET(wirebuf) (*(wirebuf+3) |= LDNS_AD_MASK) +-#define LDNS_AD_CLR(wirebuf) (*(wirebuf+3) &= ~LDNS_AD_MASK) +- +-#define LDNS_Z_MASK 0x40U +-#define LDNS_Z_SHIFT 6 +-#define LDNS_Z_WIRE(wirebuf) (*(wirebuf+3) & LDNS_Z_MASK) +-#define LDNS_Z_SET(wirebuf) (*(wirebuf+3) |= LDNS_Z_MASK) +-#define LDNS_Z_CLR(wirebuf) (*(wirebuf+3) &= ~LDNS_Z_MASK) +- +-#define LDNS_RA_MASK 0x80U +-#define LDNS_RA_SHIFT 7 +-#define LDNS_RA_WIRE(wirebuf) (*(wirebuf+3) & LDNS_RA_MASK) +-#define LDNS_RA_SET(wirebuf) (*(wirebuf+3) |= LDNS_RA_MASK) +-#define LDNS_RA_CLR(wirebuf) (*(wirebuf+3) &= ~LDNS_RA_MASK) +- +-/* Query ID */ +-#define LDNS_ID_WIRE(wirebuf) (ldns_read_uint16(wirebuf)) +-#define LDNS_ID_SET(wirebuf, id) (ldns_write_uint16(wirebuf, id)) +- +-/* Counter of the question section */ +-#define LDNS_QDCOUNT_OFF 4 +-/* +-#define QDCOUNT(wirebuf) (ntohs(*(uint16_t *)(wirebuf+QDCOUNT_OFF))) +-*/ +-#define LDNS_QDCOUNT(wirebuf) (ldns_read_uint16(wirebuf+LDNS_QDCOUNT_OFF)) +- +-/* Counter of the answer section */ +-#define LDNS_ANCOUNT_OFF 6 +-#define LDNS_ANCOUNT(wirebuf) (ldns_read_uint16(wirebuf+LDNS_ANCOUNT_OFF)) +- +-/* Counter of the authority section */ +-#define LDNS_NSCOUNT_OFF 8 +-#define LDNS_NSCOUNT(wirebuf) (ldns_read_uint16(wirebuf+LDNS_NSCOUNT_OFF)) +- +-/* Counter of the additional section */ +-#define LDNS_ARCOUNT_OFF 10 +-#define LDNS_ARCOUNT(wirebuf) (ldns_read_uint16(wirebuf+LDNS_ARCOUNT_OFF)) +- +-/** +- * converts the data on the uint8_t bytearray (in wire format) to a DNS packet. +- * This function will initialize and allocate memory space for the packet +- * structure. +- * +- * \param[in] packet pointer to the structure to hold the packet +- * \param[in] data pointer to the buffer with the data +- * \param[in] len the length of the data buffer (in bytes) +- * \return LDNS_STATUS_OK if everything succeeds, error otherwise +- */ +-ldns_status ldns_wire2pkt(ldns_pkt **packet, const uint8_t *data, size_t len); +- +-/** +- * converts the data on the uint8_t bytearray (in wire format) to a DNS packet. +- * This function will initialize and allocate memory space for the packet +- * structure. +- * +- * \param[in] packet pointer to the structure to hold the packet +- * \param[in] buffer the buffer with the data +- * \return LDNS_STATUS_OK if everything succeeds, error otherwise +- */ +-ldns_status ldns_buffer2pkt_wire(ldns_pkt **packet, ldns_buffer *buffer); +- +-/** +- * converts the data on the uint8_t bytearray (in wire format) to a DNS +- * dname rdata field. This function will initialize and allocate memory +- * space for the dname structure. The length of the wiredata of this rdf +- * is added to the *pos value. +- * +- * \param[in] dname pointer to the structure to hold the rdata value +- * \param[in] wire pointer to the buffer with the data +- * \param[in] max the length of the data buffer (in bytes) +- * \param[in] pos the position of the rdf in the buffer (ie. the number of bytes +- * from the start of the buffer) +- * \return LDNS_STATUS_OK if everything succeeds, error otherwise +- */ +-ldns_status ldns_wire2dname(ldns_rdf **dname, const uint8_t *wire, size_t max, size_t *pos); +- +-/** +- * converts the data on the uint8_t bytearray (in wire format) to DNS +- * rdata fields, and adds them to the list of rdfs of the given rr. +- * This function will initialize and allocate memory space for the dname +- * structures. +- * The length of the wiredata of these rdfs is added to the *pos value. +- * +- * All rdfs belonging to the RR are read; the rr should have no rdfs +- * yet. An error is returned if the format cannot be parsed. +- * +- * \param[in] rr pointer to the ldns_rr structure to hold the rdata value +- * \param[in] wire pointer to the buffer with the data +- * \param[in] max the length of the data buffer (in bytes) +- * \param[in] pos the position of the rdf in the buffer (ie. the number of bytes +- * from the start of the buffer) +- * \return LDNS_STATUS_OK if everything succeeds, error otherwise +- */ +-ldns_status ldns_wire2rdf(ldns_rr *rr, const uint8_t *wire, size_t max, size_t *pos); +- +-/** +- * converts the data on the uint8_t bytearray (in wire format) to a DNS +- * resource record. +- * This function will initialize and allocate memory space for the rr +- * structure. +- * The length of the wiredata of this rr is added to the *pos value. +- * +- * \param[in] rr pointer to the structure to hold the rdata value +- * \param[in] wire pointer to the buffer with the data +- * \param[in] max the length of the data buffer (in bytes) +- * \param[in] pos the position of the rr in the buffer (ie. the number of bytes +- * from the start of the buffer) +- * \param[in] section the section in the packet the rr is meant for +- * \return LDNS_STATUS_OK if everything succeeds, error otherwise +- */ +-ldns_status ldns_wire2rr(ldns_rr **rr, const uint8_t *wire, size_t max, size_t *pos, ldns_pkt_section section); +- +-#ifdef __cplusplus +-} +-#endif +- +-#endif /* LDNS_WIRE2HOST_H */ +diff --git a/include/ldns/zone.h b/include/ldns/zone.h +deleted file mode 100644 +index 0d129a0..0000000 +--- a/include/ldns/zone.h ++++ /dev/null +@@ -1,176 +0,0 @@ +-/** +- * zone.h +- * +- * zone definitions +- * - what is it +- * - get_glue function +- * - search etc +- * +- * a Net::DNS like library for C +- * +- * (c) NLnet Labs, 2005-2006 +- * +- * See the file LICENSE for the license +- */ +- +-/** +- * \file +- * +- * Defines the ldns_zone structure and functions to manipulate it. +- */ +- +- +-#ifndef LDNS_ZONE_H +-#define LDNS_ZONE_H +- +-#include <ldns/common.h> +-#include <ldns/rdata.h> +-#include <ldns/rr.h> +-#include <ldns/error.h> +- +-#ifdef __cplusplus +-extern "C" { +-#endif +- +-/** +- * DNS Zone +- * +- * A list of RR's with some +- * extra information which comes from the SOA RR +- * Note: nothing has been done to make this efficient (yet). +- */ +-struct ldns_struct_zone +-{ +- /** the soa defines a zone */ +- ldns_rr *_soa; +- /* basicly a zone is a list of rr's */ +- ldns_rr_list *_rrs; +- /* we could change this to be a b-tree etc etc todo */ +-}; +-typedef struct ldns_struct_zone ldns_zone; +- +-/** +- * create a new ldns_zone structure +- * \return a pointer to a ldns_zone structure +- */ +-ldns_zone * ldns_zone_new(void); +- +-/** +- * Return the soa record of a zone +- * \param[in] z the zone to read from +- * \return the soa record in the zone +- */ +-ldns_rr * ldns_zone_soa(const ldns_zone *z); +- +-/** +- * Returns the number of resource records in the zone, NOT counting the SOA record +- * \param[in] z the zone to read from +- * \return the number of rr's in the zone +- */ +-size_t ldns_zone_rr_count(const ldns_zone *z); +- +-/** +- * Set the zone's soa record +- * \param[in] z the zone to put the new soa in +- * \param[in] soa the soa to set +- */ +-void ldns_zone_set_soa(ldns_zone *z, ldns_rr *soa); +- +-/** +- * Get a list of a zone's content. Note that the SOA +- * isn't included in this list. You need to get the +- * with ldns_zone_soa. +- * \param[in] z the zone to read from +- * \return the rrs from this zone +- */ +-ldns_rr_list * ldns_zone_rrs(const ldns_zone *z); +- +-/** +- * Set the zone's contents +- * \param[in] z the zone to put the new soa in +- * \param[in] rrlist the rrlist to use +- */ +-void ldns_zone_set_rrs(ldns_zone *z, ldns_rr_list *rrlist); +- +-/** +- * push an rrlist to a zone structure. This function use pointer +- * copying, so the rr_list structure inside z is modified! +- * \param[in] z the zone to add to +- * \param[in] list the list to add +- * \return a true on succes otherwise falsed +- */ +-bool ldns_zone_push_rr_list(ldns_zone *z, ldns_rr_list *list); +- +-/** +- * push an single rr to a zone structure. This function use pointer +- * copying, so the rr_list structure inside z is modified! +- * \param[in] z the zone to add to +- * \param[in] rr the rr to add +- * \return a true on succes otherwise falsed +- */ +-bool ldns_zone_push_rr(ldns_zone *z, ldns_rr *rr); +- +-/** +- * Retrieve all resource records from the zone that are glue +- * records. The resulting list does are pointer references +- * to the zone's data. +- * +- * Due to the current zone implementation (as a list of rr's), this +- * function is extremely slow. Another (probably better) way to do this +- * is to use an ldns_dnssec_zone structure and the +- * ldns_dnssec_mark_and_get_glue() function. +- * +- * \param[in] z the zone to look for glue +- * \return the rr_list with the glue +- */ +-ldns_rr_list *ldns_zone_glue_rr_list(const ldns_zone *z); +- +-/** +- * Create a new zone from a file +- * \param[out] z the new zone +- * \param[in] *fp the filepointer to use +- * \param[in] *origin the zones' origin +- * \param[in] ttl default ttl to use +- * \param[in] c default class to use (IN) +- * +- * \return ldns_status mesg with an error or LDNS_STATUS_OK +- */ +-ldns_status ldns_zone_new_frm_fp(ldns_zone **z, FILE *fp, ldns_rdf *origin, uint32_t ttl, ldns_rr_class c); +- +-/** +- * Create a new zone from a file, keep track of the line numbering +- * \param[out] z the new zone +- * \param[in] *fp the filepointer to use +- * \param[in] *origin the zones' origin +- * \param[in] ttl default ttl to use +- * \param[in] c default class to use (IN) +- * \param[out] line_nr used for error msg, to get to the line number +- * +- * \return ldns_status mesg with an error or LDNS_STATUS_OK +- */ +-ldns_status ldns_zone_new_frm_fp_l(ldns_zone **z, FILE *fp, ldns_rdf *origin, uint32_t ttl, ldns_rr_class c, int *line_nr); +- +-/** +- * Frees the allocated memory for the zone, and the rr_list structure in it +- * \param[in] zone the zone to free +- */ +-void ldns_zone_free(ldns_zone *zone); +- +-/** +- * Frees the allocated memory for the zone, the soa rr in it, +- * and the rr_list structure in it, including the rr's in that. etc. +- * \param[in] zone the zone to free +- */ +-void ldns_zone_deep_free(ldns_zone *zone); +- +-/** +- * Sort the rrs in a zone, with the current impl. this is slow +- * \param[in] zone the zone to sort +- */ +-void ldns_zone_sort(ldns_zone *zone); +- +-#ifdef __cplusplus +-} +-#endif +- +-#endif /* LDNS_ZONE_H */ +diff --git a/ldns/include/ldns/buffer.h b/ldns/include/ldns/buffer.h +new file mode 100644 +index 0000000..3b64198 +--- /dev/null ++++ b/ldns/include/ldns/buffer.h +@@ -0,0 +1,645 @@ ++/* ++ * buffer.h -- generic memory buffer. ++ * ++ * Copyright (c) 2005-2008, NLnet Labs. All rights reserved. ++ * ++ * See LICENSE for the license. ++ * ++ * ++ * The buffer module implements a generic buffer. The API is based on ++ * the java.nio.Buffer interface. ++ */ ++ ++#ifndef LDNS_BUFFER_H ++#define LDNS_BUFFER_H ++ ++#include <assert.h> ++#include <stdarg.h> ++#include <string.h> ++ ++#include <ldns/error.h> ++#include <ldns/common.h> ++ ++#include "ldns/util.h" ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/** ++ * number of initial bytes in buffer of ++ * which we cannot tell the size before hand ++ */ ++#define LDNS_MIN_BUFLEN 512 ++ ++/** ++ * \file buffer.h ++ * ++ * This file contains the definition of ldns_buffer, and functions to manipulate those. ++ */ ++ ++/** ++ * implementation of buffers to ease operations ++ * ++ * ldns_buffers can contain arbitrary information, per octet. You can write ++ * to the current end of a buffer, read from the current position, and ++ * access any data within it. ++ * ++ * Example use of buffers is in the source code of \ref host2str.c ++ */ ++struct ldns_struct_buffer ++{ ++ /** The current position used for reading/writing */ ++ size_t _position; ++ ++ /** The read/write limit */ ++ size_t _limit; ++ ++ /** The amount of data the buffer can contain */ ++ size_t _capacity; ++ ++ /** The data contained in the buffer */ ++ uint8_t *_data; ++ ++ /** If the buffer is fixed it cannot be resized */ ++ unsigned _fixed : 1; ++ ++ /** The current state of the buffer. If writing to the buffer fails ++ * for any reason, this value is changed. This way, you can perform ++ * multiple writes in sequence and check for success afterwards. */ ++ ldns_status _status; ++}; ++typedef struct ldns_struct_buffer ldns_buffer; ++ ++ ++#ifdef NDEBUG ++INLINE void ++ldns_buffer_invariant(ldns_buffer *ATTR_UNUSED(buffer)) ++{ ++} ++#else ++INLINE void ++ldns_buffer_invariant(ldns_buffer *buffer) ++{ ++ assert(buffer != NULL); ++ assert(buffer->_position <= buffer->_limit); ++ assert(buffer->_limit <= buffer->_capacity); ++ assert(buffer->_data != NULL); ++} ++#endif ++ ++/** ++ * creates a new buffer with the specified capacity. ++ * ++ * \param[in] capacity the size (in bytes) to allocate for the buffer ++ * \return the created buffer ++ */ ++ldns_buffer *ldns_buffer_new(size_t capacity); ++ ++/** ++ * creates a buffer with the specified data. The data IS copied ++ * and MEMORY allocations are done. The buffer is not fixed and can ++ * be resized using buffer_reserve(). ++ * ++ * \param[in] buffer pointer to the buffer to put the data in ++ * \param[in] data the data to encapsulate in the buffer ++ * \param[in] size the size of the data ++ */ ++void ldns_buffer_new_frm_data(ldns_buffer *buffer, void *data, size_t size); ++ ++/** ++ * clears the buffer and make it ready for writing. The buffer's limit ++ * is set to the capacity and the position is set to 0. ++ * \param[in] buffer the buffer to clear ++ */ ++INLINE void ldns_buffer_clear(ldns_buffer *buffer) ++{ ++ ldns_buffer_invariant(buffer); ++ ++ /* reset status here? */ ++ ++ buffer->_position = 0; ++ buffer->_limit = buffer->_capacity; ++} ++ ++/** ++ * makes the buffer ready for reading the data that has been written to ++ * the buffer. The buffer's limit is set to the current position and ++ * the position is set to 0. ++ * ++ * \param[in] buffer the buffer to flip ++ * \return void ++ */ ++INLINE void ldns_buffer_flip(ldns_buffer *buffer) ++{ ++ ldns_buffer_invariant(buffer); ++ ++ buffer->_limit = buffer->_position; ++ buffer->_position = 0; ++} ++ ++/** ++ * make the buffer ready for re-reading the data. The buffer's ++ * position is reset to 0. ++ * \param[in] buffer the buffer to rewind ++ */ ++INLINE void ldns_buffer_rewind(ldns_buffer *buffer) ++{ ++ ldns_buffer_invariant(buffer); ++ ++ buffer->_position = 0; ++} ++ ++/** ++ * returns the current position in the buffer (as a number of bytes) ++ * \param[in] buffer the buffer ++ * \return the current position ++ */ ++INLINE size_t ++ldns_buffer_position(ldns_buffer *buffer) ++{ ++ return buffer->_position; ++} ++ ++/** ++ * sets the buffer's position to MARK. The position must be less than ++ * or equal to the buffer's limit. ++ * \param[in] buffer the buffer ++ * \param[in] mark the mark to use ++ */ ++INLINE void ++ldns_buffer_set_position(ldns_buffer *buffer, size_t mark) ++{ ++ assert(mark <= buffer->_limit); ++ buffer->_position = mark; ++} ++ ++/** ++ * changes the buffer's position by COUNT bytes. The position must not ++ * be moved behind the buffer's limit or before the beginning of the ++ * buffer. ++ * \param[in] buffer the buffer ++ * \param[in] count the count to use ++ */ ++INLINE void ++ldns_buffer_skip(ldns_buffer *buffer, ssize_t count) ++{ ++ assert(buffer->_position + count <= buffer->_limit); ++ buffer->_position += count; ++} ++ ++/** ++ * returns the maximum size of the buffer ++ * \param[in] buffer ++ * \return the size ++ */ ++INLINE size_t ++ldns_buffer_limit(ldns_buffer *buffer) ++{ ++ return buffer->_limit; ++} ++ ++/** ++ * changes the buffer's limit. If the buffer's position is greater ++ * than the new limit the position is set to the limit. ++ * \param[in] buffer the buffer ++ * \param[in] limit the new limit ++ */ ++INLINE void ++ldns_buffer_set_limit(ldns_buffer *buffer, size_t limit) ++{ ++ assert(limit <= buffer->_capacity); ++ buffer->_limit = limit; ++ if (buffer->_position > buffer->_limit) ++ buffer->_position = buffer->_limit; ++} ++ ++/** ++ * returns the number of bytes the buffer can hold. ++ * \param[in] buffer the buffer ++ * \return the number of bytes ++ */ ++INLINE size_t ++ldns_buffer_capacity(ldns_buffer *buffer) ++{ ++ return buffer->_capacity; ++} ++ ++/** ++ * changes the buffer's capacity. The data is reallocated so any ++ * pointers to the data may become invalid. The buffer's limit is set ++ * to the buffer's new capacity. ++ * \param[in] buffer the buffer ++ * \param[in] capacity the capacity to use ++ * \return whether this failed or succeeded ++ */ ++bool ldns_buffer_set_capacity(ldns_buffer *buffer, size_t capacity); ++ ++/** ++ * ensures BUFFER can contain at least AMOUNT more bytes. The buffer's ++ * capacity is increased if necessary using buffer_set_capacity(). ++ * ++ * The buffer's limit is always set to the (possibly increased) ++ * capacity. ++ * \param[in] buffer the buffer ++ * \param[in] amount amount to use ++ * \return whether this failed or succeeded ++ */ ++bool ldns_buffer_reserve(ldns_buffer *buffer, size_t amount); ++ ++/** ++ * returns a pointer to the data at the indicated position. ++ * \param[in] buffer the buffer ++ * \param[in] at position ++ * \return the pointer to the data ++ */ ++INLINE uint8_t * ++ldns_buffer_at(const ldns_buffer *buffer, size_t at) ++{ ++ assert(at <= buffer->_limit); ++ return buffer->_data + at; ++} ++ ++/** ++ * returns a pointer to the beginning of the buffer (the data at ++ * position 0). ++ * \param[in] buffer the buffer ++ * \return the pointer ++ */ ++INLINE uint8_t * ++ldns_buffer_begin(const ldns_buffer *buffer) ++{ ++ return ldns_buffer_at(buffer, 0); ++} ++ ++/** ++ * returns a pointer to the end of the buffer (the data at the buffer's ++ * limit). ++ * \param[in] buffer the buffer ++ * \return the pointer ++ */ ++INLINE uint8_t * ++ldns_buffer_end(ldns_buffer *buffer) ++{ ++ return ldns_buffer_at(buffer, buffer->_limit); ++} ++ ++/** ++ * returns a pointer to the data at the buffer's current position. ++ * \param[in] buffer the buffer ++ * \return the pointer ++ */ ++INLINE uint8_t * ++ldns_buffer_current(ldns_buffer *buffer) ++{ ++ return ldns_buffer_at(buffer, buffer->_position); ++} ++ ++/** ++ * returns the number of bytes remaining between the indicated position and ++ * the limit. ++ * \param[in] buffer the buffer ++ * \param[in] at indicated position ++ * \return number of bytes ++ */ ++INLINE size_t ++ldns_buffer_remaining_at(ldns_buffer *buffer, size_t at) ++{ ++ ldns_buffer_invariant(buffer); ++ assert(at <= buffer->_limit); ++ return buffer->_limit - at; ++} ++ ++/** ++ * returns the number of bytes remaining between the buffer's position and ++ * limit. ++ * \param[in] buffer the buffer ++ * \return the number of bytes ++ */ ++INLINE size_t ++ldns_buffer_remaining(ldns_buffer *buffer) ++{ ++ return ldns_buffer_remaining_at(buffer, buffer->_position); ++} ++ ++/** ++ * checks if the buffer has at least COUNT more bytes available. ++ * Before reading or writing the caller needs to ensure enough space ++ * is available! ++ * \param[in] buffer the buffer ++ * \param[in] at indicated position ++ * \param[in] count how much is available ++ * \return true or false (as int?) ++ */ ++INLINE int ++ldns_buffer_available_at(ldns_buffer *buffer, size_t at, size_t count) ++{ ++ return count <= ldns_buffer_remaining_at(buffer, at); ++} ++ ++/** ++ * checks if the buffer has count bytes available at the current position ++ * \param[in] buffer the buffer ++ * \param[in] count how much is available ++ * \return true or false (as int?) ++ */ ++INLINE int ++ldns_buffer_available(ldns_buffer *buffer, size_t count) ++{ ++ return ldns_buffer_available_at(buffer, buffer->_position, count); ++} ++ ++/** ++ * writes the given data to the buffer at the specified position ++ * \param[in] buffer the buffer ++ * \param[in] at the position (in number of bytes) to write the data at ++ * \param[in] data pointer to the data to write to the buffer ++ * \param[in] count the number of bytes of data to write ++ */ ++INLINE void ++ldns_buffer_write_at(ldns_buffer *buffer, size_t at, const void *data, size_t count) ++{ ++ assert(ldns_buffer_available_at(buffer, at, count)); ++ memcpy(buffer->_data + at, data, count); ++} ++ ++/** ++ * writes count bytes of data to the current position of the buffer ++ * \param[in] buffer the buffer ++ * \param[in] data the data to write ++ * \param[in] count the lenght of the data to write ++ */ ++INLINE void ++ldns_buffer_write(ldns_buffer *buffer, const void *data, size_t count) ++{ ++ ldns_buffer_write_at(buffer, buffer->_position, data, count); ++ buffer->_position += count; ++} ++ ++/** ++ * copies the given (null-delimited) string to the specified position at the buffer ++ * \param[in] buffer the buffer ++ * \param[in] at the position in the buffer ++ * \param[in] str the string to write ++ */ ++INLINE void ++ldns_buffer_write_string_at(ldns_buffer *buffer, size_t at, const char *str) ++{ ++ ldns_buffer_write_at(buffer, at, str, strlen(str)); ++} ++ ++/** ++ * copies the given (null-delimited) string to the current position at the buffer ++ * \param[in] buffer the buffer ++ * \param[in] str the string to write ++ */ ++INLINE void ++ldns_buffer_write_string(ldns_buffer *buffer, const char *str) ++{ ++ ldns_buffer_write(buffer, str, strlen(str)); ++} ++ ++/** ++ * writes the given byte of data at the given position in the buffer ++ * \param[in] buffer the buffer ++ * \param[in] at the position in the buffer ++ * \param[in] data the 8 bits to write ++ */ ++INLINE void ++ldns_buffer_write_u8_at(ldns_buffer *buffer, size_t at, uint8_t data) ++{ ++ assert(ldns_buffer_available_at(buffer, at, sizeof(data))); ++ buffer->_data[at] = data; ++} ++ ++/** ++ * writes the given byte of data at the current position in the buffer ++ * \param[in] buffer the buffer ++ * \param[in] data the 8 bits to write ++ */ ++INLINE void ++ldns_buffer_write_u8(ldns_buffer *buffer, uint8_t data) ++{ ++ ldns_buffer_write_u8_at(buffer, buffer->_position, data); ++ buffer->_position += sizeof(data); ++} ++ ++/** ++ * writes the given 2 byte integer at the given position in the buffer ++ * \param[in] buffer the buffer ++ * \param[in] at the position in the buffer ++ * \param[in] data the 16 bits to write ++ */ ++INLINE void ++ldns_buffer_write_u16_at(ldns_buffer *buffer, size_t at, uint16_t data) ++{ ++ assert(ldns_buffer_available_at(buffer, at, sizeof(data))); ++ ldns_write_uint16(buffer->_data + at, data); ++} ++ ++/** ++ * writes the given 2 byte integer at the current position in the buffer ++ * \param[in] buffer the buffer ++ * \param[in] data the 16 bits to write ++ */ ++INLINE void ++ldns_buffer_write_u16(ldns_buffer *buffer, uint16_t data) ++{ ++ ldns_buffer_write_u16_at(buffer, buffer->_position, data); ++ buffer->_position += sizeof(data); ++} ++ ++/** ++ * writes the given 4 byte integer at the given position in the buffer ++ * \param[in] buffer the buffer ++ * \param[in] at the position in the buffer ++ * \param[in] data the 32 bits to write ++ */ ++INLINE void ++ldns_buffer_write_u32_at(ldns_buffer *buffer, size_t at, uint32_t data) ++{ ++ assert(ldns_buffer_available_at(buffer, at, sizeof(data))); ++ ldns_write_uint32(buffer->_data + at, data); ++} ++ ++/** ++ * writes the given 4 byte integer at the current position in the buffer ++ * \param[in] buffer the buffer ++ * \param[in] data the 32 bits to write ++ */ ++INLINE void ++ldns_buffer_write_u32(ldns_buffer *buffer, uint32_t data) ++{ ++ ldns_buffer_write_u32_at(buffer, buffer->_position, data); ++ buffer->_position += sizeof(data); ++} ++ ++/** ++ * copies count bytes of data at the given position to the given data-array ++ * \param[in] buffer the buffer ++ * \param[in] at the position in the buffer to start ++ * \param[out] data buffer to copy to ++ * \param[in] count the length of the data to copy ++ */ ++INLINE void ++ldns_buffer_read_at(ldns_buffer *buffer, size_t at, void *data, size_t count) ++{ ++ assert(ldns_buffer_available_at(buffer, at, count)); ++ memcpy(data, buffer->_data + at, count); ++} ++ ++/** ++ * copies count bytes of data at the current position to the given data-array ++ * \param[in] buffer the buffer ++ * \param[out] data buffer to copy to ++ * \param[in] count the length of the data to copy ++ */ ++INLINE void ++ldns_buffer_read(ldns_buffer *buffer, void *data, size_t count) ++{ ++ ldns_buffer_read_at(buffer, buffer->_position, data, count); ++ buffer->_position += count; ++} ++ ++/** ++ * returns the byte value at the given position in the buffer ++ * \param[in] buffer the buffer ++ * \param[in] at the position in the buffer ++ * \return 1 byte integer ++ */ ++INLINE uint8_t ++ldns_buffer_read_u8_at(ldns_buffer *buffer, size_t at) ++{ ++ assert(ldns_buffer_available_at(buffer, at, sizeof(uint8_t))); ++ return buffer->_data[at]; ++} ++ ++/** ++ * returns the byte value at the current position in the buffer ++ * \param[in] buffer the buffer ++ * \return 1 byte integer ++ */ ++INLINE uint8_t ++ldns_buffer_read_u8(ldns_buffer *buffer) ++{ ++ uint8_t result = ldns_buffer_read_u8_at(buffer, buffer->_position); ++ buffer->_position += sizeof(uint8_t); ++ return result; ++} ++ ++/** ++ * returns the 2-byte integer value at the given position in the buffer ++ * \param[in] buffer the buffer ++ * \param[in] at position in the buffer ++ * \return 2 byte integer ++ */ ++INLINE uint16_t ++ldns_buffer_read_u16_at(ldns_buffer *buffer, size_t at) ++{ ++ assert(ldns_buffer_available_at(buffer, at, sizeof(uint16_t))); ++ return ldns_read_uint16(buffer->_data + at); ++} ++ ++/** ++ * returns the 2-byte integer value at the current position in the buffer ++ * \param[in] buffer the buffer ++ * \return 2 byte integer ++ */ ++INLINE uint16_t ++ldns_buffer_read_u16(ldns_buffer *buffer) ++{ ++ uint16_t result = ldns_buffer_read_u16_at(buffer, buffer->_position); ++ buffer->_position += sizeof(uint16_t); ++ return result; ++} ++ ++/** ++ * returns the 4-byte integer value at the given position in the buffer ++ * \param[in] buffer the buffer ++ * \param[in] at position in the buffer ++ * \return 4 byte integer ++ */ ++INLINE uint32_t ++ldns_buffer_read_u32_at(ldns_buffer *buffer, size_t at) ++{ ++ assert(ldns_buffer_available_at(buffer, at, sizeof(uint32_t))); ++ return ldns_read_uint32(buffer->_data + at); ++} ++ ++/** ++ * returns the 4-byte integer value at the current position in the buffer ++ * \param[in] buffer the buffer ++ * \return 4 byte integer ++ */ ++INLINE uint32_t ++ldns_buffer_read_u32(ldns_buffer *buffer) ++{ ++ uint32_t result = ldns_buffer_read_u32_at(buffer, buffer->_position); ++ buffer->_position += sizeof(uint32_t); ++ return result; ++} ++ ++/** ++ * returns the status of the buffer ++ * \param[in] buffer ++ * \return the status ++ */ ++INLINE ldns_status ++ldns_buffer_status(ldns_buffer *buffer) ++{ ++ return buffer->_status; ++} ++ ++/** ++ * returns true if the status of the buffer is LDNS_STATUS_OK, false otherwise ++ * \param[in] buffer the buffer ++ * \return true or false ++ */ ++INLINE bool ++ldns_buffer_status_ok(ldns_buffer *buffer) ++{ ++ if (buffer) { ++ return ldns_buffer_status(buffer) == LDNS_STATUS_OK; ++ } else { ++ return false; ++ } ++} ++ ++/** ++ * prints to the buffer, increasing the capacity if required using ++ * buffer_reserve(). The buffer's position is set to the terminating '\\0' ++ * Returns the number of characters written (not including the ++ * terminating '\\0') or -1 on failure. ++ */ ++int ldns_buffer_printf(ldns_buffer *buffer, const char *format, ...); ++/* ATTR_FORMAT(printf, 2, 3);*/ ++ ++/** ++ * frees the buffer. ++ * \param[in] *buffer the buffer to be freed ++ * \return void ++ */ ++void ldns_buffer_free(ldns_buffer *buffer); ++ ++/** ++ * Makes the buffer fixed and returns a pointer to the data. The ++ * caller is responsible for free'ing the result. ++ * \param[in] *buffer the buffer to be exported ++ * \return void ++ */ ++void *ldns_buffer_export(ldns_buffer *buffer); ++ ++/** ++ * Copy contents of the from buffer to the result buffer and then flips ++ * the result buffer. Data will be silently truncated if the result buffer is ++ * too small. ++ * \param[out] *result resulting buffer which is copied to. ++ * \param[in] *from what to copy to result. ++ */ ++void ldns_buffer_copy(ldns_buffer* result, ldns_buffer* from); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* LDNS_BUFFER_H */ +diff --git a/ldns/include/ldns/common.h b/ldns/include/ldns/common.h +new file mode 100644 +index 0000000..9abd9b9 +--- /dev/null ++++ b/ldns/include/ldns/common.h +@@ -0,0 +1,78 @@ ++/** ++ * \file common.h ++ * ++ * Common definitions for LDNS ++ */ ++ ++/** ++ * a Net::DNS like library for C ++ * ++ * (c) NLnet Labs, 2004-2006 ++ * ++ * See the file LICENSE for the license ++ */ ++ ++#ifndef LDNS_COMMON_H ++#define LDNS_COMMON_H ++ ++/* ++ * The build configuration that is used in the distributed headers, ++ * as detected and determined by the auto configure script. ++ */ ++#define LDNS_BUILD_CONFIG_HAVE_SSL 1 ++#define LDNS_BUILD_CONFIG_HAVE_INTTYPES_H 1 ++#define LDNS_BUILD_CONFIG_HAVE_ATTR_FORMAT 1 ++#define LDNS_BUILD_CONFIG_HAVE_ATTR_UNUSED 1 ++#define LDNS_BUILD_CONFIG_HAVE_SOCKLEN_T 1 ++#define LDNS_BUILD_CONFIG_USE_DANE 1 ++#define LDNS_BUILD_CONFIG_HAVE_B32_PTON 0 ++#define LDNS_BUILD_CONFIG_HAVE_B32_NTOP 0 ++ ++/* ++ * HAVE_STDBOOL_H is not available when distributed as a library, but no build ++ * configuration variables may be used (like those above) because the header ++ * is sometimes only available when using special compiler flags to enable the ++ * c99 environment. Because we cannot force the usage of this flag, we have to ++ * provide a default type. Below what is suggested by the autoconf manual. ++ */ ++/*@ignore@*/ ++/* splint barfs on this construct */ ++#ifndef __bool_true_false_are_defined ++# ifdef HAVE_STDBOOL_H ++# include <stdbool.h> ++# else ++# ifndef HAVE__BOOL ++# ifdef __cplusplus ++typedef bool _Bool; ++# else ++# define _Bool signed char ++# endif ++# endif ++# define bool _Bool ++# define false 0 ++# define true 1 ++# define __bool_true_false_are_defined 1 ++# endif ++#endif ++/*@end@*/ ++ ++#if LDNS_BUILD_CONFIG_HAVE_ATTR_FORMAT ++#define ATTR_FORMAT(archetype, string_index, first_to_check) \ ++ __attribute__ ((format (archetype, string_index, first_to_check))) ++#else /* !LDNS_BUILD_CONFIG_HAVE_ATTR_FORMAT */ ++#define ATTR_FORMAT(archetype, string_index, first_to_check) /* empty */ ++#endif /* !LDNS_BUILD_CONFIG_HAVE_ATTR_FORMAT */ ++ ++#if defined(__cplusplus) ++#define ATTR_UNUSED(x) ++#elif LDNS_BUILD_CONFIG_HAVE_ATTR_UNUSED ++#define ATTR_UNUSED(x) x __attribute__((unused)) ++#else /* !LDNS_BUILD_CONFIG_HAVE_ATTR_UNUSED */ ++#define ATTR_UNUSED(x) x ++#endif /* !LDNS_BUILD_CONFIG_HAVE_ATTR_UNUSED */ ++ ++#if !LDNS_BUILD_CONFIG_HAVE_SOCKLEN_T ++typedef int socklen_t; ++#endif ++ ++#endif /* LDNS_COMMON_H */ +diff --git a/ldns/include/ldns/config.h b/ldns/include/ldns/config.h +new file mode 100644 +index 0000000..d77cc7f +--- /dev/null ++++ b/ldns/include/ldns/config.h +@@ -0,0 +1,590 @@ ++#include "EXTERN.h" ++#include "perl.h" ++ ++/* Define if building universal (internal helper macro) */ ++/* #undef AC_APPLE_UNIVERSAL_BUILD */ ++ ++/* Define to 1 if you have the <arpa/inet.h> header file. */ ++#define HAVE_ARPA_INET_H 1 ++ ++/* Whether the C compiler accepts the "format" attribute */ ++#define HAVE_ATTR_FORMAT 1 ++ ++/* Whether the C compiler accepts the "unused" attribute */ ++#define HAVE_ATTR_UNUSED 1 ++ ++/* Define to 1 if you have the `b32_ntop' function. */ ++/* #undef HAVE_B32_NTOP */ ++ ++/* Define to 1 if you have the `b32_pton' function. */ ++/* #undef HAVE_B32_PTON */ ++ ++/* Define to 1 if you have the `b64_ntop' function. */ ++/* #undef HAVE_B64_NTOP */ ++ ++/* Define to 1 if you have the `b64_pton' function. */ ++/* #undef HAVE_B64_PTON */ ++ ++/* Define to 1 if you have the `bzero' function. */ ++#define HAVE_BZERO 1 ++ ++/* Define to 1 if you have the `calloc' function. */ ++#define HAVE_CALLOC 1 ++ ++/* Define to 1 if you have the `ctime_r' function. */ ++#define HAVE_CTIME_R 1 ++ ++/* Is a CAFILE given at configure time */ ++#define HAVE_DANE_CA_FILE 0 ++ ++/* Is a CAPATH given at configure time */ ++#define HAVE_DANE_CA_PATH 0 ++ ++/* Define to 1 if you have the declaration of `NID_secp384r1', and to 0 if you ++ don't. */ ++#define HAVE_DECL_NID_SECP384R1 1 ++ ++/* Define to 1 if you have the declaration of `NID_X9_62_prime256v1', and to 0 ++ if you don't. */ ++#define HAVE_DECL_NID_X9_62_PRIME256V1 1 ++ ++/* Define to 1 if you have the <dlfcn.h> header file. */ ++#define HAVE_DLFCN_H 1 ++ ++/* Define to 1 if you have the `endprotoent' function. */ ++#define HAVE_ENDPROTOENT 1 ++ ++/* Define to 1 if you have the `endservent' function. */ ++#define HAVE_ENDSERVENT 1 ++ ++/* Define to 1 if you have the `ENGINE_load_cryptodev' function. */ ++#define HAVE_ENGINE_LOAD_CRYPTODEV 1 ++ ++/* Define to 1 if you have the `EVP_sha256' function. */ ++#define HAVE_EVP_SHA256 1 ++ ++/* Define to 1 if you have the `fcntl' function. */ ++#define HAVE_FCNTL 1 ++ ++/* Define to 1 if you have the `fork' function. */ ++#define HAVE_FORK 1 ++ ++/* Whether getaddrinfo is available */ ++#define HAVE_GETADDRINFO 1 ++ ++/* Define to 1 if you have the <getopt.h> header file. */ ++#define HAVE_GETOPT_H 1 ++ ++/* Define to 1 if you have the `gmtime_r' function. */ ++#define HAVE_GMTIME_R 1 ++ ++/* If you have HMAC_CTX_init */ ++#define HAVE_HMAC_CTX_INIT 1 ++ ++/* Define to 1 if you have the `inet_aton' function. */ ++#define HAVE_INET_ATON 1 ++ ++/* Define to 1 if you have the `inet_ntop' function. */ ++#define HAVE_INET_NTOP 1 ++ ++/* Define to 1 if you have the `inet_pton' function. */ ++#define HAVE_INET_PTON 1 ++ ++/* define if you have inttypes.h */ ++#define HAVE_INTTYPES_H 1 ++ ++/* if the function 'ioctlsocket' is available */ ++/* #undef HAVE_IOCTLSOCKET */ ++ ++/* Define to 1 if you have the `isascii' function. */ ++#define HAVE_ISASCII 1 ++ ++/* Define to 1 if you have the `isblank' function. */ ++#define HAVE_ISBLANK 1 ++ ++/* Define to 1 if you have the `pcap' library (-lpcap). */ ++/* #undef HAVE_LIBPCAP */ ++ ++/* Define to 1 if you have the `localtime_r' function. */ ++#define HAVE_LOCALTIME_R 1 ++ ++/* Define to 1 if your system has a GNU libc compatible `malloc' function, and ++ to 0 otherwise. */ ++#define HAVE_MALLOC 1 ++ ++/* Define to 1 if you have the `memmove' function. */ ++#define HAVE_MEMMOVE 1 ++ ++/* Define to 1 if you have the <memory.h> header file. */ ++#define HAVE_MEMORY_H 1 ++ ++/* Define to 1 if you have the `memset' function. */ ++#define HAVE_MEMSET 1 ++ ++/* Define to 1 if you have the <netdb.h> header file. */ ++#define HAVE_NETDB_H 1 ++ ++/* Define to 1 if you have the <netinet/if_ether.h> header file. */ ++/* #undef HAVE_NETINET_IF_ETHER_H */ ++ ++/* Define to 1 if you have the <netinet/igmp.h> header file. */ ++/* #undef HAVE_NETINET_IGMP_H */ ++ ++/* Define to 1 if you have the <netinet/in.h> header file. */ ++#define HAVE_NETINET_IN_H 1 ++ ++/* Define to 1 if you have the <netinet/in_systm.h> header file. */ ++/* #undef HAVE_NETINET_IN_SYSTM_H */ ++ ++/* Define to 1 if you have the <netinet/ip6.h> header file. */ ++/* #undef HAVE_NETINET_IP6_H */ ++ ++/* Define to 1 if you have the <netinet/ip_compat.h> header file. */ ++/* #undef HAVE_NETINET_IP_COMPAT_H */ ++ ++/* Define to 1 if you have the <netinet/ip.h> header file. */ ++/* #undef HAVE_NETINET_IP_H */ ++ ++/* Define to 1 if you have the <netinet/udp.h> header file. */ ++/* #undef HAVE_NETINET_UDP_H */ ++ ++/* Define to 1 if you have the <net/ethernet.h> header file. */ ++/* #undef HAVE_NET_ETHERNET_H */ ++ ++/* Define to 1 if you have the <net/if.h> header file. */ ++/* #undef HAVE_NET_IF_H */ ++ ++/* Define to 1 if you have the <openssl/err.h> header file. */ ++#define HAVE_OPENSSL_ERR_H 1 ++ ++/* Define to 1 if you have the <openssl/rand.h> header file. */ ++#define HAVE_OPENSSL_RAND_H 1 ++ ++/* Define to 1 if you have the <openssl/ssl.h> header file. */ ++#define HAVE_OPENSSL_SSL_H 1 ++ ++/* Define to 1 if you have the <pcap.h> header file. */ ++/* #undef HAVE_PCAP_H */ ++ ++/* Define to 1 if you have the `random' function. */ ++#define HAVE_RANDOM 1 ++ ++/* Define to 1 if your system has a GNU libc compatible `realloc' function, ++ and to 0 otherwise. */ ++#define HAVE_REALLOC 1 ++ ++/* Define to 1 if you have the `sleep' function. */ ++#define HAVE_SLEEP 1 ++ ++/* Define to 1 if you have the `snprintf' function. */ ++#define HAVE_SNPRINTF 1 ++ ++/* Define if you have the SSL libraries installed. */ ++#define HAVE_SSL /**/ ++ ++/* Define to 1 if you have the <stdarg.h> header file. */ ++#define HAVE_STDARG_H 1 ++ ++/* Define to 1 if stdbool.h conforms to C99. */ ++#define HAVE_STDBOOL_H 1 ++ ++/* Define to 1 if you have the <stdint.h> header file. */ ++#define HAVE_STDINT_H 1 ++ ++/* Define to 1 if you have the <stdlib.h> header file. */ ++#define HAVE_STDLIB_H 1 ++ ++/* Define to 1 if you have the <strings.h> header file. */ ++#define HAVE_STRINGS_H 1 ++ ++/* Define to 1 if you have the <string.h> header file. */ ++#define HAVE_STRING_H 1 ++ ++/* Define to 1 if you have the `strlcpy' function. */ ++#ifdef HAS_STRLCPY ++#define HAVE_STRLCPY 1 ++#else ++#undef HAVE_STRLCPY ++#endif ++ ++/* Define to 1 if you have the `strtoul' function. */ ++#define HAVE_STRTOUL 1 ++ ++/* Define to 1 if you have the <sys/mount.h> header file. */ ++#define HAVE_SYS_MOUNT_H 1 ++ ++/* Define to 1 if you have the <sys/param.h> header file. */ ++#define HAVE_SYS_PARAM_H 1 ++ ++/* define if you have sys/socket.h */ ++#define HAVE_SYS_SOCKET_H 1 ++ ++/* Define to 1 if you have the <sys/stat.h> header file. */ ++#define HAVE_SYS_STAT_H 1 ++ ++/* define if you have sys/types.h */ ++#define HAVE_SYS_TYPES_H 1 ++ ++/* Define to 1 if you have the `timegm' function. */ ++#define HAVE_TIMEGM 1 ++ ++/* Define to 1 if you have the <time.h> header file. */ ++#define HAVE_TIME_H 1 ++ ++/* define if you have unistd.h */ ++#define HAVE_UNISTD_H 1 ++ ++/* Define to 1 if you have the `vfork' function. */ ++#define HAVE_VFORK 1 ++ ++/* Define to 1 if you have the <vfork.h> header file. */ ++/* #undef HAVE_VFORK_H */ ++ ++/* Define to 1 if you have the <winsock2.h> header file. */ ++/* #undef HAVE_WINSOCK2_H */ ++ ++/* Define to 1 if `fork' works. */ ++#define HAVE_WORKING_FORK 1 ++ ++/* Define to 1 if `vfork' works. */ ++#define HAVE_WORKING_VFORK 1 ++ ++/* Define to 1 if you have the <ws2tcpip.h> header file. */ ++/* #undef HAVE_WS2TCPIP_H */ ++ ++/* Define to 1 if the system has the type `_Bool'. */ ++#define HAVE__BOOL 1 ++ ++/* Is a CAFILE given at configure time */ ++/* #undef LDNS_DANE_CA_FILE */ ++ ++/* Is a CAPATH given at configure time */ ++/* #undef LDNS_DANE_CA_PATH */ ++ ++/* Define to the sub-directory where libtool stores uninstalled libraries. */ ++#define LT_OBJDIR ".libs/" ++ ++/* Define to the address where bug reports for this package should be sent. */ ++#define PACKAGE_BUGREPORT "libdns@nlnetlabs.nl" ++ ++/* Define to the full name of this package. */ ++#define PACKAGE_NAME "ldns" ++ ++/* Define to the full name and version of this package. */ ++#define PACKAGE_STRING "ldns 1.6.17" ++ ++/* Define to the one symbol short name of this package. */ ++#define PACKAGE_TARNAME "libdns" ++ ++/* Define to the home page for this package. */ ++#define PACKAGE_URL "" ++ ++/* Define to the version of this package. */ ++#define PACKAGE_VERSION "1.6.17" ++ ++/* Define this to enable RR type NINFO. */ ++/* #undef RRTYPE_NINFO */ ++ ++/* Define this to enable RR type OPENPGPKEY. */ ++/* #undef RRTYPE_OPENPGPKEY */ ++ ++/* Define this to enable RR type RKEY. */ ++/* #undef RRTYPE_RKEY */ ++ ++/* Define this to enable RR type TA. */ ++/* #undef RRTYPE_TA */ ++ ++/* Define this to enable RR type URI. */ ++/* #undef RRTYPE_URI */ ++ ++/* The size of `time_t', as computed by sizeof. */ ++#define SIZEOF_TIME_T 8 ++ ++/* Define to 1 if you have the ANSI C header files. */ ++#define STDC_HEADERS 1 ++ ++/* Define this to enable messages to stderr. */ ++/* #undef STDERR_MSGS */ ++ ++/* System configuration dir */ ++#define SYSCONFDIR sysconfdir ++ ++/* Define this to enable DANE support. */ ++#define USE_DANE 1 ++ ++/* Define this to enable ECDSA support. */ ++#define USE_ECDSA 1 ++ ++/* Define this to enable GOST support. */ ++/* #define USE_GOST 1 */ ++ ++/* Define this to enable SHA256 and SHA512 support. */ ++#define USE_SHA2 1 ++ ++/* Enable extensions on AIX 3, Interix. */ ++#ifndef _ALL_SOURCE ++# define _ALL_SOURCE 1 ++#endif ++/* Enable GNU extensions on systems that have them. */ ++#ifndef _GNU_SOURCE ++# define _GNU_SOURCE 1 ++#endif ++/* Enable threading extensions on Solaris. */ ++#ifndef _POSIX_PTHREAD_SEMANTICS ++# define _POSIX_PTHREAD_SEMANTICS 1 ++#endif ++/* Enable extensions on HP NonStop. */ ++#ifndef _TANDEM_SOURCE ++# define _TANDEM_SOURCE 1 ++#endif ++/* Enable general extensions on Solaris. */ ++#ifndef __EXTENSIONS__ ++# define __EXTENSIONS__ 1 ++#endif ++ ++ ++/* Whether the windows socket API is used */ ++/* #undef USE_WINSOCK */ ++ ++/* the version of the windows API enabled */ ++#define WINVER 0x0502 ++ ++/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most ++ significant byte first (like Motorola and SPARC, unlike Intel). */ ++#if defined AC_APPLE_UNIVERSAL_BUILD ++# if defined __BIG_ENDIAN__ ++# define WORDS_BIGENDIAN 1 ++# endif ++#else ++# ifndef WORDS_BIGENDIAN ++/* # undef WORDS_BIGENDIAN */ ++# endif ++#endif ++ ++/* Define to 1 if on MINIX. */ ++/* #undef _MINIX */ ++ ++/* Enable for compile on Minix */ ++/* #undef _NETBSD_SOURCE */ ++ ++/* Define to 2 if the system does not provide POSIX.1 features except with ++ this defined. */ ++/* #undef _POSIX_1_SOURCE */ ++ ++/* Define to 1 if you need to in order for `stat' and other things to work. */ ++/* #undef _POSIX_SOURCE */ ++ ++/* Define to empty if `const' does not conform to ANSI C. */ ++/* #undef const */ ++ ++/* in_addr_t */ ++/* #undef in_addr_t */ ++ ++/* in_port_t */ ++/* #undef in_port_t */ ++ ++/* Define to `__inline__' or `__inline' if that's what the C compiler ++ calls it, or to nothing if 'inline' is not supported under any name. */ ++#ifndef __cplusplus ++/* #undef inline */ ++#endif ++ ++/* Define to `short' if <sys/types.h> does not define. */ ++/* #undef int16_t */ ++ ++/* Define to `int' if <sys/types.h> does not define. */ ++/* #undef int32_t */ ++ ++/* Define to `long long' if <sys/types.h> does not define. */ ++/* #undef int64_t */ ++ ++/* Define to `char' if <sys/types.h> does not define. */ ++/* #undef int8_t */ ++ ++/* Define to `size_t' if <sys/types.h> does not define. */ ++/* #undef intptr_t */ ++ ++/* Define to rpl_malloc if the replacement function should be used. */ ++/* #undef malloc */ ++ ++/* Define to `int' if <sys/types.h> does not define. */ ++/* #undef pid_t */ ++ ++/* Define to rpl_realloc if the replacement function should be used. */ ++/* #undef realloc */ ++ ++/* Define to `unsigned int' if <sys/types.h> does not define. */ ++/* #undef size_t */ ++ ++/* Define to 'int' if not defined */ ++/* #undef socklen_t */ ++ ++/* Fallback member name for socket family in struct sockaddr_storage */ ++/* #undef ss_family */ ++ ++/* Define to `int' if <sys/types.h> does not define. */ ++/* #undef ssize_t */ ++ ++/* Define to `unsigned short' if <sys/types.h> does not define. */ ++/* #undef uint16_t */ ++ ++/* Define to `unsigned int' if <sys/types.h> does not define. */ ++/* #undef uint32_t */ ++ ++/* Define to `unsigned long long' if <sys/types.h> does not define. */ ++/* #undef uint64_t */ ++ ++/* Define to `unsigned char' if <sys/types.h> does not define. */ ++/* #undef uint8_t */ ++ ++/* Define as `fork' if `vfork' does not work. */ ++/* #undef vfork */ ++ ++ ++#include <stdio.h> ++#include <string.h> ++#include <unistd.h> ++#include <assert.h> ++ ++#ifndef LITTLE_ENDIAN ++#define LITTLE_ENDIAN 1234 ++#endif ++ ++#ifndef BIG_ENDIAN ++#define BIG_ENDIAN 4321 ++#endif ++ ++#ifndef BYTE_ORDER ++#ifdef WORDS_BIGENDIAN ++#define BYTE_ORDER BIG_ENDIAN ++#else ++#define BYTE_ORDER LITTLE_ENDIAN ++#endif /* WORDS_BIGENDIAN */ ++#endif /* BYTE_ORDER */ ++ ++#if STDC_HEADERS ++#include <stdlib.h> ++#include <stddef.h> ++#endif ++ ++#ifdef HAVE_STDINT_H ++#include <stdint.h> ++#endif ++ ++#ifdef HAVE_SYS_SOCKET_H ++#include <sys/socket.h> ++#endif ++ ++#ifdef HAVE_NETINET_IN_H ++#include <netinet/in.h> ++#endif ++ ++#ifdef HAVE_ARPA_INET_H ++#include <arpa/inet.h> ++#endif ++ ++#ifdef HAVE_WINSOCK2_H ++#include <winsock2.h> ++#endif ++ ++#ifdef HAVE_WS2TCPIP_H ++#include <ws2tcpip.h> ++#endif ++ ++ ++/* detect if we need to cast to unsigned int for FD_SET to avoid warnings */ ++#ifdef HAVE_WINSOCK2_H ++#define FD_SET_T (u_int) ++#else ++#define FD_SET_T ++#endif ++ ++ ++ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++int ldns_b64_ntop(uint8_t const *src, size_t srclength, ++ char *target, size_t targsize); ++/** ++ * calculates the size needed to store the result of b64_ntop ++ */ ++/*@unused@*/ ++static inline size_t ldns_b64_ntop_calculate_size(size_t srcsize) ++{ ++ return ((((srcsize + 2) / 3) * 4) + 1); ++} ++int ldns_b64_pton(char const *src, uint8_t *target, size_t targsize); ++/** ++ * calculates the size needed to store the result of ldns_b64_pton ++ */ ++/*@unused@*/ ++static inline size_t ldns_b64_pton_calculate_size(size_t srcsize) ++{ ++ return (((((srcsize + 3) / 4) * 3)) + 1); ++} ++ ++/** ++ * Given in dnssec_zone.c, also used in dnssec_sign.c:w ++ ++ */ ++int ldns_dname_compare_v(const void *a, const void *b); ++ ++#ifndef HAVE_SLEEP ++/* use windows sleep, in millisecs, instead */ ++#define sleep(x) Sleep((x)*1000) ++#endif ++ ++#ifndef HAVE_RANDOM ++#define srandom(x) srand(x) ++#define random(x) rand(x) ++#endif ++ ++#ifndef HAVE_TIMEGM ++#include <time.h> ++time_t timegm (struct tm *tm); ++#endif /* !TIMEGM */ ++#ifndef HAVE_GMTIME_R ++struct tm *gmtime_r(const time_t *timep, struct tm *result); ++#endif ++#ifndef HAVE_LOCALTIME_R ++struct tm *localtime_r(const time_t *timep, struct tm *result); ++#endif ++#ifndef HAVE_ISBLANK ++int isblank(int c); ++#endif /* !HAVE_ISBLANK */ ++#ifndef HAVE_ISASCII ++int isascii(int c); ++#endif /* !HAVE_ISASCII */ ++#ifndef HAVE_SNPRINTF ++#include <stdarg.h> ++int snprintf (char *str, size_t count, const char *fmt, ...); ++int vsnprintf (char *str, size_t count, const char *fmt, va_list arg); ++#endif /* HAVE_SNPRINTF */ ++#ifndef HAVE_INET_PTON ++int inet_pton(int af, const char* src, void* dst); ++#endif /* HAVE_INET_PTON */ ++#ifndef HAVE_INET_NTOP ++const char *inet_ntop(int af, const void *src, char *dst, size_t size); ++#endif ++#ifndef HAVE_INET_ATON ++int inet_aton(const char *cp, struct in_addr *addr); ++#endif ++#ifndef HAVE_MEMMOVE ++void *memmove(void *dest, const void *src, size_t n); ++#endif ++#ifndef HAVE_STRLCPY ++size_t strlcpy(char *dst, const char *src, size_t siz); ++#endif ++#ifdef __cplusplus ++} ++#endif ++#ifndef HAVE_GETADDRINFO ++#include "compat/fake-rfc2553.h" ++#endif ++#ifndef HAVE_STRTOUL ++#define strtoul (unsigned long)strtol ++#endif ++ +diff --git a/ldns/include/ldns/dane.h b/ldns/include/ldns/dane.h +new file mode 100644 +index 0000000..8234eb7 +--- /dev/null ++++ b/ldns/include/ldns/dane.h +@@ -0,0 +1,262 @@ ++/* ++ * dane.h -- defines for the DNS-Based Authentication of Named Entities (DANE) ++ * Transport Layer Security (TLS) Protocol: TLSA ++ * ++ * Copyright (c) 2012, NLnet Labs. All rights reserved. ++ * ++ * See LICENSE for the license. ++ * ++ */ ++ ++/** ++ * \file ++ * ++ * This module contains base functions for creating and verifying TLSA RR's ++ * with PKIX certificates, certificate chains and validation stores. ++ * (See RFC6394 and RFC6698). ++ * ++ * Since those functions heavily rely op cryptographic operations, ++ * this module is dependent on openssl. ++ */ ++ ++ ++#ifndef LDNS_DANE_H ++#define LDNS_DANE_H ++#if LDNS_BUILD_CONFIG_USE_DANE ++ ++#include <ldns/common.h> ++#include <ldns/rdata.h> ++#include <ldns/rr.h> ++#if LDNS_BUILD_CONFIG_HAVE_SSL ++#include <openssl/ssl.h> ++#include <openssl/err.h> ++#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/** ++ * The different "Certificate usage" rdata field values for a TLSA RR. ++ */ ++enum ldns_enum_tlsa_certificate_usage ++{ ++ /** CA constraint */ ++ LDNS_TLSA_USAGE_PKIX_TA = 0, ++ LDNS_TLSA_USAGE_CA_CONSTRAINT = 0, ++ /** Sevice certificate constraint */ ++ LDNS_TLSA_USAGE_PKIX_EE = 1, ++ LDNS_TLSA_USAGE_SERVICE_CERTIFICATE_CONSTRAINT = 1, ++ /** Trust anchor assertion */ ++ LDNS_TLSA_USAGE_DANE_TA = 2, ++ LDNS_TLSA_USAGE_TRUST_ANCHOR_ASSERTION = 2, ++ /** Domain issued certificate */ ++ LDNS_TLSA_USAGE_DANE_EE = 3, ++ LDNS_TLSA_USAGE_DOMAIN_ISSUED_CERTIFICATE = 3, ++ /** Reserved for Private Use */ ++ LDNS_TLSA_USAGE_PRIVCERT = 255 ++}; ++typedef enum ldns_enum_tlsa_certificate_usage ldns_tlsa_certificate_usage; ++ ++/** ++ * The different "Selector" rdata field values for a TLSA RR. ++ */ ++enum ldns_enum_tlsa_selector ++{ ++ /** ++ * Full certificate: the Certificate binary structure ++ * as defined in [RFC5280] ++ */ ++ LDNS_TLSA_SELECTOR_CERT = 0, ++ LDNS_TLSA_SELECTOR_FULL_CERTIFICATE = 0, ++ ++ /** ++ * SubjectPublicKeyInfo: DER-encoded binary structure ++ * as defined in [RFC5280] ++ */ ++ LDNS_TLSA_SELECTOR_SPKI = 1, ++ LDNS_TLSA_SELECTOR_SUBJECTPUBLICKEYINFO = 1, ++ ++ /** Reserved for Private Use */ ++ LDNS_TLSA_SELECTOR_PRIVSEL = 255 ++}; ++typedef enum ldns_enum_tlsa_selector ldns_tlsa_selector; ++ ++/** ++ * The different "Matching type" rdata field values for a TLSA RR. ++ */ ++enum ldns_enum_tlsa_matching_type ++{ ++ /** Exact match on selected content */ ++ LDNS_TLSA_MATCHING_TYPE_FULL = 0, ++ LDNS_TLSA_MATCHING_TYPE_NO_HASH_USED = 0, ++ /** SHA-256 hash of selected content [RFC6234] */ ++ LDNS_TLSA_MATCHING_TYPE_SHA2_256 = 1, ++ LDNS_TLSA_MATCHING_TYPE_SHA256 = 1, ++ /** SHA-512 hash of selected content [RFC6234] */ ++ LDNS_TLSA_MATCHING_TYPE_SHA2_512 = 2, ++ LDNS_TLSA_MATCHING_TYPE_SHA512 = 2, ++ /** Reserved for Private Use */ ++ LDNS_TLSA_MATCHING_TYPE_PRIVMATCH = 255 ++}; ++typedef enum ldns_enum_tlsa_matching_type ldns_tlsa_matching_type; ++ ++/** ++ * Known transports to use with TLSA owner names. ++ */ ++enum ldns_enum_dane_transport ++{ ++ /** TCP */ ++ LDNS_DANE_TRANSPORT_TCP = 0, ++ /** UDP */ ++ LDNS_DANE_TRANSPORT_UDP = 1, ++ /** SCTP */ ++ LDNS_DANE_TRANSPORT_SCTP = 2 ++}; ++typedef enum ldns_enum_dane_transport ldns_dane_transport; ++ ++ ++/** ++ * Creates a dname consisting of the given name, prefixed by the service port ++ * and type of transport: _<EM>port</EM>._<EM>transport</EM>.<EM>name</EM>. ++ * ++ * \param[out] tlsa_owner The created dname. ++ * \param[in] name The dname that should be prefixed. ++ * \param[in] port The service port number for wich the name should be created. ++ * \param[in] transport The transport for wich the name should be created. ++ * \return LDNS_STATUS_OK on success or an error code otherwise. ++ */ ++ldns_status ldns_dane_create_tlsa_owner(ldns_rdf** tlsa_owner, ++ const ldns_rdf* name, uint16_t port, ++ ldns_dane_transport transport); ++ ++ ++#if LDNS_BUILD_CONFIG_HAVE_SSL ++/** ++ * Creates a LDNS_RDF_TYPE_HEX type rdf based on the binary data choosen by ++ * the selector and encoded using matching_type. ++ * ++ * \param[out] rdf The created created rdf of type LDNS_RDF_TYPE_HEX. ++ * \param[in] cert The certificate from which the data is selected ++ * \param[in] selector The full certificate or the public key ++ * \param[in] matching_type The full data or the SHA256 or SHA512 hash ++ * of the selected data ++ * \return LDNS_STATUS_OK on success or an error code otherwise. ++ */ ++ldns_status ldns_dane_cert2rdf(ldns_rdf** rdf, X509* cert, ++ ldns_tlsa_selector selector, ++ ldns_tlsa_matching_type matching_type); ++ ++ ++/** ++ * Selects the certificate from cert, extra_certs or the pkix_validation_store ++ * based on the value of cert_usage and index. ++ * ++ * \param[out] selected_cert The selected cert. ++ * \param[in] cert The certificate to validate (or not) ++ * \param[in] extra_certs Intermediate certificates that might be necessary ++ * during validation. May be NULL, except when the certificate ++ * usage is "Trust Anchor Assertion" because the trust anchor has ++ * to be provided.(otherwise choose a "Domain issued certificate!" ++ * \param[in] pkix_validation_store Used when the certificate usage is ++ * "CA constraint" or "Service Certificate Constraint" to ++ * validate the certificate and, in case of "CA constraint", ++ * select the CA. ++ * When pkix_validation_store is NULL, validation is explicitely ++ * turned off and the behaviour is then the same as for "Trust ++ * anchor assertion" and "Domain issued certificate" respectively. ++ * \param[in] cert_usage Which certificate to use and how to validate. ++ * \param[in] index Used to select the trust anchor when certificate usage ++ * is "Trust Anchor Assertion". 0 is the last certificate in the ++ * validation chain. 1 the one but last, etc. When index is -1, ++ * the last certificate is used that MUST be self-signed. ++ * This can help to make sure that the intended (self signed) ++ * trust anchor is actually present in extra_certs (which is a ++ * DANE requirement). ++ * ++ * \return LDNS_STATUS_OK on success or an error code otherwise. ++ */ ++ldns_status ldns_dane_select_certificate(X509** selected_cert, ++ X509* cert, STACK_OF(X509)* extra_certs, ++ X509_STORE* pkix_validation_store, ++ ldns_tlsa_certificate_usage cert_usage, int index); ++ ++/** ++ * Creates a TLSA resource record from the certificate. ++ * No PKIX validation is performed! The given certificate is used as data ++ * regardless the value of certificate_usage. ++ * ++ * \param[out] tlsa The created TLSA resource record. ++ * \param[in] certificate_usage The value for the Certificate Usage field ++ * \param[in] selector The value for the Selector field ++ * \param[in] matching_type The value for the Matching Type field ++ * \param[in] cert The certificate which data will be represented ++ * ++ * \return LDNS_STATUS_OK on success or an error code otherwise. ++ */ ++ldns_status ldns_dane_create_tlsa_rr(ldns_rr** tlsa, ++ ldns_tlsa_certificate_usage certificate_usage, ++ ldns_tlsa_selector selector, ++ ldns_tlsa_matching_type matching_type, ++ X509* cert); ++ ++/** ++ * Verify if the given TLSA resource record matches the given certificate. ++ * Reporting on a TLSA rr mismatch (LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH) ++ * is preferred over PKIX failure (LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE). ++ * So when PKIX validation is required by the TLSA Certificate usage, ++ * but the TLSA data does not match, LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH ++ * is returned whether the PKIX validated or not. ++ * ++ * \param[in] tlsa_rr The resource record that specifies what and how to ++ * match the certificate. With tlsa_rr == NULL, regular PKIX ++ * validation is performed. ++ * \param[in] cert The certificate to match (and validate) ++ * \param[in] extra_certs Intermediate certificates that might be necessary ++ * creating the validation chain. ++ * \param[in] pkix_validation_store Used when the certificate usage is ++ * "CA constraint" or "Service Certificate Constraint" to ++ * validate the certificate. ++ * ++ * \return LDNS_STATUS_OK on success, ++ * LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH on TLSA data mismatch, ++ * LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE when TLSA matched, ++ * but the PKIX validation failed, or other ldns_status errors. ++ */ ++ldns_status ldns_dane_verify_rr(const ldns_rr* tlsa_rr, ++ X509* cert, STACK_OF(X509)* extra_certs, ++ X509_STORE* pkix_validation_store); ++ ++/** ++ * Verify if any of the given TLSA resource records matches the given ++ * certificate. ++ * ++ * \param[in] tlsas The resource records that specify what and how to ++ * match the certificate. One must match for this function ++ * to succeed. With tlsas == NULL or the number of TLSA records ++ * in tlsas == 0, regular PKIX validation is performed. ++ * \param[in] cert The certificate to match (and validate) ++ * \param[in] extra_certs Intermediate certificates that might be necessary ++ * creating the validation chain. ++ * \param[in] pkix_validation_store Used when the certificate usage is ++ * "CA constraint" or "Service Certificate Constraint" to ++ * validate the certificate. ++ * ++ * \return LDNS_STATUS_OK on success, ++ * LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE when one of the TLSA's ++ * matched but the PKIX validation failed, ++ * LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH when none of the TLSA's matched, ++ * or other ldns_status errors. ++ */ ++ldns_status ldns_dane_verify(ldns_rr_list* tlsas, ++ X509* cert, STACK_OF(X509)* extra_certs, ++ X509_STORE* pkix_validation_store); ++#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */ ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* LDNS_BUILD_CONFIG_USE_DANE */ ++#endif /* LDNS_DANE_H */ ++ +diff --git a/ldns/include/ldns/dname.h b/ldns/include/ldns/dname.h +new file mode 100644 +index 0000000..291786b +--- /dev/null ++++ b/ldns/include/ldns/dname.h +@@ -0,0 +1,211 @@ ++/* ++ * dname.h ++ * ++ * dname definitions ++ * ++ * a Net::DNS like library for C ++ * ++ * (c) NLnet Labs, 2004-2006 ++ * ++ * See the file LICENSE for the license ++ */ ++ ++/** ++ * \file dname.h ++ * ++ * dname contains function to read and manipulate domain names. ++ * ++ * Example domain names are "www.nlnetlabs.nl." and "." (the root) ++ * ++ * If a domain name ends with a dot ("."), it is called a Fully Qualified ++ * Domain Name (FQDN). In certain places (for instance when reading a zone ++ * file), an origin (which is just another domain name) non-FQDNs will be ++ * placed after the current. For instance, if i have a zone file where the ++ * origin has been set to "nl.", and my file contains the name ++ * "www.nlnetlabs", it will result in "www.nlnetlabs.nl.". Internally, dnames are ++ * always absolute (the dot is added when it is missing and there is no origin). ++ * ++ * An FQDN is also ++ * known as an absolute domain name, therefore the function to check this is ++ * called \ref ldns_dname_str_absolute ++ * ++ * Domain names are stored in \ref ldns_rdf structures, with the type ++ * \ref LDNS_RDF_TYPE_DNAME ++ * ++ * This module is *NOT* about the RR type called DNAME. ++ */ ++ ++ ++#ifndef LDNS_DNAME_H ++#define LDNS_DNAME_H ++ ++#include <ldns/common.h> ++#include <ldns/rdata.h> ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#define LDNS_DNAME_NORMALIZE tolower ++ ++/** ++ * concatenates two dnames together ++ * \param[in] rd1 the leftside ++ * \param[in] rd2 the rightside ++ * \return a new rdf with leftside/rightside ++ */ ++ldns_rdf *ldns_dname_cat_clone(const ldns_rdf *rd1, const ldns_rdf *rd2); ++ ++/** ++ * concatenates rd2 after rd1 (rd2 is copied, rd1 is modified) ++ * \param[in] rd1 the leftside ++ * \param[in] rd2 the rightside ++ * \return LDNS_STATUS_OK on success ++ */ ++ldns_status ldns_dname_cat(ldns_rdf *rd1, ldns_rdf *rd2); ++ ++/** ++ * Returns a clone of the given dname with the labels ++ * reversed ++ * \param[in] d the dname to reverse ++ * \return clone of the dname with the labels reversed. ++ */ ++ldns_rdf *ldns_dname_reverse(const ldns_rdf *d); ++ ++/** ++ * Clones the given dname from the nth label on ++ * \param[in] d The dname to clone ++ * \param[in] n the label nr to clone from, if this is 0, the complete ++ * dname is cloned ++ * \return A newly allocated *rdf structure, containing the cloned dname, ++ * or NULL if either d was NULL, not a dname, or if n >= ++ * label_count ++ */ ++ldns_rdf * ++ldns_dname_clone_from(const ldns_rdf *d, uint16_t n); ++ ++/** ++ * chop one label off the left side of a dname. so ++ * wwww.nlnetlabs.nl, becomes nlnetlabs.nl ++ * This new name is a clone and must be freed with ldns_deep_free() ++ * \param[in] d the dname to chop ++ * \return the remaining dname ++ */ ++ldns_rdf *ldns_dname_left_chop(const ldns_rdf *d); ++ ++/** ++ * count the number of labels inside a LDNS_RDF_DNAME type rdf. ++ * \param[in] *r the rdf ++ * \return the number of labels ++ */ ++uint8_t ldns_dname_label_count(const ldns_rdf *r); ++ ++/** ++ * creates a new dname rdf from a string. ++ * \param[in] str string to use ++ * \return ldns_rdf* or NULL in case of an error ++ */ ++ldns_rdf *ldns_dname_new_frm_str(const char *str); ++ ++/** ++ * Create a new dname rdf from a string ++ * \param[in] s the size of the new dname ++ * \param[in] *data pointer to the actual data ++ * ++ * \return ldns_rdf* ++ */ ++ldns_rdf *ldns_dname_new(uint16_t s, void *data); ++ ++/** ++ * Create a new dname rdf from data (the data is copied) ++ * \param[in] size the size of the data ++ * \param[in] *data pointer to the actual data ++ * ++ * \return ldns_rdf* ++ */ ++ldns_rdf *ldns_dname_new_frm_data(uint16_t size, const void *data); ++ ++/** ++ * Put a dname into canonical fmt - ie. lowercase it ++ * \param[in] rdf the dname to lowercase ++ * \return void ++ */ ++void ldns_dname2canonical(const ldns_rdf *rdf); ++ ++/** ++ * test wether the name sub falls under parent (i.e. is a subdomain ++ * of parent). This function will return false if the given dnames are ++ * equal. ++ * \param[in] sub the name to test ++ * \param[in] parent the parent's name ++ * \return true if sub falls under parent, otherwise false ++ */ ++bool ldns_dname_is_subdomain(const ldns_rdf *sub, const ldns_rdf *parent); ++ ++/** ++ * Compares the two dname rdf's according to the algorithm for ordering ++ * in RFC4034 Section 6. ++ * \param[in] dname1 First dname rdf to compare ++ * \param[in] dname2 Second dname rdf to compare ++ * \return -1 if dname1 comes before dname2, 1 if dname1 comes after dname2, and 0 if they are equal. ++ */ ++int ldns_dname_compare(const ldns_rdf *dname1, const ldns_rdf *dname2); ++int ldns_dname_compare_v(const void *, const void *); ++ ++/** ++ * Checks whether the dname matches the given wildcard ++ * \param[in] dname The dname to check ++ * \param[in] wildcard The wildcard to check with ++ * \return 1 If the wildcard matches, OR if 'wildcard' is not a wildcard and ++ * the names are *exactly* the same ++ * 0 If the wildcard does not match, or if it is not a wildcard and ++ * the names are not the same ++ */ ++int ldns_dname_match_wildcard(const ldns_rdf *dname, const ldns_rdf *wildcard); ++ ++/** ++ * check if middle lays in the interval defined by prev and next ++ * prev <= middle < next. This is usefull for nsec checking ++ * \param[in] prev the previous dname ++ * \param[in] middle the dname to check ++ * \param[in] next the next dname ++ * return 0 on error or unknown, -1 when middle is in the interval, +1 when not ++ */ ++int ldns_dname_interval(const ldns_rdf *prev, const ldns_rdf *middle, const ldns_rdf *next); ++ ++/** ++ * Checks whether the given dname string is absolute (i.e. ends with a '.') ++ * \param[in] *dname_str a string representing the dname ++ * \return true or false ++ */ ++bool ldns_dname_str_absolute(const char *dname_str); ++ ++/** ++ * Checks whether the given dname is absolute (i.e. ends with a '.') ++ * \param[in] *dname a rdf representing the dname ++ * \return true or false ++ */ ++bool ldns_dname_absolute(const ldns_rdf *dname); ++ ++/** ++ * look inside the rdf and if it is an LDNS_RDF_TYPE_DNAME ++ * try and retrieve a specific label. The labels are numbered ++ * starting from 0 (left most). ++ * \param[in] rdf the rdf to look in ++ * \param[in] labelpos return the label with this number ++ * \return a ldns_rdf* with the label as name or NULL on error ++ */ ++ldns_rdf * ldns_dname_label(const ldns_rdf *rdf, uint8_t labelpos); ++ ++/** ++ * Check if dname is a wildcard, starts with *. ++ * \param[in] dname: the rdf to look in ++ * \return true if a wildcard, false if not. ++ */ ++int ldns_dname_is_wildcard(const ldns_rdf* dname); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* LDNS_DNAME_H */ +diff --git a/ldns/include/ldns/dnssec.h b/ldns/include/ldns/dnssec.h +new file mode 100644 +index 0000000..f4cdafb +--- /dev/null ++++ b/ldns/include/ldns/dnssec.h +@@ -0,0 +1,541 @@ ++/* ++ * dnssec.h -- defines for the Domain Name System (SEC) (DNSSEC) ++ * ++ * Copyright (c) 2005-2008, NLnet Labs. All rights reserved. ++ * ++ * See LICENSE for the license. ++ * ++ * A bunch of defines that are used in the DNS ++ */ ++ ++/** ++ * \file dnssec.h ++ * ++ * This module contains base functions for DNSSEC operations ++ * (RFC4033 t/m RFC4035). ++ * ++ * Since those functions heavily rely op cryptographic operations, ++ * this module is dependent on openssl. ++ * ++ */ ++ ++ ++#ifndef LDNS_DNSSEC_H ++#define LDNS_DNSSEC_H ++ ++#include <ldns/common.h> ++#if LDNS_BUILD_CONFIG_HAVE_SSL ++#include <openssl/ssl.h> ++#include <openssl/evp.h> ++#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */ ++#include <ldns/packet.h> ++#include <ldns/keys.h> ++#include <ldns/zone.h> ++#include <ldns/resolver.h> ++#include <ldns/dnssec_zone.h> ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#define LDNS_MAX_KEYLEN 2048 ++#define LDNS_DNSSEC_KEYPROTO 3 ++/* default time before sigs expire */ ++#define LDNS_DEFAULT_EXP_TIME 2419200 /* 4 weeks */ ++ ++/** return values for the old-signature callback */ ++#define LDNS_SIGNATURE_LEAVE_ADD_NEW 0 ++#define LDNS_SIGNATURE_LEAVE_NO_ADD 1 ++#define LDNS_SIGNATURE_REMOVE_ADD_NEW 2 ++#define LDNS_SIGNATURE_REMOVE_NO_ADD 3 ++ ++/** ++ * Returns the first RRSIG rr that corresponds to the rrset ++ * with the given name and type ++ * ++ * \param[in] name The dname of the RRset covered by the RRSIG to find ++ * \param[in] type The type of the RRset covered by the RRSIG to find ++ * \param[in] rrs List of rrs to search in ++ * \returns Pointer to the first RRsig ldns_rr found, or NULL if it is ++ * not present ++ */ ++ldns_rr *ldns_dnssec_get_rrsig_for_name_and_type(const ldns_rdf *name, ++ const ldns_rr_type type, ++ const ldns_rr_list *rrs); ++ ++/** ++ * Returns the DNSKEY that corresponds to the given RRSIG rr from the list, if ++ * any ++ * ++ * \param[in] rrsig The rrsig to find the DNSKEY for ++ * \param[in] rrs The rr list to find the key in ++ * \return The DNSKEY that corresponds to the given RRSIG, or NULL if it was ++ * not found. ++ */ ++ldns_rr *ldns_dnssec_get_dnskey_for_rrsig(const ldns_rr *rrsig, const ldns_rr_list *rrs); ++ ++/** ++ * Returns the rdata field that contains the bitmap of the covered types of ++ * the given NSEC record ++ * ++ * \param[in] nsec The nsec to get the covered type bitmap of ++ * \return An ldns_rdf containing the bitmap, or NULL on error ++ */ ++ldns_rdf *ldns_nsec_get_bitmap(ldns_rr *nsec); ++ ++ ++#define LDNS_NSEC3_MAX_ITERATIONS 65535 ++ ++/** ++ * Returns the dname of the closest (provable) encloser ++ */ ++ldns_rdf * ++ldns_dnssec_nsec3_closest_encloser(ldns_rdf *qname, ++ ldns_rr_type qtype, ++ ldns_rr_list *nsec3s); ++ ++/** ++ * Checks whether the packet contains rrsigs ++ */ ++bool ++ldns_dnssec_pkt_has_rrsigs(const ldns_pkt *pkt); ++ ++/** ++ * Returns a ldns_rr_list containing the signatures covering the given name ++ * and type ++ */ ++ldns_rr_list *ldns_dnssec_pkt_get_rrsigs_for_name_and_type(const ldns_pkt *pkt, ldns_rdf *name, ldns_rr_type type); ++ ++/** ++ * Returns a ldns_rr_list containing the signatures covering the given type ++ */ ++ldns_rr_list *ldns_dnssec_pkt_get_rrsigs_for_type(const ldns_pkt *pkt, ldns_rr_type type); ++ ++/** ++ * calculates a keytag of a key for use in DNSSEC. ++ * ++ * \param[in] key the key as an RR to use for the calc. ++ * \return the keytag ++ */ ++uint16_t ldns_calc_keytag(const ldns_rr *key); ++ ++/** ++ * Calculates keytag of DNSSEC key, operates on wireformat rdata. ++ * \param[in] key the key as uncompressed wireformat rdata. ++ * \param[in] keysize length of key data. ++ * \return the keytag ++ */ ++uint16_t ldns_calc_keytag_raw(uint8_t* key, size_t keysize); ++ ++#if LDNS_BUILD_CONFIG_HAVE_SSL ++/** ++ * converts a buffer holding key material to a DSA key in openssl. ++ * ++ * \param[in] key the key to convert ++ * \return a DSA * structure with the key material ++ */ ++DSA *ldns_key_buf2dsa(ldns_buffer *key); ++/** ++ * Like ldns_key_buf2dsa, but uses raw buffer. ++ * \param[in] key the uncompressed wireformat of the key. ++ * \param[in] len length of key data ++ * \return a DSA * structure with the key material ++ */ ++DSA *ldns_key_buf2dsa_raw(unsigned char* key, size_t len); ++ ++/** ++ * Utility function to calculate hash using generic EVP_MD pointer. ++ * \param[in] data the data to hash. ++ * \param[in] len length of data. ++ * \param[out] dest the destination of the hash, must be large enough. ++ * \param[in] md the message digest to use. ++ * \return true if worked, false on failure. ++ */ ++int ldns_digest_evp(unsigned char* data, unsigned int len, ++ unsigned char* dest, const EVP_MD* md); ++ ++/** ++ * Converts a holding buffer with key material to EVP PKEY in openssl. ++ * Only available if ldns was compiled with GOST. ++ * \param[in] key data to convert ++ * \param[in] keylen length of the key data ++ * \return the key or NULL on error. ++ */ ++EVP_PKEY* ldns_gost2pkey_raw(unsigned char* key, size_t keylen); ++ ++/** ++ * Converts a holding buffer with key material to EVP PKEY in openssl. ++ * Only available if ldns was compiled with ECDSA. ++ * \param[in] key data to convert ++ * \param[in] keylen length of the key data ++ * \param[in] algo precise algorithm to initialize ECC group values. ++ * \return the key or NULL on error. ++ */ ++EVP_PKEY* ldns_ecdsa2pkey_raw(unsigned char* key, size_t keylen, uint8_t algo); ++ ++#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */ ++ ++#if LDNS_BUILD_CONFIG_HAVE_SSL ++/** ++ * converts a buffer holding key material to a RSA key in openssl. ++ * ++ * \param[in] key the key to convert ++ * \return a RSA * structure with the key material ++ */ ++RSA *ldns_key_buf2rsa(ldns_buffer *key); ++ ++/** ++ * Like ldns_key_buf2rsa, but uses raw buffer. ++ * \param[in] key the uncompressed wireformat of the key. ++ * \param[in] len length of key data ++ * \return a RSA * structure with the key material ++ */ ++RSA *ldns_key_buf2rsa_raw(unsigned char* key, size_t len); ++#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */ ++ ++/** ++ * returns a new DS rr that represents the given key rr. ++ * ++ * \param[in] *key the key to convert ++ * \param[in] h the hash to use LDNS_SHA1/LDNS_SHA256 ++ * ++ * \return ldns_rr* a new rr pointer to a DS ++ */ ++ldns_rr *ldns_key_rr2ds(const ldns_rr *key, ldns_hash h); ++ ++/** ++ * Create the type bitmap for an NSEC(3) record ++ */ ++ldns_rdf * ++ldns_dnssec_create_nsec_bitmap(ldns_rr_type rr_type_list[], ++ size_t size, ++ ldns_rr_type nsec_type); ++ ++/** ++ * returns whether a rrset of the given type is found in the rrsets. ++ * ++ * \param[in] rrsets the rrsets to be tested ++ * \param[in] type the type to test for ++ * \return int 1 if the type was found, 0 otherwise. ++ */ ++int ++ldns_dnssec_rrsets_contains_type (ldns_dnssec_rrsets *rrsets, ldns_rr_type type); ++ ++/** ++ * Creates NSEC ++ */ ++ldns_rr * ++ldns_dnssec_create_nsec(ldns_dnssec_name *from, ++ ldns_dnssec_name *to, ++ ldns_rr_type nsec_type); ++ ++ ++/** ++ * Creates NSEC3 ++ */ ++ldns_rr * ++ldns_dnssec_create_nsec3(ldns_dnssec_name *from, ++ ldns_dnssec_name *to, ++ ldns_rdf *zone_name, ++ uint8_t algorithm, ++ uint8_t flags, ++ uint16_t iterations, ++ uint8_t salt_length, ++ uint8_t *salt); ++ ++/** ++ * Create a NSEC record ++ * \param[in] cur_owner the current owner which should be taken as the starting point ++ * \param[in] next_owner the rrlist which the nsec rr should point to ++ * \param[in] rrs all rrs from the zone, to find all RR types of cur_owner in ++ * \return a ldns_rr with the nsec record in it ++ */ ++ldns_rr * ldns_create_nsec(ldns_rdf *cur_owner, ldns_rdf *next_owner, ldns_rr_list *rrs); ++ ++/** ++ * Calculates the hashed name using the given parameters ++ * \param[in] *name The owner name to calculate the hash for ++ * \param[in] algorithm The hash algorithm to use ++ * \param[in] iterations The number of hash iterations to use ++ * \param[in] salt_length The length of the salt in bytes ++ * \param[in] salt The salt to use ++ * \return The hashed owner name rdf, without the domain name ++ */ ++ldns_rdf *ldns_nsec3_hash_name(ldns_rdf *name, uint8_t algorithm, uint16_t iterations, uint8_t salt_length, uint8_t *salt); ++ ++/** ++ * Sets all the NSEC3 options. The rr to set them in must be initialized with _new() and ++ * type LDNS_RR_TYPE_NSEC3 ++ * \param[in] *rr The RR to set the values in ++ * \param[in] algorithm The NSEC3 hash algorithm ++ * \param[in] flags The flags field ++ * \param[in] iterations The number of hash iterations ++ * \param[in] salt_length The length of the salt in bytes ++ * \param[in] salt The salt bytes ++ */ ++void ldns_nsec3_add_param_rdfs(ldns_rr *rr, ++ uint8_t algorithm, ++ uint8_t flags, ++ uint16_t iterations, ++ uint8_t salt_length, ++ uint8_t *salt); ++ ++/* this will NOT return the NSEC3 completed, you will have to run the ++ finalize function on the rrlist later! */ ++ldns_rr * ++ldns_create_nsec3(ldns_rdf *cur_owner, ++ ldns_rdf *cur_zone, ++ ldns_rr_list *rrs, ++ uint8_t algorithm, ++ uint8_t flags, ++ uint16_t iterations, ++ uint8_t salt_length, ++ uint8_t *salt, ++ bool emptynonterminal); ++ ++/** ++ * Returns the hash algorithm used in the given NSEC3 RR ++ * \param[in] *nsec3_rr The RR to read from ++ * \return The algorithm identifier, or 0 on error ++ */ ++uint8_t ldns_nsec3_algorithm(const ldns_rr *nsec3_rr); ++ ++/** ++ * Returns flags field ++ */ ++uint8_t ++ldns_nsec3_flags(const ldns_rr *nsec3_rr); ++ ++/** ++ * Returns true if the opt-out flag has been set in the given NSEC3 RR ++ * \param[in] *nsec3_rr The RR to read from ++ * \return true if the RR has type NSEC3 and the opt-out bit has been set, false otherwise ++ */ ++bool ldns_nsec3_optout(const ldns_rr *nsec3_rr); ++ ++/** ++ * Returns the number of hash iterations used in the given NSEC3 RR ++ * \param[in] *nsec3_rr The RR to read from ++ * \return The number of iterations ++ */ ++uint16_t ldns_nsec3_iterations(const ldns_rr *nsec3_rr); ++ ++/** ++ * Returns the salt used in the given NSEC3 RR ++ * \param[in] *nsec3_rr The RR to read from ++ * \return The salt rdf, or NULL on error ++ */ ++ldns_rdf *ldns_nsec3_salt(const ldns_rr *nsec3_rr); ++ ++/** ++ * Returns the length of the salt used in the given NSEC3 RR ++ * \param[in] *nsec3_rr The RR to read from ++ * \return The length of the salt in bytes ++ */ ++uint8_t ldns_nsec3_salt_length(const ldns_rr *nsec3_rr); ++ ++/** ++ * Returns the salt bytes used in the given NSEC3 RR ++ * \param[in] *nsec3_rr The RR to read from ++ * \return The salt in bytes, this is alloced, so you need to free it ++ */ ++uint8_t *ldns_nsec3_salt_data(const ldns_rr *nsec3_rr); ++ ++/** ++ * Returns the first label of the next ownername in the NSEC3 chain (ie. without the domain) ++ * \param[in] nsec3_rr The RR to read from ++ * \return The first label of the next owner name in the NSEC3 chain, or NULL on error ++ */ ++ldns_rdf *ldns_nsec3_next_owner(const ldns_rr *nsec3_rr); ++ ++/** ++ * Returns the bitmap specifying the covered types of the given NSEC3 RR ++ * \param[in] *nsec3_rr The RR to read from ++ * \return The covered type bitmap rdf ++ */ ++ldns_rdf *ldns_nsec3_bitmap(const ldns_rr *nsec3_rr); ++ ++/** ++ * Calculates the hashed name using the parameters of the given NSEC3 RR ++ * \param[in] *nsec The RR to use the parameters from ++ * \param[in] *name The owner name to calculate the hash for ++ * \return The hashed owner name rdf, without the domain name ++ */ ++ldns_rdf *ldns_nsec3_hash_name_frm_nsec3(const ldns_rr *nsec, ldns_rdf *name); ++ ++/** ++ * Check if RR type t is enumerated and set in the RR type bitmap rdf. ++ * \param[in] bitmap the RR type bitmap rdf to look in ++ * \param[in] type the type to check for ++ * \return true when t is found and set, otherwise return false ++ */ ++bool ldns_nsec_bitmap_covers_type(const ldns_rdf* bitmap, ldns_rr_type type); ++ ++/** ++ * Checks if RR type t is enumerated in the type bitmap rdf and sets the bit. ++ * \param[in] bitmap the RR type bitmap rdf to look in ++ * \param[in] type the type to for which the bit to set ++ * \return LDNS_STATUS_OK on success. LDNS_STATUS_TYPE_NOT_IN_BITMAP is ++ * returned when the bitmap does not contain the bit to set. ++ */ ++ldns_status ldns_nsec_bitmap_set_type(ldns_rdf* bitmap, ldns_rr_type type); ++ ++/** ++ * Checks if RR type t is enumerated in the type bitmap rdf and clears the bit. ++ * \param[in] bitmap the RR type bitmap rdf to look in ++ * \param[in] type the type to for which the bit to clear ++ * \return LDNS_STATUS_OK on success. LDNS_STATUS_TYPE_NOT_IN_BITMAP is ++ * returned when the bitmap does not contain the bit to clear. ++ */ ++ldns_status ldns_nsec_bitmap_clear_type(ldns_rdf* bitmap, ldns_rr_type type); ++ ++/** ++ * Checks coverage of NSEC(3) RR name span ++ * Remember that nsec and name must both be in canonical form (ie use ++ * \ref ldns_rr2canonical and \ref ldns_dname2canonical prior to calling this ++ * function) ++ * ++ * \param[in] nsec The NSEC RR to check ++ * \param[in] name The owner dname to check, if the nsec record is a NSEC3 record, this should be the hashed name ++ * \return true if the NSEC RR covers the owner name ++ */ ++bool ldns_nsec_covers_name(const ldns_rr *nsec, const ldns_rdf *name); ++ ++#if LDNS_BUILD_CONFIG_HAVE_SSL ++/** ++ * verify a packet ++ * \param[in] p the packet ++ * \param[in] t the rr set type to check ++ * \param[in] o the rr set name to check ++ * \param[in] k list of keys ++ * \param[in] s list of sigs (may be null) ++ * \param[out] good_keys keys which validated the packet ++ * \return status ++ * ++ */ ++ldns_status ldns_pkt_verify(ldns_pkt *p, ldns_rr_type t, ldns_rdf *o, ldns_rr_list *k, ldns_rr_list *s, ldns_rr_list *good_keys); ++ ++/** ++ * verify a packet ++ * \param[in] p the packet ++ * \param[in] t the rr set type to check ++ * \param[in] o the rr set name to check ++ * \param[in] k list of keys ++ * \param[in] s list of sigs (may be null) ++ * \param[in] check_time the time for which the validation is performed ++ * \param[out] good_keys keys which validated the packet ++ * \return status ++ * ++ */ ++ldns_status ldns_pkt_verify_time(ldns_pkt *p, ldns_rr_type t, ldns_rdf *o, ldns_rr_list *k, ldns_rr_list *s, time_t check_time, ldns_rr_list *good_keys); ++ ++#endif ++ ++/** ++ * chains nsec3 list ++ */ ++ldns_status ++ldns_dnssec_chain_nsec3_list(ldns_rr_list *nsec3_rrs); ++ ++/** ++ * compare for nsec3 sort ++ */ ++int ++qsort_rr_compare_nsec3(const void *a, const void *b); ++ ++/** ++ * sort nsec3 list ++ */ ++void ++ldns_rr_list_sort_nsec3(ldns_rr_list *unsorted); ++ ++/** ++ * Default callback function to always leave present signatures, and ++ * add new ones ++ * \param[in] sig The signature to check for removal (unused) ++ * \param[in] n Optional argument (unused) ++ * \return LDNS_SIGNATURE_LEAVE_ADD_NEW ++ */ ++int ldns_dnssec_default_add_to_signatures(ldns_rr *sig, void *n); ++/** ++ * Default callback function to always leave present signatures, and ++ * add no new ones for the keys of these signatures ++ * \param[in] sig The signature to check for removal (unused) ++ * \param[in] n Optional argument (unused) ++ * \return LDNS_SIGNATURE_LEAVE_NO_ADD ++ */ ++int ldns_dnssec_default_leave_signatures(ldns_rr *sig, void *n); ++/** ++ * Default callback function to always remove present signatures, but ++ * add no new ones ++ * \param[in] sig The signature to check for removal (unused) ++ * \param[in] n Optional argument (unused) ++ * \return LDNS_SIGNATURE_REMOVE_NO_ADD ++ */ ++int ldns_dnssec_default_delete_signatures(ldns_rr *sig, void *n); ++/** ++ * Default callback function to always leave present signatures, and ++ * add new ones ++ * \param[in] sig The signature to check for removal (unused) ++ * \param[in] n Optional argument (unused) ++ * \return LDNS_SIGNATURE_REMOVE_ADD_NEW ++ */ ++int ldns_dnssec_default_replace_signatures(ldns_rr *sig, void *n); ++ ++#if LDNS_BUILD_CONFIG_HAVE_SSL ++/** ++ * Converts the DSA signature from ASN1 representation (RFC2459, as ++ * used by OpenSSL) to raw signature data as used in DNS (rfc2536) ++ * ++ * \param[in] sig The signature in RFC2459 format ++ * \param[in] sig_len The length of the signature ++ * \return a new rdf with the signature ++ */ ++ldns_rdf * ++ldns_convert_dsa_rrsig_asn12rdf(const ldns_buffer *sig, ++ const long sig_len); ++ ++/** ++ * Converts the RRSIG signature RDF (in rfc2536 format) to a buffer ++ * with the signature in rfc2459 format ++ * ++ * \param[out] target_buffer buffer to place the signature data ++ * \param[in] sig_rdf The signature rdf to convert ++ * \return LDNS_STATUS_OK on success, error code otherwise ++ */ ++ldns_status ++ldns_convert_dsa_rrsig_rdf2asn1(ldns_buffer *target_buffer, ++ const ldns_rdf *sig_rdf); ++ ++/** ++ * Converts the ECDSA signature from ASN1 representation (as ++ * used by OpenSSL) to raw signature data as used in DNS ++ * This routine is only present if ldns is compiled with ecdsa support. ++ * ++ * \param[in] sig The signature in ASN1 format ++ * \param[in] sig_len The length of the signature ++ * \return a new rdf with the signature ++ */ ++ldns_rdf * ++ldns_convert_ecdsa_rrsig_asn12rdf(const ldns_buffer *sig, const long sig_len); ++ ++/** ++ * Converts the RRSIG signature RDF (from DNS) to a buffer with the ++ * signature in ASN1 format as openssl uses it. ++ * This routine is only present if ldns is compiled with ecdsa support. ++ * ++ * \param[out] target_buffer buffer to place the signature data in ASN1. ++ * \param[in] sig_rdf The signature rdf to convert ++ * \return LDNS_STATUS_OK on success, error code otherwise ++ */ ++ldns_status ++ldns_convert_ecdsa_rrsig_rdf2asn1(ldns_buffer *target_buffer, ++ const ldns_rdf *sig_rdf); ++ ++#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */ ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* LDNS_DNSSEC_H */ +diff --git a/ldns/include/ldns/dnssec_sign.h b/ldns/include/ldns/dnssec_sign.h +new file mode 100644 +index 0000000..f51c7fb +--- /dev/null ++++ b/ldns/include/ldns/dnssec_sign.h +@@ -0,0 +1,383 @@ ++/** dnssec_verify */ ++ ++#ifndef LDNS_DNSSEC_SIGN_H ++#define LDNS_DNSSEC_SIGN_H ++ ++#include <ldns/dnssec.h> ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/* sign functions */ ++ ++/** Sign flag that makes DNSKEY type signed by all keys, not only by SEP keys*/ ++#define LDNS_SIGN_DNSKEY_WITH_ZSK 1 ++ ++/** ++ * Create an empty RRSIG RR (i.e. without the actual signature data) ++ * \param[in] rrset The RRset to create the signature for ++ * \param[in] key The key that will create the signature ++ * \return signature rr ++ */ ++ldns_rr * ++ldns_create_empty_rrsig(ldns_rr_list *rrset, ++ ldns_key *key); ++ ++/** ++ * Sign the buffer which contains the wiredata of an rrset, and the ++ * corresponding empty rrsig rr with the given key ++ * \param[in] sign_buf the buffer with data to sign ++ * \param[in] key the key to sign with ++ * \return an rdata field with the signature data ++ */ ++ldns_rdf * ++ldns_sign_public_buffer(ldns_buffer *sign_buf, ldns_key *key); ++ ++/** ++ * Sign an rrset ++ * \param[in] rrset the rrset ++ * \param[in] keys the keys to use ++ * \return a rr_list with the signatures ++ */ ++ldns_rr_list *ldns_sign_public(ldns_rr_list *rrset, ldns_key_list *keys); ++ ++#if LDNS_BUILD_CONFIG_HAVE_SSL ++/** ++ * Sign a buffer with the DSA key (hash with SHA1) ++ * \param[in] to_sign buffer with the data ++ * \param[in] key the key to use ++ * \return a ldns_rdf with the signed data ++ */ ++ldns_rdf *ldns_sign_public_dsa(ldns_buffer *to_sign, DSA *key); ++ ++/** ++ * Sign data with EVP (general method for different algorithms) ++ * ++ * \param[in] to_sign The ldns_buffer containing raw data that is ++ * to be signed ++ * \param[in] key The EVP_PKEY key structure to sign with ++ * \param[in] digest_type The digest algorithm to use in the creation of ++ * the signature ++ * \return ldns_rdf for the RRSIG ldns_rr ++ */ ++ldns_rdf *ldns_sign_public_evp(ldns_buffer *to_sign, ++ EVP_PKEY *key, ++ const EVP_MD *digest_type); ++ ++/** ++ * Sign a buffer with the RSA key (hash with SHA1) ++ * \param[in] to_sign buffer with the data ++ * \param[in] key the key to use ++ * \return a ldns_rdf with the signed data ++ */ ++ldns_rdf *ldns_sign_public_rsasha1(ldns_buffer *to_sign, RSA *key); ++ ++/** ++ * Sign a buffer with the RSA key (hash with MD5) ++ * \param[in] to_sign buffer with the data ++ * \param[in] key the key to use ++ * \return a ldns_rdf with the signed data ++ */ ++ldns_rdf *ldns_sign_public_rsamd5(ldns_buffer *to_sign, RSA *key); ++#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */ ++ ++/** ++ * Marks the names in the zone that are occluded. Those names will be skipped ++ * when walking the tree with the ldns_dnssec_name_node_next_nonglue() ++ * function. But watch out! Names that are partially occluded (like glue with ++ * the same name as the delegation) will not be marked and should specifically ++ * be taken into account separately. ++ * ++ * When glue_list is given (not NULL), in the process of marking the names, all ++ * glue resource records will be pushed to that list, even glue at the delegation name. ++ * ++ * \param[in] zone the zone in which to mark the names ++ * \param[in] glue_list the list to which to push the glue rrs ++ * \return LDNS_STATUS_OK on success, an error code otherwise ++ */ ++ldns_status ++ldns_dnssec_zone_mark_and_get_glue( ++ ldns_dnssec_zone *zone, ldns_rr_list *glue_list); ++ ++/** ++ * Marks the names in the zone that are occluded. Those names will be skipped ++ * when walking the tree with the ldns_dnssec_name_node_next_nonglue() ++ * function. But watch out! Names that are partially occluded (like glue with ++ * the same name as the delegation) will not be marked and should specifically ++ * be taken into account separately. ++ * ++ * \param[in] zone the zone in which to mark the names ++ * \return LDNS_STATUS_OK on succesful completion ++ */ ++ldns_status ++ldns_dnssec_zone_mark_glue(ldns_dnssec_zone *zone); ++ ++/** ++ * Finds the first dnssec_name node in the rbtree that is not occluded. ++ * It *does* return names that are partially occluded. ++ * ++ * \param[in] node the first node to check ++ * \return the first node that has not been marked as glue, or NULL ++ * if not found (TODO: make that LDNS_RBTREE_NULL?) ++ */ ++ldns_rbnode_t *ldns_dnssec_name_node_next_nonglue(ldns_rbnode_t *node); ++ ++/** ++ * Adds NSEC records to the given dnssec_zone ++ * ++ * \param[in] zone the zone to add the records to ++ * \param[in] new_rrs ldns_rr's created by this function are ++ * added to this rr list, so the caller can free them later ++ * \return LDNS_STATUS_OK on success, an error code otherwise ++ */ ++ldns_status ldns_dnssec_zone_create_nsecs(ldns_dnssec_zone *zone, ++ ldns_rr_list *new_rrs); ++ ++/** ++ * Adds NSEC3 records to the zone ++ */ ++ldns_status ++ldns_dnssec_zone_create_nsec3s(ldns_dnssec_zone *zone, ++ ldns_rr_list *new_rrs, ++ uint8_t algorithm, ++ uint8_t flags, ++ uint16_t iterations, ++ uint8_t salt_length, ++ uint8_t *salt); ++ ++/** ++ * remove signatures if callback function tells to ++ * ++ * \param[in] signatures list of signatures to check, and ++ * possibly remove, depending on the value of the ++ * callback ++ * \param[in] key_list these are marked to be used or not, ++ * on the return value of the callback ++ * \param[in] func this function is called to specify what to ++ * do with each signature (and corresponding key) ++ * \param[in] arg Optional argument for the callback function ++ * \returns pointer to the new signatures rrs (the original ++ * passed to this function may have been removed) ++ */ ++ldns_dnssec_rrs *ldns_dnssec_remove_signatures(ldns_dnssec_rrs *signatures, ++ ldns_key_list *key_list, ++ int (*func)(ldns_rr *, void *), ++ void *arg); ++ ++/** ++ * Adds signatures to the zone ++ * ++ * \param[in] zone the zone to add RRSIG Resource Records to ++ * \param[in] new_rrs the RRSIG RRs that are created are also ++ * added to this list, so the caller can free them ++ * later ++ * \param[in] key_list list of keys to sign with. ++ * \param[in] func Callback function to decide what keys to ++ * use and what to do with old signatures ++ * \param[in] arg Optional argument for the callback function ++ * \param[in] flags option flags for signing process. 0 makes DNSKEY ++ * RRset signed with the minimal key set, that is only SEP keys are used ++ * for signing. If there are no SEP keys available, non-SEP keys will ++ * be used. LDNS_SIGN_DNSKEY_WITH_ZSK makes DNSKEY type signed with all ++ * keys. 0 is the default. ++ * \return LDNS_STATUS_OK on success, error otherwise ++ */ ++ldns_status ldns_dnssec_zone_create_rrsigs_flg(ldns_dnssec_zone *zone, ++ ldns_rr_list *new_rrs, ++ ldns_key_list *key_list, ++ int (*func)(ldns_rr *, void*), ++ void *arg, ++ int flags); ++ ++/** ++ * Adds signatures to the zone ++ * ++ * \param[in] zone the zone to add RRSIG Resource Records to ++ * \param[in] new_rrs the RRSIG RRs that are created are also ++ * added to this list, so the caller can free them ++ * later ++ * \param[in] key_list list of keys to sign with. ++ * \param[in] func Callback function to decide what keys to ++ * use and what to do with old signatures ++ * \param[in] arg Optional argument for the callback function ++ * \return LDNS_STATUS_OK on success, error otherwise ++ */ ++ldns_status ldns_dnssec_zone_create_rrsigs(ldns_dnssec_zone *zone, ++ ldns_rr_list *new_rrs, ++ ldns_key_list *key_list, ++ int (*func)(ldns_rr *, void*), ++ void *arg); ++ ++/** ++ * signs the given zone with the given keys ++ * ++ * \param[in] zone the zone to sign ++ * \param[in] key_list the list of keys to sign the zone with ++ * \param[in] new_rrs newly created resource records are added to this list, to free them later ++ * \param[in] func callback function that decides what to do with old signatures ++ * This function takes an ldns_rr* and an optional void *arg argument, and returns one of four values: ++ * LDNS_SIGNATURE_LEAVE_ADD_NEW: ++ * leave the signature and add a new one for the corresponding key ++ * LDNS_SIGNATURE_REMOVE_ADD_NEW: ++ * remove the signature and replace is with a new one from the same key ++ * LDNS_SIGNATURE_LEAVE_NO_ADD: ++ * leave the signature and do not add a new one with the corresponding key ++ * LDNS_SIGNATURE_REMOVE_NO_ADD: ++ * remove the signature and do not replace ++ * ++ * \param[in] arg optional argument for the callback function ++ * \param[in] flags option flags for signing process. 0 makes DNSKEY ++ * RRset signed with the minimal key set, that is only SEP keys are used ++ * for signing. If there are no SEP keys available, non-SEP keys will ++ * be used. LDNS_SIGN_DNSKEY_WITH_ZSK makes DNSKEY type signed with all ++ * keys. 0 is the default. ++ * \return LDNS_STATUS_OK on success, an error code otherwise ++ */ ++ldns_status ldns_dnssec_zone_sign_flg(ldns_dnssec_zone *zone, ++ ldns_rr_list *new_rrs, ++ ldns_key_list *key_list, ++ int (*func)(ldns_rr *, void *), ++ void *arg, ++ int flags); ++ ++/** ++ * signs the given zone with the given new zone, with NSEC3 ++ * ++ * \param[in] zone the zone to sign ++ * \param[in] key_list the list of keys to sign the zone with ++ * \param[in] new_rrs newly created resource records are added to this list, to free them later ++ * \param[in] func callback function that decides what to do with old signatures ++ * \param[in] arg optional argument for the callback function ++ * \param[in] algorithm the NSEC3 hashing algorithm to use ++ * \param[in] flags NSEC3 flags ++ * \param[in] iterations the number of NSEC3 hash iterations to use ++ * \param[in] salt_length the length (in octets) of the NSEC3 salt ++ * \param[in] salt the NSEC3 salt data ++ * \param[in] signflags option flags for signing process. 0 is the default. ++ * \return LDNS_STATUS_OK on success, an error code otherwise ++ */ ++ldns_status ldns_dnssec_zone_sign_nsec3_flg(ldns_dnssec_zone *zone, ++ ldns_rr_list *new_rrs, ++ ldns_key_list *key_list, ++ int (*func)(ldns_rr *, void *), ++ void *arg, ++ uint8_t algorithm, ++ uint8_t flags, ++ uint16_t iterations, ++ uint8_t salt_length, ++ uint8_t *salt, ++ int signflags); ++ ++/** ++ * signs the given zone with the given new zone, with NSEC3 ++ * ++ * \param[in] zone the zone to sign ++ * \param[in] key_list the list of keys to sign the zone with ++ * \param[in] new_rrs newly created resource records are added to this list, to free them later ++ * \param[in] func callback function that decides what to do with old signatures ++ * \param[in] arg optional argument for the callback function ++ * \param[in] algorithm the NSEC3 hashing algorithm to use ++ * \param[in] flags NSEC3 flags ++ * \param[in] iterations the number of NSEC3 hash iterations to use ++ * \param[in] salt_length the length (in octets) of the NSEC3 salt ++ * \param[in] salt the NSEC3 salt data ++ * \param[in] signflags option flags for signing process. 0 is the default. ++ * \param[out] map a referenced rbtree pointer variable. The newly created ++ * rbtree will contain mappings from hashed owner names to the ++ * unhashed name. ++ * \return LDNS_STATUS_OK on success, an error code otherwise ++ */ ++ldns_status ldns_dnssec_zone_sign_nsec3_flg_mkmap(ldns_dnssec_zone *zone, ++ ldns_rr_list *new_rrs, ++ ldns_key_list *key_list, ++ int (*func)(ldns_rr *, void *), ++ void *arg, ++ uint8_t algorithm, ++ uint8_t flags, ++ uint16_t iterations, ++ uint8_t salt_length, ++ uint8_t *salt, ++ int signflags, ++ ldns_rbtree_t **map ++ ); ++ ++ ++/** ++ * signs the given zone with the given keys ++ * ++ * \param[in] zone the zone to sign ++ * \param[in] key_list the list of keys to sign the zone with ++ * \param[in] new_rrs newly created resource records are added to this list, to free them later ++ * \param[in] func callback function that decides what to do with old signatures ++ * This function takes an ldns_rr* and an optional void *arg argument, and returns one of four values: ++ * LDNS_SIGNATURE_LEAVE_ADD_NEW: ++ * leave the signature and add a new one for the corresponding key ++ * LDNS_SIGNATURE_REMOVE_ADD_NEW: ++ * remove the signature and replace is with a new one from the same key ++ * LDNS_SIGNATURE_LEAVE_NO_ADD: ++ * leave the signature and do not add a new one with the corresponding key ++ * LDNS_SIGNATURE_REMOVE_NO_ADD: ++ * remove the signature and do not replace ++ * ++ * \param[in] arg optional argument for the callback function ++ * \return LDNS_STATUS_OK on success, an error code otherwise ++ */ ++ldns_status ldns_dnssec_zone_sign(ldns_dnssec_zone *zone, ++ ldns_rr_list *new_rrs, ++ ldns_key_list *key_list, ++ int (*func)(ldns_rr *, void *), ++ void *arg); ++ ++/** ++ * signs the given zone with the given new zone, with NSEC3 ++ * ++ * \param[in] zone the zone to sign ++ * \param[in] key_list the list of keys to sign the zone with ++ * \param[in] new_rrs newly created resource records are added to this list, to free them later ++ * \param[in] func callback function that decides what to do with old signatures ++ * \param[in] arg optional argument for the callback function ++ * \param[in] algorithm the NSEC3 hashing algorithm to use ++ * \param[in] flags NSEC3 flags ++ * \param[in] iterations the number of NSEC3 hash iterations to use ++ * \param[in] salt_length the length (in octets) of the NSEC3 salt ++ * \param[in] salt the NSEC3 salt data ++ * \return LDNS_STATUS_OK on success, an error code otherwise ++ */ ++ldns_status ldns_dnssec_zone_sign_nsec3(ldns_dnssec_zone *zone, ++ ldns_rr_list *new_rrs, ++ ldns_key_list *key_list, ++ int (*func)(ldns_rr *, void *), ++ void *arg, ++ uint8_t algorithm, ++ uint8_t flags, ++ uint16_t iterations, ++ uint8_t salt_length, ++ uint8_t *salt); ++ ++/** ++ * Signs the zone, and returns a newly allocated signed zone ++ * \param[in] zone the zone to sign ++ * \param[in] key_list list of keys to sign with ++ * \return signed zone ++ */ ++ldns_zone *ldns_zone_sign(const ldns_zone *zone, ldns_key_list *key_list); ++ ++/** ++ * Signs the zone with NSEC3, and returns a newly allocated signed zone ++ * \param[in] zone the zone to sign ++ * \param[in] key_list list of keys to sign with ++ * \param[in] algorithm the NSEC3 hashing algorithm to use ++ * \param[in] flags NSEC3 flags ++ * \param[in] iterations the number of NSEC3 hash iterations to use ++ * \param[in] salt_length the length (in octets) of the NSEC3 salt ++ * \param[in] salt the NSEC3 salt data ++ * \return signed zone ++ */ ++ldns_zone *ldns_zone_sign_nsec3(ldns_zone *zone, ldns_key_list *key_list, uint8_t algorithm, uint8_t flags, uint16_t iterations, uint8_t salt_length, uint8_t *salt); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif +diff --git a/ldns/include/ldns/dnssec_verify.h b/ldns/include/ldns/dnssec_verify.h +new file mode 100644 +index 0000000..e8b1a91 +--- /dev/null ++++ b/ldns/include/ldns/dnssec_verify.h +@@ -0,0 +1,857 @@ ++/** dnssec_verify */ ++ ++#ifndef LDNS_DNSSEC_VERIFY_H ++#define LDNS_DNSSEC_VERIFY_H ++ ++#define LDNS_DNSSEC_TRUST_TREE_MAX_PARENTS 10 ++ ++#include <ldns/dnssec.h> ++#include <ldns/host2str.h> ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/** ++ * Chain structure that contains all DNSSEC data needed to ++ * verify an rrset ++ */ ++typedef struct ldns_dnssec_data_chain_struct ldns_dnssec_data_chain; ++struct ldns_dnssec_data_chain_struct ++{ ++ ldns_rr_list *rrset; ++ ldns_rr_list *signatures; ++ ldns_rr_type parent_type; ++ ldns_dnssec_data_chain *parent; ++ ldns_pkt_rcode packet_rcode; ++ ldns_rr_type packet_qtype; ++ bool packet_nodata; ++}; ++ ++/** ++ * Creates a new dnssec_chain structure ++ * \return ldns_dnssec_data_chain * ++ */ ++ldns_dnssec_data_chain *ldns_dnssec_data_chain_new(void); ++ ++/** ++ * Frees a dnssec_data_chain structure ++ * ++ * \param[in] *chain The chain to free ++ */ ++void ldns_dnssec_data_chain_free(ldns_dnssec_data_chain *chain); ++ ++/** ++ * Frees a dnssec_data_chain structure, and all data ++ * contained therein ++ * ++ * \param[in] *chain The dnssec_data_chain to free ++ */ ++void ldns_dnssec_data_chain_deep_free(ldns_dnssec_data_chain *chain); ++ ++/** ++ * Prints the dnssec_data_chain to the given file stream ++ * ++ * \param[in] *out The file stream to print to ++ * \param[in] *chain The dnssec_data_chain to print ++ */ ++void ldns_dnssec_data_chain_print(FILE *out, const ldns_dnssec_data_chain *chain); ++ ++/** ++ * Prints the dnssec_data_chain to the given file stream ++ * ++ * \param[in] *out The file stream to print to ++ * \param[in] *fmt The format of the textual representation ++ * \param[in] *chain The dnssec_data_chain to print ++ */ ++void ldns_dnssec_data_chain_print_fmt(FILE *out, ++ const ldns_output_format *fmt, ++ const ldns_dnssec_data_chain *chain); ++ ++/** ++ * Build an ldns_dnssec_data_chain, which contains all ++ * DNSSEC data that is needed to derive the trust tree later ++ * ++ * The data_set will be cloned ++ * ++ * \param[in] *res resolver structure for further needed queries ++ * \param[in] qflags resolution flags ++ * \param[in] *data_set The original rrset where the chain ends ++ * \param[in] *pkt optional, can contain the original packet ++ * (and hence the sigs and maybe the key) ++ * \param[in] *orig_rr The original Resource Record ++ * ++ * \return the DNSSEC data chain ++ */ ++ldns_dnssec_data_chain *ldns_dnssec_build_data_chain(ldns_resolver *res, ++ const uint16_t qflags, ++ const ldns_rr_list *data_set, ++ const ldns_pkt *pkt, ++ ldns_rr *orig_rr); ++ ++/** ++ * Tree structure that contains the relation of DNSSEC data, ++ * and their cryptographic status. ++ * ++ * This tree is derived from a data_chain, and can be used ++ * to look whether there is a connection between an RRSET ++ * and a trusted key. The tree only contains pointers to the ++ * data_chain, and therefore one should *never* free() the ++ * data_chain when there is still a trust tree derived from ++ * that chain. ++ * ++ * Example tree: ++ * key key key ++ * \ | / ++ * \ | / ++ * \ | / ++ * ds ++ * | ++ * key ++ * | ++ * key ++ * | ++ * rr ++ * ++ * For each signature there is a parent; if the parent ++ * pointer is null, it couldn't be found and there was no ++ * denial; otherwise is a tree which contains either a ++ * DNSKEY, a DS, or a NSEC rr ++ */ ++typedef struct ldns_dnssec_trust_tree_struct ldns_dnssec_trust_tree; ++struct ldns_dnssec_trust_tree_struct ++{ ++ ldns_rr *rr; ++ /* the complete rrset this rr was in */ ++ ldns_rr_list *rrset; ++ ldns_dnssec_trust_tree *parents[LDNS_DNSSEC_TRUST_TREE_MAX_PARENTS]; ++ ldns_status parent_status[LDNS_DNSSEC_TRUST_TREE_MAX_PARENTS]; ++ /** for debugging, add signatures too (you might want ++ those if they contain errors) */ ++ ldns_rr *parent_signature[LDNS_DNSSEC_TRUST_TREE_MAX_PARENTS]; ++ size_t parent_count; ++}; ++ ++/** ++ * Creates a new (empty) dnssec_trust_tree structure ++ * ++ * \return ldns_dnssec_trust_tree * ++ */ ++ldns_dnssec_trust_tree *ldns_dnssec_trust_tree_new(void); ++ ++/** ++ * Frees the dnssec_trust_tree recursively ++ * ++ * There is no deep free; all data in the trust tree ++ * consists of pointers to a data_chain ++ * ++ * \param[in] tree The tree to free ++ */ ++void ldns_dnssec_trust_tree_free(ldns_dnssec_trust_tree *tree); ++ ++/** ++ * returns the depth of the trust tree ++ * ++ * \param[in] tree tree to calculate the depth of ++ * \return The depth of the tree ++ */ ++size_t ldns_dnssec_trust_tree_depth(ldns_dnssec_trust_tree *tree); ++ ++/** ++ * Prints the dnssec_trust_tree structure to the given file ++ * stream. ++ * ++ * If a link status is not LDNS_STATUS_OK; the status and ++ * relevant signatures are printed too ++ * ++ * \param[in] *out The file stream to print to ++ * \param[in] tree The trust tree to print ++ * \param[in] tabs Prepend each line with tabs*2 spaces ++ * \param[in] extended If true, add little explanation lines to the output ++ */ ++void ldns_dnssec_trust_tree_print(FILE *out, ++ ldns_dnssec_trust_tree *tree, ++ size_t tabs, ++ bool extended); ++ ++/** ++ * Prints the dnssec_trust_tree structure to the given file ++ * stream. ++ * ++ * If a link status is not LDNS_STATUS_OK; the status and ++ * relevant signatures are printed too ++ * ++ * \param[in] *out The file stream to print to ++ * \param[in] *fmt The format of the textual representation ++ * \param[in] tree The trust tree to print ++ * \param[in] tabs Prepend each line with tabs*2 spaces ++ * \param[in] extended If true, add little explanation lines to the output ++ */ ++void ldns_dnssec_trust_tree_print_fmt(FILE *out, ++ const ldns_output_format *fmt, ++ ldns_dnssec_trust_tree *tree, ++ size_t tabs, ++ bool extended); ++ ++/** ++ * Adds a trust tree as a parent for the given trust tree ++ * ++ * \param[in] *tree The tree to add the parent to ++ * \param[in] *parent The parent tree to add ++ * \param[in] *parent_signature The RRSIG relevant to this parent/child ++ * connection ++ * \param[in] parent_status The DNSSEC status for this parent, child and RRSIG ++ * \return LDNS_STATUS_OK if the addition succeeds, error otherwise ++ */ ++ldns_status ldns_dnssec_trust_tree_add_parent(ldns_dnssec_trust_tree *tree, ++ const ldns_dnssec_trust_tree *parent, ++ const ldns_rr *parent_signature, ++ const ldns_status parent_status); ++ ++/** ++ * Generates a dnssec_trust_tree for the given rr from the ++ * given data_chain ++ * ++ * This does not clone the actual data; Don't free the ++ * data_chain before you are done with this tree ++ * ++ * \param[in] *data_chain The chain to derive the trust tree from ++ * \param[in] *rr The RR this tree will be about ++ * \return ldns_dnssec_trust_tree * ++ */ ++ldns_dnssec_trust_tree *ldns_dnssec_derive_trust_tree( ++ ldns_dnssec_data_chain *data_chain, ++ ldns_rr *rr); ++ ++/** ++ * Generates a dnssec_trust_tree for the given rr from the ++ * given data_chain ++ * ++ * This does not clone the actual data; Don't free the ++ * data_chain before you are done with this tree ++ * ++ * \param[in] *data_chain The chain to derive the trust tree from ++ * \param[in] *rr The RR this tree will be about ++ * \param[in] check_time the time for which the validation is performed ++ * \return ldns_dnssec_trust_tree * ++ */ ++ldns_dnssec_trust_tree *ldns_dnssec_derive_trust_tree_time( ++ ldns_dnssec_data_chain *data_chain, ++ ldns_rr *rr, time_t check_time); ++ ++/** ++ * Sub function for derive_trust_tree that is used for a 'normal' rrset ++ * ++ * \param[in] new_tree The trust tree that we are building ++ * \param[in] data_chain The data chain containing the data for the trust tree ++ * \param[in] cur_sig_rr The currently relevant signature ++ */ ++void ldns_dnssec_derive_trust_tree_normal_rrset( ++ ldns_dnssec_trust_tree *new_tree, ++ ldns_dnssec_data_chain *data_chain, ++ ldns_rr *cur_sig_rr); ++ ++/** ++ * Sub function for derive_trust_tree that is used for a 'normal' rrset ++ * ++ * \param[in] new_tree The trust tree that we are building ++ * \param[in] data_chain The data chain containing the data for the trust tree ++ * \param[in] cur_sig_rr The currently relevant signature ++ * \param[in] check_time the time for which the validation is performed ++ */ ++void ldns_dnssec_derive_trust_tree_normal_rrset_time( ++ ldns_dnssec_trust_tree *new_tree, ++ ldns_dnssec_data_chain *data_chain, ++ ldns_rr *cur_sig_rr, time_t check_time); ++ ++ ++/** ++ * Sub function for derive_trust_tree that is used for DNSKEY rrsets ++ * ++ * \param[in] new_tree The trust tree that we are building ++ * \param[in] data_chain The data chain containing the data for the trust tree ++ * \param[in] cur_rr The currently relevant DNSKEY RR ++ * \param[in] cur_sig_rr The currently relevant signature ++ */ ++void ldns_dnssec_derive_trust_tree_dnskey_rrset( ++ ldns_dnssec_trust_tree *new_tree, ++ ldns_dnssec_data_chain *data_chain, ++ ldns_rr *cur_rr, ++ ldns_rr *cur_sig_rr); ++ ++/** ++ * Sub function for derive_trust_tree that is used for DNSKEY rrsets ++ * ++ * \param[in] new_tree The trust tree that we are building ++ * \param[in] data_chain The data chain containing the data for the trust tree ++ * \param[in] cur_rr The currently relevant DNSKEY RR ++ * \param[in] cur_sig_rr The currently relevant signature ++ * \param[in] check_time the time for which the validation is performed ++ */ ++void ldns_dnssec_derive_trust_tree_dnskey_rrset_time( ++ ldns_dnssec_trust_tree *new_tree, ++ ldns_dnssec_data_chain *data_chain, ++ ldns_rr *cur_rr, ldns_rr *cur_sig_rr, ++ time_t check_time); ++ ++/** ++ * Sub function for derive_trust_tree that is used for DS rrsets ++ * ++ * \param[in] new_tree The trust tree that we are building ++ * \param[in] data_chain The data chain containing the data for the trust tree ++ * \param[in] cur_rr The currently relevant DS RR ++ */ ++void ldns_dnssec_derive_trust_tree_ds_rrset( ++ ldns_dnssec_trust_tree *new_tree, ++ ldns_dnssec_data_chain *data_chain, ++ ldns_rr *cur_rr); ++ ++/** ++ * Sub function for derive_trust_tree that is used for DS rrsets ++ * ++ * \param[in] new_tree The trust tree that we are building ++ * \param[in] data_chain The data chain containing the data for the trust tree ++ * \param[in] cur_rr The currently relevant DS RR ++ * \param[in] check_time the time for which the validation is performed ++ */ ++void ldns_dnssec_derive_trust_tree_ds_rrset_time( ++ ldns_dnssec_trust_tree *new_tree, ++ ldns_dnssec_data_chain *data_chain, ++ ldns_rr *cur_rr, time_t check_time); ++ ++/** ++ * Sub function for derive_trust_tree that is used when there are no ++ * signatures ++ * ++ * \param[in] new_tree The trust tree that we are building ++ * \param[in] data_chain The data chain containing the data for the trust tree ++ */ ++void ldns_dnssec_derive_trust_tree_no_sig( ++ ldns_dnssec_trust_tree *new_tree, ++ ldns_dnssec_data_chain *data_chain); ++ ++/** ++ * Sub function for derive_trust_tree that is used when there are no ++ * signatures ++ * ++ * \param[in] new_tree The trust tree that we are building ++ * \param[in] data_chain The data chain containing the data for the trust tree ++ * \param[in] check_time the time for which the validation is performed ++ */ ++void ldns_dnssec_derive_trust_tree_no_sig_time( ++ ldns_dnssec_trust_tree *new_tree, ++ ldns_dnssec_data_chain *data_chain, ++ time_t check_time); ++ ++ ++/** ++ * Returns OK if there is a trusted path in the tree to one of ++ * the DNSKEY or DS RRs in the given list ++ * ++ * \param *tree The trust tree so search ++ * \param *keys A ldns_rr_list of DNSKEY and DS rrs to look for ++ * ++ * \return LDNS_STATUS_OK if there is a trusted path to one of ++ * the keys, or the *first* error encountered ++ * if there were no paths ++ */ ++ldns_status ldns_dnssec_trust_tree_contains_keys( ++ ldns_dnssec_trust_tree *tree, ++ ldns_rr_list *keys); ++ ++/** ++ * Verifies a list of signatures for one rrset. ++ * ++ * \param[in] rrset the rrset to verify ++ * \param[in] rrsig a list of signatures to check ++ * \param[in] keys a list of keys to check with ++ * \param[out] good_keys if this is a (initialized) list, the pointer to keys ++ * from keys that validate one of the signatures ++ * are added to it ++ * \return status LDNS_STATUS_OK if there is at least one correct key ++ */ ++ldns_status ldns_verify(ldns_rr_list *rrset, ++ ldns_rr_list *rrsig, ++ const ldns_rr_list *keys, ++ ldns_rr_list *good_keys); ++ ++/** ++ * Verifies a list of signatures for one rrset. ++ * ++ * \param[in] rrset the rrset to verify ++ * \param[in] rrsig a list of signatures to check ++ * \param[in] keys a list of keys to check with ++ * \param[in] check_time the time for which the validation is performed ++ * \param[out] good_keys if this is a (initialized) list, the pointer to keys ++ * from keys that validate one of the signatures ++ * are added to it ++ * \return status LDNS_STATUS_OK if there is at least one correct key ++ */ ++ldns_status ldns_verify_time(ldns_rr_list *rrset, ++ ldns_rr_list *rrsig, ++ const ldns_rr_list *keys, ++ time_t check_time, ++ ldns_rr_list *good_keys); ++ ++ ++/** ++ * Verifies a list of signatures for one rrset, but disregard the time. ++ * Inception and Expiration are not checked. ++ * ++ * \param[in] rrset the rrset to verify ++ * \param[in] rrsig a list of signatures to check ++ * \param[in] keys a list of keys to check with ++ * \param[out] good_keys if this is a (initialized) list, the pointer to keys ++ * from keys that validate one of the signatures ++ * are added to it ++ * \return status LDNS_STATUS_OK if there is at least one correct key ++ */ ++ldns_status ldns_verify_notime(ldns_rr_list *rrset, ++ ldns_rr_list *rrsig, ++ const ldns_rr_list *keys, ++ ldns_rr_list *good_keys); ++ ++/** ++ * Tries to build an authentication chain from the given ++ * keys down to the queried domain. ++ * ++ * If we find a valid trust path, return the valid keys for the domain. ++ * ++ * \param[in] res the current resolver ++ * \param[in] domain the domain we want valid keys for ++ * \param[in] keys the current set of trusted keys ++ * \param[out] status pointer to the status variable where the result ++ * code will be stored ++ * \return the set of trusted keys for the domain, or NULL if no ++ * trust path could be built. ++ */ ++ldns_rr_list *ldns_fetch_valid_domain_keys(const ldns_resolver * res, ++ const ldns_rdf * domain, ++ const ldns_rr_list * keys, ++ ldns_status *status); ++ ++/** ++ * Tries to build an authentication chain from the given ++ * keys down to the queried domain. ++ * ++ * If we find a valid trust path, return the valid keys for the domain. ++ * ++ * \param[in] res the current resolver ++ * \param[in] domain the domain we want valid keys for ++ * \param[in] keys the current set of trusted keys ++ * \param[in] check_time the time for which the validation is performed ++ * \param[out] status pointer to the status variable where the result ++ * code will be stored ++ * \return the set of trusted keys for the domain, or NULL if no ++ * trust path could be built. ++ */ ++ldns_rr_list *ldns_fetch_valid_domain_keys_time(const ldns_resolver * res, ++ const ldns_rdf * domain, const ldns_rr_list * keys, ++ time_t check_time, ldns_status *status); ++ ++ ++/** ++ * Validates the DNSKEY RRset for the given domain using the provided ++ * trusted keys. ++ * ++ * \param[in] res the current resolver ++ * \param[in] domain the domain we want valid keys for ++ * \param[in] keys the current set of trusted keys ++ * \return the set of trusted keys for the domain, or NULL if the RRSET ++ * could not be validated ++ */ ++ldns_rr_list *ldns_validate_domain_dnskey (const ldns_resolver *res, ++ const ldns_rdf *domain, ++ const ldns_rr_list *keys); ++ ++/** ++ * Validates the DNSKEY RRset for the given domain using the provided ++ * trusted keys. ++ * ++ * \param[in] res the current resolver ++ * \param[in] domain the domain we want valid keys for ++ * \param[in] keys the current set of trusted keys ++ * \param[in] check_time the time for which the validation is performed ++ * \return the set of trusted keys for the domain, or NULL if the RRSET ++ * could not be validated ++ */ ++ldns_rr_list *ldns_validate_domain_dnskey_time( ++ const ldns_resolver *res, const ldns_rdf *domain, ++ const ldns_rr_list *keys, time_t check_time); ++ ++ ++/** ++ * Validates the DS RRset for the given domain using the provided trusted keys. ++ * ++ * \param[in] res the current resolver ++ * \param[in] domain the domain we want valid keys for ++ * \param[in] keys the current set of trusted keys ++ * \return the set of trusted keys for the domain, or NULL if the RRSET could not be validated ++ */ ++ldns_rr_list *ldns_validate_domain_ds(const ldns_resolver *res, ++ const ldns_rdf * ++ domain, ++ const ldns_rr_list * keys); ++ ++/** ++ * Validates the DS RRset for the given domain using the provided trusted keys. ++ * ++ * \param[in] res the current resolver ++ * \param[in] domain the domain we want valid keys for ++ * \param[in] keys the current set of trusted keys ++ * \param[in] check_time the time for which the validation is performed ++ * \return the set of trusted keys for the domain, or NULL if the RRSET could not be validated ++ */ ++ldns_rr_list *ldns_validate_domain_ds_time( ++ const ldns_resolver *res, const ldns_rdf *domain, ++ const ldns_rr_list * keys, time_t check_time); ++ ++ ++/** ++ * Verifies a list of signatures for one RRset using a valid trust path. ++ * ++ * \param[in] res the current resolver ++ * \param[in] rrset the rrset to verify ++ * \param[in] rrsigs a list of signatures to check ++ * \param[out] validating_keys if this is a (initialized) list, the ++ * keys from keys that validate one of ++ * the signatures are added to it ++ * \return status LDNS_STATUS_OK if there is at least one correct key ++ */ ++ldns_status ldns_verify_trusted(ldns_resolver *res, ++ ldns_rr_list *rrset, ++ ldns_rr_list *rrsigs, ++ ldns_rr_list *validating_keys); ++ ++/** ++ * Verifies a list of signatures for one RRset using a valid trust path. ++ * ++ * \param[in] res the current resolver ++ * \param[in] rrset the rrset to verify ++ * \param[in] rrsigs a list of signatures to check ++ * \param[in] check_time the time for which the validation is performed ++ * \param[out] validating_keys if this is a (initialized) list, the ++ * keys from keys that validate one of ++ * the signatures are added to it ++ * \return status LDNS_STATUS_OK if there is at least one correct key ++ */ ++ldns_status ldns_verify_trusted_time( ++ ldns_resolver *res, ldns_rr_list *rrset, ++ ldns_rr_list *rrsigs, time_t check_time, ++ ldns_rr_list *validating_keys); ++ ++ ++/** ++ * denial is not just a river in egypt ++ * ++ * \param[in] rr The (query) RR to check the denial of existence for ++ * \param[in] nsecs The list of NSEC RRs that are supposed to deny the ++ * existence of the RR ++ * \param[in] rrsigs The RRSIG RR covering the NSEC RRs ++ * \return LDNS_STATUS_OK if the NSEC RRs deny the existence, error code ++ * containing the reason they do not otherwise ++ */ ++ldns_status ldns_dnssec_verify_denial(ldns_rr *rr, ++ ldns_rr_list *nsecs, ++ ldns_rr_list *rrsigs); ++ ++/** ++ * Denial of existence using NSEC3 records ++ * Since NSEC3 is a bit more complicated than normal denial, some ++ * context arguments are needed ++ * ++ * \param[in] rr The (query) RR to check the denial of existence for ++ * \param[in] nsecs The list of NSEC3 RRs that are supposed to deny the ++ * existence of the RR ++ * \param[in] rrsigs The RRSIG rr covering the NSEC RRs ++ * \param[in] packet_rcode The RCODE value of the packet that provided the ++ * NSEC3 RRs ++ * \param[in] packet_qtype The original query RR type ++ * \param[in] packet_nodata True if the providing packet had an empty ANSWER ++ * section ++ * \return LDNS_STATUS_OK if the NSEC3 RRs deny the existence, error code ++ * containing the reason they do not otherwise ++ */ ++ldns_status ldns_dnssec_verify_denial_nsec3(ldns_rr *rr, ++ ldns_rr_list *nsecs, ++ ldns_rr_list *rrsigs, ++ ldns_pkt_rcode packet_rcode, ++ ldns_rr_type packet_qtype, ++ bool packet_nodata); ++ ++/** ++ * Same as ldns_status ldns_dnssec_verify_denial_nsec3 but also returns ++ * the nsec rr that matched. ++ * ++ * \param[in] rr The (query) RR to check the denial of existence for ++ * \param[in] nsecs The list of NSEC3 RRs that are supposed to deny the ++ * existence of the RR ++ * \param[in] rrsigs The RRSIG rr covering the NSEC RRs ++ * \param[in] packet_rcode The RCODE value of the packet that provided the ++ * NSEC3 RRs ++ * \param[in] packet_qtype The original query RR type ++ * \param[in] packet_nodata True if the providing packet had an empty ANSWER ++ * section ++ * \param[in] match On match, the given (reference to a) pointer will be set ++ * to point to the matching nsec resource record. ++ * \return LDNS_STATUS_OK if the NSEC3 RRs deny the existence, error code ++ * containing the reason they do not otherwise ++ */ ++ldns_status ldns_dnssec_verify_denial_nsec3_match(ldns_rr *rr, ++ ldns_rr_list *nsecs, ++ ldns_rr_list *rrsigs, ++ ldns_pkt_rcode packet_rcode, ++ ldns_rr_type packet_qtype, ++ bool packet_nodata, ++ ldns_rr **match); ++/** ++ * Verifies the already processed data in the buffers ++ * This function should probably not be used directly. ++ * ++ * \param[in] rawsig_buf Buffer containing signature data to use ++ * \param[in] verify_buf Buffer containing data to verify ++ * \param[in] key_buf Buffer containing key data to use ++ * \param[in] algo Signing algorithm ++ * \return status LDNS_STATUS_OK if the data verifies. Error if not. ++ */ ++ldns_status ldns_verify_rrsig_buffers(ldns_buffer *rawsig_buf, ++ ldns_buffer *verify_buf, ++ ldns_buffer *key_buf, ++ uint8_t algo); ++ ++/** ++ * Like ldns_verify_rrsig_buffers, but uses raw data. ++ * ++ * \param[in] sig signature data to use ++ * \param[in] siglen length of signature data to use ++ * \param[in] verify_buf Buffer containing data to verify ++ * \param[in] key key data to use ++ * \param[in] keylen length of key data to use ++ * \param[in] algo Signing algorithm ++ * \return status LDNS_STATUS_OK if the data verifies. Error if not. ++ */ ++ldns_status ldns_verify_rrsig_buffers_raw(unsigned char* sig, ++ size_t siglen, ++ ldns_buffer *verify_buf, ++ unsigned char* key, ++ size_t keylen, ++ uint8_t algo); ++ ++/** ++ * Verifies an rrsig. All keys in the keyset are tried. ++ * \param[in] rrset the rrset to check ++ * \param[in] rrsig the signature of the rrset ++ * \param[in] keys the keys to try ++ * \param[out] good_keys if this is a (initialized) list, the pointer to keys ++ * from keys that validate one of the signatures ++ * are added to it ++ * \return a list of keys which validate the rrsig + rrset. Returns ++ * status LDNS_STATUS_OK if at least one key matched. Else an error. ++ */ ++ldns_status ldns_verify_rrsig_keylist(ldns_rr_list *rrset, ++ ldns_rr *rrsig, ++ const ldns_rr_list *keys, ++ ldns_rr_list *good_keys); ++ ++/** ++ * Verifies an rrsig. All keys in the keyset are tried. ++ * \param[in] rrset the rrset to check ++ * \param[in] rrsig the signature of the rrset ++ * \param[in] keys the keys to try ++ * \param[in] check_time the time for which the validation is performed ++ * \param[out] good_keys if this is a (initialized) list, the pointer to keys ++ * from keys that validate one of the signatures ++ * are added to it ++ * \return a list of keys which validate the rrsig + rrset. Returns ++ * status LDNS_STATUS_OK if at least one key matched. Else an error. ++ */ ++ldns_status ldns_verify_rrsig_keylist_time( ++ ldns_rr_list *rrset, ldns_rr *rrsig, ++ const ldns_rr_list *keys, time_t check_time, ++ ldns_rr_list *good_keys); ++ ++ ++/** ++ * Verifies an rrsig. All keys in the keyset are tried. Time is not checked. ++ * \param[in] rrset the rrset to check ++ * \param[in] rrsig the signature of the rrset ++ * \param[in] keys the keys to try ++ * \param[out] good_keys if this is a (initialized) list, the pointer to keys ++ * from keys that validate one of the signatures ++ * are added to it ++ * \return a list of keys which validate the rrsig + rrset. Returns ++ * status LDNS_STATUS_OK if at least one key matched. Else an error. ++ */ ++ldns_status ldns_verify_rrsig_keylist_notime(ldns_rr_list *rrset, ++ ldns_rr *rrsig, ++ const ldns_rr_list *keys, ++ ldns_rr_list *good_keys); ++ ++/** ++ * verify an rrsig with 1 key ++ * \param[in] rrset the rrset ++ * \param[in] rrsig the rrsig to verify ++ * \param[in] key the key to use ++ * \return status message wether verification succeeded. ++ */ ++ldns_status ldns_verify_rrsig(ldns_rr_list *rrset, ++ ldns_rr *rrsig, ++ ldns_rr *key); ++ ++ ++/** ++ * verify an rrsig with 1 key ++ * \param[in] rrset the rrset ++ * \param[in] rrsig the rrsig to verify ++ * \param[in] key the key to use ++ * \param[in] check_time the time for which the validation is performed ++ * \return status message wether verification succeeded. ++ */ ++ldns_status ldns_verify_rrsig_time( ++ ldns_rr_list *rrset, ldns_rr *rrsig, ++ ldns_rr *key, time_t check_time); ++ ++ ++#if LDNS_BUILD_CONFIG_HAVE_SSL ++/** ++ * verifies a buffer with signature data for a buffer with rrset data ++ * with an EVP_PKEY ++ * ++ * \param[in] sig the signature data ++ * \param[in] rrset the rrset data, sorted and processed for verification ++ * \param[in] key the EVP key structure ++ * \param[in] digest_type The digest type of the signature ++ */ ++ldns_status ldns_verify_rrsig_evp(ldns_buffer *sig, ++ ldns_buffer *rrset, ++ EVP_PKEY *key, ++ const EVP_MD *digest_type); ++ ++/** ++ * Like ldns_verify_rrsig_evp, but uses raw signature data. ++ * \param[in] sig the signature data, wireformat uncompressed ++ * \param[in] siglen length of the signature data ++ * \param[in] rrset the rrset data, sorted and processed for verification ++ * \param[in] key the EVP key structure ++ * \param[in] digest_type The digest type of the signature ++ */ ++ldns_status ldns_verify_rrsig_evp_raw(unsigned char *sig, ++ size_t siglen, ++ ldns_buffer *rrset, ++ EVP_PKEY *key, ++ const EVP_MD *digest_type); ++#endif ++ ++/** ++ * verifies a buffer with signature data (DSA) for a buffer with rrset data ++ * with a buffer with key data. ++ * ++ * \param[in] sig the signature data ++ * \param[in] rrset the rrset data, sorted and processed for verification ++ * \param[in] key the key data ++ */ ++ldns_status ldns_verify_rrsig_dsa(ldns_buffer *sig, ++ ldns_buffer *rrset, ++ ldns_buffer *key); ++ ++/** ++ * verifies a buffer with signature data (RSASHA1) for a buffer with rrset data ++ * with a buffer with key data. ++ * ++ * \param[in] sig the signature data ++ * \param[in] rrset the rrset data, sorted and processed for verification ++ * \param[in] key the key data ++ */ ++ldns_status ldns_verify_rrsig_rsasha1(ldns_buffer *sig, ++ ldns_buffer *rrset, ++ ldns_buffer *key); ++ ++/** ++ * verifies a buffer with signature data (RSAMD5) for a buffer with rrset data ++ * with a buffer with key data. ++ * ++ * \param[in] sig the signature data ++ * \param[in] rrset the rrset data, sorted and processed for verification ++ * \param[in] key the key data ++ */ ++ldns_status ldns_verify_rrsig_rsamd5(ldns_buffer *sig, ++ ldns_buffer *rrset, ++ ldns_buffer *key); ++ ++/** ++ * Like ldns_verify_rrsig_dsa, but uses raw signature and key data. ++ * \param[in] sig raw uncompressed wireformat signature data ++ * \param[in] siglen length of signature data ++ * \param[in] rrset ldns buffer with prepared rrset data. ++ * \param[in] key raw uncompressed wireformat key data ++ * \param[in] keylen length of key data ++ */ ++ldns_status ldns_verify_rrsig_dsa_raw(unsigned char* sig, ++ size_t siglen, ++ ldns_buffer* rrset, ++ unsigned char* key, ++ size_t keylen); ++ ++/** ++ * Like ldns_verify_rrsig_rsasha1, but uses raw signature and key data. ++ * \param[in] sig raw uncompressed wireformat signature data ++ * \param[in] siglen length of signature data ++ * \param[in] rrset ldns buffer with prepared rrset data. ++ * \param[in] key raw uncompressed wireformat key data ++ * \param[in] keylen length of key data ++ */ ++ldns_status ldns_verify_rrsig_rsasha1_raw(unsigned char* sig, ++ size_t siglen, ++ ldns_buffer* rrset, ++ unsigned char* key, ++ size_t keylen); ++ ++/** ++ * Like ldns_verify_rrsig_rsasha256, but uses raw signature and key data. ++ * \param[in] sig raw uncompressed wireformat signature data ++ * \param[in] siglen length of signature data ++ * \param[in] rrset ldns buffer with prepared rrset data. ++ * \param[in] key raw uncompressed wireformat key data ++ * \param[in] keylen length of key data ++ */ ++ ++ldns_status ldns_verify_rrsig_rsasha256_raw(unsigned char* sig, ++ size_t siglen, ++ ldns_buffer* rrset, ++ unsigned char* key, ++ size_t keylen); ++ ++/** ++ * Like ldns_verify_rrsig_rsasha512, but uses raw signature and key data. ++ * \param[in] sig raw uncompressed wireformat signature data ++ * \param[in] siglen length of signature data ++ * \param[in] rrset ldns buffer with prepared rrset data. ++ * \param[in] key raw uncompressed wireformat key data ++ * \param[in] keylen length of key data ++ */ ++ldns_status ldns_verify_rrsig_rsasha512_raw(unsigned char* sig, ++ size_t siglen, ++ ldns_buffer* rrset, ++ unsigned char* key, ++ size_t keylen); ++ ++/** ++ * Like ldns_verify_rrsig_rsamd5, but uses raw signature and key data. ++ * \param[in] sig raw uncompressed wireformat signature data ++ * \param[in] siglen length of signature data ++ * \param[in] rrset ldns buffer with prepared rrset data. ++ * \param[in] key raw uncompressed wireformat key data ++ * \param[in] keylen length of key data ++ */ ++ldns_status ldns_verify_rrsig_rsamd5_raw(unsigned char* sig, ++ size_t siglen, ++ ldns_buffer* rrset, ++ unsigned char* key, ++ size_t keylen); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif ++ +diff --git a/ldns/include/ldns/dnssec_zone.h b/ldns/include/ldns/dnssec_zone.h +new file mode 100644 +index 0000000..b794f94 +--- /dev/null ++++ b/ldns/include/ldns/dnssec_zone.h +@@ -0,0 +1,483 @@ ++/* ++ * special zone file structures and functions for better dnssec handling ++ * ++ * A zone contains a SOA dnssec_zone_rrset, and an AVL tree of 'normal' ++ * dnssec_zone_rrsets, indexed by name and type ++ */ ++ ++#ifndef LDNS_DNSSEC_ZONE_H ++#define LDNS_DNSSEC_ZONE_H ++ ++#include <ldns/rbtree.h> ++#include <ldns/host2str.h> ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/** ++ * Singly linked list of rrs ++ */ ++typedef struct ldns_struct_dnssec_rrs ldns_dnssec_rrs; ++struct ldns_struct_dnssec_rrs ++{ ++ ldns_rr *rr; ++ ldns_dnssec_rrs *next; ++}; ++ ++/** ++ * Singly linked list of RRsets ++ */ ++typedef struct ldns_struct_dnssec_rrsets ldns_dnssec_rrsets; ++struct ldns_struct_dnssec_rrsets ++{ ++ ldns_dnssec_rrs *rrs; ++ ldns_rr_type type; ++ ldns_dnssec_rrs *signatures; ++ ldns_dnssec_rrsets *next; ++}; ++ ++/** ++ * Structure containing all resource records for a domain name ++ * Including the derived NSEC3, if present ++ */ ++typedef struct ldns_struct_dnssec_name ldns_dnssec_name; ++struct ldns_struct_dnssec_name ++{ ++ /** ++ * pointer to a dname containing the name. ++ * Usually points to the owner name of the first RR of the first RRset ++ */ ++ ldns_rdf *name; ++ /** ++ * Usually, the name is a pointer to the owner name of the first rr for ++ * this name, but sometimes there is no actual data to point to, ++ * for instance in ++ * names representing empty nonterminals. If so, set alloced to true to ++ * indicate that this data must also be freed when the name is freed ++ */ ++ bool name_alloced; ++ /** ++ * The rrsets for this name ++ */ ++ ldns_dnssec_rrsets *rrsets; ++ /** ++ * NSEC pointing to the next name (or NSEC3 pointing to the next NSEC3) ++ */ ++ ldns_rr *nsec; ++ /** ++ * signatures for the NSEC record ++ */ ++ ldns_dnssec_rrs *nsec_signatures; ++ /** ++ * Unlike what the name is_glue suggests, this field is set to true by ++ * ldns_dnssec_zone_mark_glue() or ldns_dnssec_zone_mark_and_get_glue() ++ * when the name, this dnssec_name struct represents, is occluded. ++ * Names that contain other occluded rrsets and records with glue on ++ * the delegation point will NOT have this bool set to true. ++ * This field should NOT be read directly, but only via the ++ * ldns_dnssec_name_is_glue() function! ++ */ ++ bool is_glue; ++ /** ++ * pointer to store the hashed name (only used when in an NSEC3 zone ++ */ ++ ldns_rdf *hashed_name; ++}; ++ ++/** ++ * Structure containing a dnssec zone ++ */ ++struct ldns_struct_dnssec_zone { ++ /** points to the name containing the SOA RR */ ++ ldns_dnssec_name *soa; ++ /** tree of ldns_dnssec_names */ ++ ldns_rbtree_t *names; ++ /** tree of ldns_dnssec_names by nsec3 hashes (when applicible) */ ++ ldns_rbtree_t *hashed_names; ++ /** points to the first added NSEC3 rr whose parameters will be ++ * assumed for all subsequent NSEC3 rr's and which will be used ++ * to calculate hashed names ++ */ ++ ldns_rr *_nsec3params; ++}; ++typedef struct ldns_struct_dnssec_zone ldns_dnssec_zone; ++ ++/** ++ * Creates a new entry for 1 pointer to an rr and 1 pointer to the next rrs ++ * \return the allocated data ++ */ ++ldns_dnssec_rrs *ldns_dnssec_rrs_new(void); ++ ++/** ++ * Frees the list of rrs, but *not* the individual ldns_rr records ++ * contained in the list ++ * ++ * \param[in] rrs the data structure to free ++ */ ++void ldns_dnssec_rrs_free(ldns_dnssec_rrs *rrs); ++ ++/** ++ * Frees the list of rrs, and the individual ldns_rr records ++ * contained in the list ++ * ++ * \param[in] rrs the data structure to free ++ */ ++void ldns_dnssec_rrs_deep_free(ldns_dnssec_rrs *rrs); ++ ++/** ++ * Adds an RR to the list of RRs. The list will remain ordered. ++ * If an equal RR already exists, this RR will not be added. ++ * ++ * \param[in] rrs the list to add to ++ * \param[in] rr the RR to add ++ * \return LDNS_STATUS_OK on success ++ */ ++ldns_status ldns_dnssec_rrs_add_rr(ldns_dnssec_rrs *rrs, ldns_rr *rr); ++ ++/** ++ * Prints the given rrs to the file descriptor ++ * ++ * \param[in] out the file descriptor to print to ++ * \param[in] rrs the list of RRs to print ++ */ ++void ldns_dnssec_rrs_print(FILE *out, ldns_dnssec_rrs *rrs); ++ ++/** ++ * Prints the given rrs to the file descriptor ++ * ++ * \param[in] out the file descriptor to print to ++ * \param[in] fmt the format of the textual representation ++ * \param[in] rrs the list of RRs to print ++ */ ++void ldns_dnssec_rrs_print_fmt(FILE *out, ++ const ldns_output_format *fmt, ldns_dnssec_rrs *rrs); ++ ++/** ++ * Creates a new list (entry) of RRsets ++ * \return the newly allocated structure ++ */ ++ldns_dnssec_rrsets *ldns_dnssec_rrsets_new(void); ++ ++/** ++ * Frees the list of rrsets and their rrs, but *not* the ldns_rr ++ * records in the sets ++ * ++ * \param[in] rrsets the data structure to free ++ */ ++void ldns_dnssec_rrsets_free(ldns_dnssec_rrsets *rrsets); ++ ++/** ++ * Frees the list of rrsets and their rrs, and the ldns_rr ++ * records in the sets ++ * ++ * \param[in] rrsets the data structure to free ++ */ ++void ldns_dnssec_rrsets_deep_free(ldns_dnssec_rrsets *rrsets); ++ ++/** ++ * Returns the rr type of the rrset (that is head of the given list) ++ * ++ * \param[in] rrsets the rrset to get the type of ++ * \return the rr type ++ */ ++ldns_rr_type ldns_dnssec_rrsets_type(ldns_dnssec_rrsets *rrsets); ++ ++/** ++ * Sets the RR type of the rrset (that is head of the given list) ++ * ++ * \param[in] rrsets the rrset to set the type of ++ * \param[in] type the type to set ++ * \return LDNS_STATUS_OK on success ++ */ ++ldns_status ldns_dnssec_rrsets_set_type(ldns_dnssec_rrsets *rrsets, ++ ldns_rr_type type); ++ ++/** ++ * Add an ldns_rr to the corresponding RRset in the given list of RRsets. ++ * If it is not present, add it as a new RRset with 1 record. ++ * ++ * \param[in] rrsets the list of rrsets to add the RR to ++ * \param[in] rr the rr to add to the list of rrsets ++ * \return LDNS_STATUS_OK on success ++ */ ++ldns_status ldns_dnssec_rrsets_add_rr(ldns_dnssec_rrsets *rrsets, ldns_rr *rr); ++ ++/** ++ * Print the given list of rrsets to the fiven file descriptor ++ * ++ * \param[in] out the file descriptor to print to ++ * \param[in] rrsets the list of RRsets to print ++ * \param[in] follow if set to false, only print the first RRset ++ */ ++void ldns_dnssec_rrsets_print(FILE *out, ++ ldns_dnssec_rrsets *rrsets, ++ bool follow); ++ ++/** ++ * Print the given list of rrsets to the fiven file descriptor ++ * ++ * \param[in] out the file descriptor to print to ++ * \param[in] fmt the format of the textual representation ++ * \param[in] rrsets the list of RRsets to print ++ * \param[in] follow if set to false, only print the first RRset ++ */ ++void ldns_dnssec_rrsets_print_fmt(FILE *out, ++ const ldns_output_format *fmt, ++ ldns_dnssec_rrsets *rrsets, ++ bool follow); ++ ++ ++/** ++ * Create a new data structure for a dnssec name ++ * \return the allocated structure ++ */ ++ldns_dnssec_name *ldns_dnssec_name_new(void); ++ ++/** ++ * Create a new data structure for a dnssec name for the given RR ++ * ++ * \param[in] rr the RR to derive properties from, and to add to the name ++ */ ++ldns_dnssec_name *ldns_dnssec_name_new_frm_rr(ldns_rr *rr); ++ ++/** ++ * Frees the name structure and its rrs and rrsets. ++ * Individual ldns_rr records therein are not freed ++ * ++ * \param[in] name the structure to free ++ */ ++void ldns_dnssec_name_free(ldns_dnssec_name *name); ++ ++/** ++ * Frees the name structure and its rrs and rrsets. ++ * Individual ldns_rr records contained in the name are also freed ++ * ++ * \param[in] name the structure to free ++ */ ++void ldns_dnssec_name_deep_free(ldns_dnssec_name *name); ++ ++/** ++ * Returns the domain name of the given dnssec_name structure ++ * ++ * \param[in] name the dnssec name to get the domain name from ++ * \return the domain name ++ */ ++ldns_rdf *ldns_dnssec_name_name(ldns_dnssec_name *name); ++ ++ ++/** ++ * Sets the domain name of the given dnssec_name structure ++ * ++ * \param[in] name the dnssec name to set the domain name of ++ * \param[in] dname the domain name to set it to. This data is *not* copied. ++ */ ++void ldns_dnssec_name_set_name(ldns_dnssec_name *name, ++ ldns_rdf *dname); ++/** ++ * Returns if dnssec_name structure is marked as glue. ++ * The ldns_dnssec_zone_mark_glue() function has to be called on a zone before ++ * using this function. ++ * Only names that have only glue rrsets will be marked. ++ * Names that have other occluded rrsets and names containing glue on the ++ * delegation point will NOT be marked! ++ * ++ * \param[in] name the dnssec name to get the domain name from ++ * \return true if the structure is marked as glue, false otherwise. ++ */ ++bool ldns_dnssec_name_is_glue(ldns_dnssec_name *name); ++ ++/** ++ * Sets the NSEC(3) RR of the given dnssec_name structure ++ * ++ * \param[in] name the dnssec name to set the domain name of ++ * \param[in] nsec the nsec rr to set it to. This data is *not* copied. ++ */ ++void ldns_dnssec_name_set_nsec(ldns_dnssec_name *name, ldns_rr *nsec); ++ ++/** ++ * Compares the domain names of the two arguments in their ++ * canonical ordening. ++ * ++ * \param[in] a The first dnssec_name to compare ++ * \param[in] b The second dnssec_name to compare ++ * \return -1 if the domain name of a comes before that of b in canonical ++ * ordening, 1 if it is the other way around, and 0 if they are ++ * equal ++ */ ++int ldns_dnssec_name_cmp(const void *a, const void *b); ++ ++/** ++ * Inserts the given rr at the right place in the current dnssec_name ++ * No checking is done whether the name matches ++ * ++ * \param[in] name The ldns_dnssec_name to add the RR to ++ * \param[in] rr The RR to add ++ * \return LDNS_STATUS_OK on success, error code otherwise ++ */ ++ldns_status ldns_dnssec_name_add_rr(ldns_dnssec_name *name, ++ ldns_rr *rr); ++ ++/** ++ * Find the RRset with the given type in within this name structure ++ * ++ * \param[in] name the name to find the RRset in ++ * \param[in] type the type of the RRset to find ++ * \return the RRset, or NULL if not present ++ */ ++ldns_dnssec_rrsets *ldns_dnssec_name_find_rrset(ldns_dnssec_name *name, ++ ldns_rr_type type); ++ ++/** ++ * Find the RRset with the given name and type in the zone ++ * ++ * \param[in] zone the zone structure to find the RRset in ++ * \param[in] dname the domain name of the RRset to find ++ * \param[in] type the type of the RRset to find ++ * \return the RRset, or NULL if not present ++ */ ++ldns_dnssec_rrsets *ldns_dnssec_zone_find_rrset(ldns_dnssec_zone *zone, ++ ldns_rdf *dname, ++ ldns_rr_type type); ++ ++/** ++ * Prints the RRs in the dnssec name structure to the given ++ * file descriptor ++ * ++ * \param[in] out the file descriptor to print to ++ * \param[in] name the name structure to print the contents of ++ */ ++void ldns_dnssec_name_print(FILE *out, ldns_dnssec_name *name); ++ ++/** ++ * Prints the RRs in the dnssec name structure to the given ++ * file descriptor ++ * ++ * \param[in] out the file descriptor to print to ++ * \param[in] fmt the format of the textual representation ++ * \param[in] name the name structure to print the contents of ++ */ ++void ldns_dnssec_name_print_fmt(FILE *out, ++ const ldns_output_format *fmt, ldns_dnssec_name *name); ++ ++/** ++ * Creates a new dnssec_zone structure ++ * \return the allocated structure ++ */ ++ldns_dnssec_zone *ldns_dnssec_zone_new(void); ++ ++/** ++ * Create a new dnssec zone from a file. ++ * \param[out] z the new zone ++ * \param[in] *fp the filepointer to use ++ * \param[in] *origin the zones' origin ++ * \param[in] c default class to use (IN) ++ * \param[in] ttl default ttl to use ++ * ++ * \return ldns_status mesg with an error or LDNS_STATUS_OK ++ */ ++ldns_status ldns_dnssec_zone_new_frm_fp(ldns_dnssec_zone** z, FILE* fp, ++ ldns_rdf* origin, uint32_t ttl, ldns_rr_class c); ++ ++/** ++ * Create a new dnssec zone from a file, keep track of the line numbering ++ * \param[out] z the new zone ++ * \param[in] *fp the filepointer to use ++ * \param[in] *origin the zones' origin ++ * \param[in] ttl default ttl to use ++ * \param[in] c default class to use (IN) ++ * \param[out] line_nr used for error msg, to get to the line number ++ * ++ * \return ldns_status mesg with an error or LDNS_STATUS_OK ++ */ ++ldns_status ldns_dnssec_zone_new_frm_fp_l(ldns_dnssec_zone** z, FILE* fp, ++ ldns_rdf* origin, uint32_t ttl, ldns_rr_class c, int* line_nr); ++ ++/** ++ * Frees the given zone structure, and its rbtree of dnssec_names ++ * Individual ldns_rr RRs within those names are *not* freed ++ * \param[in] *zone the zone to free ++ */ ++void ldns_dnssec_zone_free(ldns_dnssec_zone *zone); ++ ++/** ++ * Frees the given zone structure, and its rbtree of dnssec_names ++ * Individual ldns_rr RRs within those names are also freed ++ * \param[in] *zone the zone to free ++ */ ++void ldns_dnssec_zone_deep_free(ldns_dnssec_zone *zone); ++ ++/** ++ * Adds the given RR to the zone. ++ * It find whether there is a dnssec_name with that name present. ++ * If so, add it to that, if not create a new one. ++ * Special handling of NSEC and RRSIG provided ++ * ++ * \param[in] zone the zone to add the RR to ++ * \param[in] rr The RR to add ++ * \return LDNS_STATUS_OK on success, an error code otherwise ++ */ ++ldns_status ldns_dnssec_zone_add_rr(ldns_dnssec_zone *zone, ++ ldns_rr *rr); ++ ++/** ++ * Prints the rbtree of ldns_dnssec_name structures to the file descriptor ++ * ++ * \param[in] out the file descriptor to print the names to ++ * \param[in] tree the tree of ldns_dnssec_name structures to print ++ * \param[in] print_soa if true, print SOA records, if false, skip them ++ */ ++void ldns_dnssec_zone_names_print(FILE *out, ldns_rbtree_t *tree, bool print_soa); ++ ++/** ++ * Prints the rbtree of ldns_dnssec_name structures to the file descriptor ++ * ++ * \param[in] out the file descriptor to print the names to ++ * \param[in] fmt the format of the textual representation ++ * \param[in] tree the tree of ldns_dnssec_name structures to print ++ * \param[in] print_soa if true, print SOA records, if false, skip them ++ */ ++void ldns_dnssec_zone_names_print_fmt(FILE *out, const ldns_output_format *fmt, ++ ldns_rbtree_t *tree, bool print_soa); ++ ++/** ++ * Prints the complete zone to the given file descriptor ++ * ++ * \param[in] out the file descriptor to print to ++ * \param[in] zone the dnssec_zone to print ++ */ ++void ldns_dnssec_zone_print(FILE *out, ldns_dnssec_zone *zone); ++ ++/** ++ * Prints the complete zone to the given file descriptor ++ * ++ * \param[in] out the file descriptor to print to ++ * \param[in] fmt the format of the textual representation ++ * \param[in] zone the dnssec_zone to print ++ */ ++void ldns_dnssec_zone_print_fmt(FILE *out, ++ const ldns_output_format *fmt, ldns_dnssec_zone *zone); ++ ++/** ++ * Adds explicit dnssec_name structures for the empty nonterminals ++ * in this zone. (this is needed for NSEC3 generation) ++ * ++ * \param[in] zone the zone to check for empty nonterminals ++ * return LDNS_STATUS_OK on success. ++ */ ++ldns_status ldns_dnssec_zone_add_empty_nonterminals(ldns_dnssec_zone *zone); ++ ++/** ++ * If a NSEC3PARAM is available in the apex, walks the zone and returns true ++ * on the first optout nsec3. ++ * ++ * \param[in] zone the zone to check for nsec3 optout records ++ * return true when the zone has at least one nsec3 optout record. ++ */ ++bool ldns_dnssec_zone_is_nsec3_optout(ldns_dnssec_zone* zone); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif +diff --git a/ldns/include/ldns/duration.h b/ldns/include/ldns/duration.h +new file mode 100644 +index 0000000..f12edc4 +--- /dev/null ++++ b/ldns/include/ldns/duration.h +@@ -0,0 +1,109 @@ ++/* ++ * $Id: duration.h 4341 2011-01-31 15:21:09Z matthijs $ ++ * ++ * Copyright (c) 2009 NLNet Labs. All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR ++ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ++ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER ++ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR ++ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN ++ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ * ++ */ ++ ++/** ++ * ++ * This file is copied from the OpenDNSSEC source repository ++ * and only slightly adapted to make it fit. ++ */ ++ ++/** ++ * ++ * Durations. ++ */ ++ ++#ifndef LDNS_DURATION_H ++#define LDNS_DURATION_H ++ ++#include <stdint.h> ++#include <time.h> ++ ++/** ++ * Duration. ++ * ++ */ ++typedef struct ldns_duration_struct ldns_duration_type; ++struct ldns_duration_struct ++{ ++ time_t years; ++ time_t months; ++ time_t weeks; ++ time_t days; ++ time_t hours; ++ time_t minutes; ++ time_t seconds; ++}; ++ ++/** ++ * Create a new 'instant' duration. ++ * \return ldns_duration_type* created duration ++ * ++ */ ++ldns_duration_type* ldns_duration_create(void); ++ ++/** ++ * Compare durations. ++ * \param[in] d1 one duration ++ * \param[in] d2 another duration ++ * \return int 0 if equal, -1 if d1 < d2, 1 if d2 < d1 ++ * ++ */ ++int ldns_duration_compare(ldns_duration_type* d1, ldns_duration_type* d2); ++ ++/** ++ * Create a duration from string. ++ * \param[in] str string-format duration ++ * \return ldns_duration_type* created duration ++ * ++ */ ++ldns_duration_type* ldns_duration_create_from_string(const char* str); ++ ++/** ++ * Convert a duration to a string. ++ * \param[in] duration duration to be converted ++ * \return char* string-format duration ++ * ++ */ ++char* ldns_duration2string(ldns_duration_type* duration); ++ ++/** ++ * Convert a duration to a time. ++ * \param[in] duration duration to be converted ++ * \return time_t time-format duration ++ * ++ */ ++time_t ldns_duration2time(ldns_duration_type* duration); ++ ++/** ++ * Clean up duration. ++ * \param[in] duration duration to be cleaned up ++ * ++ */ ++void ldns_duration_cleanup(ldns_duration_type* duration); ++ ++#endif /* LDNS_DURATION_H */ +diff --git a/ldns/include/ldns/error.h b/ldns/include/ldns/error.h +new file mode 100644 +index 0000000..cc11958 +--- /dev/null ++++ b/ldns/include/ldns/error.h +@@ -0,0 +1,147 @@ ++/** ++ * \file error.h ++ * ++ * Defines error numbers and functions to translate those to a readable string. ++ * ++ */ ++ ++/** ++ * a Net::DNS like library for C ++ * ++ * (c) NLnet Labs, 2005-2006 ++ * ++ * See the file LICENSE for the license ++ */ ++ ++#ifndef LDNS_ERROR_H ++#define LDNS_ERROR_H ++ ++#include <ldns/util.h> ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++enum ldns_enum_status { ++ LDNS_STATUS_OK, ++ LDNS_STATUS_EMPTY_LABEL, ++ LDNS_STATUS_LABEL_OVERFLOW, ++ LDNS_STATUS_DOMAINNAME_OVERFLOW, ++ LDNS_STATUS_DOMAINNAME_UNDERFLOW, ++ LDNS_STATUS_DDD_OVERFLOW, ++ LDNS_STATUS_PACKET_OVERFLOW, ++ LDNS_STATUS_INVALID_POINTER, ++ LDNS_STATUS_MEM_ERR, ++ LDNS_STATUS_INTERNAL_ERR, ++ LDNS_STATUS_SSL_ERR, ++ LDNS_STATUS_ERR, ++ LDNS_STATUS_INVALID_INT, ++ LDNS_STATUS_INVALID_IP4, ++ LDNS_STATUS_INVALID_IP6, ++ LDNS_STATUS_INVALID_STR, ++ LDNS_STATUS_INVALID_B32_EXT, ++ LDNS_STATUS_INVALID_B64, ++ LDNS_STATUS_INVALID_HEX, ++ LDNS_STATUS_INVALID_TIME, ++ LDNS_STATUS_NETWORK_ERR, ++ LDNS_STATUS_ADDRESS_ERR, ++ LDNS_STATUS_FILE_ERR, ++ LDNS_STATUS_UNKNOWN_INET, ++ LDNS_STATUS_NOT_IMPL, ++ LDNS_STATUS_NULL, ++ LDNS_STATUS_CRYPTO_UNKNOWN_ALGO, ++ LDNS_STATUS_CRYPTO_ALGO_NOT_IMPL, ++ LDNS_STATUS_CRYPTO_NO_RRSIG, ++ LDNS_STATUS_CRYPTO_NO_DNSKEY, ++ LDNS_STATUS_CRYPTO_NO_TRUSTED_DNSKEY, ++ LDNS_STATUS_CRYPTO_NO_DS, ++ LDNS_STATUS_CRYPTO_NO_TRUSTED_DS, ++ LDNS_STATUS_CRYPTO_NO_MATCHING_KEYTAG_DNSKEY, ++ LDNS_STATUS_CRYPTO_VALIDATED, ++ LDNS_STATUS_CRYPTO_BOGUS, ++ LDNS_STATUS_CRYPTO_SIG_EXPIRED, ++ LDNS_STATUS_CRYPTO_SIG_NOT_INCEPTED, ++ LDNS_STATUS_CRYPTO_TSIG_BOGUS, ++ LDNS_STATUS_CRYPTO_TSIG_ERR, ++ LDNS_STATUS_CRYPTO_EXPIRATION_BEFORE_INCEPTION, ++ LDNS_STATUS_CRYPTO_TYPE_COVERED_ERR, ++ LDNS_STATUS_ENGINE_KEY_NOT_LOADED, ++ LDNS_STATUS_NSEC3_ERR, ++ LDNS_STATUS_RES_NO_NS, ++ LDNS_STATUS_RES_QUERY, ++ LDNS_STATUS_WIRE_INCOMPLETE_HEADER, ++ LDNS_STATUS_WIRE_INCOMPLETE_QUESTION, ++ LDNS_STATUS_WIRE_INCOMPLETE_ANSWER, ++ LDNS_STATUS_WIRE_INCOMPLETE_AUTHORITY, ++ LDNS_STATUS_WIRE_INCOMPLETE_ADDITIONAL, ++ LDNS_STATUS_NO_DATA, ++ LDNS_STATUS_CERT_BAD_ALGORITHM, ++ LDNS_STATUS_SYNTAX_TYPE_ERR, ++ LDNS_STATUS_SYNTAX_CLASS_ERR, ++ LDNS_STATUS_SYNTAX_TTL_ERR, ++ LDNS_STATUS_SYNTAX_INCLUDE_ERR_NOTIMPL, ++ LDNS_STATUS_SYNTAX_RDATA_ERR, ++ LDNS_STATUS_SYNTAX_DNAME_ERR, ++ LDNS_STATUS_SYNTAX_VERSION_ERR, ++ LDNS_STATUS_SYNTAX_ALG_ERR, ++ LDNS_STATUS_SYNTAX_KEYWORD_ERR, ++ LDNS_STATUS_SYNTAX_TTL, ++ LDNS_STATUS_SYNTAX_ORIGIN, ++ LDNS_STATUS_SYNTAX_INCLUDE, ++ LDNS_STATUS_SYNTAX_EMPTY, ++ LDNS_STATUS_SYNTAX_ITERATIONS_OVERFLOW, ++ LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR, ++ LDNS_STATUS_SYNTAX_INTEGER_OVERFLOW, ++ LDNS_STATUS_SYNTAX_BAD_ESCAPE, ++ LDNS_STATUS_SOCKET_ERROR, ++ LDNS_STATUS_SYNTAX_ERR, ++ LDNS_STATUS_DNSSEC_EXISTENCE_DENIED, ++ LDNS_STATUS_DNSSEC_NSEC_RR_NOT_COVERED, ++ LDNS_STATUS_DNSSEC_NSEC_WILDCARD_NOT_COVERED, ++ LDNS_STATUS_DNSSEC_NSEC3_ORIGINAL_NOT_FOUND, ++ LDNS_STATUS_MISSING_RDATA_FIELDS_RRSIG, ++ LDNS_STATUS_MISSING_RDATA_FIELDS_KEY, ++ LDNS_STATUS_CRYPTO_SIG_EXPIRED_WITHIN_MARGIN, ++ LDNS_STATUS_CRYPTO_SIG_NOT_INCEPTED_WITHIN_MARGIN, ++ LDNS_STATUS_DANE_STATUS_MESSAGES, ++ LDNS_STATUS_DANE_UNKNOWN_CERTIFICATE_USAGE, ++ LDNS_STATUS_DANE_UNKNOWN_SELECTOR, ++ LDNS_STATUS_DANE_UNKNOWN_MATCHING_TYPE, ++ LDNS_STATUS_DANE_UNKNOWN_PROTOCOL, ++ LDNS_STATUS_DANE_UNKNOWN_TRANSPORT, ++ LDNS_STATUS_DANE_MISSING_EXTRA_CERTS, ++ LDNS_STATUS_DANE_EXTRA_CERTS_NOT_USED, ++ LDNS_STATUS_DANE_OFFSET_OUT_OF_RANGE, ++ LDNS_STATUS_DANE_INSECURE, ++ LDNS_STATUS_DANE_BOGUS, ++ LDNS_STATUS_DANE_TLSA_DID_NOT_MATCH, ++ LDNS_STATUS_DANE_NON_CA_CERTIFICATE, ++ LDNS_STATUS_DANE_PKIX_DID_NOT_VALIDATE, ++ LDNS_STATUS_DANE_PKIX_NO_SELF_SIGNED_TRUST_ANCHOR, ++ LDNS_STATUS_EXISTS_ERR, ++ LDNS_STATUS_INVALID_ILNP64, ++ LDNS_STATUS_INVALID_EUI48, ++ LDNS_STATUS_INVALID_EUI64, ++ LDNS_STATUS_WIRE_RDATA_ERR, ++ LDNS_STATUS_INVALID_TAG, ++ LDNS_STATUS_TYPE_NOT_IN_BITMAP, ++ LDNS_STATUS_INVALID_RDF_TYPE, ++ LDNS_STATUS_RDATA_OVERFLOW ++}; ++typedef enum ldns_enum_status ldns_status; ++ ++extern ldns_lookup_table ldns_error_str[]; ++ ++/** ++ * look up a descriptive text by each error. This function ++ * could use a better name ++ * \param[in] err ldns_status number ++ * \return the string for that error ++ */ ++const char *ldns_get_errorstr_by_id(ldns_status err); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* LDNS_ERROR_H */ +diff --git a/ldns/include/ldns/higher.h b/ldns/include/ldns/higher.h +new file mode 100644 +index 0000000..597e134 +--- /dev/null ++++ b/ldns/include/ldns/higher.h +@@ -0,0 +1,113 @@ ++/** ++ * \file higher.h ++ * ++ * Specifies some higher level functions that could ++ * be useful for certain applications ++ */ ++ ++/* ++ * a Net::DNS like library for C ++ * ++ * (c) NLnet Labs, 2005-2006 ++ * ++ * See the file LICENSE for the license ++ */ ++ ++#ifndef LDNS_HIGHER_H ++#define LDNS_HIGHER_H ++ ++#include <ldns/resolver.h> ++#include <ldns/rdata.h> ++#include <ldns/rr.h> ++#include <ldns/host2str.h> ++#include <ldns/tsig.h> ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/** ++ * Ask the resolver about name ++ * and return all address records ++ * \param[in] r the resolver to use ++ * \param[in] name the name to look for ++ * \param[in] c the class to use ++ * \param[in] flags give some optional flags to the query ++ */ ++ldns_rr_list *ldns_get_rr_list_addr_by_name(ldns_resolver *r, ldns_rdf *name, ldns_rr_class c, uint16_t flags); ++ ++/** ++ * ask the resolver about the address ++ * and return the name ++ * \param[in] r the resolver to use ++ * \param[in] addr the addr to look for ++ * \param[in] c the class to use ++ * \param[in] flags give some optional flags to the query ++ */ ++ldns_rr_list *ldns_get_rr_list_name_by_addr(ldns_resolver *r, ldns_rdf *addr, ldns_rr_class c, uint16_t flags); ++ ++/** ++ * wade through fp (a /etc/hosts like file) ++ * and return a rr_list containing all the ++ * defined hosts in there ++ * \param[in] fp the file pointer to use ++ * \return ldns_rr_list * with the names ++ */ ++ldns_rr_list *ldns_get_rr_list_hosts_frm_fp(FILE *fp); ++ ++/** ++ * wade through fp (a /etc/hosts like file) ++ * and return a rr_list containing all the ++ * defined hosts in there ++ * \param[in] fp the file pointer to use ++ * \param[in] line_nr pointer to an integer containing the current line number (for debugging purposes) ++ * \return ldns_rr_list * with the names ++ */ ++ldns_rr_list *ldns_get_rr_list_hosts_frm_fp_l(FILE *fp, int *line_nr); ++ ++/** ++ * wade through fp (a /etc/hosts like file) ++ * and return a rr_list containing all the ++ * defined hosts in there ++ * \param[in] filename the filename to use (NULL for /etc/hosts) ++ * \return ldns_rr_list * with the names ++ */ ++ldns_rr_list *ldns_get_rr_list_hosts_frm_file(char *filename); ++ ++/** ++ * This function is a wrapper function for ldns_get_rr_list_name_by_addr ++ * and ldns_get_rr_list_addr_by_name. It's name is from the getaddrinfo() ++ * library call. It tries to mimic that call, but without the lowlevel ++ * stuff. ++ * \param[in] res The resolver. If this value is NULL then a resolver will ++ * be created by ldns_getaddrinfo. ++ * \param[in] node the name or ip address to look up ++ * \param[in] c the class to look in ++ * \param[out] list put the found RR's in this list ++ * \return the number of RR found. ++ */ ++uint16_t ldns_getaddrinfo(ldns_resolver *res, ldns_rdf *node, ldns_rr_class c, ldns_rr_list **list); ++ ++/** ++ * Check if t is enumerated in the nsec type rdata ++ * \param[in] nsec the NSEC Record to look in ++ * \param[in] t the type to check for ++ * \return true when t is found, otherwise return false ++ */ ++bool ldns_nsec_type_check(ldns_rr *nsec, ldns_rr_type t); ++ ++/** ++ * Print a number of rdf's of the RR. The rdfnum-list must ++ * be ended by -1, otherwise unpredictable things might happen. ++ * rdfs may be printed multiple times ++ * \param[in] fp FILE * to write to ++ * \param[in] r RR to write ++ * \param[in] rdfnum a list of rdf to print. ++ */ ++void ldns_print_rr_rdf(FILE *fp, ldns_rr *r, int rdfnum, ...); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* LDNS_HIGHER_H */ +diff --git a/ldns/include/ldns/host2str.h b/ldns/include/ldns/host2str.h +new file mode 100644 +index 0000000..e69389e +--- /dev/null ++++ b/ldns/include/ldns/host2str.h +@@ -0,0 +1,891 @@ ++/** ++ * host2str.h - txt presentation of RRs ++ * ++ * a Net::DNS like library for C ++ * ++ * (c) NLnet Labs, 2005-2006 ++ * ++ * See the file LICENSE for the license ++ */ ++ ++/** ++ * \file ++ * ++ * Contains functions to translate the main structures to their text ++ * representation, as well as functions to print them. ++ */ ++ ++#ifndef LDNS_HOST2STR_H ++#define LDNS_HOST2STR_H ++ ++#include <ldns/common.h> ++#include <ldns/error.h> ++#include <ldns/rr.h> ++#include <ldns/rdata.h> ++#include <ldns/packet.h> ++#include <ldns/buffer.h> ++#include <ldns/resolver.h> ++#include <ldns/zone.h> ++#include <ctype.h> ++ ++#include "ldns/util.h" ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#define LDNS_APL_IP4 1 ++#define LDNS_APL_IP6 2 ++#define LDNS_APL_MASK 0x7f ++#define LDNS_APL_NEGATION 0x80 ++ ++/** ++ * Represent a NULL pointer (instead of a pointer to a ldns_rr as "; (null)" ++ * as opposed to outputting nothing at all in such a case. ++ */ ++/* Flag Name Flag Nr. Has data associated ++ ---------------------------------------------------------------------*/ ++#define LDNS_COMMENT_NULLS (1 << 0) ++/** Show key id with DNSKEY RR's as comment */ ++#define LDNS_COMMENT_KEY_ID (1 << 1) ++/** Show if a DNSKEY is a ZSK or KSK as comment */ ++#define LDNS_COMMENT_KEY_TYPE (1 << 2) ++/** Show DNSKEY key size as comment */ ++#define LDNS_COMMENT_KEY_SIZE (1 << 3) ++/** Provide bubblebabble representation for DS RR's as comment */ ++#define LDNS_COMMENT_BUBBLEBABBLE (1 << 4) ++/** Show when a NSEC3 RR has the optout flag set as comment */ ++#define LDNS_COMMENT_FLAGS (1 << 5) ++/** Show the unhashed owner and next owner names for NSEC3 RR's as comment */ ++#define LDNS_COMMENT_NSEC3_CHAIN (1 << 6) /* yes */ ++/** Print mark up */ ++#define LDNS_COMMENT_LAYOUT (1 << 7) ++/** Also comment KEY_ID with RRSIGS **/ ++#define LDNS_COMMENT_RRSIGS (1 << 8) ++#define LDNS_FMT_ZEROIZE_RRSIGS (1 << 9) ++#define LDNS_FMT_PAD_SOA_SERIAL (1 << 10) ++#define LDNS_FMT_RFC3597 (1 << 11) /* yes */ ++ ++#define LDNS_FMT_FLAGS_WITH_DATA 2 ++ ++/** Show key id, type and size as comment for DNSKEY RR's */ ++#define LDNS_COMMENT_KEY (LDNS_COMMENT_KEY_ID \ ++ |LDNS_COMMENT_KEY_TYPE\ ++ |LDNS_COMMENT_KEY_SIZE) ++ ++/** ++ * Output format specifier ++ * ++ * Determines how Packets, Resource Records and Resource record data fiels are ++ * formatted when printing or converting to string. ++ * Currently it is only used to specify what aspects of a Resource Record are ++ * annotated in the comment section of the textual representation the record. ++ * This is speciefed with flags and potential exra data (such as for example ++ * a lookup map of hashes to real names for annotation NSEC3 records). ++ */ ++struct ldns_struct_output_format ++{ ++ /** Specification of how RR's should be formatted in text */ ++ int flags; ++ /** Potential extra data to be used with formatting RR's in text */ ++ void *data; ++}; ++typedef struct ldns_struct_output_format ldns_output_format; ++ ++/** ++ * Output format struct with additional data for flags that use them. ++ * This struct may not be initialized directly. Use ldns_output_format_init ++ * to initialize. ++ */ ++struct ldns_struct_output_format_storage ++{ int flags; ++ ldns_rbtree_t* hashmap; /* for LDNS_COMMENT_NSEC3_CHAIN */ ++ ldns_rdf* bitmap; /* for LDNS_FMT_RFC3597 */ ++}; ++typedef struct ldns_struct_output_format_storage ldns_output_format_storage; ++ ++/** ++ * Standard output format record that disables commenting in the textual ++ * representation of Resource Records completely. ++ */ ++extern const ldns_output_format *ldns_output_format_nocomments; ++/** ++ * Standard output format record that annotated only DNSKEY RR's with commenti ++ * text. ++ */ ++extern const ldns_output_format *ldns_output_format_onlykeyids; ++/** ++ * The default output format record. Same as ldns_output_format_onlykeyids. ++ */ ++extern const ldns_output_format *ldns_output_format_default; ++/** ++ * Standard output format record that shows all DNSKEY related information in ++ * the comment text, plus the optout flag when set with NSEC3's, plus the ++ * bubblebabble representation of DS RR's. ++ */ ++extern const ldns_output_format *ldns_output_format_bubblebabble; ++ ++/** ++ * Initialize output format storage to the default value. ++ * \param[in] fmt A reference to an output_format_ storage struct ++ * \return The initialized storage struct typecasted to ldns_output_format ++ */ ++INLINE ++ldns_output_format* ldns_output_format_init(ldns_output_format_storage* fmt) { ++ fmt->flags = ldns_output_format_default->flags; ++ fmt->hashmap = NULL; ++ fmt->bitmap = NULL; ++ return (ldns_output_format*)fmt; ++} ++ ++/** ++ * Set an ouput format flag. ++ */ ++INLINE void ldns_output_format_set(ldns_output_format* fmt, int flag) { ++ fmt->flags |= flag; ++} ++ ++/** ++ * Clear an ouput format flag. ++ */ ++INLINE void ldns_output_format_clear(ldns_output_format* fmt, int flag) { ++ fmt->flags &= !flag; ++} ++ ++/** ++ * Makes sure the LDNS_FMT_RFC3597 is set in the output format. ++ * Marks the type to be printed in RFC3597 format. ++ * /param[in] fmt the output format to update ++ * /param[in] the type to be printed in RFC3597 format ++ * /return LDNS_STATUS_OK on success ++ */ ++ldns_status ++ldns_output_format_set_type(ldns_output_format* fmt, ldns_rr_type type); ++ ++/** ++ * Makes sure the LDNS_FMT_RFC3597 is set in the output format. ++ * Marks the type to not be printed in RFC3597 format. When no other types ++ * have been marked before, all known types (except the given one) will be ++ * marked for printing in RFC3597 format. ++ * /param[in] fmt the output format to update ++ * /param[in] the type not to be printed in RFC3597 format ++ * /return LDNS_STATUS_OK on success ++ */ ++ldns_status ++ldns_output_format_clear_type(ldns_output_format* fmt, ldns_rr_type type); ++ ++/** ++ * Converts an ldns packet opcode value to its mnemonic, and adds that ++ * to the output buffer ++ * \param[in] *output the buffer to add the data to ++ * \param[in] opcode to find the string representation of ++ * \return LDNS_STATUS_OK on success, or a buffer failure mode on error ++ */ ++ldns_status ++ldns_pkt_opcode2buffer_str(ldns_buffer *output, ldns_pkt_opcode opcode); ++ ++/** ++ * Converts an ldns packet rcode value to its mnemonic, and adds that ++ * to the output buffer ++ * \param[in] *output the buffer to add the data to ++ * \param[in] rcode to find the string representation of ++ * \return LDNS_STATUS_OK on success, or a buffer failure mode on error ++ */ ++ldns_status ++ldns_pkt_rcode2buffer_str(ldns_buffer *output, ldns_pkt_rcode rcode); ++ ++/** ++ * Converts an ldns algorithm type to its mnemonic, and adds that ++ * to the output buffer ++ * \param[in] *output the buffer to add the data to ++ * \param[in] algorithm to find the string representation of ++ * \return LDNS_STATUS_OK on success, or a buffer failure mode on error ++ */ ++ldns_status ++ldns_algorithm2buffer_str(ldns_buffer *output, ++ ldns_algorithm algorithm); ++ ++/** ++ * Converts an ldns certificate algorithm type to its mnemonic, ++ * and adds that to the output buffer ++ * \param[in] *output the buffer to add the data to ++ * \param[in] cert_algorithm to find the string representation of ++ * \return LDNS_STATUS_OK on success, or a buffer failure mode on error ++ */ ++ldns_status ++ldns_cert_algorithm2buffer_str(ldns_buffer *output, ++ ldns_cert_algorithm cert_algorithm); ++ ++ ++/** ++ * Converts a packet opcode to its mnemonic and returns that as ++ * an allocated null-terminated string. ++ * Remember to free it. ++ * ++ * \param[in] opcode the opcode to convert to text ++ * \return null terminated char * data, or NULL on error ++ */ ++char *ldns_pkt_opcode2str(ldns_pkt_opcode opcode); ++ ++/** ++ * Converts a packet rcode to its mnemonic and returns that as ++ * an allocated null-terminated string. ++ * Remember to free it. ++ * ++ * \param[in] rcode the rcode to convert to text ++ * \return null terminated char * data, or NULL on error ++ */ ++char *ldns_pkt_rcode2str(ldns_pkt_rcode rcode); ++ ++/** ++ * Converts a signing algorithms to its mnemonic and returns that as ++ * an allocated null-terminated string. ++ * Remember to free it. ++ * ++ * \param[in] algorithm the algorithm to convert to text ++ * \return null terminated char * data, or NULL on error ++ */ ++char *ldns_pkt_algorithm2str(ldns_algorithm algorithm); ++ ++/** ++ * Converts a cert algorithm to its mnemonic and returns that as ++ * an allocated null-terminated string. ++ * Remember to free it. ++ * ++ * \param[in] cert_algorithm to convert to text ++ * \return null terminated char * data, or NULL on error ++ */ ++char *ldns_pkt_cert_algorithm2str(ldns_cert_algorithm cert_algorithm); ++ ++/** ++ * Converts an LDNS_RDF_TYPE_A rdata element to string format and adds it to the output buffer ++ * \param[in] *rdf The rdata to convert ++ * \param[in] *output The buffer to add the data to ++ * \return LDNS_STATUS_OK on success, and error status on failure ++ */ ++ldns_status ldns_rdf2buffer_str_a(ldns_buffer *output, const ldns_rdf *rdf); ++ ++/** ++ * Converts an LDNS_RDF_TYPE_AAAA rdata element to string format and adds it to the output buffer ++ * \param[in] *rdf The rdata to convert ++ * \param[in] *output The buffer to add the data to ++ * \return LDNS_STATUS_OK on success, and error status on failure ++ */ ++ldns_status ldns_rdf2buffer_str_aaaa(ldns_buffer *output, const ldns_rdf *rdf); ++ ++/** ++ * Converts an LDNS_RDF_TYPE_STR rdata element to string format and adds it to the output buffer ++ * \param[in] *rdf The rdata to convert ++ * \param[in] *output The buffer to add the data to ++ * \return LDNS_STATUS_OK on success, and error status on failure ++ */ ++ldns_status ldns_rdf2buffer_str_str(ldns_buffer *output, const ldns_rdf *rdf); ++ ++/** ++ * Converts an LDNS_RDF_TYPE_B64 rdata element to string format and adds it to the output buffer ++ * \param[in] *rdf The rdata to convert ++ * \param[in] *output The buffer to add the data to ++ * \return LDNS_STATUS_OK on success, and error status on failure ++ */ ++ldns_status ldns_rdf2buffer_str_b64(ldns_buffer *output, const ldns_rdf *rdf); ++ ++/** ++ * Converts an LDNS_RDF_TYPE_B32_EXT rdata element to string format and adds it to the output buffer ++ * \param[in] *rdf The rdata to convert ++ * \param[in] *output The buffer to add the data to ++ * \return LDNS_STATUS_OK on success, and error status on failure ++ */ ++ldns_status ldns_rdf2buffer_str_b32_ext(ldns_buffer *output, const ldns_rdf *rdf); ++ ++/** ++ * Converts an LDNS_RDF_TYPE_HEX rdata element to string format and adds it to the output buffer ++ * \param[in] *rdf The rdata to convert ++ * \param[in] *output The buffer to add the data to ++ * \return LDNS_STATUS_OK on success, and error status on failure ++ */ ++ldns_status ldns_rdf2buffer_str_hex(ldns_buffer *output, const ldns_rdf *rdf); ++ ++/** ++ * Converts an LDNS_RDF_TYPE_TYPE rdata element to string format and adds it to the output buffer ++ * \param[in] *rdf The rdata to convert ++ * \param[in] *output The buffer to add the data to ++ * \return LDNS_STATUS_OK on success, and error status on failure ++ */ ++ldns_status ldns_rdf2buffer_str_type(ldns_buffer *output, const ldns_rdf *rdf); ++ ++/** ++ * Converts an LDNS_RDF_TYPE_CLASS rdata element to string format and adds it to the output buffer ++ * \param[in] *rdf The rdata to convert ++ * \param[in] *output The buffer to add the data to ++ * \return LDNS_STATUS_OK on success, and error status on failure ++ */ ++ldns_status ldns_rdf2buffer_str_class(ldns_buffer *output, const ldns_rdf *rdf); ++ ++/** ++ * Converts an LDNS_RDF_TYPE_ALG rdata element to string format and adds it to the output buffer ++ * \param[in] *rdf The rdata to convert ++ * \param[in] *output The buffer to add the data to ++ * \return LDNS_STATUS_OK on success, and error status on failure ++ */ ++ldns_status ldns_rdf2buffer_str_alg(ldns_buffer *output, const ldns_rdf *rdf); ++ ++/** ++ * Converts an ldns_rr_type value to its string representation, ++ * and places it in the given buffer ++ * \param[in] *output The buffer to add the data to ++ * \param[in] type the ldns_rr_type to convert ++ * \return LDNS_STATUS_OK on success, and error status on failure ++ */ ++ldns_status ldns_rr_type2buffer_str(ldns_buffer *output, ++ const ldns_rr_type type); ++ ++/** ++ * Converts an ldns_rr_type value to its string representation, ++ * and returns that string. For unknown types, the string ++ * "TYPE<id>" is returned. This function allocates data that must be ++ * freed by the caller ++ * \param[in] type the ldns_rr_type to convert ++ * \return a newly allocated string ++ */ ++char *ldns_rr_type2str(const ldns_rr_type type); ++ ++/** ++ * Converts an ldns_rr_class value to its string representation, ++ * and places it in the given buffer ++ * \param[in] *output The buffer to add the data to ++ * \param[in] klass the ldns_rr_class to convert ++ * \return LDNS_STATUS_OK on success, and error status on failure ++ */ ++ldns_status ldns_rr_class2buffer_str(ldns_buffer *output, ++ const ldns_rr_class klass); ++ ++/** ++ * Converts an ldns_rr_class value to its string representation, ++ * and returns that string. For unknown types, the string ++ * "CLASS<id>" is returned. This function allocates data that must be ++ * freed by the caller ++ * \param[in] klass the ldns_rr_class to convert ++ * \return a newly allocated string ++ */ ++char *ldns_rr_class2str(const ldns_rr_class klass); ++ ++ ++/** ++ * Converts an LDNS_RDF_TYPE_CERT rdata element to string format and adds it to the output buffer ++ * \param[in] *rdf The rdata to convert ++ * \param[in] *output The buffer to add the data to ++ * \return LDNS_STATUS_OK on success, and error status on failure ++ */ ++ldns_status ldns_rdf2buffer_str_cert_alg(ldns_buffer *output, const ldns_rdf *rdf); ++ ++/** ++ * Converts an LDNS_RDF_TYPE_LOC rdata element to string format and adds it to the output buffer ++ * \param[in] *rdf The rdata to convert ++ * \param[in] *output The buffer to add the data to ++ * \return LDNS_STATUS_OK on success, and error status on failure ++ */ ++ldns_status ldns_rdf2buffer_str_loc(ldns_buffer *output, const ldns_rdf *rdf); ++ ++/** ++ * Converts an LDNS_RDF_TYPE_UNKNOWN rdata element to string format and adds it to the output buffer ++ * \param[in] *rdf The rdata to convert ++ * \param[in] *output The buffer to add the data to ++ * \return LDNS_STATUS_OK on success, and error status on failure ++ */ ++ldns_status ldns_rdf2buffer_str_unknown(ldns_buffer *output, const ldns_rdf *rdf); ++ ++/** ++ * Converts an LDNS_RDF_TYPE_NSAP rdata element to string format and adds it to the output buffer ++ * \param[in] *rdf The rdata to convert ++ * \param[in] *output The buffer to add the data to ++ * \return LDNS_STATUS_OK on success, and error status on failure ++ */ ++ldns_status ldns_rdf2buffer_str_nsap(ldns_buffer *output, const ldns_rdf *rdf); ++ ++/** ++ * Converts an LDNS_RDF_TYPE_ATMA rdata element to string format and adds it to the output buffer ++ * \param[in] *rdf The rdata to convert ++ * \param[in] *output The buffer to add the data to ++ * \return LDNS_STATUS_OK on success, and error status on failure ++ */ ++ldns_status ldns_rdf2buffer_str_atma(ldns_buffer *output, const ldns_rdf *rdf); ++ ++/** ++ * Converts an LDNS_RDF_TYPE_WKS rdata element to string format and adds it to the output buffer ++ * \param[in] *rdf The rdata to convert ++ * \param[in] *output The buffer to add the data to ++ * \return LDNS_STATUS_OK on success, and error status on failure ++ */ ++ldns_status ldns_rdf2buffer_str_wks(ldns_buffer *output, const ldns_rdf *rdf); ++ ++/** ++ * Converts an LDNS_RDF_TYPE_NSEC rdata element to string format and adds it to the output buffer ++ * \param[in] *rdf The rdata to convert ++ * \param[in] *output The buffer to add the data to ++ * \return LDNS_STATUS_OK on success, and error status on failure ++ */ ++ldns_status ldns_rdf2buffer_str_nsec(ldns_buffer *output, const ldns_rdf *rdf); ++ ++/** ++ * Converts an LDNS_RDF_TYPE_PERIOD rdata element to string format and adds it to the output buffer ++ * \param[in] *rdf The rdata to convert ++ * \param[in] *output The buffer to add the data to ++ * \return LDNS_STATUS_OK on success, and error status on failure ++ */ ++ldns_status ldns_rdf2buffer_str_period(ldns_buffer *output, const ldns_rdf *rdf); ++ ++/** ++ * Converts an LDNS_RDF_TYPE_TSIGTIME rdata element to string format and adds it to the output buffer ++ * \param[in] *rdf The rdata to convert ++ * \param[in] *output The buffer to add the data to ++ * \return LDNS_STATUS_OK on success, and error status on failure ++ */ ++ldns_status ldns_rdf2buffer_str_tsigtime(ldns_buffer *output, const ldns_rdf *rdf); ++ ++/** ++ * Converts an LDNS_RDF_TYPE_APL rdata element to string format and adds it to the output buffer ++ * \param[in] *rdf The rdata to convert ++ * \param[in] *output The buffer to add the data to ++ * \return LDNS_STATUS_OK on success, and error status on failure ++ */ ++ldns_status ldns_rdf2buffer_str_apl(ldns_buffer *output, const ldns_rdf *rdf); ++ ++/** ++ * Converts an LDNS_RDF_TYPE_INT16_DATA rdata element to string format and adds it to the output buffer ++ * \param[in] *rdf The rdata to convert ++ * \param[in] *output The buffer to add the data to ++ * \return LDNS_STATUS_OK on success, and error status on failure ++ */ ++ldns_status ldns_rdf2buffer_str_int16_data(ldns_buffer *output, const ldns_rdf *rdf); ++ ++/** ++ * Converts an LDNS_RDF_TYPE_IPSECKEY rdata element to string format and adds it to the output buffer ++ * \param[in] *rdf The rdata to convert ++ * \param[in] *output The buffer to add the data to ++ * \return LDNS_STATUS_OK on success, and error status on failure ++ */ ++ldns_status ldns_rdf2buffer_str_ipseckey(ldns_buffer *output, const ldns_rdf *rdf); ++ ++/** ++ * Converts the data in the rdata field to presentation ++ * format (as char *) and appends it to the given buffer ++ * ++ * \param[in] output pointer to the buffer to append the data to ++ * \param[in] rdf the pointer to the rdafa field containing the data ++ * \return status ++ */ ++ldns_status ldns_rdf2buffer_str(ldns_buffer *output, const ldns_rdf *rdf); ++ ++/** ++ * Converts the data in the resource record to presentation ++ * format (as char *) and appends it to the given buffer. ++ * The presentation format of DNSKEY record is annotated with comments giving ++ * the id, type and size of the key. ++ * ++ * \param[in] output pointer to the buffer to append the data to ++ * \param[in] rr the pointer to the rr field to convert ++ * \return status ++ */ ++ldns_status ldns_rr2buffer_str(ldns_buffer *output, const ldns_rr *rr); ++ ++/** ++ * Converts the data in the resource record to presentation ++ * format (as char *) and appends it to the given buffer. ++ * The presentation format is annotated with comments giving ++ * additional information on the record. ++ * ++ * \param[in] output pointer to the buffer to append the data to ++ * \param[in] fmt how to format the textual representation of the ++ * resource record. ++ * \param[in] rr the pointer to the rr field to convert ++ * \return status ++ */ ++ldns_status ldns_rr2buffer_str_fmt(ldns_buffer *output, ++ const ldns_output_format *fmt, const ldns_rr *rr); ++ ++/** ++ * Converts the data in the DNS packet to presentation ++ * format (as char *) and appends it to the given buffer ++ * ++ * \param[in] output pointer to the buffer to append the data to ++ * \param[in] pkt the pointer to the packet to convert ++ * \return status ++ */ ++ldns_status ldns_pkt2buffer_str(ldns_buffer *output, const ldns_pkt *pkt); ++ ++/** ++ * Converts the data in the DNS packet to presentation ++ * format (as char *) and appends it to the given buffer ++ * ++ * \param[in] output pointer to the buffer to append the data to ++ * \param[in] fmt how to format the textual representation of the packet ++ * \param[in] pkt the pointer to the packet to convert ++ * \return status ++ */ ++ldns_status ldns_pkt2buffer_str_fmt(ldns_buffer *output, ++ const ldns_output_format *fmt, const ldns_pkt *pkt); ++ ++/** ++ * Converts an LDNS_RDF_TYPE_NSEC3_SALT rdata element to string format and adds it to the output buffer ++ * \param[in] *rdf The rdata to convert ++ * \param[in] *output The buffer to add the data to ++ * \return LDNS_STATUS_OK on success, and error status on failure ++ */ ++ldns_status ldns_rdf2buffer_str_nsec3_salt(ldns_buffer *output, const ldns_rdf *rdf); ++ ++ ++/** ++ * Converts the data in the DNS packet to presentation ++ * format (as char *) and appends it to the given buffer ++ * ++ * \param[in] output pointer to the buffer to append the data to ++ * \param[in] k the pointer to the private key to convert ++ * \return status ++ */ ++ldns_status ldns_key2buffer_str(ldns_buffer *output, const ldns_key *k); ++ ++/** ++ * Converts an LDNS_RDF_TYPE_INT8 rdata element to string format and adds it to the output buffer ++ * \param[in] *rdf The rdata to convert ++ * \param[in] *output The buffer to add the data to ++ * \return LDNS_STATUS_OK on success, and error status on failure ++ */ ++ldns_status ldns_rdf2buffer_str_int8(ldns_buffer *output, const ldns_rdf *rdf); ++ ++/** ++ * Converts an LDNS_RDF_TYPE_INT16 rdata element to string format and adds it to the output buffer ++ * \param[in] *rdf The rdata to convert ++ * \param[in] *output The buffer to add the data to ++ * \return LDNS_STATUS_OK on success, and error status on failure ++ */ ++ldns_status ldns_rdf2buffer_str_int16(ldns_buffer *output, const ldns_rdf *rdf); ++ ++/** ++ * Converts an LDNS_RDF_TYPE_INT32 rdata element to string format and adds it to the output buffer ++ * \param[in] *rdf The rdata to convert ++ * \param[in] *output The buffer to add the data to ++ * \return LDNS_STATUS_OK on success, and error status on failure ++ */ ++ldns_status ldns_rdf2buffer_str_int32(ldns_buffer *output, const ldns_rdf *rdf); ++ ++/** ++ * Converts an LDNS_RDF_TYPE_TIME rdata element to string format and adds it to the output buffer ++ * \param[in] *rdf The rdata to convert ++ * \param[in] *output The buffer to add the data to ++ * \return LDNS_STATUS_OK on success, and error status on failure ++ */ ++ldns_status ldns_rdf2buffer_str_time(ldns_buffer *output, const ldns_rdf *rdf); ++ ++/** ++ * Converts an LDNS_RDF_TYPE_ILNP64 rdata element to 4 hexadecimal numbers ++ * separated by colons and adds it to the output buffer ++ * \param[in] *rdf The rdata to convert ++ * \param[in] *output The buffer to add the data to ++ * \return LDNS_STATUS_OK on success, and error status on failure ++ */ ++ldns_status ldns_rdf2buffer_str_ilnp64(ldns_buffer *output, ++ const ldns_rdf *rdf); ++ ++/** ++ * Converts an LDNS_RDF_TYPE_EUI48 rdata element to 6 hexadecimal numbers ++ * separated by dashes and adds it to the output buffer ++ * \param[in] *rdf The rdata to convert ++ * \param[in] *output The buffer to add the data to ++ * \return LDNS_STATUS_OK on success, and error status on failure ++ */ ++ldns_status ldns_rdf2buffer_str_eui48(ldns_buffer *output, ++ const ldns_rdf *rdf); ++ ++/** ++ * Converts an LDNS_RDF_TYPE_EUI64 rdata element to 8 hexadecimal numbers ++ * separated by dashes and adds it to the output buffer ++ * \param[in] *rdf The rdata to convert ++ * \param[in] *output The buffer to add the data to ++ * \return LDNS_STATUS_OK on success, and error status on failure ++ */ ++ldns_status ldns_rdf2buffer_str_eui64(ldns_buffer *output, ++ const ldns_rdf *rdf); ++ ++/** ++ * Adds the LDNS_RDF_TYPE_TAG rdata to the output buffer, ++ * provided it contains only alphanumeric characters. ++ * \param[in] *rdf The rdata to convert ++ * \param[in] *output The buffer to add the data to ++ * \return LDNS_STATUS_OK on success, and error status on failure ++ */ ++ldns_status ldns_rdf2buffer_str_tag(ldns_buffer *output, ++ const ldns_rdf *rdf); ++ ++/** ++ * Adds the LDNS_RDF_TYPE_LONG_STR rdata to the output buffer, in-between ++ * double quotes and all non printable characters properly escaped. ++ * \param[in] *rdf The rdata to convert ++ * \param[in] *output The buffer to add the data to ++ * \return LDNS_STATUS_OK on success, and error status on failure ++ */ ++ldns_status ldns_rdf2buffer_str_long_str(ldns_buffer *output, ++ const ldns_rdf *rdf); ++ ++/** ++ * Converts an LDNS_RDF_TYPE_HIP rdata element to presentation format for ++ * the algorithm, HIT and Public Key and adds it the output buffer . ++ * \param[in] *rdf The rdata to convert ++ * \param[in] *output The buffer to add the data to ++ * \return LDNS_STATUS_OK on success, and error status on failure ++ */ ++ldns_status ldns_rdf2buffer_str_hip(ldns_buffer *output, ++ const ldns_rdf *rdf); ++ ++/** ++ * Converts the data in the rdata field to presentation format and ++ * returns that as a char *. ++ * Remember to free it. ++ * ++ * \param[in] rdf The rdata field to convert ++ * \return null terminated char * data, or NULL on error ++ */ ++char *ldns_rdf2str(const ldns_rdf *rdf); ++ ++/** ++ * Converts the data in the resource record to presentation format and ++ * returns that as a char *. ++ * Remember to free it. ++ * ++ * \param[in] rr The rdata field to convert ++ * \return null terminated char * data, or NULL on error ++ */ ++char *ldns_rr2str(const ldns_rr *rr); ++ ++/** ++ * Converts the data in the resource record to presentation format and ++ * returns that as a char *. ++ * Remember to free it. ++ * ++ * \param[in] fmt how to format the resource record ++ * \param[in] rr The rdata field to convert ++ * \return null terminated char * data, or NULL on error ++ */ ++char *ldns_rr2str_fmt(const ldns_output_format *fmt, const ldns_rr *rr); ++ ++/** ++ * Converts the data in the DNS packet to presentation format and ++ * returns that as a char *. ++ * Remember to free it. ++ * ++ * \param[in] pkt The rdata field to convert ++ * \return null terminated char * data, or NULL on error ++ */ ++char *ldns_pkt2str(const ldns_pkt *pkt); ++ ++/** ++ * Converts the data in the DNS packet to presentation format and ++ * returns that as a char *. ++ * Remember to free it. ++ * ++ * \param[in] fmt how to format the packet ++ * \param[in] pkt The rdata field to convert ++ * \return null terminated char * data, or NULL on error ++ */ ++char *ldns_pkt2str_fmt(const ldns_output_format *fmt, const ldns_pkt *pkt); ++ ++/** ++ * Converts a private key to the test presentation fmt and ++ * returns that as a char *. ++ * Remember to free it. ++ * ++ * \param[in] k the key to convert to text ++ * \return null terminated char * data, or NULL on error ++ */ ++char *ldns_key2str(const ldns_key *k); ++ ++/** ++ * Converts a list of resource records to presentation format ++ * and returns that as a char *. ++ * Remember to free it. ++ * ++ * \param[in] rr_list the rr_list to convert to text ++ * \return null terminated char * data, or NULL on error ++ */ ++char *ldns_rr_list2str(const ldns_rr_list *rr_list); ++ ++/** ++ * Converts a list of resource records to presentation format ++ * and returns that as a char *. ++ * Remember to free it. ++ * ++ * \param[in] fmt how to format the list of resource records ++ * \param[in] rr_list the rr_list to convert to text ++ * \return null terminated char * data, or NULL on error ++ */ ++char *ldns_rr_list2str_fmt( ++ const ldns_output_format *fmt, const ldns_rr_list *rr_list); ++ ++/** ++ * Returns a copy of the data in the buffer as a null terminated ++ * char * string. The returned string must be freed by the caller. ++ * The buffer must be in write modus and may thus not have been flipped. ++ * ++ * \param[in] buffer buffer containing char * data ++ * \return null terminated char * data, or NULL on error ++ */ ++char *ldns_buffer2str(ldns_buffer *buffer); ++ ++/** ++ * Exports and returns the data in the buffer as a null terminated ++ * char * string. The returned string must be freed by the caller. ++ * The buffer must be in write modus and may thus not have been flipped. ++ * The buffer is fixed after this function returns. ++ * ++ * \param[in] buffer buffer containing char * data ++ * \return null terminated char * data, or NULL on error ++ */ ++char *ldns_buffer_export2str(ldns_buffer *buffer); ++ ++/** ++ * Prints the data in the rdata field to the given file stream ++ * (in presentation format) ++ * ++ * \param[in] output the file stream to print to ++ * \param[in] rdf the rdata field to print ++ * \return void ++ */ ++void ldns_rdf_print(FILE *output, const ldns_rdf *rdf); ++ ++/** ++ * Prints the data in the resource record to the given file stream ++ * (in presentation format) ++ * ++ * \param[in] output the file stream to print to ++ * \param[in] rr the resource record to print ++ * \return void ++ */ ++void ldns_rr_print(FILE *output, const ldns_rr *rr); ++ ++/** ++ * Prints the data in the resource record to the given file stream ++ * (in presentation format) ++ * ++ * \param[in] output the file stream to print to ++ * \param[in] fmt format of the textual representation ++ * \param[in] rr the resource record to print ++ * \return void ++ */ ++void ldns_rr_print_fmt(FILE *output, ++ const ldns_output_format *fmt, const ldns_rr *rr); ++ ++/** ++ * Prints the data in the DNS packet to the given file stream ++ * (in presentation format) ++ * ++ * \param[in] output the file stream to print to ++ * \param[in] pkt the packet to print ++ * \return void ++ */ ++void ldns_pkt_print(FILE *output, const ldns_pkt *pkt); ++ ++/** ++ * Prints the data in the DNS packet to the given file stream ++ * (in presentation format) ++ * ++ * \param[in] output the file stream to print to ++ * \param[in] fmt format of the textual representation ++ * \param[in] pkt the packet to print ++ * \return void ++ */ ++void ldns_pkt_print_fmt(FILE *output, ++ const ldns_output_format *fmt, const ldns_pkt *pkt); ++ ++/** ++ * Converts a rr_list to presentation format and appends it to ++ * the output buffer ++ * \param[in] output the buffer to append output to ++ * \param[in] list the ldns_rr_list to print ++ * \return ldns_status ++ */ ++ldns_status ldns_rr_list2buffer_str(ldns_buffer *output, const ldns_rr_list *list); ++ ++/** ++ * Converts a rr_list to presentation format and appends it to ++ * the output buffer ++ * \param[in] output the buffer to append output to ++ * \param[in] fmt format of the textual representation ++ * \param[in] list the ldns_rr_list to print ++ * \return ldns_status ++ */ ++ldns_status ldns_rr_list2buffer_str_fmt(ldns_buffer *output, ++ const ldns_output_format *fmt, const ldns_rr_list *list); ++ ++/** ++ * Converts the header of a packet to presentation format and appends it to ++ * the output buffer ++ * \param[in] output the buffer to append output to ++ * \param[in] pkt the packet to convert the header of ++ * \return ldns_status ++ */ ++ldns_status ldns_pktheader2buffer_str(ldns_buffer *output, const ldns_pkt *pkt); ++ ++/** ++ * print a rr_list to output ++ * \param[in] output the fd to print to ++ * \param[in] list the rr_list to print ++ */ ++void ldns_rr_list_print(FILE *output, const ldns_rr_list *list); ++ ++/** ++ * print a rr_list to output ++ * \param[in] output the fd to print to ++ * \param[in] fmt format of the textual representation ++ * \param[in] list the rr_list to print ++ */ ++void ldns_rr_list_print_fmt(FILE *output, ++ const ldns_output_format *fmt, const ldns_rr_list *list); ++ ++/** ++ * Print a resolver (in sofar that is possible) state ++ * to output. ++ * \param[in] output the fd to print to ++ * \param[in] r the resolver to print ++ */ ++void ldns_resolver_print(FILE *output, const ldns_resolver *r); ++ ++/** ++ * Print a resolver (in sofar that is possible) state ++ * to output. ++ * \param[in] output the fd to print to ++ * \param[in] fmt format of the textual representation ++ * \param[in] r the resolver to print ++ */ ++void ldns_resolver_print_fmt(FILE *output, ++ const ldns_output_format *fmt, const ldns_resolver *r); ++ ++/** ++ * Print a zone structure * to output. Note the SOA record ++ * is included in this output ++ * \param[in] output the fd to print to ++ * \param[in] z the zone to print ++ */ ++void ldns_zone_print(FILE *output, const ldns_zone *z); ++ ++/** ++ * Print a zone structure * to output. Note the SOA record ++ * is included in this output ++ * \param[in] output the fd to print to ++ * \param[in] fmt format of the textual representation ++ * \param[in] z the zone to print ++ */ ++void ldns_zone_print_fmt(FILE *output, ++ const ldns_output_format *fmt, const ldns_zone *z); ++ ++/** ++ * Print the ldns_rdf containing a dname to the buffer ++ * \param[in] output the buffer to print to ++ * \param[in] dname the dname to print ++ * \return ldns_status message if the printing succeeded ++ */ ++ldns_status ldns_rdf2buffer_str_dname(ldns_buffer *output, const ldns_rdf *dname); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* LDNS_HOST2STR_H */ +diff --git a/ldns/include/ldns/host2wire.h b/ldns/include/ldns/host2wire.h +new file mode 100644 +index 0000000..94693cd +--- /dev/null ++++ b/ldns/include/ldns/host2wire.h +@@ -0,0 +1,197 @@ ++/* ++ * host2wire.h - 2wire conversion routines ++ * ++ * a Net::DNS like library for C ++ * ++ * (c) NLnet Labs, 2005-2006 ++ * ++ * See the file LICENSE for the license ++ */ ++ ++/** ++ * \file ++ * ++ * Contains all functions to translate the main structures to wire format ++ */ ++ ++#ifndef LDNS_HOST2WIRE_H ++#define LDNS_HOST2WIRE_H ++ ++#include <ldns/common.h> ++#include <ldns/error.h> ++#include <ldns/rr.h> ++#include <ldns/rdata.h> ++#include <ldns/packet.h> ++#include <ldns/buffer.h> ++#include <ctype.h> ++ ++#include "ldns/util.h" ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/** ++ * Copies the dname data to the buffer in wire format ++ * \param[out] *buffer buffer to append the result to ++ * \param[in] *name rdata dname to convert ++ * \return ldns_status ++ */ ++ldns_status ldns_dname2buffer_wire(ldns_buffer *buffer, const ldns_rdf *name); ++ ++/** ++ * Copies the dname data to the buffer in wire format ++ * \param[out] *buffer buffer to append the result to ++ * \param[in] *name rdata dname to convert ++ * \param[out] *compression_data data structure holding state for compression ++ * \return ldns_status ++ */ ++ldns_status ldns_dname2buffer_wire_compress(ldns_buffer *buffer, const ldns_rdf *name, ldns_rbtree_t *compression_data); ++ ++/** ++ * Copies the rdata data to the buffer in wire format ++ * \param[out] *output buffer to append the result to ++ * \param[in] *rdf rdata to convert ++ * \return ldns_status ++ */ ++ldns_status ldns_rdf2buffer_wire(ldns_buffer *output, const ldns_rdf *rdf); ++ ++/** ++ * Copies the rdata data to the buffer in wire format ++ * \param[out] *output buffer to append the result to ++ * \param[in] *rdf rdata to convert ++ * \param[out] *compression_data data structure holding state for compression ++ * \return ldns_status ++ */ ++ldns_status ldns_rdf2buffer_wire_compress(ldns_buffer *output, const ldns_rdf *rdf, ldns_rbtree_t *compression_data); ++ ++/** ++ * Copies the rdata data to the buffer in wire format ++ * If the rdata is a dname, the letters will be lowercased ++ * during the conversion ++ * \param[out] *output buffer to append the result to ++ * \param[in] *rdf rdata to convert ++ * \return ldns_status ++ */ ++ldns_status ldns_rdf2buffer_wire_canonical(ldns_buffer *output, ++ const ldns_rdf *rdf); ++ ++/** ++ * Copies the rr data to the buffer in wire format ++ * \param[out] *output buffer to append the result to ++ * \param[in] *rr resource record to convert ++ * \param[in] section the section in the packet this rr is supposed to be in ++ * (to determine whether to add rdata or not) ++ * \return ldns_status ++ */ ++ldns_status ldns_rr2buffer_wire(ldns_buffer *output, ++ const ldns_rr *rr, ++ int section); ++ ++/** ++ * Copies the rr data to the buffer in wire format while doing DNAME compression ++ * \param[out] *output buffer to append the result to ++ * \param[in] *rr resource record to convert ++ * \param[in] section the section in the packet this rr is supposed to be in ++ * (to determine whether to add rdata or not) ++ * \param[out] *compression_data data structure holding state information for compression ++ * \return ldns_status ++ */ ++ldns_status ldns_rr2buffer_wire_compress(ldns_buffer *output, ++ const ldns_rr *rr, ++ int section, ++ ldns_rbtree_t *compression_data); ++ ++/** ++ * Copies the rr data to the buffer in wire format, in canonical format ++ * according to RFC3597 (every dname in rdata fields of RR's mentioned in ++ * that RFC will be lowercased) ++ * \param[out] *output buffer to append the result to ++ * \param[in] *rr resource record to convert ++ * \param[in] section the section in the packet this rr is supposed to be in ++ * (to determine whether to add rdata or not) ++ * \return ldns_status ++ */ ++ldns_status ldns_rr2buffer_wire_canonical(ldns_buffer *output, ++ const ldns_rr *rr, ++ int section); ++ ++ ++/** ++ * Converts a rrsig to wireformat BUT EXCLUDE the rrsig rdata ++ * This is needed in DNSSEC verification ++ * \param[out] output buffer to append the result to ++ * \param[in] sigrr signature rr to operate on ++ * \return ldns_status ++ */ ++ldns_status ldns_rrsig2buffer_wire(ldns_buffer *output, const ldns_rr *sigrr); ++ ++/** ++ * Converts an rr's rdata to wireformat, while excluding ++ * the ownername and all the stuff before the rdata. ++ * This is needed in DNSSEC keytag calculation, the ds ++ * calcalution from the key and maybe elsewhere. ++ * ++ * \param[out] *output buffer where to put the result ++ * \param[in] *rr rr to operate on ++ * \return ldns_status ++ */ ++ldns_status ldns_rr_rdata2buffer_wire(ldns_buffer *output, const ldns_rr *rr); ++ ++/** ++ * Copies the packet data to the buffer in wire format ++ * \param[out] *output buffer to append the result to ++ * \param[in] *pkt packet to convert ++ * \return ldns_status ++ */ ++ldns_status ldns_pkt2buffer_wire(ldns_buffer *output, const ldns_pkt *pkt); ++ ++/** ++ * Copies the rr_list data to the buffer in wire format ++ * \param[out] *output buffer to append the result to ++ * \param[in] *rrlist rr_list to to convert ++ * \return ldns_status ++ */ ++ldns_status ldns_rr_list2buffer_wire(ldns_buffer *output, const ldns_rr_list *rrlist); ++ ++/** ++ * Allocates an array of uint8_t at dest, and puts the wireformat of the ++ * given rdf in that array. The result_size value contains the ++ * length of the array, if it succeeds, and 0 otherwise (in which case ++ * the function also returns NULL) ++ * ++ * \param[out] dest pointer to the array of bytes to be created ++ * \param[in] rdf the rdata field to convert ++ * \param[out] size the size of the converted result ++ */ ++ldns_status ldns_rdf2wire(uint8_t **dest, const ldns_rdf *rdf, size_t *size); ++ ++/** ++ * Allocates an array of uint8_t at dest, and puts the wireformat of the ++ * given rr in that array. The result_size value contains the ++ * length of the array, if it succeeds, and 0 otherwise (in which case ++ * the function also returns NULL) ++ * ++ * If the section argument is LDNS_SECTION_QUESTION, data like ttl and rdata ++ * are not put into the result ++ * ++ * \param[out] dest pointer to the array of bytes to be created ++ * \param[in] rr the rr to convert ++ * \param[in] section the rr section, determines how the rr is written. ++ * \param[out] size the size of the converted result ++ */ ++ldns_status ldns_rr2wire(uint8_t **dest, const ldns_rr *rr, int section, size_t *size); ++ ++/** ++ * Allocates an array of uint8_t at dest, and puts the wireformat of the ++ * given packet in that array. The result_size value contains the ++ * length of the array, if it succeeds, and 0 otherwise (in which case ++ * the function also returns NULL) ++ */ ++ldns_status ldns_pkt2wire(uint8_t **dest, const ldns_pkt *p, size_t *size); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* LDNS_HOST2WIRE_H */ +diff --git a/ldns/include/ldns/keys.h b/ldns/include/ldns/keys.h +new file mode 100644 +index 0000000..d3b4873 +--- /dev/null ++++ b/ldns/include/ldns/keys.h +@@ -0,0 +1,621 @@ ++/* ++ * ++ * keys.h ++ * ++ * priv key definitions ++ * ++ * a Net::DNS like library for C ++ * ++ * (c) NLnet Labs, 2005-2006 ++ * ++ * See the file LICENSE for the license ++ */ ++ ++/** ++ * \file ++ * ++ * Addendum to \ref dnssec.h, this module contains key and algorithm definitions and functions. ++ */ ++ ++ ++#ifndef LDNS_KEYS_H ++#define LDNS_KEYS_H ++ ++#include <ldns/common.h> ++#if LDNS_BUILD_CONFIG_HAVE_SSL ++#include <openssl/ssl.h> ++#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */ ++#include <ldns/util.h> ++#include <errno.h> ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++extern ldns_lookup_table ldns_signing_algorithms[]; ++ ++#define LDNS_KEY_ZONE_KEY 0x0100 /* rfc 4034 */ ++#define LDNS_KEY_SEP_KEY 0x0001 /* rfc 4034 */ ++#define LDNS_KEY_REVOKE_KEY 0x0080 /* rfc 5011 */ ++ ++/** ++ * Algorithms used in dns ++ */ ++enum ldns_enum_algorithm ++{ ++ LDNS_RSAMD5 = 1, /* RFC 4034,4035 */ ++ LDNS_DH = 2, ++ LDNS_DSA = 3, ++ LDNS_ECC = 4, ++ LDNS_RSASHA1 = 5, ++ LDNS_DSA_NSEC3 = 6, ++ LDNS_RSASHA1_NSEC3 = 7, ++ LDNS_RSASHA256 = 8, /* RFC 5702 */ ++ LDNS_RSASHA512 = 10, /* RFC 5702 */ ++ LDNS_ECC_GOST = 12, /* RFC 5933 */ ++ LDNS_ECDSAP256SHA256 = 13, /* RFC 6605 */ ++ LDNS_ECDSAP384SHA384 = 14, /* RFC 6605 */ ++ LDNS_INDIRECT = 252, ++ LDNS_PRIVATEDNS = 253, ++ LDNS_PRIVATEOID = 254 ++}; ++typedef enum ldns_enum_algorithm ldns_algorithm; ++ ++/** ++ * Hashing algorithms used in the DS record ++ */ ++enum ldns_enum_hash ++{ ++ LDNS_SHA1 = 1, /* RFC 4034 */ ++ LDNS_SHA256 = 2, /* RFC 4509 */ ++ LDNS_HASH_GOST = 3, /* RFC 5933 */ ++ LDNS_SHA384 = 4 /* RFC 6605 */ ++}; ++typedef enum ldns_enum_hash ldns_hash; ++ ++/** ++ * Algorithms used in dns for signing ++ */ ++enum ldns_enum_signing_algorithm ++{ ++ LDNS_SIGN_RSAMD5 = LDNS_RSAMD5, ++ LDNS_SIGN_RSASHA1 = LDNS_RSASHA1, ++ LDNS_SIGN_DSA = LDNS_DSA, ++ LDNS_SIGN_RSASHA1_NSEC3 = LDNS_RSASHA1_NSEC3, ++ LDNS_SIGN_RSASHA256 = LDNS_RSASHA256, ++ LDNS_SIGN_RSASHA512 = LDNS_RSASHA512, ++ LDNS_SIGN_DSA_NSEC3 = LDNS_DSA_NSEC3, ++ LDNS_SIGN_ECC_GOST = LDNS_ECC_GOST, ++ LDNS_SIGN_ECDSAP256SHA256 = LDNS_ECDSAP256SHA256, ++ LDNS_SIGN_ECDSAP384SHA384 = LDNS_ECDSAP384SHA384, ++ LDNS_SIGN_HMACMD5 = 157, /* not official! This type is for TSIG, not DNSSEC */ ++ LDNS_SIGN_HMACSHA1 = 158, /* not official! This type is for TSIG, not DNSSEC */ ++ LDNS_SIGN_HMACSHA256 = 159 /* ditto */ ++}; ++typedef enum ldns_enum_signing_algorithm ldns_signing_algorithm; ++ ++/** ++ * General key structure, can contain all types of keys that ++ * are used in DNSSEC. Mostly used to store private keys, since ++ * public keys can also be stored in a \ref ldns_rr with type ++ * \ref LDNS_RR_TYPE_DNSKEY. ++ * ++ * This structure can also store some variables that influence the ++ * signatures generated by signing with this key, for instance the ++ * inception date. ++ */ ++struct ldns_struct_key { ++ ldns_signing_algorithm _alg; ++ /** Whether to use this key when signing */ ++ bool _use; ++ /** Storage pointers for the types of keys supported */ ++ /* TODO remove unions? */ ++ struct { ++#if LDNS_BUILD_CONFIG_HAVE_SSL ++#ifndef S_SPLINT_S ++ /* The key can be an OpenSSL EVP Key ++ */ ++ EVP_PKEY *key; ++#endif ++#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */ ++ /** ++ * The key can be an HMAC key ++ */ ++ struct { ++ unsigned char *key; ++ size_t size; ++ } hmac; ++ /** the key structure can also just point to some external ++ * key data ++ */ ++ void *external_key; ++ } _key; ++ /** Depending on the key we can have extra data */ ++ union { ++ /** Some values that influence generated signatures */ ++ struct { ++ /** The TTL of the rrset that is currently signed */ ++ uint32_t orig_ttl; ++ /** The inception date of signatures made with this key. */ ++ uint32_t inception; ++ /** The expiration date of signatures made with this key. */ ++ uint32_t expiration; ++ /** The keytag of this key. */ ++ uint16_t keytag; ++ /** The dnssec key flags as specified in RFC4035, like ZSK and KSK */ ++ uint16_t flags; ++ } dnssec; ++ } _extra; ++ /** Owner name of the key */ ++ ldns_rdf *_pubkey_owner; ++}; ++typedef struct ldns_struct_key ldns_key; ++ ++/** ++ * Same as rr_list, but now for keys ++ */ ++struct ldns_struct_key_list ++{ ++ size_t _key_count; ++ ldns_key **_keys; ++}; ++typedef struct ldns_struct_key_list ldns_key_list; ++ ++ ++/** ++ * Creates a new empty key list ++ * \return a new ldns_key_list structure pointer ++ */ ++ldns_key_list *ldns_key_list_new(void); ++ ++/** ++ * Creates a new empty key structure ++ * \return a new ldns_key * structure ++ */ ++ldns_key *ldns_key_new(void); ++ ++/** ++ * Creates a new key based on the algorithm ++ * ++ * \param[in] a The algorithm to use ++ * \param[in] size the number of bytes for the keysize ++ * \return a new ldns_key structure with the key ++ */ ++ldns_key *ldns_key_new_frm_algorithm(ldns_signing_algorithm a, uint16_t size); ++ ++/** ++ * Creates a new priv key based on the ++ * contents of the file pointed by fp. ++ * ++ * The file should be in Private-key-format v1.x. ++ * ++ * \param[out] k the new ldns_key structure ++ * \param[in] fp the file pointer to use ++ * \return an error or LDNS_STATUS_OK ++ */ ++ldns_status ldns_key_new_frm_fp(ldns_key **k, FILE *fp); ++ ++/** ++ * Creates a new private key based on the ++ * contents of the file pointed by fp ++ * ++ * The file should be in Private-key-format v1.x. ++ * ++ * \param[out] k the new ldns_key structure ++ * \param[in] fp the file pointer to use ++ * \param[in] line_nr pointer to an integer containing the current line number (for debugging purposes) ++ * \return an error or LDNS_STATUS_OK ++ */ ++ldns_status ldns_key_new_frm_fp_l(ldns_key **k, FILE *fp, int *line_nr); ++ ++#if LDNS_BUILD_CONFIG_HAVE_SSL ++/** ++ * Read the key with the given id from the given engine and store it ++ * in the given ldns_key structure. The algorithm type is set ++ */ ++ldns_status ldns_key_new_frm_engine(ldns_key **key, ENGINE *e, char *key_id, ldns_algorithm); ++ ++ ++/** ++ * frm_fp helper function. This function parses the ++ * remainder of the (RSA) priv. key file generated from bind9 ++ * \param[in] fp the file to parse ++ * \return NULL on failure otherwise a RSA structure ++ */ ++RSA *ldns_key_new_frm_fp_rsa(FILE *fp); ++#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */ ++ ++#if LDNS_BUILD_CONFIG_HAVE_SSL ++/** ++ * frm_fp helper function. This function parses the ++ * remainder of the (RSA) priv. key file generated from bind9 ++ * \param[in] fp the file to parse ++ * \param[in] line_nr pointer to an integer containing the current line number (for debugging purposes) ++ * \return NULL on failure otherwise a RSA structure ++ */ ++RSA *ldns_key_new_frm_fp_rsa_l(FILE *fp, int *line_nr); ++#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */ ++ ++#if LDNS_BUILD_CONFIG_HAVE_SSL ++/** ++ * frm_fp helper function. This function parses the ++ * remainder of the (DSA) priv. key file ++ * \param[in] fp the file to parse ++ * \return NULL on failure otherwise a RSA structure ++ */ ++DSA *ldns_key_new_frm_fp_dsa(FILE *fp); ++#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */ ++ ++#if LDNS_BUILD_CONFIG_HAVE_SSL ++/** ++ * frm_fp helper function. This function parses the ++ * remainder of the (DSA) priv. key file ++ * \param[in] fp the file to parse ++ * \param[in] line_nr pointer to an integer containing the current line number (for debugging purposes) ++ * \return NULL on failure otherwise a RSA structure ++ */ ++DSA *ldns_key_new_frm_fp_dsa_l(FILE *fp, int *line_nr); ++#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */ ++ ++#if LDNS_BUILD_CONFIG_HAVE_SSL ++/** ++ * frm_fp helper function. This function parses the ++ * remainder of the (HMAC-MD5) key file ++ * This function allocated a buffer that needs to be freed ++ * \param[in] fp the file to parse ++ * \param[out] hmac_size the number of bits in the resulting buffer ++ * \return NULL on failure otherwise a newly allocated char buffer ++ */ ++unsigned char *ldns_key_new_frm_fp_hmac(FILE *fp, size_t *hmac_size); ++#endif ++ ++#if LDNS_BUILD_CONFIG_HAVE_SSL ++/** ++ * frm_fp helper function. This function parses the ++ * remainder of the (HMAC-MD5) key file ++ * This function allocated a buffer that needs to be freed ++ * \param[in] fp the file to parse ++ * \param[in] line_nr pointer to an integer containing the current line number (for error reporting purposes) ++ * \param[out] hmac_size the number of bits in the resulting buffer ++ * \return NULL on failure otherwise a newly allocated char buffer ++ */ ++unsigned char *ldns_key_new_frm_fp_hmac_l(FILE *fp, int *line_nr, size_t *hmac_size); ++#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */ ++ ++/* acces write functions */ ++/** ++ * Set the key's algorithm ++ * \param[in] k the key ++ * \param[in] l the algorithm ++ */ ++void ldns_key_set_algorithm(ldns_key *k, ldns_signing_algorithm l); ++#if LDNS_BUILD_CONFIG_HAVE_SSL ++/** ++ * Set the key's evp key ++ * \param[in] k the key ++ * \param[in] e the evp key ++ */ ++void ldns_key_set_evp_key(ldns_key *k, EVP_PKEY *e); ++ ++/** ++ * Set the key's rsa data. ++ * The rsa data should be freed by the user. ++ * \param[in] k the key ++ * \param[in] r the rsa data ++ */ ++void ldns_key_set_rsa_key(ldns_key *k, RSA *r); ++ ++/** ++ * Set the key's dsa data ++ * The dsa data should be freed by the user. ++ * \param[in] k the key ++ * \param[in] d the dsa data ++ */ ++void ldns_key_set_dsa_key(ldns_key *k, DSA *d); ++ ++/** ++ * Assign the key's rsa data ++ * The rsa data will be freed automatically when the key is freed. ++ * \param[in] k the key ++ * \param[in] r the rsa data ++ */ ++void ldns_key_assign_rsa_key(ldns_key *k, RSA *r); ++ ++/** ++ * Assign the key's dsa data ++ * The dsa data will be freed automatically when the key is freed. ++ * \param[in] k the key ++ * \param[in] d the dsa data ++ */ ++void ldns_key_assign_dsa_key(ldns_key *k, DSA *d); ++ ++/** ++ * Get the PKEY id for GOST, loads GOST into openssl as a side effect. ++ * Only available if GOST is compiled into the library and openssl. ++ * \return the gost id for EVP_CTX creation. ++ */ ++int ldns_key_EVP_load_gost_id(void); ++ ++/** Release the engine reference held for the GOST engine. */ ++void ldns_key_EVP_unload_gost(void); ++#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */ ++ ++/** ++ * Set the key's hmac data ++ * \param[in] k the key ++ * \param[in] hmac the raw key data ++ */ ++void ldns_key_set_hmac_key(ldns_key *k, unsigned char *hmac); ++ ++/** ++ * Set the key id data. This is used if the key points to ++ * some externally stored key data ++ * ++ * Only the pointer is set, the data there is not copied, ++ * and must be freed manually; ldns_key_deep_free() does ++ * *not* free this data ++ * \param[in] key the key ++ * \param[in] external_key key id data ++ */ ++void ldns_key_set_external_key(ldns_key *key, void *external_key); ++ ++/** ++ * Set the key's hmac size ++ * \param[in] k the key ++ * \param[in] hmac_size the size of the hmac data ++ */ ++void ldns_key_set_hmac_size(ldns_key *k, size_t hmac_size); ++/** ++ * Set the key's original ttl ++ * \param[in] k the key ++ * \param[in] t the ttl ++ */ ++void ldns_key_set_origttl(ldns_key *k, uint32_t t); ++/** ++ * Set the key's inception date (seconds after epoch) ++ * \param[in] k the key ++ * \param[in] i the inception ++ */ ++void ldns_key_set_inception(ldns_key *k, uint32_t i); ++/** ++ * Set the key's expiration date (seconds after epoch) ++ * \param[in] k the key ++ * \param[in] e the expiration ++ */ ++void ldns_key_set_expiration(ldns_key *k, uint32_t e); ++/** ++ * Set the key's pubkey owner ++ * \param[in] k the key ++ * \param[in] r the owner ++ */ ++void ldns_key_set_pubkey_owner(ldns_key *k, ldns_rdf *r); ++/** ++ * Set the key's key tag ++ * \param[in] k the key ++ * \param[in] tag the keytag ++ */ ++void ldns_key_set_keytag(ldns_key *k, uint16_t tag); ++/** ++ * Set the key's flags ++ * \param[in] k the key ++ * \param[in] flags the flags ++ */ ++void ldns_key_set_flags(ldns_key *k, uint16_t flags); ++/** ++ * Set the keylist's key count to count ++ * \param[in] key the key ++ * \param[in] count the cuont ++ */ ++void ldns_key_list_set_key_count(ldns_key_list *key, size_t count); ++ ++/** ++ * pushes a key to a keylist ++ * \param[in] key_list the key_list to push to ++ * \param[in] key the key to push ++ * \return false on error, otherwise true ++ */ ++bool ldns_key_list_push_key(ldns_key_list *key_list, ldns_key *key); ++ ++/** ++ * returns the number of keys in the key list ++ * \param[in] key_list the key_list ++ * \return the numbers of keys in the list ++ */ ++size_t ldns_key_list_key_count(const ldns_key_list *key_list); ++ ++/** ++ * returns a pointer to the key in the list at the given position ++ * \param[in] key the key ++ * \param[in] nr the position in the list ++ * \return the key ++ */ ++ldns_key *ldns_key_list_key(const ldns_key_list *key, size_t nr); ++ ++#if LDNS_BUILD_CONFIG_HAVE_SSL ++/** ++ * returns the (openssl) RSA struct contained in the key ++ * \param[in] k the key to look in ++ * \return the RSA * structure in the key ++ */ ++RSA *ldns_key_rsa_key(const ldns_key *k); ++/** ++ * returns the (openssl) EVP struct contained in the key ++ * \param[in] k the key to look in ++ * \return the RSA * structure in the key ++ */ ++EVP_PKEY *ldns_key_evp_key(const ldns_key *k); ++#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */ ++ ++/** ++ * returns the (openssl) DSA struct contained in the key ++ */ ++#if LDNS_BUILD_CONFIG_HAVE_SSL ++DSA *ldns_key_dsa_key(const ldns_key *k); ++#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */ ++ ++/** ++ * return the signing alg of the key ++ * \param[in] k the key ++ * \return the algorithm ++ */ ++ldns_signing_algorithm ldns_key_algorithm(const ldns_key *k); ++/** ++ * set the use flag ++ * \param[in] k the key ++ * \param[in] v the boolean value to set the _use field to ++ */ ++void ldns_key_set_use(ldns_key *k, bool v); ++/** ++ * return the use flag ++ * \param[in] k the key ++ * \return the boolean value of the _use field ++ */ ++bool ldns_key_use(const ldns_key *k); ++/** ++ * return the hmac key data ++ * \param[in] k the key ++ * \return the hmac key data ++ */ ++unsigned char *ldns_key_hmac_key(const ldns_key *k); ++/** ++ * return the key id key data ++ * \param[in] k the key ++ * \return the key id data ++ */ ++void *ldns_key_external_key(const ldns_key *k); ++/** ++ * return the hmac key size ++ * \param[in] k the key ++ * \return the hmac key size ++ */ ++size_t ldns_key_hmac_size(const ldns_key *k); ++/** ++ * return the original ttl of the key ++ * \param[in] k the key ++ * \return the original ttl ++ */ ++uint32_t ldns_key_origttl(const ldns_key *k); ++/** ++ * return the key's inception date ++ * \param[in] k the key ++ * \return the inception date ++ */ ++uint32_t ldns_key_inception(const ldns_key *k); ++/** ++ * return the key's expiration date ++ * \param[in] k the key ++ * \return the experiration date ++ */ ++uint32_t ldns_key_expiration(const ldns_key *k); ++/** ++ * return the keytag ++ * \param[in] k the key ++ * \return the keytag ++ */ ++uint16_t ldns_key_keytag(const ldns_key *k); ++/** ++ * return the public key's owner ++ * \param[in] k the key ++ * \return the owner ++ */ ++ldns_rdf *ldns_key_pubkey_owner(const ldns_key *k); ++/** ++ * Set the 'use' flag for all keys in the list ++ * \param[in] keys The key_list ++ * \param[in] v The value to set the use flags to ++ */ ++void ++ldns_key_list_set_use(ldns_key_list *keys, bool v); ++ ++/** ++ * return the flag of the key ++ * \param[in] k the key ++ * \return the flag ++ */ ++uint16_t ldns_key_flags(const ldns_key *k); ++ ++/** ++ * pops the last rr from a keylist ++ * \param[in] key_list the rr_list to pop from ++ * \return NULL if nothing to pop. Otherwise the popped RR ++ */ ++ldns_key *ldns_key_list_pop_key(ldns_key_list *key_list); ++ ++/** ++ * converts a ldns_key to a public key rr ++ * If the key data exists at an external point, the corresponding ++ * rdata field must still be added with ldns_rr_rdf_push() to the ++ * result rr of this function ++ * ++ * \param[in] k the ldns_key to convert ++ * \return ldns_rr representation of the key ++ */ ++ldns_rr *ldns_key2rr(const ldns_key *k); ++ ++/** ++ * print a private key to the file ouput ++ * ++ * \param[in] output the FILE descriptor where to print to ++ * \param[in] k the ldns_key to print ++ */ ++void ldns_key_print(FILE *output, const ldns_key *k); ++ ++/** ++ * frees a key structure, but not its internal data structures ++ * ++ * \param[in] key the key object to free ++ */ ++void ldns_key_free(ldns_key *key); ++ ++/** ++ * frees a key structure and all its internal data structures, except ++ * the data set by ldns_key_set_external_key() ++ * ++ * \param[in] key the key object to free ++ */ ++void ldns_key_deep_free(ldns_key *key); ++ ++/** ++ * Frees a key list structure ++ * \param[in] key_list the key list object to free ++ */ ++void ldns_key_list_free(ldns_key_list *key_list); ++ ++/** ++ * Instantiates a DNSKEY or DS RR from file. ++ * \param[in] filename the file to read the record from ++ * \return the corresponding RR, or NULL if the parsing failed ++ */ ++ldns_rr * ldns_read_anchor_file(const char *filename); ++ ++/** ++ * Returns the 'default base name' for key files; ++ * IE. K\<zone\>+\<alg\>+\<keytag\> ++ * (without the .key or .private) ++ * The memory for this is allocated by this function, ++ * and should be freed by the caller ++ * ++ * \param[in] key the key to get the file name from ++ * \returns A string containing the file base name ++ */ ++char *ldns_key_get_file_base_name(ldns_key *key); ++ ++/** ++ * See if a key algorithm is supported ++ * \param[in] algo the signing algorithm number. ++ * \returns true if supported. ++ */ ++int ldns_key_algo_supported(int algo); ++ ++/** ++ * Get signing algorithm by name. Comparison is case insensitive. ++ * \param[in] name string with the name. ++ * \returns 0 on parse failure or the algorithm number. ++ */ ++ldns_signing_algorithm ldns_get_signing_algorithm_by_name(const char* name); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* LDNS_KEYS_H */ +diff --git a/ldns/include/ldns/ldns.h b/ldns/include/ldns/ldns.h +new file mode 100644 +index 0000000..60663ef +--- /dev/null ++++ b/ldns/include/ldns/ldns.h +@@ -0,0 +1,158 @@ ++/* ++ * dns.h -- defines for the Domain Name System ++ * ++ * Copyright (c) 2005-2008, NLnet Labs. All rights reserved. ++ * ++ * See LICENSE for the license. ++ * ++ * This library was created by: ++ * Jelte Jansen, Erik Rozendaal and Miek Gieben ++ * ++ * A bunch of defines that are used in the DNS. ++ */ ++ ++ ++/** ++\mainpage LDNS Documentation ++ ++\section introduction Introduction ++ ++The goal of ldns is to simplify DNS programming, it supports recent RFCs ++like the DNSSEC documents, and allow developers to easily create software ++conforming to current RFCs, and experimental software for current Internet ++drafts. A secondary benefit of using ldns is speed, because ldns is written ++in C, and although it is not optimized for performance, it should be a lot ++faster than Perl. ++ ++The first main tool to use ldns is Drill, from which part of the library was ++derived. From version 1.0.0 on, drill is included in the ldns release ++and will not be distributed separately anymore. The library also includes some ++other examples and tools to show how it can be used. These can be found in the ++examples/ directory in the tarball. ++ ++ldns depends on OpenSSL for it's cryptographic functions. ++Feature list ++ ++ - Transparent IPv4 and IPv6 support (overridable if necessary), ++ - TSIG support, ++ - DNSSEC support; signing and verification, ++ - small size, ++ - online documentation as well as manual pages. ++ ++If you want to send us patches please use the code from git. ++ ++\section using_ldns Using ldns ++ ++Almost all interaction between an application and ldns goes through the ldns ++data structures (\ref ldns_rr, \ref ldns_pkt, etc.). These are input or ++output to the functions of ldns. For example, \ref ldns_zone_new_frm_fp ++reads a zone from a \c FILE pointer, and returns an \ref ldns_zone ++structure. ++ ++ ++Let's use Drill as an example. Drill is a tool much like dig, whose most ++basic function is to send 1 query to a nameserver and print the response. ++ ++To be able to do this, drill uses the resolver module of ldns, which acts as ++a stub resolver. The resolver module uses the net module to actually send ++the query that drill requested. It then uses the wire2host module to ++translate the response and place it in ldns' internal structures. These are ++passed back to drill, which then uses the host2str module to print the ++response in presentation format. ++ ++\section gettingstarted Getting Started ++ ++See the \ref design page for a very high level description of the design ++choices made for ldns. ++ ++For an overview of the functions and types ldns provides, you can check out ++the \ref ldns ldns header file descriptions. ++ ++If you want to see some libdns action, you can read our tutorials: ++ - \ref tutorial1_mx ++ - \ref tutorial2_zone ++ - \ref tutorial3_signzone ++ ++Or you can just use the menu above to browse through the API docs. ++ ++<div style="visibility:hidden;"> ++\image html LogoInGradientBar2-y100.png ++</div> ++*/ ++ ++/** ++ * \file ldns.h ++ * ++ * Including this file will include all ldns files, and define some lookup tables. ++ */ ++ ++#ifndef LDNS_DNS_H ++#define LDNS_DNS_H ++ ++#include <stdio.h> ++#include <stdlib.h> ++ ++#include <ldns/util.h> ++#include <ldns/buffer.h> ++#include <ldns/common.h> ++#include <ldns/dane.h> ++#include <ldns/dname.h> ++#include <ldns/dnssec.h> ++#include <ldns/dnssec_verify.h> ++#include <ldns/dnssec_sign.h> ++#include <ldns/duration.h> ++#include <ldns/error.h> ++#include <ldns/higher.h> ++#include <ldns/host2str.h> ++#include <ldns/host2wire.h> ++#include <ldns/net.h> ++#include <ldns/packet.h> ++#include <ldns/rdata.h> ++#include <ldns/resolver.h> ++#include <ldns/rr.h> ++#include <ldns/str2host.h> ++#include <ldns/tsig.h> ++#include <ldns/update.h> ++#include <ldns/wire2host.h> ++#include <ldns/rr_functions.h> ++#include <ldns/keys.h> ++#include <ldns/parse.h> ++#include <ldns/zone.h> ++#include <ldns/dnssec_zone.h> ++#include <ldns/radix.h> ++#include <ldns/rbtree.h> ++#include <ldns/sha1.h> ++#include <ldns/sha2.h> ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#define LDNS_IP4ADDRLEN (32/8) ++#define LDNS_IP6ADDRLEN (128/8) ++#define LDNS_PORT 53 ++#define LDNS_ROOT_LABEL_STR "." ++#define LDNS_DEFAULT_TTL 3600 ++ ++/* lookup tables for standard DNS stuff */ ++ ++/** Taken from RFC 2538, section 2.1. */ ++extern ldns_lookup_table ldns_certificate_types[]; ++/** Taken from RFC 2535, section 7. */ ++extern ldns_lookup_table ldns_algorithms[]; ++/** Taken from RFC 2538. */ ++extern ldns_lookup_table ldns_cert_algorithms[]; ++/** rr types */ ++extern ldns_lookup_table ldns_rr_classes[]; ++/** Response codes */ ++extern ldns_lookup_table ldns_rcodes[]; ++/** Operation codes */ ++extern ldns_lookup_table ldns_opcodes[]; ++/** EDNS flags */ ++extern ldns_lookup_table ldns_edns_flags[]; ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* LDNS_DNS_H */ +diff --git a/ldns/include/ldns/net.h b/ldns/include/ldns/net.h +new file mode 100644 +index 0000000..692a9fb +--- /dev/null ++++ b/ldns/include/ldns/net.h +@@ -0,0 +1,207 @@ ++/* ++ * net.h ++ * ++ * DNS Resolver definitions ++ * ++ * a Net::DNS like library for C ++ * ++ * (c) NLnet Labs, 2005-2006 ++ * ++ * See the file LICENSE for the license ++ */ ++ ++#ifndef LDNS_NET_H ++#define LDNS_NET_H ++ ++#include <ldns/ldns.h> ++#include <sys/socket.h> ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#define LDNS_DEFAULT_TIMEOUT_SEC 5 ++#define LDNS_DEFAULT_TIMEOUT_USEC 0 ++ ++/** ++ * \file ++ * ++ * Contains functions to send and receive packets over a network. ++ */ ++ ++/** ++ * Sends a buffer to an ip using udp and return the respons as a ldns_pkt ++ * \param[in] qbin the ldns_buffer to be send ++ * \param[in] to the ip addr to send to ++ * \param[in] tolen length of the ip addr ++ * \param[in] timeout the timeout value for the network ++ * \param[out] answersize size of the packet ++ * \param[out] result packet with the answer ++ * \return status ++ */ ++ldns_status ldns_udp_send(uint8_t **result, ldns_buffer *qbin, const struct sockaddr_storage *to, socklen_t tolen, struct timeval timeout, size_t *answersize); ++ ++/** ++ * Send an udp query and don't wait for an answer but return ++ * the socket ++ * \param[in] qbin the ldns_buffer to be send ++ * \param[in] to the ip addr to send to ++ * \param[in] tolen length of the ip addr ++ * \param[in] timeout *unused*, was the timeout value for the network ++ * \return the socket used ++ */ ++int ldns_udp_bgsend(ldns_buffer *qbin, const struct sockaddr_storage *to, socklen_t tolen, struct timeval timeout); ++ ++/** ++ * Send an tcp query and don't wait for an answer but return ++ * the socket ++ * \param[in] qbin the ldns_buffer to be send ++ * \param[in] to the ip addr to send to ++ * \param[in] tolen length of the ip addr ++ * \param[in] timeout the timeout value for the connect attempt ++ * \return the socket used ++ */ ++int ldns_tcp_bgsend(ldns_buffer *qbin, const struct sockaddr_storage *to, socklen_t tolen, struct timeval timeout); ++ ++/** ++ * Sends a buffer to an ip using tcp and return the respons as a ldns_pkt ++ * \param[in] qbin the ldns_buffer to be send ++ * \param[in] qbin the ldns_buffer to be send ++ * \param[in] to the ip addr to send to ++ * \param[in] tolen length of the ip addr ++ * \param[in] timeout the timeout value for the network ++ * \param[out] answersize size of the packet ++ * \param[out] result packet with the answer ++ * \return status ++ */ ++ldns_status ldns_tcp_send(uint8_t **result, ldns_buffer *qbin, const struct sockaddr_storage *to, socklen_t tolen, struct timeval timeout, size_t *answersize); ++ ++/** ++ * Sends ptk to the nameserver at the resolver object. Returns the data ++ * as a ldns_pkt ++ * ++ * \param[out] pkt packet received from the nameserver ++ * \param[in] r the resolver to use ++ * \param[in] query_pkt the query to send ++ * \return status ++ */ ++ldns_status ldns_send(ldns_pkt **pkt, ldns_resolver *r, const ldns_pkt *query_pkt); ++ ++/** ++ * Sends and ldns_buffer (presumably containing a packet to the nameserver at the resolver object. Returns the data ++ * as a ldns_pkt ++ * ++ * \param[out] pkt packet received from the nameserver ++ * \param[in] r the resolver to use ++ * \param[in] qb the buffer to send ++ * \param[in] tsig_mac the tsig MAC to authenticate the response with (NULL to do no TSIG authentication) ++ * \return status ++ */ ++ldns_status ldns_send_buffer(ldns_pkt **pkt, ldns_resolver *r, ldns_buffer *qb, ldns_rdf *tsig_mac); ++ ++/** ++ * Create a tcp socket to the specified address ++ * \param[in] to ip and family ++ * \param[in] tolen length of to ++ * \param[in] timeout timeout for the connect attempt ++ * \return a socket descriptor ++ */ ++int ldns_tcp_connect(const struct sockaddr_storage *to, socklen_t tolen, struct timeval timeout); ++ ++/** ++ * Create a udp socket to the specified address ++ * \param[in] to ip and family ++ * \param[in] timeout *unused*, was timeout for the socket ++ * \return a socket descriptor ++ */ ++int ldns_udp_connect(const struct sockaddr_storage *to, struct timeval timeout); ++ ++/** ++ * send a query via tcp to a server. Don't want for the answer ++ * ++ * \param[in] qbin the buffer to send ++ * \param[in] sockfd the socket to use ++ * \param[in] to which ip to send it ++ * \param[in] tolen socketlen ++ * \return number of bytes sent ++ */ ++ssize_t ldns_tcp_send_query(ldns_buffer *qbin, int sockfd, const struct sockaddr_storage *to, socklen_t tolen); ++ ++/** ++ * send a query via udp to a server. Don;t want for the answer ++ * ++ * \param[in] qbin the buffer to send ++ * \param[in] sockfd the socket to use ++ * \param[in] to which ip to send it ++ * \param[in] tolen socketlen ++ * \return number of bytes sent ++ */ ++ssize_t ldns_udp_send_query(ldns_buffer *qbin, int sockfd, const struct sockaddr_storage *to, socklen_t tolen); ++ ++/** ++ * Gives back a raw packet from the wire and reads the header data from the given ++ * socket. Allocates the data (of size size) itself, so don't forget to free ++ * ++ * \param[in] sockfd the socket to read from ++ * \param[out] size the number of bytes that are read ++ * \param[in] timeout the time allowed between packets. ++ * \return the data read ++ */ ++uint8_t *ldns_tcp_read_wire_timeout(int sockfd, size_t *size, struct timeval timeout); ++ ++/** ++ * This routine may block. Use ldns_tcp_read_wire_timeout, it checks timeouts. ++ * Gives back a raw packet from the wire and reads the header data from the given ++ * socket. Allocates the data (of size size) itself, so don't forget to free ++ * ++ * \param[in] sockfd the socket to read from ++ * \param[out] size the number of bytes that are read ++ * \return the data read ++ */ ++uint8_t *ldns_tcp_read_wire(int sockfd, size_t *size); ++ ++/** ++ * Gives back a raw packet from the wire and reads the header data from the given ++ * socket. Allocates the data (of size size) itself, so don't forget to free ++ * ++ * \param[in] sockfd the socket to read from ++ * \param[in] fr the address of the client (if applicable) ++ * \param[in] *frlen the lenght of the client's addr (if applicable) ++ * \param[out] size the number of bytes that are read ++ * \return the data read ++ */ ++uint8_t *ldns_udp_read_wire(int sockfd, size_t *size, struct sockaddr_storage *fr, socklen_t *frlen); ++ ++/** ++ * returns the native sockaddr representation from the rdf. ++ * \param[in] rd the ldns_rdf to operate on ++ * \param[in] port what port to use. 0 means; use default (53) ++ * \param[out] size what is the size of the sockaddr_storage ++ * \return struct sockaddr* the address in the format so other ++ * functions can use it (sendto) ++ */ ++struct sockaddr_storage * ldns_rdf2native_sockaddr_storage(const ldns_rdf *rd, uint16_t port, size_t *size); ++ ++/** ++ * returns an rdf with the sockaddr info. works for ip4 and ip6 ++ * \param[in] sock the struct sockaddr_storage to convert ++ * \param[in] port what port was used. When NULL this is not set ++ * \return ldns_rdf* wth the address ++ */ ++ldns_rdf * ldns_sockaddr_storage2rdf(struct sockaddr_storage *sock, uint16_t *port); ++ ++/** ++ * Prepares the resolver for an axfr query ++ * The query is sent and the answers can be read with ldns_axfr_next ++ * \param[in] resolver the resolver to use ++ * \param[in] domain the domain to exfr ++ * \param[in] c the class to use ++ * \return ldns_status the status of the transfer ++ */ ++ldns_status ldns_axfr_start(ldns_resolver *resolver, ldns_rdf *domain, ldns_rr_class c); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* LDNS_NET_H */ +diff --git a/ldns/include/ldns/packet.h b/ldns/include/ldns/packet.h +new file mode 100644 +index 0000000..e66aa34 +--- /dev/null ++++ b/ldns/include/ldns/packet.h +@@ -0,0 +1,891 @@ ++/* ++ * packet.h ++ * ++ * DNS packet definitions ++ * ++ * a Net::DNS like library for C ++ * ++ * (c) NLnet Labs, 2005-2006 ++ * ++ * See the file LICENSE for the license ++ */ ++ ++/** ++ * \file ++ * ++ * Contains the definition of ldns_pkt and its parts, as well ++ * as functions to manipulate those. ++ */ ++ ++ ++#ifndef LDNS_PACKET_H ++#define LDNS_PACKET_H ++ ++#define LDNS_MAX_PACKETLEN 65535 ++ ++/* allow flags to be given to mk_query */ ++#define LDNS_QR 1 /* QueRy - query flag */ ++#define LDNS_AA 2 /* Authoritative Answer - server flag */ ++#define LDNS_TC 4 /* TrunCated - server flag */ ++#define LDNS_RD 8 /* Recursion Desired - query flag */ ++#define LDNS_CD 16 /* Checking Disabled - query flag */ ++#define LDNS_RA 32 /* Recursion Available - server flag */ ++#define LDNS_AD 64 /* Authenticated Data - server flag */ ++ ++#include <ldns/error.h> ++#include <ldns/common.h> ++#include <ldns/rr.h> ++#include <sys/time.h> ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/* opcodes for pkt's */ ++enum ldns_enum_pkt_opcode { ++ LDNS_PACKET_QUERY = 0, ++ LDNS_PACKET_IQUERY = 1, ++ LDNS_PACKET_STATUS = 2, /* there is no 3?? DNS is weird */ ++ LDNS_PACKET_NOTIFY = 4, ++ LDNS_PACKET_UPDATE = 5 ++}; ++typedef enum ldns_enum_pkt_opcode ldns_pkt_opcode; ++ ++/* rcodes for pkts */ ++enum ldns_enum_pkt_rcode { ++ LDNS_RCODE_NOERROR = 0, ++ LDNS_RCODE_FORMERR = 1, ++ LDNS_RCODE_SERVFAIL = 2, ++ LDNS_RCODE_NXDOMAIN = 3, ++ LDNS_RCODE_NOTIMPL = 4, ++ LDNS_RCODE_REFUSED = 5, ++ LDNS_RCODE_YXDOMAIN = 6, ++ LDNS_RCODE_YXRRSET = 7, ++ LDNS_RCODE_NXRRSET = 8, ++ LDNS_RCODE_NOTAUTH = 9, ++ LDNS_RCODE_NOTZONE = 10 ++}; ++typedef enum ldns_enum_pkt_rcode ldns_pkt_rcode; ++ ++/** ++ * Header of a dns packet ++ * ++ * Contains the information about the packet itself, as specified in RFC1035 ++<pre> ++4.1.1. Header section format ++ ++The header contains the following fields: ++ ++ 1 1 1 1 1 1 ++ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 ++ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ ++ | ID | ++ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ ++ |QR| Opcode |AA|TC|RD|RA| Z | RCODE | ++ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ ++ | QDCOUNT | ++ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ ++ | ANCOUNT | ++ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ ++ | NSCOUNT | ++ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ ++ | ARCOUNT | ++ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ ++ ++where: ++ ++ID A 16 bit identifier assigned by the program that ++ generates any kind of query. This identifier is copied ++ the corresponding reply and can be used by the requester ++ to match up replies to outstanding queries. ++ ++QR A one bit field that specifies whether this message is a ++ query (0), or a response (1). ++ ++OPCODE A four bit field that specifies kind of query in this ++ message. This value is set by the originator of a query ++ and copied into the response. The values are: ++ ++ 0 a standard query (QUERY) ++ ++ 1 an inverse query (IQUERY) ++ ++ 2 a server status request (STATUS) ++ ++ 3-15 reserved for future use ++ ++AA Authoritative Answer - this bit is valid in responses, ++ and specifies that the responding name server is an ++ authority for the domain name in question section. ++ ++ Note that the contents of the answer section may have ++ multiple owner names because of aliases. The AA bit ++ ++ corresponds to the name which matches the query name, or ++ the first owner name in the answer section. ++ ++TC TrunCation - specifies that this message was truncated ++ due to length greater than that permitted on the ++ transmission channel. ++ ++RD Recursion Desired - this bit may be set in a query and ++ is copied into the response. If RD is set, it directs ++ the name server to pursue the query recursively. ++ Recursive query support is optional. ++ ++RA Recursion Available - this be is set or cleared in a ++ response, and denotes whether recursive query support is ++ available in the name server. ++ ++Z Reserved for future use. Must be zero in all queries ++ and responses. ++ ++RCODE Response code - this 4 bit field is set as part of ++ responses. The values have the following ++ interpretation: ++ ++ 0 No error condition ++ ++ 1 Format error - The name server was ++ unable to interpret the query. ++ ++ 2 Server failure - The name server was ++ unable to process this query due to a ++ problem with the name server. ++ ++ 3 Name Error - Meaningful only for ++ responses from an authoritative name ++ server, this code signifies that the ++ domain name referenced in the query does ++ not exist. ++ ++ 4 Not Implemented - The name server does ++ not support the requested kind of query. ++ ++ 5 Refused - The name server refuses to ++ perform the specified operation for ++ policy reasons. For example, a name ++ server may not wish to provide the ++ information to the particular requester, ++ or a name server may not wish to perform ++ a particular operation (e.g., zone ++ ++ transfer) for particular data. ++ ++ 6-15 Reserved for future use. ++ ++QDCOUNT an unsigned 16 bit integer specifying the number of ++ entries in the question section. ++ ++ANCOUNT an unsigned 16 bit integer specifying the number of ++ resource records in the answer section. ++ ++NSCOUNT an unsigned 16 bit integer specifying the number of name ++ server resource records in the authority records ++ section. ++ ++ARCOUNT an unsigned 16 bit integer specifying the number of ++ resource records in the additional records section. ++ ++</pre> ++ */ ++struct ldns_struct_hdr ++{ ++ /** Id of a packet */ ++ uint16_t _id; ++ /** Query bit (0=query, 1=answer) */ ++ bool _qr; ++ /** Authoritative answer */ ++ bool _aa; ++ /** Packet truncated */ ++ bool _tc; ++ /** Recursion desired */ ++ bool _rd; ++ /** Checking disabled */ ++ bool _cd; ++ /** Recursion available */ ++ bool _ra; ++ /** Authentic data */ ++ bool _ad; ++ /** Query type */ ++ ldns_pkt_opcode _opcode; /* XXX 8 bits? */ ++ /** Response code */ ++ uint8_t _rcode; ++ /** question sec */ ++ uint16_t _qdcount; ++ /** answer sec */ ++ uint16_t _ancount; ++ /** auth sec */ ++ uint16_t _nscount; ++ /** add sec */ ++ uint16_t _arcount; ++}; ++typedef struct ldns_struct_hdr ldns_hdr; ++ ++/** ++ * DNS packet ++ * ++ * This structure contains a complete DNS packet (either a query or an answer) ++ * ++ * It is the complete representation of what you actually send to a ++ * nameserver, and what it sends back (assuming you are the client here). ++ */ ++struct ldns_struct_pkt ++{ ++ /** Header section */ ++ ldns_hdr *_header; ++ /* extra items needed in a packet */ ++ /** The size of the wire format of the packet in octets */ ++ ldns_rdf *_answerfrom; ++ /** Timestamp of the time the packet was sent or created */ ++ struct timeval timestamp; ++ /** The duration of the query this packet is an answer to */ ++ uint32_t _querytime; ++ /** The size of the wire format of the packet in octets */ ++ size_t _size; ++ /** Optional tsig rr */ ++ ldns_rr *_tsig_rr; ++ /** EDNS0 available buffer size, see RFC2671 */ ++ uint16_t _edns_udp_size; ++ /** EDNS0 Extended rcode */ ++ uint8_t _edns_extended_rcode; ++ /** EDNS Version */ ++ uint8_t _edns_version; ++ /* OPT pseudo-RR presence flag */ ++ uint8_t _edns_present; ++ /** Reserved EDNS data bits */ ++ uint16_t _edns_z; ++ /** Arbitrary EDNS rdata */ ++ ldns_rdf *_edns_data; ++ /** Question section */ ++ ldns_rr_list *_question; ++ /** Answer section */ ++ ldns_rr_list *_answer; ++ /** Authority section */ ++ ldns_rr_list *_authority; ++ /** Additional section */ ++ ldns_rr_list *_additional; ++}; ++typedef struct ldns_struct_pkt ldns_pkt; ++ ++/** ++ * The sections of a packet ++ */ ++enum ldns_enum_pkt_section { ++ LDNS_SECTION_QUESTION = 0, ++ LDNS_SECTION_ANSWER = 1, ++ LDNS_SECTION_AUTHORITY = 2, ++ LDNS_SECTION_ADDITIONAL = 3, ++ /** bogus section, if not interested */ ++ LDNS_SECTION_ANY = 4, ++ /** used to get all non-question rrs from a packet */ ++ LDNS_SECTION_ANY_NOQUESTION = 5 ++}; ++typedef enum ldns_enum_pkt_section ldns_pkt_section; ++ ++/** ++ * The different types of packets ++ */ ++enum ldns_enum_pkt_type { ++ LDNS_PACKET_QUESTION, ++ LDNS_PACKET_REFERRAL, ++ LDNS_PACKET_ANSWER, ++ LDNS_PACKET_NXDOMAIN, ++ LDNS_PACKET_NODATA, ++ LDNS_PACKET_UNKNOWN ++}; ++typedef enum ldns_enum_pkt_type ldns_pkt_type; ++ ++/* prototypes */ ++ ++/* read */ ++ ++/** ++ * Read the packet id ++ * \param[in] p the packet ++ * \return the packet id ++ */ ++uint16_t ldns_pkt_id(const ldns_pkt *p); ++/** ++ * Read the packet's qr bit ++ * \param[in] p the packet ++ * \return value of the bit ++ */ ++bool ldns_pkt_qr(const ldns_pkt *p); ++/** ++ * Read the packet's aa bit ++ * \param[in] p the packet ++ * \return value of the bit ++ */ ++bool ldns_pkt_aa(const ldns_pkt *p); ++/** ++ * Read the packet's tc bit ++ * \param[in] p the packet ++ * \return value of the bit ++ */ ++bool ldns_pkt_tc(const ldns_pkt *p); ++/** ++ * Read the packet's rd bit ++ * \param[in] p the packet ++ * \return value of the bit ++ */ ++bool ldns_pkt_rd(const ldns_pkt *p); ++/** ++ * Read the packet's cd bit ++ * \param[in] p the packet ++ * \return value of the bit ++ */ ++bool ldns_pkt_cd(const ldns_pkt *p); ++/** ++ * Read the packet's ra bit ++ * \param[in] p the packet ++ * \return value of the bit ++ */ ++bool ldns_pkt_ra(const ldns_pkt *p); ++/** ++ * Read the packet's ad bit ++ * \param[in] p the packet ++ * \return value of the bit ++ */ ++bool ldns_pkt_ad(const ldns_pkt *p); ++/** ++ * Read the packet's code ++ * \param[in] p the packet ++ * \return the opcode ++ */ ++ldns_pkt_opcode ldns_pkt_get_opcode(const ldns_pkt *p); ++/** ++ * Return the packet's respons code ++ * \param[in] p the packet ++ * \return the respons code ++ */ ++ldns_pkt_rcode ldns_pkt_get_rcode(const ldns_pkt *p); ++/** ++ * Return the packet's qd count ++ * \param[in] p the packet ++ * \return the qd count ++ */ ++uint16_t ldns_pkt_qdcount(const ldns_pkt *p); ++/** ++ * Return the packet's an count ++ * \param[in] p the packet ++ * \return the an count ++ */ ++uint16_t ldns_pkt_ancount(const ldns_pkt *p); ++/** ++ * Return the packet's ns count ++ * \param[in] p the packet ++ * \return the ns count ++ */ ++uint16_t ldns_pkt_nscount(const ldns_pkt *p); ++/** ++ * Return the packet's ar count ++ * \param[in] p the packet ++ * \return the ar count ++ */ ++uint16_t ldns_pkt_arcount(const ldns_pkt *p); ++ ++/** ++ * Return the packet's answerfrom ++ * \param[in] p packet ++ * \return the name of the server ++ */ ++ldns_rdf *ldns_pkt_answerfrom(const ldns_pkt *p); ++ ++/** ++ * Return the packet's timestamp ++ * \param[in] p the packet ++ * \return the timestamp ++ */ ++struct timeval ldns_pkt_timestamp(const ldns_pkt *p); ++/** ++ * Return the packet's querytime ++ * \param[in] p the packet ++ * \return the querytime ++ */ ++uint32_t ldns_pkt_querytime(const ldns_pkt *p); ++ ++/** ++ * Return the packet's size in bytes ++ * \param[in] p the packet ++ * \return the size ++ */ ++size_t ldns_pkt_size(const ldns_pkt *p); ++ ++/** ++ * Return the number of RRs in the given section. ++ * Returns the sum of all RRs when LDNS_SECTION_ANY is given. ++ * Returns the sum of all non-question RRs when LDNS_SECTION_ANY_NOQUESTION ++ * is given. ++ * \param[in] p the packet ++ * \param[in] s the section ++ * \return the number of RRs in the given section ++ */ ++uint16_t ldns_pkt_section_count(const ldns_pkt *p, ldns_pkt_section s); ++ ++/** ++ * Return the packet's tsig pseudo rr's ++ * \param[in] p the packet ++ * \return the tsig rr ++ */ ++ldns_rr *ldns_pkt_tsig(const ldns_pkt *p); ++ ++/** ++ * Return the packet's question section ++ * \param[in] p the packet ++ * \return the section ++ */ ++ldns_rr_list *ldns_pkt_question(const ldns_pkt *p); ++/** ++ * Return the packet's answer section ++ * \param[in] p the packet ++ * \return the section ++ */ ++ldns_rr_list *ldns_pkt_answer(const ldns_pkt *p); ++/** ++ * Return the packet's authority section ++ * \param[in] p the packet ++ * \return the section ++ */ ++ldns_rr_list *ldns_pkt_authority(const ldns_pkt *p); ++/** ++ * Return the packet's additional section ++ * \param[in] p the packet ++ * \return the section ++ */ ++ldns_rr_list *ldns_pkt_additional(const ldns_pkt *p); ++/** ++ * Return the packet's question, answer, authority and additional sections ++ * concatenated, in a new rr_list clone. ++ * \param[in] p the packet ++ * \return the rrs ++ */ ++ldns_rr_list *ldns_pkt_all(const ldns_pkt *p); ++/** ++ * Return the packet's answer, authority and additional sections concatenated, ++ * in a new rr_list clone. Like ldns_pkt_all but without the questions. ++ * \param[in] p the packet ++ * \return the rrs except the question rrs ++ */ ++ldns_rr_list *ldns_pkt_all_noquestion(const ldns_pkt *p); ++ ++/** ++ * return all the rr_list's in the packet. Clone the lists, instead ++ * of returning pointers. ++ * \param[in] p the packet to look in ++ * \param[in] s what section(s) to return ++ * \return ldns_rr_list with the rr's or NULL if none were found ++ */ ++ldns_rr_list *ldns_pkt_get_section_clone(const ldns_pkt *p, ldns_pkt_section s); ++ ++/** ++ * return all the rr with a specific name from a packet. Optionally ++ * specify from which section in the packet ++ * \param[in] p the packet ++ * \param[in] r the name ++ * \param[in] s the packet's section ++ * \return a list with the rr's or NULL if none were found ++ */ ++ldns_rr_list *ldns_pkt_rr_list_by_name(ldns_pkt *p, ldns_rdf *r, ldns_pkt_section s); ++/** ++ * return all the rr with a specific type from a packet. Optionally ++ * specify from which section in the packet ++ * \param[in] p the packet ++ * \param[in] t the type ++ * \param[in] s the packet's section ++ * \return a list with the rr's or NULL if none were found ++ */ ++ldns_rr_list *ldns_pkt_rr_list_by_type(const ldns_pkt *p, ldns_rr_type t, ldns_pkt_section s); ++/** ++ * return all the rr with a specific type and type from a packet. Optionally ++ * specify from which section in the packet ++ * \param[in] packet the packet ++ * \param[in] ownername the name ++ * \param[in] type the type ++ * \param[in] sec the packet's section ++ * \return a list with the rr's or NULL if none were found ++ */ ++ldns_rr_list *ldns_pkt_rr_list_by_name_and_type(const ldns_pkt *packet, const ldns_rdf *ownername, ldns_rr_type type, ldns_pkt_section sec); ++ ++ ++/** ++ * check to see if an rr exist in the packet ++ * \param[in] pkt the packet to examine ++ * \param[in] sec in which section to look ++ * \param[in] rr the rr to look for ++ */ ++bool ldns_pkt_rr(ldns_pkt *pkt, ldns_pkt_section sec, ldns_rr *rr); ++ ++ ++/** ++ * sets the flags in a packet. ++ * \param[in] pkt the packet to operate on ++ * \param[in] flags ORed values: LDNS_QR| LDNS_AR for instance ++ * \return true on success otherwise false ++ */ ++bool ldns_pkt_set_flags(ldns_pkt *pkt, uint16_t flags); ++ ++/** ++ * Set the packet's id ++ * \param[in] p the packet ++ * \param[in] id the id to set ++ */ ++void ldns_pkt_set_id(ldns_pkt *p, uint16_t id); ++/** ++ * Set the packet's id to a random value ++ * \param[in] p the packet ++ */ ++void ldns_pkt_set_random_id(ldns_pkt *p); ++/** ++ * Set the packet's qr bit ++ * \param[in] p the packet ++ * \param[in] b the value to set (boolean) ++ */ ++void ldns_pkt_set_qr(ldns_pkt *p, bool b); ++/** ++ * Set the packet's aa bit ++ * \param[in] p the packet ++ * \param[in] b the value to set (boolean) ++ */ ++void ldns_pkt_set_aa(ldns_pkt *p, bool b); ++/** ++ * Set the packet's tc bit ++ * \param[in] p the packet ++ * \param[in] b the value to set (boolean) ++ */ ++void ldns_pkt_set_tc(ldns_pkt *p, bool b); ++/** ++ * Set the packet's rd bit ++ * \param[in] p the packet ++ * \param[in] b the value to set (boolean) ++ */ ++void ldns_pkt_set_rd(ldns_pkt *p, bool b); ++/** ++ * Set the packet's cd bit ++ * \param[in] p the packet ++ * \param[in] b the value to set (boolean) ++ */ ++void ldns_pkt_set_cd(ldns_pkt *p, bool b); ++/** ++ * Set the packet's ra bit ++ * \param[in] p the packet ++ * \param[in] b the value to set (boolean) ++ */ ++void ldns_pkt_set_ra(ldns_pkt *p, bool b); ++/** ++ * Set the packet's ad bit ++ * \param[in] p the packet ++ * \param[in] b the value to set (boolean) ++ */ ++void ldns_pkt_set_ad(ldns_pkt *p, bool b); ++ ++/** ++ * Set the packet's opcode ++ * \param[in] p the packet ++ * \param[in] c the opcode ++ */ ++void ldns_pkt_set_opcode(ldns_pkt *p, ldns_pkt_opcode c); ++/** ++ * Set the packet's respons code ++ * \param[in] p the packet ++ * \param[in] c the rcode ++ */ ++void ldns_pkt_set_rcode(ldns_pkt *p, uint8_t c); ++/** ++ * Set the packet's qd count ++ * \param[in] p the packet ++ * \param[in] c the count ++ */ ++void ldns_pkt_set_qdcount(ldns_pkt *p, uint16_t c); ++/** ++ * Set the packet's an count ++ * \param[in] p the packet ++ * \param[in] c the count ++ */ ++void ldns_pkt_set_ancount(ldns_pkt *p, uint16_t c); ++/** ++ * Set the packet's ns count ++ * \param[in] p the packet ++ * \param[in] c the count ++ */ ++void ldns_pkt_set_nscount(ldns_pkt *p, uint16_t c); ++/** ++ * Set the packet's arcount ++ * \param[in] p the packet ++ * \param[in] c the count ++ */ ++void ldns_pkt_set_arcount(ldns_pkt *p, uint16_t c); ++/** ++ * Set the packet's answering server ++ * \param[in] p the packet ++ * \param[in] r the address ++ */ ++void ldns_pkt_set_answerfrom(ldns_pkt *p, ldns_rdf *r); ++/** ++ * Set the packet's query time ++ * \param[in] p the packet ++ * \param[in] t the querytime in msec ++ */ ++void ldns_pkt_set_querytime(ldns_pkt *p, uint32_t t); ++/** ++ * Set the packet's size ++ * \param[in] p the packet ++ * \param[in] s the size ++ */ ++void ldns_pkt_set_size(ldns_pkt *p, size_t s); ++ ++/** ++ * Set the packet's timestamp ++ * \param[in] p the packet ++ * \param[in] timeval the timestamp ++ */ ++void ldns_pkt_set_timestamp(ldns_pkt *p, struct timeval timeval); ++/** ++ * Set a packet's section count to x ++ * \param[in] p the packet ++ * \param[in] s the section ++ * \param[in] x the section count ++ */ ++void ldns_pkt_set_section_count(ldns_pkt *p, ldns_pkt_section s, uint16_t x); ++/** ++ * Set the packet's tsig rr ++ * \param[in] p the packet ++ * \param[in] t the tsig rr ++ */ ++void ldns_pkt_set_tsig(ldns_pkt *p, ldns_rr *t); ++ ++/** ++ * looks inside the packet to determine ++ * what kind of packet it is, AUTH, NXDOMAIN, REFERRAL, etc. ++ * \param[in] p the packet to examine ++ * \return the type of packet ++ */ ++ldns_pkt_type ldns_pkt_reply_type(ldns_pkt *p); ++ ++/** ++ * return the packet's edns udp size ++ * \param[in] packet the packet ++ * \return the size ++ */ ++uint16_t ldns_pkt_edns_udp_size(const ldns_pkt *packet); ++/** ++ * return the packet's edns extended rcode ++ * \param[in] packet the packet ++ * \return the rcode ++ */ ++uint8_t ldns_pkt_edns_extended_rcode(const ldns_pkt *packet); ++/** ++ * return the packet's edns version ++ * \param[in] packet the packet ++ * \return the version ++ */ ++uint8_t ldns_pkt_edns_version(const ldns_pkt *packet); ++/** ++ * return the packet's edns z value ++ * \param[in] packet the packet ++ * \return the z value ++ */ ++uint16_t ldns_pkt_edns_z(const ldns_pkt *packet); ++/** ++ * return the packet's edns data ++ * \param[in] packet the packet ++ * \return the data ++ */ ++ldns_rdf *ldns_pkt_edns_data(const ldns_pkt *packet); ++ ++/** ++ * return the packet's edns do bit ++ * \param[in] packet the packet ++ * \return the bit's value ++ */ ++bool ldns_pkt_edns_do(const ldns_pkt *packet); ++/** ++ * Set the packet's edns do bit ++ * \param[in] packet the packet ++ * \param[in] value the bit's new value ++ */ ++void ldns_pkt_set_edns_do(ldns_pkt *packet, bool value); ++ ++/** ++ * returns true if this packet needs and EDNS rr to be sent. ++ * At the moment the only reason is an expected packet ++ * size larger than 512 bytes, but for instance dnssec would ++ * be a good reason too. ++ * ++ * \param[in] packet the packet to check ++ * \return true if packet needs edns rr ++ */ ++bool ldns_pkt_edns(const ldns_pkt *packet); ++ ++/** ++ * Set the packet's edns udp size ++ * \param[in] packet the packet ++ * \param[in] s the size ++ */ ++void ldns_pkt_set_edns_udp_size(ldns_pkt *packet, uint16_t s); ++/** ++ * Set the packet's edns extended rcode ++ * \param[in] packet the packet ++ * \param[in] c the code ++ */ ++void ldns_pkt_set_edns_extended_rcode(ldns_pkt *packet, uint8_t c); ++/** ++ * Set the packet's edns version ++ * \param[in] packet the packet ++ * \param[in] v the version ++ */ ++void ldns_pkt_set_edns_version(ldns_pkt *packet, uint8_t v); ++/** ++ * Set the packet's edns z value ++ * \param[in] packet the packet ++ * \param[in] z the value ++ */ ++void ldns_pkt_set_edns_z(ldns_pkt *packet, uint16_t z); ++/** ++ * Set the packet's edns data ++ * \param[in] packet the packet ++ * \param[in] data the data ++ */ ++void ldns_pkt_set_edns_data(ldns_pkt *packet, ldns_rdf *data); ++ ++/** ++ * allocates and initializes a ldns_pkt structure. ++ * \return pointer to the new packet ++ */ ++ldns_pkt *ldns_pkt_new(void); ++ ++/** ++ * frees the packet structure and all data that it contains. ++ * \param[in] packet The packet structure to free ++ * \return void ++ */ ++void ldns_pkt_free(ldns_pkt *packet); ++ ++/** ++ * creates a query packet for the given name, type, class. ++ * \param[out] p the packet to be returned ++ * \param[in] rr_name the name to query for (as string) ++ * \param[in] rr_type the type to query for ++ * \param[in] rr_class the class to query for ++ * \param[in] flags packet flags ++ * \return LDNS_STATUS_OK or a ldns_status mesg with the error ++ */ ++ldns_status ldns_pkt_query_new_frm_str(ldns_pkt **p, const char *rr_name, ldns_rr_type rr_type, ldns_rr_class rr_class , uint16_t flags); ++ ++/** ++ * creates an IXFR request packet for the given name, class. ++ * adds the SOA record to the authority section. ++ * \param[out] p the packet to be returned ++ * \param[in] rr_name the name to query for (as string) ++ * \param[in] rr_class the class to query for ++ * \param[in] flags packet flags ++ * \param[in] soa soa record to be added to the authority section ++ * \return LDNS_STATUS_OK or a ldns_status mesg with the error ++ */ ++ldns_status ldns_pkt_ixfr_request_new_frm_str(ldns_pkt **p, const char *rr_name, ldns_rr_class rr_class, uint16_t flags, ldns_rr* soa); ++ ++/** ++ * creates a packet with a query in it for the given name, type and class. ++ * \param[in] rr_name the name to query for ++ * \param[in] rr_type the type to query for ++ * \param[in] rr_class the class to query for ++ * \param[in] flags packet flags ++ * \return ldns_pkt* a pointer to the new pkt ++ */ ++ldns_pkt *ldns_pkt_query_new(ldns_rdf *rr_name, ldns_rr_type rr_type, ldns_rr_class rr_class, uint16_t flags); ++ ++/** ++ * creates an IXFR request packet for the given name, type and class. ++ * adds the SOA record to the authority section. ++ * \param[in] rr_name the name to query for ++ * \param[in] rr_class the class to query for ++ * \param[in] flags packet flags ++ * \param[in] soa soa record to be added to the authority section ++ * \return ldns_pkt* a pointer to the new pkt ++ */ ++ldns_pkt *ldns_pkt_ixfr_request_new(ldns_rdf *rr_name, ldns_rr_class rr_class, uint16_t flags, ldns_rr* soa); ++ ++/** ++ * clones the given packet, creating a fully allocated copy ++ * ++ * \param[in] pkt the packet to clone ++ * \return ldns_pkt* pointer to the new packet ++ */ ++ldns_pkt *ldns_pkt_clone(const ldns_pkt *pkt); ++ ++/** ++ * directly set the additional section ++ * \param[in] p packet to operate on ++ * \param[in] rr rrlist to set ++ */ ++void ldns_pkt_set_additional(ldns_pkt *p, ldns_rr_list *rr); ++ ++/** ++ * directly set the answer section ++ * \param[in] p packet to operate on ++ * \param[in] rr rrlist to set ++ */ ++void ldns_pkt_set_answer(ldns_pkt *p, ldns_rr_list *rr); ++ ++/** ++ * directly set the question section ++ * \param[in] p packet to operate on ++ * \param[in] rr rrlist to set ++ */ ++void ldns_pkt_set_question(ldns_pkt *p, ldns_rr_list *rr); ++ ++/** ++ * directly set the auhority section ++ * \param[in] p packet to operate on ++ * \param[in] rr rrlist to set ++ */ ++void ldns_pkt_set_authority(ldns_pkt *p, ldns_rr_list *rr); ++ ++/** ++ * push an rr on a packet ++ * \param[in] packet packet to operate on ++ * \param[in] section where to put it ++ * \param[in] rr rr to push ++ * \return a boolean which is true when the rr was added ++ */ ++bool ldns_pkt_push_rr(ldns_pkt *packet, ldns_pkt_section section, ldns_rr *rr); ++ ++/** ++ * push an rr on a packet, provided the RR is not there. ++ * \param[in] pkt packet to operate on ++ * \param[in] sec where to put it ++ * \param[in] rr rr to push ++ * \return a boolean which is true when the rr was added ++ */ ++bool ldns_pkt_safe_push_rr(ldns_pkt *pkt, ldns_pkt_section sec, ldns_rr *rr); ++ ++/** ++ * push a rr_list on a packet ++ * \param[in] packet packet to operate on ++ * \param[in] section where to put it ++ * \param[in] list the rr_list to push ++ * \return a boolean which is true when the rr was added ++ */ ++bool ldns_pkt_push_rr_list(ldns_pkt *packet, ldns_pkt_section section, ldns_rr_list *list); ++ ++/** ++ * push an rr_list to a packet, provided the RRs are not already there. ++ * \param[in] pkt packet to operate on ++ * \param[in] sec where to put it ++ * \param[in] list the rr_list to push ++ * \return a boolean which is true when the rr was added ++ */ ++bool ldns_pkt_safe_push_rr_list(ldns_pkt *pkt, ldns_pkt_section sec, ldns_rr_list *list); ++ ++/** ++ * check if a packet is empty ++ * \param[in] p packet ++ * \return true: empty, false: not empty ++ */ ++bool ldns_pkt_empty(ldns_pkt *p); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* LDNS_PACKET_H */ +diff --git a/ldns/include/ldns/parse.h b/ldns/include/ldns/parse.h +new file mode 100644 +index 0000000..0e9034c +--- /dev/null ++++ b/ldns/include/ldns/parse.h +@@ -0,0 +1,167 @@ ++/* ++ * parse.h ++ * ++ * a Net::DNS like library for C ++ * LibDNS Team @ NLnet Labs ++ * (c) NLnet Labs, 2005-2006 ++ * See the file LICENSE for the license ++ */ ++ ++#ifndef LDNS_PARSE_H ++#define LDNS_PARSE_H ++ ++#include <ldns/common.h> ++#include <ldns/buffer.h> ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#define LDNS_PARSE_SKIP_SPACE "\f\n\r\v" ++#define LDNS_PARSE_NORMAL " \f\n\r\t\v" ++#define LDNS_PARSE_NO_NL " \t" ++#define LDNS_MAX_LINELEN 10230 ++#define LDNS_MAX_KEYWORDLEN 32 ++ ++ ++/** ++ * \file ++ * ++ * Contains some low-level parsing functions, mostly used in the _frm_str ++ * family of functions. ++ */ ++ ++/** ++ * different type of directives in zone files ++ * We now deal with $TTL, $ORIGIN and $INCLUDE. ++ * The latter is not implemented in ldns (yet) ++ */ ++enum ldns_enum_directive ++{ ++ LDNS_DIR_TTL, ++ LDNS_DIR_ORIGIN, ++ LDNS_DIR_INCLUDE ++}; ++typedef enum ldns_enum_directive ldns_directive; ++ ++/** ++ * returns a token/char from the stream F. ++ * This function deals with ( and ) in the stream, ++ * and ignores them when encountered ++ * \param[in] *f the file to read from ++ * \param[out] *token the read token is put here ++ * \param[in] *delim chars at which the parsing should stop ++ * \param[in] *limit how much to read. If 0 the builtin maximum is used ++ * \return 0 on error of EOF of the stream F. Otherwise return the length of what is read ++ */ ++ssize_t ldns_fget_token(FILE *f, char *token, const char *delim, size_t limit); ++ ++/** ++ * returns a token/char from the stream F. ++ * This function deals with ( and ) in the stream, ++ * and ignores when it finds them. ++ * \param[in] *f the file to read from ++ * \param[out] *token the token is put here ++ * \param[in] *delim chars at which the parsing should stop ++ * \param[in] *limit how much to read. If 0 use builtin maximum ++ * \param[in] line_nr pointer to an integer containing the current line number (for debugging purposes) ++ * \return 0 on error of EOF of F otherwise return the length of what is read ++ */ ++ssize_t ldns_fget_token_l(FILE *f, char *token, const char *delim, size_t limit, int *line_nr); ++ ++/** ++ * returns a token/char from the buffer b. ++ * This function deals with ( and ) in the buffer, ++ * and ignores when it finds them. ++ * \param[in] *b the buffer to read from ++ * \param[out] *token the token is put here ++ * \param[in] *delim chars at which the parsing should stop ++ * \param[in] *limit how much to read. If 0 the builtin maximum is used ++ * \returns 0 on error of EOF of b. Otherwise return the length of what is read ++ */ ++ssize_t ldns_bget_token(ldns_buffer *b, char *token, const char *delim, size_t limit); ++ ++/* ++ * searches for keyword and delim in a file. Gives everything back ++ * after the keyword + k_del until we hit d_del ++ * \param[in] f file pointer to read from ++ * \param[in] keyword keyword to look for ++ * \param[in] k_del keyword delimeter ++ * \param[out] data the data found ++ * \param[in] d_del the data delimeter ++ * \param[in] data_limit maximum size the the data buffer ++ * \return the number of character read ++ */ ++ssize_t ldns_fget_keyword_data(FILE *f, const char *keyword, const char *k_del, char *data, const char *d_del, size_t data_limit); ++ ++/* ++ * searches for keyword and delim. Gives everything back ++ * after the keyword + k_del until we hit d_del ++ * \param[in] f file pointer to read from ++ * \param[in] keyword keyword to look for ++ * \param[in] k_del keyword delimeter ++ * \param[out] data the data found ++ * \param[in] d_del the data delimeter ++ * \param[in] data_limit maximum size the the data buffer ++ * \param[in] line_nr pointer to an integer containing the current line number (for ++debugging purposes) ++ * \return the number of character read ++ */ ++ssize_t ldns_fget_keyword_data_l(FILE *f, const char *keyword, const char *k_del, char *data, const char *d_del, size_t data_limit, int *line_nr); ++ ++/* ++ * searches for keyword and delim in a buffer. Gives everything back ++ * after the keyword + k_del until we hit d_del ++ * \param[in] b buffer pointer to read from ++ * \param[in] keyword keyword to look for ++ * \param[in] k_del keyword delimeter ++ * \param[out] data the data found ++ * \param[in] d_del the data delimeter ++ * \param[in] data_limit maximum size the the data buffer ++ * \return the number of character read ++ */ ++ssize_t ldns_bget_keyword_data(ldns_buffer *b, const char *keyword, const char *k_del, char *data, const char *d_del, size_t data_limit); ++ ++/** ++ * returns the next character from a buffer. Advances the position pointer with 1. ++ * When end of buffer is reached returns EOF. This is the buffer's equivalent ++ * for getc(). ++ * \param[in] *buffer buffer to read from ++ * \return EOF on failure otherwise return the character ++ */ ++int ldns_bgetc(ldns_buffer *buffer); ++ ++/** ++ * skips all of the characters in the given string in the buffer, moving ++ * the position to the first character that is not in *s. ++ * \param[in] *buffer buffer to use ++ * \param[in] *s characters to skip ++ * \return void ++ */ ++void ldns_bskipcs(ldns_buffer *buffer, const char *s); ++ ++/** ++ * skips all of the characters in the given string in the fp, moving ++ * the position to the first character that is not in *s. ++ * \param[in] *fp file to use ++ * \param[in] *s characters to skip ++ * \return void ++ */ ++void ldns_fskipcs(FILE *fp, const char *s); ++ ++ ++/** ++ * skips all of the characters in the given string in the fp, moving ++ * the position to the first character that is not in *s. ++ * \param[in] *fp file to use ++ * \param[in] *s characters to skip ++ * \param[in] line_nr pointer to an integer containing the current line number (for debugging purposes) ++ * \return void ++ */ ++void ldns_fskipcs_l(FILE *fp, const char *s, int *line_nr); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* LDNS_PARSE_H */ +diff --git a/ldns/include/ldns/radix.h b/ldns/include/ldns/radix.h +new file mode 100644 +index 0000000..1885959 +--- /dev/null ++++ b/ldns/include/ldns/radix.h +@@ -0,0 +1,240 @@ ++/* ++ * radix.h -- generic radix tree ++ * ++ * Copyright (c) 2012, NLnet Labs. All rights reserved. ++ * ++ * This software is open source. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * ++ * Redistributions of source code must retain the above copyright notice, ++ * this list of conditions and the following disclaimer. ++ * ++ * Redistributions in binary form must reproduce the above copyright notice, ++ * this list of conditions and the following disclaimer in the documentation ++ * and/or other materials provided with the distribution. ++ * ++ * Neither the name of the NLNET LABS nor the names of its contributors may ++ * be used to endorse or promote products derived from this software without ++ * specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED ++ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR ++ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ++ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING ++ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ * ++ */ ++ ++/** ++ * \file ++ * Radix tree. Implementation taken from NSD 4, adjusted for use in ldns. ++ * ++ */ ++ ++#ifndef LDNS_RADIX_H_ ++#define LDNS_RADIX_H_ ++ ++#include <ldns/error.h> ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++typedef uint16_t radix_strlen_t; ++typedef struct ldns_radix_array_t ldns_radix_array_t; ++typedef struct ldns_radix_node_t ldns_radix_node_t; ++typedef struct ldns_radix_t ldns_radix_t; ++ ++/** Radix node select edge array */ ++struct ldns_radix_array_t { ++ /** Additional string after the selection byte for this edge. */ ++ uint8_t* str; ++ /** Length of additional string for this edge. */ ++ radix_strlen_t len; ++ /** Node that deals with byte+str. */ ++ ldns_radix_node_t* edge; ++}; ++ ++/** A node in a radix tree */ ++struct ldns_radix_node_t { ++ /** Key corresponding to this node. */ ++ uint8_t* key; ++ /** Key length corresponding to this node. */ ++ radix_strlen_t klen; ++ /** Data corresponding to this node. */ ++ void* data; ++ /** Parent node. */ ++ ldns_radix_node_t* parent; ++ /** Index in the the parent node select edge array. */ ++ uint8_t parent_index; ++ /** Length of the array. */ ++ uint16_t len; ++ /** Offset of the array. */ ++ uint16_t offset; ++ /** Capacity of the array. */ ++ uint16_t capacity; ++ /** Select edge array. */ ++ ldns_radix_array_t* array; ++}; ++ ++/** An entire radix tree */ ++struct ldns_radix_t { ++ /** Root. */ ++ ldns_radix_node_t* root; ++ /** Number of nodes in tree. */ ++ size_t count; ++}; ++ ++/** ++ * Create a new radix tree. ++ * @return: new radix tree. ++ * ++ */ ++ldns_radix_t* ldns_radix_create(void); ++ ++/** ++ * Initialize radix tree. ++ * @param tree: uninitialized radix tree. ++ * ++ */ ++void ldns_radix_init(ldns_radix_t* tree); ++ ++/** ++ * Free the radix tree. ++ * @param tree: radix tree. ++ * ++ */ ++void ldns_radix_free(ldns_radix_t* tree); ++ ++/** ++ * Insert data into the tree. ++ * @param tree: tree to insert to. ++ * @param key: key. ++ * @param len: length of key. ++ * @param data: data. ++ * @return: status. ++ * ++ */ ++ldns_status ldns_radix_insert(ldns_radix_t* tree, uint8_t* key, ++ radix_strlen_t len, void* data); ++ ++/** ++ * Delete data from the tree. ++ * @param tree: tree to insert to. ++ * @param key: key. ++ * @param len: length of key. ++ * @return: unlinked data or NULL if not present. ++ * ++ */ ++void* ldns_radix_delete(ldns_radix_t* tree, uint8_t* key, radix_strlen_t len); ++ ++/** ++ * Search data in the tree. ++ * @param tree: tree to insert to. ++ * @param key: key. ++ * @param len: length of key. ++ * @return: the radix node or NULL if not found. ++ * ++ */ ++ldns_radix_node_t* ldns_radix_search(ldns_radix_t* tree, uint8_t* key, ++ radix_strlen_t len); ++ ++/** ++ * Search data in the tree, and if not found, find the closest smaller ++ * element in the tree. ++ * @param tree: tree to insert to. ++ * @param key: key. ++ * @param len: length of key. ++ * @param result: the radix node with the exact or closest match. NULL if ++ * the key is smaller than the smallest key in the tree. ++ * @return 1 if exact match, 0 otherwise. ++ * ++ */ ++int ldns_radix_find_less_equal(ldns_radix_t* tree, uint8_t* key, ++ radix_strlen_t len, ldns_radix_node_t** result); ++ ++/** ++ * Get the first element in the tree. ++ * @param tree: tree. ++ * @return: the radix node with the first element. ++ * ++ */ ++ldns_radix_node_t* ldns_radix_first(ldns_radix_t* tree); ++ ++/** ++ * Get the last element in the tree. ++ * @param tree: tree. ++ * @return: the radix node with the last element. ++ * ++ */ ++ldns_radix_node_t* ldns_radix_last(ldns_radix_t* tree); ++ ++/** ++ * Next element. ++ * @param node: node. ++ * @return: node with next element. ++ * ++ */ ++ldns_radix_node_t* ldns_radix_next(ldns_radix_node_t* node); ++ ++/** ++ * Previous element. ++ * @param node: node. ++ * @return: node with previous element. ++ * ++ */ ++ldns_radix_node_t* ldns_radix_prev(ldns_radix_node_t* node); ++ ++/** ++ * Split radix tree intwo. ++ * @param tree1: one tree. ++ * @param num: number of elements to split off. ++ * @param tree2: another tree. ++ * @return: status. ++ * ++ */ ++ldns_status ldns_radix_split(ldns_radix_t* tree1, size_t num, ++ ldns_radix_t** tree2); ++ ++/** ++ * Join two radix trees. ++ * @param tree1: one tree. ++ * @param tree2: another tree. ++ * @return: status. ++ * ++ */ ++ldns_status ldns_radix_join(ldns_radix_t* tree1, ldns_radix_t* tree2); ++ ++/** ++ * Call function for all nodes in the tree, such that leaf nodes are ++ * called before parent nodes. ++ * @param node: start node. ++ * @param func: function. ++ * @param arg: user argument. ++ * ++ */ ++void ldns_radix_traverse_postorder(ldns_radix_node_t* node, ++ void (*func)(ldns_radix_node_t*, void*), void* arg); ++ ++/** ++ * Print radix tree (for debugging purposes). ++ * @param fd: file descriptor. ++ * @param tree: tree. ++ * ++ */ ++void ldns_radix_printf(FILE* fd, ldns_radix_t* tree); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* LDNS_RADIX_H_ */ +diff --git a/ldns/include/ldns/rbtree.h b/ldns/include/ldns/rbtree.h +new file mode 100644 +index 0000000..c891934 +--- /dev/null ++++ b/ldns/include/ldns/rbtree.h +@@ -0,0 +1,230 @@ ++/* ++ * rbtree.h -- generic red-black tree ++ * ++ * Copyright (c) 2001-2008, NLnet Labs. All rights reserved. ++ * ++ * This software is open source. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * ++ * Redistributions of source code must retain the above copyright notice, ++ * this list of conditions and the following disclaimer. ++ * ++ * Redistributions in binary form must reproduce the above copyright notice, ++ * this list of conditions and the following disclaimer in the documentation ++ * and/or other materials provided with the distribution. ++ * ++ * Neither the name of the NLNET LABS nor the names of its contributors may ++ * be used to endorse or promote products derived from this software without ++ * specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED ++ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR ++ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ++ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING ++ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ * ++ */ ++ ++/** ++ * \file ++ * Red black tree. Implementation taken from NSD 3.0.5, adjusted for use ++ * in unbound (memory allocation, logging and so on). ++ */ ++ ++#ifndef LDNS_RBTREE_H_ ++#define LDNS_RBTREE_H_ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/** ++ * This structure must be the first member of the data structure in ++ * the rbtree. This allows easy casting between an rbnode_t and the ++ * user data (poor man's inheritance). ++ * Or you can use the data pointer member to get to your data item. ++ */ ++typedef struct ldns_rbnode_t ldns_rbnode_t; ++/** ++ * The rbnode_t struct definition. ++ */ ++struct ldns_rbnode_t { ++ /** parent in rbtree, RBTREE_NULL for root */ ++ ldns_rbnode_t *parent; ++ /** left node (smaller items) */ ++ ldns_rbnode_t *left; ++ /** right node (larger items) */ ++ ldns_rbnode_t *right; ++ /** pointer to sorting key */ ++ const void *key; ++ /** pointer to data */ ++ const void *data; ++ /** colour of this node */ ++ uint8_t color; ++}; ++ ++/** The nullpointer, points to empty node */ ++#define LDNS_RBTREE_NULL &ldns_rbtree_null_node ++/** the global empty node */ ++extern ldns_rbnode_t ldns_rbtree_null_node; ++ ++/** An entire red black tree */ ++typedef struct ldns_rbtree_t ldns_rbtree_t; ++/** definition for tree struct */ ++struct ldns_rbtree_t { ++ /** The root of the red-black tree */ ++ ldns_rbnode_t *root; ++ ++ /** The number of the nodes in the tree */ ++ size_t count; ++ ++ /** ++ * Key compare function. <0,0,>0 like strcmp. ++ * Return 0 on two NULL ptrs. ++ */ ++ int (*cmp) (const void *, const void *); ++}; ++ ++/** ++ * Create new tree (malloced) with given key compare function. ++ * @param cmpf: compare function (like strcmp) takes pointers to two keys. ++ * @return: new tree, empty. ++ */ ++ldns_rbtree_t *ldns_rbtree_create(int (*cmpf)(const void *, const void *)); ++ ++/** ++ * Free the complete tree (but not its keys) ++ * @param rbtree The tree to free ++ */ ++void ldns_rbtree_free(ldns_rbtree_t *rbtree); ++ ++/** ++ * Init a new tree (malloced by caller) with given key compare function. ++ * @param rbtree: uninitialised memory for new tree, returned empty. ++ * @param cmpf: compare function (like strcmp) takes pointers to two keys. ++ */ ++void ldns_rbtree_init(ldns_rbtree_t *rbtree, int (*cmpf)(const void *, const void *)); ++ ++/** ++ * Insert data into the tree. ++ * @param rbtree: tree to insert to. ++ * @param data: element to insert. ++ * @return: data ptr or NULL if key already present. ++ */ ++ldns_rbnode_t *ldns_rbtree_insert(ldns_rbtree_t *rbtree, ldns_rbnode_t *data); ++ ++/** ++ * Insert data into the tree (reversed arguments, for use as callback) ++ * \param[in] data element to insert ++ * \param[out] rbtree tree to insert in to ++ * \return data ptr or NULL if key is already present ++ */ ++void ldns_rbtree_insert_vref(ldns_rbnode_t *data, void *rbtree); ++ ++/** ++ * Delete element from tree. ++ * @param rbtree: tree to delete from. ++ * @param key: key of item to delete. ++ * @return: node that is now unlinked from the tree. User to delete it. ++ * returns 0 if node not present ++ */ ++ldns_rbnode_t *ldns_rbtree_delete(ldns_rbtree_t *rbtree, const void *key); ++ ++/** ++ * Find key in tree. Returns NULL if not found. ++ * @param rbtree: tree to find in. ++ * @param key: key that must match. ++ * @return: node that fits or NULL. ++ */ ++ldns_rbnode_t *ldns_rbtree_search(ldns_rbtree_t *rbtree, const void *key); ++ ++/** ++ * Find, but match does not have to be exact. ++ * @param rbtree: tree to find in. ++ * @param key: key to find position of. ++ * @param result: set to the exact node if present, otherwise to element that ++ * precedes the position of key in the tree. NULL if no smaller element. ++ * @return: true if exact match in result. Else result points to <= element, ++ * or NULL if key is smaller than the smallest key. ++ */ ++int ldns_rbtree_find_less_equal(ldns_rbtree_t *rbtree, const void *key, ++ ldns_rbnode_t **result); ++ ++/** ++ * Returns first (smallest) node in the tree ++ * @param rbtree: tree ++ * @return: smallest element or NULL if tree empty. ++ */ ++ldns_rbnode_t *ldns_rbtree_first(ldns_rbtree_t *rbtree); ++ ++/** ++ * Returns last (largest) node in the tree ++ * @param rbtree: tree ++ * @return: largest element or NULL if tree empty. ++ */ ++ldns_rbnode_t *ldns_rbtree_last(ldns_rbtree_t *rbtree); ++ ++/** ++ * Returns next larger node in the tree ++ * @param rbtree: tree ++ * @return: next larger element or NULL if no larger in tree. ++ */ ++ldns_rbnode_t *ldns_rbtree_next(ldns_rbnode_t *rbtree); ++ ++/** ++ * Returns previous smaller node in the tree ++ * @param rbtree: tree ++ * @return: previous smaller element or NULL if no previous in tree. ++ */ ++ldns_rbnode_t *ldns_rbtree_previous(ldns_rbnode_t *rbtree); ++ ++/** ++ * split off 'elements' number of elements from the start ++ * of the name tree and return a new tree containing those ++ * elements ++ */ ++ldns_rbtree_t *ldns_rbtree_split(ldns_rbtree_t *tree, size_t elements); ++ ++/** ++ * add all node from the second tree to the first (removing them from the ++ * second), and fix up nsec(3)s if present ++ */ ++void ldns_rbtree_join(ldns_rbtree_t *tree1, ldns_rbtree_t *tree2); ++ ++/** ++ * Call with node=variable of struct* with rbnode_t as first element. ++ * with type is the type of a pointer to that struct. ++ */ ++#define LDNS_RBTREE_FOR(node, type, rbtree) \ ++ for(node=(type)ldns_rbtree_first(rbtree); \ ++ (ldns_rbnode_t*)node != LDNS_RBTREE_NULL; \ ++ node = (type)ldns_rbtree_next((ldns_rbnode_t*)node)) ++ ++/** ++ * Call function for all elements in the redblack tree, such that ++ * leaf elements are called before parent elements. So that all ++ * elements can be safely free()d. ++ * Note that your function must not remove the nodes from the tree. ++ * Since that may trigger rebalances of the rbtree. ++ * @param tree: the tree ++ * @param func: function called with element and user arg. ++ * The function must not alter the rbtree. ++ * @param arg: user argument. ++ */ ++void ldns_traverse_postorder(ldns_rbtree_t* tree, ++ void (*func)(ldns_rbnode_t*, void*), void* arg); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* UTIL_RBTREE_H_ */ +diff --git a/ldns/include/ldns/rdata.h b/ldns/include/ldns/rdata.h +new file mode 100644 +index 0000000..22665b1 +--- /dev/null ++++ b/ldns/include/ldns/rdata.h +@@ -0,0 +1,451 @@ ++/* ++ * rdata.h ++ * ++ * rdata definitions ++ * ++ * a Net::DNS like library for C ++ * ++ * (c) NLnet Labs, 2005-2006 ++ * ++ * See the file LICENSE for the license ++ */ ++ ++ ++/** ++ * \file ++ * ++ * Defines ldns_rdf and functions to manipulate those. ++ */ ++ ++ ++#ifndef LDNS_RDATA_H ++#define LDNS_RDATA_H ++ ++#include <ldns/common.h> ++#include <ldns/error.h> ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#define LDNS_MAX_RDFLEN 65535 ++ ++#define LDNS_RDF_SIZE_BYTE 1 ++#define LDNS_RDF_SIZE_WORD 2 ++#define LDNS_RDF_SIZE_DOUBLEWORD 4 ++#define LDNS_RDF_SIZE_6BYTES 6 ++#define LDNS_RDF_SIZE_8BYTES 8 ++#define LDNS_RDF_SIZE_16BYTES 16 ++ ++#define LDNS_NSEC3_VARS_OPTOUT_MASK 0x01 ++ ++/** ++ * The different types of RDATA fields. ++ */ ++enum ldns_enum_rdf_type ++{ ++ /** none */ ++ LDNS_RDF_TYPE_NONE, ++ /** domain name */ ++ LDNS_RDF_TYPE_DNAME, ++ /** 8 bits */ ++ LDNS_RDF_TYPE_INT8, ++ /** 16 bits */ ++ LDNS_RDF_TYPE_INT16, ++ /** 32 bits */ ++ LDNS_RDF_TYPE_INT32, ++ /** A record */ ++ LDNS_RDF_TYPE_A, ++ /** AAAA record */ ++ LDNS_RDF_TYPE_AAAA, ++ /** txt string */ ++ LDNS_RDF_TYPE_STR, ++ /** apl data */ ++ LDNS_RDF_TYPE_APL, ++ /** b32 string */ ++ LDNS_RDF_TYPE_B32_EXT, ++ /** b64 string */ ++ LDNS_RDF_TYPE_B64, ++ /** hex string */ ++ LDNS_RDF_TYPE_HEX, ++ /** nsec type codes */ ++ LDNS_RDF_TYPE_NSEC, ++ /** a RR type */ ++ LDNS_RDF_TYPE_TYPE, ++ /** a class */ ++ LDNS_RDF_TYPE_CLASS, ++ /** certificate algorithm */ ++ LDNS_RDF_TYPE_CERT_ALG, ++ /** a key algorithm */ ++ LDNS_RDF_TYPE_ALG, ++ /** unknown types */ ++ LDNS_RDF_TYPE_UNKNOWN, ++ /** time (32 bits) */ ++ LDNS_RDF_TYPE_TIME, ++ /** period */ ++ LDNS_RDF_TYPE_PERIOD, ++ /** tsig time 48 bits */ ++ LDNS_RDF_TYPE_TSIGTIME, ++ /** Represents the Public Key Algorithm, HIT and Public Key fields ++ for the HIP RR types. A HIP specific rdf type is used because of ++ the unusual layout in wireformat (see RFC 5205 Section 5) */ ++ LDNS_RDF_TYPE_HIP, ++ /** variable length any type rdata where the length ++ is specified by the first 2 bytes */ ++ LDNS_RDF_TYPE_INT16_DATA, ++ /** protocol and port bitmaps */ ++ LDNS_RDF_TYPE_SERVICE, ++ /** location data */ ++ LDNS_RDF_TYPE_LOC, ++ /** well known services */ ++ LDNS_RDF_TYPE_WKS, ++ /** NSAP */ ++ LDNS_RDF_TYPE_NSAP, ++ /** ATMA */ ++ LDNS_RDF_TYPE_ATMA, ++ /** IPSECKEY */ ++ LDNS_RDF_TYPE_IPSECKEY, ++ /** nsec3 hash salt */ ++ LDNS_RDF_TYPE_NSEC3_SALT, ++ /** nsec3 base32 string (with length byte on wire */ ++ LDNS_RDF_TYPE_NSEC3_NEXT_OWNER, ++ ++ /** 4 shorts represented as 4 * 16 bit hex numbers ++ * separated by colons. For NID and L64. ++ */ ++ LDNS_RDF_TYPE_ILNP64, ++ ++ /** 6 * 8 bit hex numbers separated by dashes. For EUI48. */ ++ LDNS_RDF_TYPE_EUI48, ++ /** 8 * 8 bit hex numbers separated by dashes. For EUI64. */ ++ LDNS_RDF_TYPE_EUI64, ++ ++ /** A non-zero sequence of US-ASCII letters and numbers in lower case. ++ * For CAA. ++ */ ++ LDNS_RDF_TYPE_TAG, ++ ++ /** A <character-string> encoding of the value field as specified ++ * [RFC1035], Section 5.1., encoded as remaining rdata. ++ * For CAA. ++ */ ++ LDNS_RDF_TYPE_LONG_STR, ++ ++ /** Since RFC7218 TLSA records can be given with mnemonics, ++ * hence these rdata field types. But as with DNSKEYs, the output ++ * is always numeric. ++ */ ++ LDNS_RDF_TYPE_CERTIFICATE_USAGE, ++ LDNS_RDF_TYPE_SELECTOR, ++ LDNS_RDF_TYPE_MATCHING_TYPE, ++ ++ /* Aliases */ ++ LDNS_RDF_TYPE_BITMAP = LDNS_RDF_TYPE_NSEC ++}; ++typedef enum ldns_enum_rdf_type ldns_rdf_type; ++ ++/** ++ * algorithms used in CERT rrs ++ */ ++enum ldns_enum_cert_algorithm ++{ ++ LDNS_CERT_PKIX = 1, ++ LDNS_CERT_SPKI = 2, ++ LDNS_CERT_PGP = 3, ++ LDNS_CERT_IPKIX = 4, ++ LDNS_CERT_ISPKI = 5, ++ LDNS_CERT_IPGP = 6, ++ LDNS_CERT_ACPKIX = 7, ++ LDNS_CERT_IACPKIX = 8, ++ LDNS_CERT_URI = 253, ++ LDNS_CERT_OID = 254 ++}; ++typedef enum ldns_enum_cert_algorithm ldns_cert_algorithm; ++ ++ ++ ++/** ++ * Resource record data field. ++ * ++ * The data is a network ordered array of bytes, which size is specified by ++ * the (16-bit) size field. To correctly parse it, use the type ++ * specified in the (16-bit) type field with a value from \ref ldns_rdf_type. ++ */ ++struct ldns_struct_rdf ++{ ++ /** The size of the data (in octets) */ ++ size_t _size; ++ /** The type of the data */ ++ ldns_rdf_type _type; ++ /** Pointer to the data (raw octets) */ ++ void *_data; ++}; ++typedef struct ldns_struct_rdf ldns_rdf; ++ ++/* prototypes */ ++ ++/* write access functions */ ++ ++/** ++ * sets the size of the rdf. ++ * \param[in] *rd the rdf to operate on ++ * \param[in] size the new size ++ * \return void ++ */ ++void ldns_rdf_set_size(ldns_rdf *rd, size_t size); ++ ++/** ++ * sets the size of the rdf. ++ * \param[in] *rd the rdf to operate on ++ * \param[in] type the new type ++ * \return void ++ */ ++void ldns_rdf_set_type(ldns_rdf *rd, ldns_rdf_type type); ++ ++/** ++ * sets the size of the rdf. ++ * \param[in] *rd the rdf to operate on ++ * \param[in] *data pointer to the new data ++ * \return void ++ */ ++void ldns_rdf_set_data(ldns_rdf *rd, void *data); ++ ++/* read access */ ++ ++/** ++ * returns the size of the rdf. ++ * \param[in] *rd the rdf to read from ++ * \return uint16_t with the size ++ */ ++size_t ldns_rdf_size(const ldns_rdf *rd); ++ ++/** ++ * returns the type of the rdf. We need to insert _get_ ++ * here to prevent conflict the the rdf_type TYPE. ++ * \param[in] *rd the rdf to read from ++ * \return ldns_rdf_type with the type ++ */ ++ldns_rdf_type ldns_rdf_get_type(const ldns_rdf *rd); ++ ++/** ++ * returns the data of the rdf. ++ * \param[in] *rd the rdf to read from ++ * ++ * \return uint8_t* pointer to the rdf's data ++ */ ++uint8_t *ldns_rdf_data(const ldns_rdf *rd); ++ ++/* creator functions */ ++ ++/** ++ * allocates a new rdf structure and fills it. ++ * This function DOES NOT copy the contents from ++ * the buffer, unlinke ldns_rdf_new_frm_data() ++ * \param[in] type type of the rdf ++ * \param[in] size size of the buffer ++ * \param[in] data pointer to the buffer to be copied ++ * \return the new rdf structure or NULL on failure ++ */ ++ldns_rdf *ldns_rdf_new(ldns_rdf_type type, size_t size, void *data); ++ ++/** ++ * allocates a new rdf structure and fills it. ++ * This function _does_ copy the contents from ++ * the buffer, unlinke ldns_rdf_new() ++ * \param[in] type type of the rdf ++ * \param[in] size size of the buffer ++ * \param[in] data pointer to the buffer to be copied ++ * \return the new rdf structure or NULL on failure ++ */ ++ldns_rdf *ldns_rdf_new_frm_data(ldns_rdf_type type, size_t size, const void *data); ++ ++/** ++ * creates a new rdf from a string. ++ * \param[in] type type to use ++ * \param[in] str string to use ++ * \return ldns_rdf* or NULL in case of an error ++ */ ++ldns_rdf *ldns_rdf_new_frm_str(ldns_rdf_type type, const char *str); ++ ++/** ++ * creates a new rdf from a file containing a string. ++ * \param[out] r the new rdf ++ * \param[in] type type to use ++ * \param[in] fp the file pointer to use ++ * \return LDNS_STATUS_OK or the error ++ */ ++ldns_status ldns_rdf_new_frm_fp(ldns_rdf **r, ldns_rdf_type type, FILE *fp); ++ ++/** ++ * creates a new rdf from a file containing a string. ++ * \param[out] r the new rdf ++ * \param[in] type type to use ++ * \param[in] fp the file pointer to use ++ * \param[in] line_nr pointer to an integer containing the current line number (for debugging purposes) ++ * \return LDNS_STATUS_OK or the error ++ */ ++ldns_status ldns_rdf_new_frm_fp_l(ldns_rdf **r, ldns_rdf_type type, FILE *fp, int *line_nr); ++ ++/* destroy functions */ ++ ++/** ++ * frees a rdf structure, leaving the ++ * data pointer intact. ++ * \param[in] rd the pointer to be freed ++ * \return void ++ */ ++void ldns_rdf_free(ldns_rdf *rd); ++ ++/** ++ * frees a rdf structure _and_ frees the ++ * data. rdf should be created with _new_frm_data ++ * \param[in] rd the rdf structure to be freed ++ * \return void ++ */ ++void ldns_rdf_deep_free(ldns_rdf *rd); ++ ++/* conversion functions */ ++ ++/** ++ * returns the rdf containing the native uint8_t repr. ++ * \param[in] type the ldns_rdf type to use ++ * \param[in] value the uint8_t to use ++ * \return ldns_rdf* with the converted value ++ */ ++ldns_rdf *ldns_native2rdf_int8(ldns_rdf_type type, uint8_t value); ++ ++/** ++ * returns the rdf containing the native uint16_t representation. ++ * \param[in] type the ldns_rdf type to use ++ * \param[in] value the uint16_t to use ++ * \return ldns_rdf* with the converted value ++ */ ++ldns_rdf *ldns_native2rdf_int16(ldns_rdf_type type, uint16_t value); ++ ++/** ++ * returns an rdf that contains the given int32 value. ++ * ++ * Because multiple rdf types can contain an int32, the ++ * type must be specified ++ * \param[in] type the ldns_rdf type to use ++ * \param[in] value the uint32_t to use ++ * \return ldns_rdf* with the converted value ++ */ ++ldns_rdf *ldns_native2rdf_int32(ldns_rdf_type type, uint32_t value); ++ ++/** ++ * returns an int16_data rdf that contains the data in the ++ * given array, preceded by an int16 specifying the length. ++ * ++ * The memory is copied, and an LDNS_RDF_TYPE_INT16DATA is returned ++ * \param[in] size the size of the data ++ * \param[in] *data pointer to the actual data ++ * ++ * \return ldns_rd* the rdf with the data ++ */ ++ldns_rdf *ldns_native2rdf_int16_data(size_t size, uint8_t *data); ++ ++/** ++ * reverses an rdf, only actually useful for AAAA and A records. ++ * The returned rdf has the type LDNS_RDF_TYPE_DNAME! ++ * \param[in] *rd rdf to be reversed ++ * \return the reversed rdf (a newly created rdf) ++ */ ++ldns_rdf *ldns_rdf_address_reverse(ldns_rdf *rd); ++ ++/** ++ * returns the native uint8_t representation from the rdf. ++ * \param[in] rd the ldns_rdf to operate on ++ * \return uint8_t the value extracted ++ */ ++uint8_t ldns_rdf2native_int8(const ldns_rdf *rd); ++ ++/** ++ * returns the native uint16_t representation from the rdf. ++ * \param[in] rd the ldns_rdf to operate on ++ * \return uint16_t the value extracted ++ */ ++uint16_t ldns_rdf2native_int16(const ldns_rdf *rd); ++ ++/** ++ * returns the native uint32_t representation from the rdf. ++ * \param[in] rd the ldns_rdf to operate on ++ * \return uint32_t the value extracted ++ */ ++uint32_t ldns_rdf2native_int32(const ldns_rdf *rd); ++ ++/** ++ * returns the native time_t representation from the rdf. ++ * \param[in] rd the ldns_rdf to operate on ++ * \return time_t the value extracted (32 bits currently) ++ */ ++time_t ldns_rdf2native_time_t(const ldns_rdf *rd); ++ ++/** ++ * converts a ttl value (like 5d2h) to a long. ++ * \param[in] nptr the start of the string ++ * \param[out] endptr points to the last char in case of error ++ * \return the convert duration value ++ */ ++uint32_t ldns_str2period(const char *nptr, const char **endptr); ++ ++/** ++ * removes \\DDD, \\[space] and other escapes from the input. ++ * See RFC 1035, section 5.1. ++ * \param[in] word what to check ++ * \param[in] length the string ++ * \return ldns_status mesg ++ */ ++ldns_status ldns_octet(char *word, size_t *length); ++ ++/** ++ * clones a rdf structure. The data is copied. ++ * \param[in] rd rdf to be copied ++ * \return a new rdf structure ++ */ ++ldns_rdf *ldns_rdf_clone(const ldns_rdf *rd); ++ ++/** ++ * compares two rdf's on their wire formats. ++ * (To order dnames according to rfc4034, use ldns_dname_compare) ++ * \param[in] rd1 the first one ++ * \param[in] rd2 the second one ++ * \return 0 if equal ++ * \return -1 if rd1 comes before rd2 ++ * \return +1 if rd2 comes before rd1 ++ */ ++int ldns_rdf_compare(const ldns_rdf *rd1, const ldns_rdf *rd2); ++ ++/** ++ * Gets the algorithm value, the HIT and Public Key data from the rdf with ++ * type LDNS_RDF_TYPE_HIP. ++ * \param[in] rdf the rdf with type LDNS_RDF_TYPE_HIP ++ * \param[out] alg the algorithm ++ * \param[out] hit_size the size of the HIT data ++ * \param[out] hit the hit data ++ * \param[out] pk_size the size of the Public Key data ++ * \param[out] pk the Public Key data ++ * \return LDNS_STATUS_OK on success, and the error otherwise ++ */ ++ldns_status ldns_rdf_hip_get_alg_hit_pk(ldns_rdf *rdf, uint8_t* alg, ++ uint8_t *hit_size, uint8_t** hit, ++ uint16_t *pk_size, uint8_t** pk); ++ ++/** ++ * Creates a new LDNS_RDF_TYPE_HIP rdf from given data. ++ * \param[out] rdf the newly created LDNS_RDF_TYPE_HIP rdf ++ * \param[in] alg the algorithm ++ * \param[in] hit_size the size of the HIT data ++ * \param[in] hit the hit data ++ * \param[in] pk_size the size of the Public Key data ++ * \param[in] pk the Public Key data ++ * \return LDNS_STATUS_OK on success, and the error otherwise ++ */ ++ldns_status ldns_rdf_hip_new_frm_alg_hit_pk(ldns_rdf** rdf, uint8_t alg, ++ uint8_t hit_size, uint8_t *hit, uint16_t pk_size, uint8_t *pk); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* LDNS_RDATA_H */ +diff --git a/ldns/include/ldns/resolver.h b/ldns/include/ldns/resolver.h +new file mode 100644 +index 0000000..228485c +--- /dev/null ++++ b/ldns/include/ldns/resolver.h +@@ -0,0 +1,805 @@ ++/* ++ * resolver.h ++ * ++ * DNS Resolver definitions ++ * ++ * a Net::DNS like library for C ++ * ++ * (c) NLnet Labs, 2005-2006 ++ * ++ * See the file LICENSE for the license ++ */ ++ ++/** ++ * \file ++ * ++ * Defines the ldns_resolver structure, a stub resolver that can send queries and parse answers. ++ * ++ */ ++ ++#ifndef LDNS_RESOLVER_H ++#define LDNS_RESOLVER_H ++ ++#include <ldns/error.h> ++#include <ldns/common.h> ++#include <ldns/rr.h> ++#include <ldns/tsig.h> ++#include <ldns/rdata.h> ++#include <ldns/packet.h> ++#include <sys/time.h> ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/** Default location of the resolv.conf file */ ++#define LDNS_RESOLV_CONF "/etc/resolv.conf" ++/** Default location of the hosts file */ ++#define LDNS_RESOLV_HOSTS "/etc/hosts" ++ ++#define LDNS_RESOLV_KEYWORD -1 ++#define LDNS_RESOLV_DEFDOMAIN 0 ++#define LDNS_RESOLV_NAMESERVER 1 ++#define LDNS_RESOLV_SEARCH 2 ++#define LDNS_RESOLV_SORTLIST 3 ++#define LDNS_RESOLV_OPTIONS 4 ++#define LDNS_RESOLV_ANCHOR 5 ++#define LDNS_RESOLV_KEYWORDS 6 ++ ++#define LDNS_RESOLV_INETANY 0 ++#define LDNS_RESOLV_INET 1 ++#define LDNS_RESOLV_INET6 2 ++ ++#define LDNS_RESOLV_RTT_INF 0 /* infinity */ ++#define LDNS_RESOLV_RTT_MIN 1 /* reachable */ ++ ++/** ++ * DNS stub resolver structure ++ */ ++struct ldns_struct_resolver ++{ ++ /** Port to send queries to */ ++ uint16_t _port; ++ ++ /** Array of nameservers to query (IP addresses or dnames) */ ++ ldns_rdf **_nameservers; ++ /** Number of nameservers in \c _nameservers */ ++ size_t _nameserver_count; /* how many do we have */ ++ ++ /** Round trip time; 0 -> infinity. Unit: ms? */ ++ size_t *_rtt; ++ ++ /** Whether or not to be recursive */ ++ bool _recursive; ++ ++ /** Print debug information */ ++ bool _debug; ++ ++ /** Default domain to add to non fully qualified domain names */ ++ ldns_rdf *_domain; ++ ++ /** Searchlist array, add the names in this array if a query cannot be found */ ++ ldns_rdf **_searchlist; ++ ++ /** Number of entries in the searchlist array */ ++ size_t _searchlist_count; ++ ++ /** Number of times to retry before giving up */ ++ uint8_t _retry; ++ /** Time to wait before retrying */ ++ uint8_t _retrans; ++ /** Use new fallback mechanism (try EDNS, then do TCP) */ ++ bool _fallback; ++ ++ /** Whether to do DNSSEC */ ++ bool _dnssec; ++ /** Whether to set the CD bit on DNSSEC requests */ ++ bool _dnssec_cd; ++ /** Optional trust anchors for complete DNSSEC validation */ ++ ldns_rr_list * _dnssec_anchors; ++ /** Whether to use tcp or udp (tcp if the value is true)*/ ++ bool _usevc; ++ /** Whether to ignore the tc bit */ ++ bool _igntc; ++ /** Whether to use ip6: 0->does not matter, 1 is IPv4, 2 is IPv6 */ ++ uint8_t _ip6; ++ /** If true append the default domain */ ++ bool _defnames; ++ /** If true apply the search list */ ++ bool _dnsrch; ++ /** Timeout for socket connections */ ++ struct timeval _timeout; ++ /** Only try the first nameserver, and return with an error directly if it fails */ ++ bool _fail; ++ /** Randomly choose a nameserver */ ++ bool _random; ++ /** Keep some things to make AXFR possible */ ++ int _socket; ++ /** Count the number of LDNS_RR_TYPE_SOA RRs we have seen so far ++ * (the second one signifies the end of the AXFR) ++ */ ++ int _axfr_soa_count; ++ /* when axfring we get complete packets from the server ++ but we want to give the caller 1 rr at a time, so ++ keep the current pkt */ ++ /** Packet currently handled when doing part of an AXFR */ ++ ldns_pkt *_cur_axfr_pkt; ++ /** Counter for within the AXFR packets */ ++ uint16_t _axfr_i; ++ /* EDNS0 available buffer size */ ++ uint16_t _edns_udp_size; ++ /* serial for IXFR */ ++ uint32_t _serial; ++ ++ /* Optional tsig key for signing queries, ++ outgoing messages are signed if and only if both are set ++ */ ++ /** Name of the key to use with TSIG, if _tsig_keyname and _tsig_keydata both contain values, outgoing messages are automatically signed with TSIG. */ ++ char *_tsig_keyname; ++ /** Secret key data to use with TSIG, if _tsig_keyname and _tsig_keydata both contain values, outgoing messages are automatically signed with TSIG. */ ++ char *_tsig_keydata; ++ /** TSIG signing algorithm */ ++ char *_tsig_algorithm; ++ ++ /** Source address to query from */ ++ ldns_rdf *_source; ++}; ++typedef struct ldns_struct_resolver ldns_resolver; ++ ++/* prototypes */ ++/* read access functions */ ++ ++/** ++ * Get the port the resolver should use ++ * \param[in] r the resolver ++ * \return the port number ++ */ ++uint16_t ldns_resolver_port(const ldns_resolver *r); ++ ++/** ++ * Get the source address the resolver should use ++ * \param[in] r the resolver ++ * \return the source rdf ++ */ ++ldns_rdf *ldns_resolver_source(const ldns_resolver *r); ++ ++/** ++ * Is the resolver set to recurse ++ * \param[in] r the resolver ++ * \return true if so, otherwise false ++ */ ++bool ldns_resolver_recursive(const ldns_resolver *r); ++ ++/** ++ * Get the debug status of the resolver ++ * \param[in] r the resolver ++ * \return true if so, otherwise false ++ */ ++bool ldns_resolver_debug(const ldns_resolver *r); ++ ++/** ++ * Get the number of retries ++ * \param[in] r the resolver ++ * \return the number of retries ++ */ ++uint8_t ldns_resolver_retry(const ldns_resolver *r); ++ ++/** ++ * Get the retransmit interval ++ * \param[in] r the resolver ++ * \return the retransmit interval ++ */ ++uint8_t ldns_resolver_retrans(const ldns_resolver *r); ++ ++/** ++ * Get the truncation fallback status ++ * \param[in] r the resolver ++ * \return whether the truncation fallback mechanism is used ++ */ ++bool ldns_resolver_fallback(const ldns_resolver *r); ++ ++/** ++ * Does the resolver use ip6 or ip4 ++ * \param[in] r the resolver ++ * \return 0: both, 1: ip4, 2:ip6 ++ */ ++uint8_t ldns_resolver_ip6(const ldns_resolver *r); ++ ++/** ++ * Get the resolver's udp size ++ * \param[in] r the resolver ++ * \return the udp mesg size ++ */ ++uint16_t ldns_resolver_edns_udp_size(const ldns_resolver *r); ++/** ++ * Does the resolver use tcp or udp ++ * \param[in] r the resolver ++ * \return true: tcp, false: udp ++ */ ++bool ldns_resolver_usevc(const ldns_resolver *r); ++/** ++ * Does the resolver only try the first nameserver ++ * \param[in] r the resolver ++ * \return true: yes, fail, false: no, try the others ++ */ ++bool ldns_resolver_fail(const ldns_resolver *r); ++/** ++ * Does the resolver apply default domain name ++ * \param[in] r the resolver ++ * \return true: yes, false: no ++ */ ++bool ldns_resolver_defnames(const ldns_resolver *r); ++/** ++ * Does the resolver apply search list ++ * \param[in] r the resolver ++ * \return true: yes, false: no ++ */ ++bool ldns_resolver_dnsrch(const ldns_resolver *r); ++/** ++ * Does the resolver do DNSSEC ++ * \param[in] r the resolver ++ * \return true: yes, false: no ++ */ ++bool ldns_resolver_dnssec(const ldns_resolver *r); ++/** ++ * Does the resolver set the CD bit ++ * \param[in] r the resolver ++ * \return true: yes, false: no ++ */ ++bool ldns_resolver_dnssec_cd(const ldns_resolver *r); ++/** ++ * Get the resolver's DNSSEC anchors ++ * \param[in] r the resolver ++ * \return an rr_list containg trusted DNSSEC anchors ++ */ ++ldns_rr_list * ldns_resolver_dnssec_anchors(const ldns_resolver *r); ++/** ++ * Does the resolver ignore the TC bit (truncated) ++ * \param[in] r the resolver ++ * \return true: yes, false: no ++ */ ++bool ldns_resolver_igntc(const ldns_resolver *r); ++/** ++ * Does the resolver randomize the nameserver before usage ++ * \param[in] r the resolver ++ * \return true: yes, false: no ++ */ ++bool ldns_resolver_random(const ldns_resolver *r); ++/** ++ * How many nameserver are configured in the resolver ++ * \param[in] r the resolver ++ * \return number of nameservers ++ */ ++size_t ldns_resolver_nameserver_count(const ldns_resolver *r); ++/** ++ * What is the default dname to add to relative queries ++ * \param[in] r the resolver ++ * \return the dname which is added ++ */ ++ldns_rdf *ldns_resolver_domain(const ldns_resolver *r); ++/** ++ * What is the timeout on socket connections ++ * \param[in] r the resolver ++ * \return the timeout as struct timeval ++ */ ++struct timeval ldns_resolver_timeout(const ldns_resolver *r); ++/** ++ * What is the searchlist as used by the resolver ++ * \param[in] r the resolver ++ * \return a ldns_rdf pointer to a list of the addresses ++ */ ++ldns_rdf** ldns_resolver_searchlist(const ldns_resolver *r); ++/** ++ * Return the configured nameserver ip address ++ * \param[in] r the resolver ++ * \return a ldns_rdf pointer to a list of the addresses ++ */ ++ldns_rdf** ldns_resolver_nameservers(const ldns_resolver *r); ++/** ++ * Return the used round trip times for the nameservers ++ * \param[in] r the resolver ++ * \return a size_t* pointer to the list. ++ * yet) ++ */ ++size_t * ldns_resolver_rtt(const ldns_resolver *r); ++/** ++ * Return the used round trip time for a specific nameserver ++ * \param[in] r the resolver ++ * \param[in] pos the index to the nameserver ++ * \return the rrt, 0: infinite, >0: undefined (as of * yet) ++ */ ++size_t ldns_resolver_nameserver_rtt(const ldns_resolver *r, size_t pos); ++/** ++ * Return the tsig keyname as used by the nameserver ++ * \param[in] r the resolver ++ * \return the name used. ++ */ ++char *ldns_resolver_tsig_keyname(const ldns_resolver *r); ++/** ++ * Return the tsig algorithm as used by the nameserver ++ * \param[in] r the resolver ++ * \return the algorithm used. ++ */ ++char *ldns_resolver_tsig_algorithm(const ldns_resolver *r); ++/** ++ * Return the tsig keydata as used by the nameserver ++ * \param[in] r the resolver ++ * \return the keydata used. ++ */ ++char *ldns_resolver_tsig_keydata(const ldns_resolver *r); ++/** ++ * pop the last nameserver from the resolver. ++ * \param[in] r the resolver ++ * \return the popped address or NULL if empty ++ */ ++ldns_rdf* ldns_resolver_pop_nameserver(ldns_resolver *r); ++ ++/** ++ * Return the resolver's searchlist count ++ * \param[in] r the resolver ++ * \return the searchlist count ++ */ ++size_t ldns_resolver_searchlist_count(const ldns_resolver *r); ++ ++/* write access function */ ++/** ++ * Set the port the resolver should use ++ * \param[in] r the resolver ++ * \param[in] p the port number ++ */ ++void ldns_resolver_set_port(ldns_resolver *r, uint16_t p); ++ ++/** ++ * Set the source rdf (address) the resolver should use ++ * \param[in] r the resolver ++ * \param[in] s the source address ++ */ ++void ldns_resolver_set_source(ldns_resolver *r, ldns_rdf *s); ++ ++/** ++ * Set the resolver recursion ++ * \param[in] r the resolver ++ * \param[in] b true: set to recurse, false: unset ++ */ ++void ldns_resolver_set_recursive(ldns_resolver *r, bool b); ++ ++/** ++ * Set the resolver debugging ++ * \param[in] r the resolver ++ * \param[in] b true: debug on: false debug off ++ */ ++void ldns_resolver_set_debug(ldns_resolver *r, bool b); ++ ++/** ++ * Incremental the resolver's nameserver count. ++ * \param[in] r the resolver ++ */ ++void ldns_resolver_incr_nameserver_count(ldns_resolver *r); ++ ++/** ++ * Decrement the resolver's nameserver count. ++ * \param[in] r the resolver ++ */ ++void ldns_resolver_dec_nameserver_count(ldns_resolver *r); ++ ++/** ++ * Set the resolver's nameserver count directly. ++ * \param[in] r the resolver ++ * \param[in] c the nameserver count ++ */ ++void ldns_resolver_set_nameserver_count(ldns_resolver *r, size_t c); ++ ++/** ++ * Set the resolver's nameserver count directly by using an rdf list ++ * \param[in] r the resolver ++ * \param[in] rd the resolver addresses ++ */ ++void ldns_resolver_set_nameservers(ldns_resolver *r, ldns_rdf **rd); ++ ++/** ++ * Set the resolver's default domain. This gets appended when no ++ * absolute name is given ++ * \param[in] r the resolver ++ * \param[in] rd the name to append ++ */ ++void ldns_resolver_set_domain(ldns_resolver *r, ldns_rdf *rd); ++ ++/** ++ * Set the resolver's socket time out when talking to remote hosts ++ * \param[in] r the resolver ++ * \param[in] timeout the timeout to use ++ */ ++void ldns_resolver_set_timeout(ldns_resolver *r, struct timeval timeout); ++ ++/** ++ * Push a new rd to the resolver's searchlist ++ * \param[in] r the resolver ++ * \param[in] rd to push ++ */ ++void ldns_resolver_push_searchlist(ldns_resolver *r, ldns_rdf *rd); ++ ++/** ++ * Whether the resolver uses the name set with _set_domain ++ * \param[in] r the resolver ++ * \param[in] b true: use the defaults, false: don't use them ++ */ ++void ldns_resolver_set_defnames(ldns_resolver *r, bool b); ++ ++/** ++ * Whether the resolver uses a virtual circuit (TCP) ++ * \param[in] r the resolver ++ * \param[in] b true: use TCP, false: don't use TCP ++ */ ++void ldns_resolver_set_usevc(ldns_resolver *r, bool b); ++ ++/** ++ * Whether the resolver uses the searchlist ++ * \param[in] r the resolver ++ * \param[in] b true: use the list, false: don't use the list ++ */ ++void ldns_resolver_set_dnsrch(ldns_resolver *r, bool b); ++ ++/** ++ * Whether the resolver uses DNSSEC ++ * \param[in] r the resolver ++ * \param[in] b true: use DNSSEC, false: don't use DNSSEC ++ */ ++void ldns_resolver_set_dnssec(ldns_resolver *r, bool b); ++ ++/** ++ * Whether the resolver uses the checking disable bit ++ * \param[in] r the resolver ++ * \param[in] b true: enable , false: don't use TCP ++ */ ++void ldns_resolver_set_dnssec_cd(ldns_resolver *r, bool b); ++/** ++ * Set the resolver's DNSSEC anchor list directly. RRs should be of type DS or DNSKEY. ++ * \param[in] r the resolver ++ * \param[in] l the list of RRs to use as trust anchors ++ */ ++void ldns_resolver_set_dnssec_anchors(ldns_resolver *r, ldns_rr_list * l); ++ ++/** ++ * Push a new trust anchor to the resolver. It must be a DS or DNSKEY rr ++ * \param[in] r the resolver. ++ * \param[in] rr the RR to add as a trust anchor. ++ * \return a status ++ */ ++ldns_status ldns_resolver_push_dnssec_anchor(ldns_resolver *r, ldns_rr *rr); ++ ++/** ++ * Set the resolver retrans timeout (in seconds) ++ * \param[in] r the resolver ++ * \param[in] re the retransmission interval in seconds ++ */ ++void ldns_resolver_set_retrans(ldns_resolver *r, uint8_t re); ++ ++/** ++ * Set whether the resolvers truncation fallback mechanism is used ++ * when ldns_resolver_query() is called. ++ * \param[in] r the resolver ++ * \param[in] fallback whether to use the fallback mechanism ++ */ ++void ldns_resolver_set_fallback(ldns_resolver *r, bool fallback); ++ ++/** ++ * Set the number of times a resolver should retry a nameserver before the ++ * next one is tried. ++ * \param[in] r the resolver ++ * \param[in] re the number of retries ++ */ ++void ldns_resolver_set_retry(ldns_resolver *r, uint8_t re); ++ ++/** ++ * Whether the resolver uses ip6 ++ * \param[in] r the resolver ++ * \param[in] i 0: no pref, 1: ip4, 2: ip6 ++ */ ++void ldns_resolver_set_ip6(ldns_resolver *r, uint8_t i); ++ ++/** ++ * Whether or not to fail after one failed query ++ * \param[in] r the resolver ++ * \param[in] b true: yes fail, false: continue with next nameserver ++ */ ++void ldns_resolver_set_fail(ldns_resolver *r, bool b); ++ ++/** ++ * Whether or not to ignore the TC bit ++ * \param[in] r the resolver ++ * \param[in] b true: yes ignore, false: don't ignore ++ */ ++void ldns_resolver_set_igntc(ldns_resolver *r, bool b); ++ ++/** ++ * Set maximum udp size ++ * \param[in] r the resolver ++ * \param[in] s the udp max size ++ */ ++void ldns_resolver_set_edns_udp_size(ldns_resolver *r, uint16_t s); ++ ++/** ++ * Set the tsig key name ++ * \param[in] r the resolver ++ * \param[in] tsig_keyname the tsig key name ++ */ ++void ldns_resolver_set_tsig_keyname(ldns_resolver *r, char *tsig_keyname); ++ ++/** ++ * Set the tsig algorithm ++ * \param[in] r the resolver ++ * \param[in] tsig_algorithm the tsig algorithm ++ */ ++void ldns_resolver_set_tsig_algorithm(ldns_resolver *r, char *tsig_algorithm); ++ ++/** ++ * Set the tsig key data ++ * \param[in] r the resolver ++ * \param[in] tsig_keydata the key data ++ */ ++void ldns_resolver_set_tsig_keydata(ldns_resolver *r, char *tsig_keydata); ++ ++/** ++ * Set round trip time for all nameservers. Note this currently ++ * differentiates between: unreachable and reachable. ++ * \param[in] r the resolver ++ * \param[in] rtt a list with the times ++ */ ++void ldns_resolver_set_rtt(ldns_resolver *r, size_t *rtt); ++ ++/** ++ * Set round trip time for a specific nameserver. Note this ++ * currently differentiates between: unreachable and reachable. ++ * \param[in] r the resolver ++ * \param[in] pos the nameserver position ++ * \param[in] value the rtt ++ */ ++void ldns_resolver_set_nameserver_rtt(ldns_resolver *r, size_t pos, size_t value); ++ ++/** ++ * Should the nameserver list be randomized before each use ++ * \param[in] r the resolver ++ * \param[in] b: true: randomize, false: don't ++ */ ++void ldns_resolver_set_random(ldns_resolver *r, bool b); ++ ++/** ++ * Push a new nameserver to the resolver. It must be an IP ++ * address v4 or v6. ++ * \param[in] r the resolver ++ * \param[in] n the ip address ++ * \return ldns_status a status ++ */ ++ldns_status ldns_resolver_push_nameserver(ldns_resolver *r, ldns_rdf *n); ++ ++/** ++ * Push a new nameserver to the resolver. It must be an ++ * A or AAAA RR record type ++ * \param[in] r the resolver ++ * \param[in] rr the resource record ++ * \return ldns_status a status ++ */ ++ldns_status ldns_resolver_push_nameserver_rr(ldns_resolver *r, ldns_rr *rr); ++ ++/** ++ * Push a new nameserver rr_list to the resolver. ++ * \param[in] r the resolver ++ * \param[in] rrlist the rr_list to push ++ * \return ldns_status a status ++ */ ++ldns_status ldns_resolver_push_nameserver_rr_list(ldns_resolver *r, ldns_rr_list *rrlist); ++ ++/** ++ * Send the query for using the resolver and take the search list into account ++ * The search algorithm is as follows: ++ * If the name is absolute, try it as-is, otherwise apply the search list ++ * \param[in] *r operate using this resolver ++ * \param[in] *rdf query for this name ++ * \param[in] t query for this type (may be 0, defaults to A) ++ * \param[in] c query for this class (may be 0, default to IN) ++ * \param[in] flags the query flags ++ * ++ * \return ldns_pkt* a packet with the reply from the nameserver ++ */ ++ldns_pkt* ldns_resolver_search(const ldns_resolver *r, const ldns_rdf *rdf, ldns_rr_type t, ldns_rr_class c, uint16_t flags); ++ ++ ++/** ++ * Send the query for using the resolver and take the search list into account ++ * The search algorithm is as follows: ++ * If the name is absolute, try it as-is, otherwise apply the search list ++ * \param[out] pkt a packet with the reply from the nameserver ++ * \param[in] *r operate using this resolver ++ * \param[in] *rdf query for this name ++ * \param[in] t query for this type (may be 0, defaults to A) ++ * \param[in] c query for this class (may be 0, default to IN) ++ * \param[in] flags the query flags ++ * ++ * \return ldns_status LDNS_STATUS_OK on success ++ */ ++ldns_status ldns_resolver_search_status(ldns_pkt** pkt, ldns_resolver *r, const ldns_rdf *rdf, ldns_rr_type t, ldns_rr_class c, uint16_t flags); ++ ++/** ++ * Form a query packet from a resolver and name/type/class combo ++ * \param[out] **q a pointer to a ldns_pkt pointer (initialized by this function) ++ * \param[in] *r operate using this resolver ++ * \param[in] *name query for this name ++ * \param[in] t query for this type (may be 0, defaults to A) ++ * \param[in] c query for this class (may be 0, default to IN) ++ * \param[in] f the query flags ++ * ++ * \return ldns_pkt* a packet with the reply from the nameserver ++ */ ++ldns_status ldns_resolver_prepare_query_pkt(ldns_pkt **q, ldns_resolver *r, const ldns_rdf *name, ldns_rr_type t, ldns_rr_class c, uint16_t f); ++ ++/** ++ * Send the query for name as-is ++ * \param[out] **answer a pointer to a ldns_pkt pointer (initialized by this function) ++ * \param[in] *r operate using this resolver ++ * \param[in] *name query for this name ++ * \param[in] t query for this type (may be 0, defaults to A) ++ * \param[in] c query for this class (may be 0, default to IN) ++ * \param[in] flags the query flags ++ * ++ * \return ldns_pkt* a packet with the reply from the nameserver ++ */ ++ldns_status ldns_resolver_send(ldns_pkt **answer, ldns_resolver *r, const ldns_rdf *name, ldns_rr_type t, ldns_rr_class c, uint16_t flags); ++ ++/** ++ * Send the given packet to a nameserver ++ * \param[out] **answer a pointer to a ldns_pkt pointer (initialized by this function) ++ * \param[in] *r operate using this resolver ++ * \param[in] *query_pkt query ++ */ ++ldns_status ldns_resolver_send_pkt(ldns_pkt **answer, ldns_resolver *r, ldns_pkt *query_pkt); ++ ++/** ++ * Send a query to a nameserver ++ * \param[out] pkt a packet with the reply from the nameserver ++ * \param[in] *r operate using this resolver ++ * \param[in] *name query for this name ++ * \param[in] *t query for this type (may be 0, defaults to A) ++ * \param[in] *c query for this class (may be 0, default to IN) ++ * \param[in] flags the query flags ++ * ++ * \return ldns_status LDNS_STATUS_OK on success ++ * if _defnames is true the default domain will be added ++ */ ++ldns_status ldns_resolver_query_status(ldns_pkt** pkt, ldns_resolver *r, const ldns_rdf *name, ldns_rr_type t, ldns_rr_class c, uint16_t flags); ++ ++ ++/** ++ * Send a query to a nameserver ++ * \param[in] *r operate using this resolver ++ * (despite the const in the declaration, ++ * the struct is altered as a side-effect) ++ * \param[in] *name query for this name ++ * \param[in] *t query for this type (may be 0, defaults to A) ++ * \param[in] *c query for this class (may be 0, default to IN) ++ * \param[in] flags the query flags ++ * ++ * \return ldns_pkt* a packet with the reply from the nameserver ++ * if _defnames is true the default domain will be added ++ */ ++ldns_pkt* ldns_resolver_query(const ldns_resolver *r, const ldns_rdf *name, ldns_rr_type t, ldns_rr_class c, uint16_t flags); ++ ++ ++/** ++ * Create a new resolver structure ++ * \return ldns_resolver* pointer to new structure ++ */ ++ldns_resolver* ldns_resolver_new(void); ++ ++/** ++ * Clone a resolver ++ * \param[in] r the resolver to clone ++ * \return ldns_resolver* pointer to new structure ++ */ ++ldns_resolver* ldns_resolver_clone(ldns_resolver *r); ++ ++/** ++ * Create a resolver structure from a file like /etc/resolv.conf ++ * \param[out] r the new resolver ++ * \param[in] fp file pointer to create new resolver from ++ * if NULL use /etc/resolv.conf ++ * \return LDNS_STATUS_OK or the error ++ */ ++ldns_status ldns_resolver_new_frm_fp(ldns_resolver **r, FILE *fp); ++ ++/** ++ * Create a resolver structure from a file like /etc/resolv.conf ++ * \param[out] r the new resolver ++ * \param[in] fp file pointer to create new resolver from ++ * if NULL use /etc/resolv.conf ++ * \param[in] line_nr pointer to an integer containing the current line number (for debugging purposes) ++ * \return LDNS_STATUS_OK or the error ++ */ ++ldns_status ldns_resolver_new_frm_fp_l(ldns_resolver **r, FILE *fp, int *line_nr); ++ ++/** ++ * Configure a resolver by means of a resolv.conf file ++ * The file may be NULL in which case there will be ++ * looked the RESOLV_CONF (defaults to /etc/resolv.conf ++ * \param[out] r the new resolver ++ * \param[in] filename the filename to use ++ * \return LDNS_STATUS_OK or the error ++ */ ++ldns_status ldns_resolver_new_frm_file(ldns_resolver **r, const char *filename); ++ ++/** ++ * Frees the allocated space for this resolver. Only frees the resolver pionter! You should probably be using _deep_free. ++ * \param res resolver to free ++ */ ++void ldns_resolver_free(ldns_resolver *res); ++ ++/** ++ * Frees the allocated space for this resolver and all it's data ++ * \param res resolver to free ++ */ ++void ldns_resolver_deep_free(ldns_resolver *res); ++ ++/** ++ * Get the next stream of RRs in a AXFR ++ * \param[in] resolver the resolver to use. First ldns_axfr_start() must be ++ * called ++ * \return ldns_rr the next RR from the AXFR stream ++ * After you get this returned RR (not NULL: on error), then check if ++ * ldns_axfr_complete() is true to see if the zone transfer has completed. ++ */ ++ldns_rr* ldns_axfr_next(ldns_resolver *resolver); ++ ++/** ++ * Abort a transfer that is in progress ++ * \param[in] resolver the resolver that is used ++ */ ++void ldns_axfr_abort(ldns_resolver *resolver); ++ ++/** ++ * Returns true if the axfr transfer has completed (i.e. 2 SOA RRs and no errors were encountered ++ * \param[in] resolver the resolver that is used ++ * \return bool true if axfr transfer was completed without error ++ */ ++bool ldns_axfr_complete(const ldns_resolver *resolver); ++ ++/** ++ * Returns a pointer to the last ldns_pkt that was sent by the server in the AXFR transfer ++ * uasable for instance to get the error code on failure ++ * \param[in] res the resolver that was used in the axfr transfer ++ * \return ldns_pkt the last packet sent ++ */ ++ldns_pkt *ldns_axfr_last_pkt(const ldns_resolver *res); ++ ++/** ++ * Get the serial for requesting IXFR. ++ * \param[in] r the resolver ++ * \param[in] serial serial ++ */ ++void ldns_resolver_set_ixfr_serial(ldns_resolver *r, uint32_t serial); ++ ++/** ++ * Get the serial for requesting IXFR. ++ * \param[in] res the resolver ++ * \return uint32_t serial ++ */ ++uint32_t ldns_resolver_get_ixfr_serial(const ldns_resolver *res); ++ ++/** ++ * Randomize the nameserver list in the resolver ++ * \param[in] r the resolver ++ */ ++void ldns_resolver_nameservers_randomize(ldns_resolver *r); ++ ++/** ++ * Returns true if at least one of the provided keys is a trust anchor ++ * \param[in] r the current resolver ++ * \param[in] keys the keyset to check ++ * \param[out] trusted_keys the subset of trusted keys in the 'keys' rrset ++ * \return true if at least one of the provided keys is a configured trust anchor ++ */ ++bool ldns_resolver_trusted_key(const ldns_resolver *r, ldns_rr_list * keys, ldns_rr_list * trusted_keys); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* LDNS_RESOLVER_H */ +diff --git a/ldns/include/ldns/rr.h b/ldns/include/ldns/rr.h +new file mode 100644 +index 0000000..75ac352 +--- /dev/null ++++ b/ldns/include/ldns/rr.h +@@ -0,0 +1,929 @@ ++/* ++ * rr.h - resource record definitions ++ * ++ * a Net::DNS like library for C ++ * ++ * (c) NLnet Labs, 2005-2006 ++ * ++ * See the file LICENSE for the license ++ */ ++ ++/** ++ * \file ++ * ++ * Contains the definition of ldns_rr and functions to manipulate those. ++ */ ++ ++ ++#ifndef LDNS_RR_H ++#define LDNS_RR_H ++ ++#include <ldns/common.h> ++#include <ldns/rdata.h> ++#include <ldns/buffer.h> ++#include <ldns/error.h> ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/** Maximum length of a dname label */ ++#define LDNS_MAX_LABELLEN 63 ++/** Maximum length of a complete dname */ ++#define LDNS_MAX_DOMAINLEN 255 ++/** Maximum number of pointers in 1 dname */ ++#define LDNS_MAX_POINTERS 65535 ++/** The bytes TTL, CLASS and length use up in an rr */ ++#define LDNS_RR_OVERHEAD 10 ++ ++/* The first fields are contiguous and can be referenced instantly */ ++#define LDNS_RDATA_FIELD_DESCRIPTORS_COMMON 258 ++ ++ ++ ++/** ++ * The different RR classes. ++ */ ++enum ldns_enum_rr_class ++{ ++ /** the Internet */ ++ LDNS_RR_CLASS_IN = 1, ++ /** Chaos class */ ++ LDNS_RR_CLASS_CH = 3, ++ /** Hesiod (Dyer 87) */ ++ LDNS_RR_CLASS_HS = 4, ++ /** None class, dynamic update */ ++ LDNS_RR_CLASS_NONE = 254, ++ /** Any class */ ++ LDNS_RR_CLASS_ANY = 255, ++ ++ LDNS_RR_CLASS_FIRST = 0, ++ LDNS_RR_CLASS_LAST = 65535, ++ LDNS_RR_CLASS_COUNT = LDNS_RR_CLASS_LAST - LDNS_RR_CLASS_FIRST + 1 ++}; ++typedef enum ldns_enum_rr_class ldns_rr_class; ++ ++/** ++ * Used to specify whether compression is allowed. ++ */ ++enum ldns_enum_rr_compress ++{ ++ /** compression is allowed */ ++ LDNS_RR_COMPRESS, ++ LDNS_RR_NO_COMPRESS ++}; ++typedef enum ldns_enum_rr_compress ldns_rr_compress; ++ ++/** ++ * The different RR types. ++ */ ++enum ldns_enum_rr_type ++{ ++ /** a host address */ ++ LDNS_RR_TYPE_A = 1, ++ /** an authoritative name server */ ++ LDNS_RR_TYPE_NS = 2, ++ /** a mail destination (Obsolete - use MX) */ ++ LDNS_RR_TYPE_MD = 3, ++ /** a mail forwarder (Obsolete - use MX) */ ++ LDNS_RR_TYPE_MF = 4, ++ /** the canonical name for an alias */ ++ LDNS_RR_TYPE_CNAME = 5, ++ /** marks the start of a zone of authority */ ++ LDNS_RR_TYPE_SOA = 6, ++ /** a mailbox domain name (EXPERIMENTAL) */ ++ LDNS_RR_TYPE_MB = 7, ++ /** a mail group member (EXPERIMENTAL) */ ++ LDNS_RR_TYPE_MG = 8, ++ /** a mail rename domain name (EXPERIMENTAL) */ ++ LDNS_RR_TYPE_MR = 9, ++ /** a null RR (EXPERIMENTAL) */ ++ LDNS_RR_TYPE_NULL = 10, ++ /** a well known service description */ ++ LDNS_RR_TYPE_WKS = 11, ++ /** a domain name pointer */ ++ LDNS_RR_TYPE_PTR = 12, ++ /** host information */ ++ LDNS_RR_TYPE_HINFO = 13, ++ /** mailbox or mail list information */ ++ LDNS_RR_TYPE_MINFO = 14, ++ /** mail exchange */ ++ LDNS_RR_TYPE_MX = 15, ++ /** text strings */ ++ LDNS_RR_TYPE_TXT = 16, ++ /** RFC1183 */ ++ LDNS_RR_TYPE_RP = 17, ++ /** RFC1183 */ ++ LDNS_RR_TYPE_AFSDB = 18, ++ /** RFC1183 */ ++ LDNS_RR_TYPE_X25 = 19, ++ /** RFC1183 */ ++ LDNS_RR_TYPE_ISDN = 20, ++ /** RFC1183 */ ++ LDNS_RR_TYPE_RT = 21, ++ /** RFC1706 */ ++ LDNS_RR_TYPE_NSAP = 22, ++ /** RFC1348 */ ++ LDNS_RR_TYPE_NSAP_PTR = 23, ++ /** 2535typecode */ ++ LDNS_RR_TYPE_SIG = 24, ++ /** 2535typecode */ ++ LDNS_RR_TYPE_KEY = 25, ++ /** RFC2163 */ ++ LDNS_RR_TYPE_PX = 26, ++ /** RFC1712 */ ++ LDNS_RR_TYPE_GPOS = 27, ++ /** ipv6 address */ ++ LDNS_RR_TYPE_AAAA = 28, ++ /** LOC record RFC1876 */ ++ LDNS_RR_TYPE_LOC = 29, ++ /** 2535typecode */ ++ LDNS_RR_TYPE_NXT = 30, ++ /** draft-ietf-nimrod-dns-01.txt */ ++ LDNS_RR_TYPE_EID = 31, ++ /** draft-ietf-nimrod-dns-01.txt */ ++ LDNS_RR_TYPE_NIMLOC = 32, ++ /** SRV record RFC2782 */ ++ LDNS_RR_TYPE_SRV = 33, ++ /** http://www.jhsoft.com/rfc/af-saa-0069.000.rtf */ ++ LDNS_RR_TYPE_ATMA = 34, ++ /** RFC2915 */ ++ LDNS_RR_TYPE_NAPTR = 35, ++ /** RFC2230 */ ++ LDNS_RR_TYPE_KX = 36, ++ /** RFC2538 */ ++ LDNS_RR_TYPE_CERT = 37, ++ /** RFC2874 */ ++ LDNS_RR_TYPE_A6 = 38, ++ /** RFC2672 */ ++ LDNS_RR_TYPE_DNAME = 39, ++ /** dnsind-kitchen-sink-02.txt */ ++ LDNS_RR_TYPE_SINK = 40, ++ /** Pseudo OPT record... */ ++ LDNS_RR_TYPE_OPT = 41, ++ /** RFC3123 */ ++ LDNS_RR_TYPE_APL = 42, ++ /** RFC4034, RFC3658 */ ++ LDNS_RR_TYPE_DS = 43, ++ /** SSH Key Fingerprint */ ++ LDNS_RR_TYPE_SSHFP = 44, /* RFC 4255 */ ++ /** IPsec Key */ ++ LDNS_RR_TYPE_IPSECKEY = 45, /* RFC 4025 */ ++ /** DNSSEC */ ++ LDNS_RR_TYPE_RRSIG = 46, /* RFC 4034 */ ++ LDNS_RR_TYPE_NSEC = 47, /* RFC 4034 */ ++ LDNS_RR_TYPE_DNSKEY = 48, /* RFC 4034 */ ++ ++ LDNS_RR_TYPE_DHCID = 49, /* RFC 4701 */ ++ /* NSEC3 */ ++ LDNS_RR_TYPE_NSEC3 = 50, /* RFC 5155 */ ++ LDNS_RR_TYPE_NSEC3PARAM = 51, /* RFC 5155 */ ++ LDNS_RR_TYPE_NSEC3PARAMS = 51, ++ LDNS_RR_TYPE_TLSA = 52, /* RFC 6698 */ ++ ++ LDNS_RR_TYPE_HIP = 55, /* RFC 5205 */ ++ ++ /** draft-reid-dnsext-zs */ ++ LDNS_RR_TYPE_NINFO = 56, ++ /** draft-reid-dnsext-rkey */ ++ LDNS_RR_TYPE_RKEY = 57, ++ /** draft-ietf-dnsop-trust-history */ ++ LDNS_RR_TYPE_TALINK = 58, ++ LDNS_RR_TYPE_CDS = 59, /* RFC 7344 */ ++ LDNS_RR_TYPE_CDNSKEY = 60, /* RFC 7344 */ ++ /** draft-ietf-dane-openpgpkey */ ++ LDNS_RR_TYPE_OPENPGPKEY = 61, ++ ++ LDNS_RR_TYPE_SPF = 99, /* RFC 4408 */ ++ ++ LDNS_RR_TYPE_UINFO = 100, ++ LDNS_RR_TYPE_UID = 101, ++ LDNS_RR_TYPE_GID = 102, ++ LDNS_RR_TYPE_UNSPEC = 103, ++ ++ LDNS_RR_TYPE_NID = 104, /* RFC 6742 */ ++ LDNS_RR_TYPE_L32 = 105, /* RFC 6742 */ ++ LDNS_RR_TYPE_L64 = 106, /* RFC 6742 */ ++ LDNS_RR_TYPE_LP = 107, /* RFC 6742 */ ++ ++ LDNS_RR_TYPE_EUI48 = 108, /* RFC 7043 */ ++ LDNS_RR_TYPE_EUI64 = 109, /* RFC 7043 */ ++ ++ LDNS_RR_TYPE_TKEY = 249, /* RFC 2930 */ ++ LDNS_RR_TYPE_TSIG = 250, ++ LDNS_RR_TYPE_IXFR = 251, ++ LDNS_RR_TYPE_AXFR = 252, ++ /** A request for mailbox-related records (MB, MG or MR) */ ++ LDNS_RR_TYPE_MAILB = 253, ++ /** A request for mail agent RRs (Obsolete - see MX) */ ++ LDNS_RR_TYPE_MAILA = 254, ++ /** any type (wildcard) */ ++ LDNS_RR_TYPE_ANY = 255, ++ /** draft-faltstrom-uri-06 */ ++ LDNS_RR_TYPE_URI = 256, ++ LDNS_RR_TYPE_CAA = 257, /* RFC 6844 */ ++ ++ /** DNSSEC Trust Authorities */ ++ LDNS_RR_TYPE_TA = 32768, ++ /* RFC 4431, 5074, DNSSEC Lookaside Validation */ ++ LDNS_RR_TYPE_DLV = 32769, ++ ++ /* type codes from nsec3 experimental phase ++ LDNS_RR_TYPE_NSEC3 = 65324, ++ LDNS_RR_TYPE_NSEC3PARAMS = 65325, */ ++ LDNS_RR_TYPE_FIRST = 0, ++ LDNS_RR_TYPE_LAST = 65535, ++ LDNS_RR_TYPE_COUNT = LDNS_RR_TYPE_LAST - LDNS_RR_TYPE_FIRST + 1 ++}; ++typedef enum ldns_enum_rr_type ldns_rr_type; ++ ++/** ++ * Resource Record ++ * ++ * This is the basic DNS element that contains actual data ++ * ++ * From RFC1035: ++ * <pre> ++3.2.1. Format ++ ++All RRs have the same top level format shown below: ++ ++ 1 1 1 1 1 1 ++ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 ++ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ ++ | | ++ / / ++ / NAME / ++ | | ++ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ ++ | TYPE | ++ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ ++ | CLASS | ++ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ ++ | TTL | ++ | | ++ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ ++ | RDLENGTH | ++ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--| ++ / RDATA / ++ / / ++ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ ++ ++where: ++ ++NAME an owner name, i.e., the name of the node to which this ++ resource record pertains. ++ ++TYPE two octets containing one of the RR TYPE codes. ++ ++CLASS two octets containing one of the RR CLASS codes. ++ ++TTL a 32 bit signed integer that specifies the time interval ++ that the resource record may be cached before the source ++ of the information should again be consulted. Zero ++ values are interpreted to mean that the RR can only be ++ used for the transaction in progress, and should not be ++ cached. For example, SOA records are always distributed ++ with a zero TTL to prohibit caching. Zero values can ++ also be used for extremely volatile data. ++ ++RDLENGTH an unsigned 16 bit integer that specifies the length in ++ octets of the RDATA field. ++ ++RDATA a variable length string of octets that describes the ++ resource. The format of this information varies ++ according to the TYPE and CLASS of the resource record. ++ * </pre> ++ * ++ * The actual amount and type of rdata fields depend on the RR type of the ++ * RR, and can be found by using \ref ldns_rr_descriptor functions. ++ */ ++struct ldns_struct_rr ++{ ++ /** Owner name, uncompressed */ ++ ldns_rdf *_owner; ++ /** Time to live */ ++ uint32_t _ttl; ++ /** Number of data fields */ ++ size_t _rd_count; ++ /** the type of the RR. A, MX etc. */ ++ ldns_rr_type _rr_type; ++ /** Class of the resource record. */ ++ ldns_rr_class _rr_class; ++ /* everything in the rdata is in network order */ ++ /** The array of rdata's */ ++ ldns_rdf **_rdata_fields; ++ /** question rr [it would be nicer if thous is after _rd_count] ++ ABI change: Fix this in next major release ++ */ ++ bool _rr_question; ++}; ++typedef struct ldns_struct_rr ldns_rr; ++ ++/** ++ * List or Set of Resource Records ++ * ++ * Contains a list of rr's <br> ++ * No official RFC-like checks are made ++ */ ++struct ldns_struct_rr_list ++{ ++ size_t _rr_count; ++ size_t _rr_capacity; ++ ldns_rr **_rrs; ++}; ++typedef struct ldns_struct_rr_list ldns_rr_list; ++ ++/** ++ * Contains all information about resource record types. ++ * ++ * This structure contains, for all rr types, the rdata fields that are defined. ++ */ ++struct ldns_struct_rr_descriptor ++{ ++ /** Type of the RR that is described here */ ++ ldns_rr_type _type; ++ /** Textual name of the RR type. */ ++ const char *_name; ++ /** Minimum number of rdata fields in the RRs of this type. */ ++ uint8_t _minimum; ++ /** Maximum number of rdata fields in the RRs of this type. */ ++ uint8_t _maximum; ++ /** Wireformat specification for the rr, i.e. the types of rdata fields in their respective order. */ ++ const ldns_rdf_type *_wireformat; ++ /** Special rdf types */ ++ ldns_rdf_type _variable; ++ /** Specifies whether compression can be used for dnames in this RR type. */ ++ ldns_rr_compress _compress; ++ /** The number of DNAMEs in the _wireformat string, for parsing. */ ++ uint8_t _dname_count; ++}; ++typedef struct ldns_struct_rr_descriptor ldns_rr_descriptor; ++ ++ ++/** ++ * Create a rr type bitmap rdf providing enough space to set all ++ * known (to ldns) rr types. ++ * \param[out] rdf the constructed rdf ++ * \return LDNS_STATUS_OK if all went well. ++ */ ++ldns_status ldns_rdf_bitmap_known_rr_types_space(ldns_rdf** rdf); ++ ++/** ++ * Create a rr type bitmap rdf with at least all known (to ldns) rr types set. ++ * \param[out] rdf the constructed rdf ++ * \return LDNS_STATUS_OK if all went well. ++ */ ++ldns_status ldns_rdf_bitmap_known_rr_types(ldns_rdf** rdf); ++ ++ ++/** ++ * creates a new rr structure. ++ * \return ldns_rr * ++ */ ++ldns_rr* ldns_rr_new(void); ++ ++/** ++ * creates a new rr structure, based on the given type. ++ * alloc enough space to hold all the rdf's ++ */ ++ldns_rr* ldns_rr_new_frm_type(ldns_rr_type t); ++ ++/** ++ * frees an RR structure ++ * \param[in] *rr the RR to be freed ++ * \return void ++ */ ++void ldns_rr_free(ldns_rr *rr); ++ ++/** ++ * creates an rr from a string. ++ * The string should be a fully filled-in rr, like ++ * ownername <space> TTL <space> CLASS <space> ++ * TYPE <space> RDATA. ++ * \param[out] n the rr to return ++ * \param[in] str the string to convert ++ * \param[in] default_ttl default ttl value for the rr. ++ * If 0 DEF_TTL will be used ++ * \param[in] origin when the owner is relative add this. ++ * The caller must ldns_rdf_deep_free it. ++ * \param[out] prev the previous ownername. if this value is not NULL, ++ * the function overwrites this with the ownername found in this ++ * string. The caller must then ldns_rdf_deep_free it. ++ * \return a status msg describing an error or LDNS_STATUS_OK ++ */ ++ldns_status ldns_rr_new_frm_str(ldns_rr **n, const char *str, ++ uint32_t default_ttl, ldns_rdf *origin, ++ ldns_rdf **prev); ++ ++/** ++ * creates an rr for the question section from a string, i.e. ++ * without RDATA fields ++ * Origin and previous RR functionality are the same as in ++ * ldns_rr_new_frm_str() ++ * \param[out] n the rr to return ++ * \param[in] str the string to convert ++ * \param[in] origin when the owner is relative add this. ++ * The caller must ldns_rdf_deep_free it. ++ * \param prev the previous ownername. the function overwrite this with ++ * the current found ownername. The caller must ldns_rdf_deep_free it. ++ * \return a status msg describing an error or LDNS_STATUS_OK ++ */ ++ldns_status ldns_rr_new_question_frm_str(ldns_rr **n, const char *str, ++ ldns_rdf *origin, ldns_rdf **prev); ++ ++/** ++ * creates a new rr from a file containing a string. ++ * \param[out] rr the new rr ++ * \param[in] fp the file pointer to use ++ * \param[in] default_ttl pointer to a default ttl for the rr. If NULL DEF_TTL will be used ++ * the pointer will be updated if the file contains a $TTL directive ++ * \param[in] origin when the owner is relative add this ++ * the pointer will be updated if the file contains a $ORIGIN directive ++ * The caller must ldns_rdf_deep_free it. ++ * \param[in] prev when the owner is whitespaces use this as the * ownername ++ * the pointer will be updated after the call ++ * The caller must ldns_rdf_deep_free it. ++ * \return a ldns_status with an error or LDNS_STATUS_OK ++ */ ++ldns_status ldns_rr_new_frm_fp(ldns_rr **rr, FILE *fp, uint32_t *default_ttl, ldns_rdf **origin, ldns_rdf **prev); ++ ++/** ++ * creates a new rr from a file containing a string. ++ * \param[out] rr the new rr ++ * \param[in] fp the file pointer to use ++ * \param[in] default_ttl a default ttl for the rr. If NULL DEF_TTL will be used ++ * the pointer will be updated if the file contains a $TTL directive ++ * \param[in] origin when the owner is relative add this ++ * the pointer will be updated if the file contains a $ORIGIN directive ++ * The caller must ldns_rdf_deep_free it. ++ * \param[in] line_nr pointer to an integer containing the current line number (for debugging purposes) ++ * \param[in] prev when the owner is whitespaces use this as the * ownername ++ * the pointer will be updated after the call ++ * The caller must ldns_rdf_deep_free it. ++ * \return a ldns_status with an error or LDNS_STATUS_OK ++ */ ++ldns_status ldns_rr_new_frm_fp_l(ldns_rr **rr, FILE *fp, uint32_t *default_ttl, ldns_rdf **origin, ldns_rdf **prev, int *line_nr); ++ ++/** ++ * sets the owner in the rr structure. ++ * \param[in] *rr rr to operate on ++ * \param[in] *owner set to this owner ++ * \return void ++ */ ++void ldns_rr_set_owner(ldns_rr *rr, ldns_rdf *owner); ++ ++/** ++ * sets the question flag in the rr structure. ++ * \param[in] *rr rr to operate on ++ * \param[in] question question flag ++ * \return void ++ */ ++void ldns_rr_set_question(ldns_rr *rr, bool question); ++ ++/** ++ * sets the ttl in the rr structure. ++ * \param[in] *rr rr to operate on ++ * \param[in] ttl set to this ttl ++ * \return void ++ */ ++void ldns_rr_set_ttl(ldns_rr *rr, uint32_t ttl); ++ ++/** ++ * sets the rd_count in the rr. ++ * \param[in] *rr rr to operate on ++ * \param[in] count set to this count ++ * \return void ++ */ ++void ldns_rr_set_rd_count(ldns_rr *rr, size_t count); ++ ++/** ++ * sets the type in the rr. ++ * \param[in] *rr rr to operate on ++ * \param[in] rr_type set to this type ++ * \return void ++ */ ++void ldns_rr_set_type(ldns_rr *rr, ldns_rr_type rr_type); ++ ++/** ++ * sets the class in the rr. ++ * \param[in] *rr rr to operate on ++ * \param[in] rr_class set to this class ++ * \return void ++ */ ++void ldns_rr_set_class(ldns_rr *rr, ldns_rr_class rr_class); ++ ++/** ++ * sets a rdf member, it will be set on the ++ * position given. The old value is returned, like pop. ++ * \param[in] *rr the rr to operate on ++ * \param[in] *f the rdf to set ++ * \param[in] position the position the set the rdf ++ * \return the old value in the rr, NULL on failyre ++ */ ++ldns_rdf* ldns_rr_set_rdf(ldns_rr *rr, const ldns_rdf *f, size_t position); ++ ++/** ++ * sets rd_field member, it will be ++ * placed in the next available spot. ++ * \param[in] *rr rr to operate on ++ * \param[in] *f the data field member to set ++ * \return bool ++ */ ++bool ldns_rr_push_rdf(ldns_rr *rr, const ldns_rdf *f); ++ ++/** ++ * removes a rd_field member, it will be ++ * popped from the last position. ++ * \param[in] *rr rr to operate on ++ * \return rdf which was popped (null if nothing) ++ */ ++ldns_rdf* ldns_rr_pop_rdf(ldns_rr *rr); ++ ++/** ++ * returns the rdata field member counter. ++ * \param[in] *rr rr to operate on ++ * \param[in] nr the number of the rdf to return ++ * \return ldns_rdf * ++ */ ++ldns_rdf* ldns_rr_rdf(const ldns_rr *rr, size_t nr); ++ ++/** ++ * returns the owner name of an rr structure. ++ * \param[in] *rr rr to operate on ++ * \return ldns_rdf * ++ */ ++ldns_rdf* ldns_rr_owner(const ldns_rr *rr); ++ ++/** ++ * returns the question flag of an rr structure. ++ * \param[in] *rr rr to operate on ++ * \return bool true if question ++ */ ++bool ldns_rr_is_question(const ldns_rr *rr); ++ ++/** ++ * returns the ttl of an rr structure. ++ * \param[in] *rr the rr to read from ++ * \return the ttl of the rr ++ */ ++uint32_t ldns_rr_ttl(const ldns_rr *rr); ++ ++/** ++ * returns the rd_count of an rr structure. ++ * \param[in] *rr the rr to read from ++ * \return the rd count of the rr ++ */ ++size_t ldns_rr_rd_count(const ldns_rr *rr); ++ ++/** ++ * returns the type of the rr. ++ * \param[in] *rr the rr to read from ++ * \return the type of the rr ++ */ ++ldns_rr_type ldns_rr_get_type(const ldns_rr *rr); ++ ++/** ++ * returns the class of the rr. ++ * \param[in] *rr the rr to read from ++ * \return the class of the rr ++ */ ++ldns_rr_class ldns_rr_get_class(const ldns_rr *rr); ++ ++/* rr_lists */ ++ ++/** ++ * returns the number of rr's in an rr_list. ++ * \param[in] rr_list the rr_list to read from ++ * \return the number of rr's ++ */ ++size_t ldns_rr_list_rr_count(const ldns_rr_list *rr_list); ++ ++/** ++ * sets the number of rr's in an rr_list. ++ * \param[in] rr_list the rr_list to set the count on ++ * \param[in] count the number of rr in this list ++ * \return void ++ */ ++void ldns_rr_list_set_rr_count(ldns_rr_list *rr_list, size_t count); ++ ++/** ++ * set a rr on a specific index in a ldns_rr_list ++ * \param[in] rr_list the rr_list to use ++ * \param[in] r the rr to set ++ * \param[in] count index into the rr_list ++ * \return the old rr which was stored in the rr_list, or ++ * NULL is the index was too large ++ * set a specific rr */ ++ldns_rr * ldns_rr_list_set_rr(ldns_rr_list *rr_list, const ldns_rr *r, size_t count); ++ ++/** ++ * returns a specific rr of an rrlist. ++ * \param[in] rr_list the rr_list to read from ++ * \param[in] nr return this rr ++ * \return the rr at position nr ++ */ ++ldns_rr* ldns_rr_list_rr(const ldns_rr_list *rr_list, size_t nr); ++ ++/** ++ * creates a new rr_list structure. ++ * \return a new rr_list structure ++ */ ++ldns_rr_list* ldns_rr_list_new(void); ++ ++/** ++ * frees an rr_list structure. ++ * \param[in] rr_list the list to free ++ */ ++void ldns_rr_list_free(ldns_rr_list *rr_list); ++ ++/** ++ * frees an rr_list structure and all rrs contained therein. ++ * \param[in] rr_list the list to free ++ */ ++void ldns_rr_list_deep_free(ldns_rr_list *rr_list); ++ ++/** ++ * concatenates two ldns_rr_lists together. This modifies ++ * *left (to extend it and add the pointers from *right). ++ * \param[in] left the leftside ++ * \param[in] right the rightside ++ * \return a left with right concatenated to it ++ */ ++bool ldns_rr_list_cat(ldns_rr_list *left, ldns_rr_list *right); ++ ++/** ++ * concatenates two ldns_rr_lists together, but makes clones of the rr's ++ * (instead of pointer copying). ++ * \param[in] left the leftside ++ * \param[in] right the rightside ++ * \return a new rr_list with leftside/rightside concatenated ++ */ ++ldns_rr_list* ldns_rr_list_cat_clone(ldns_rr_list *left, ldns_rr_list *right); ++ ++/** ++ * pushes an rr to an rrlist. ++ * \param[in] rr_list the rr_list to push to ++ * \param[in] rr the rr to push ++ * \return false on error, otherwise true ++ */ ++bool ldns_rr_list_push_rr(ldns_rr_list *rr_list, const ldns_rr *rr); ++ ++/** ++ * pushes an rr_list to an rrlist. ++ * \param[in] rr_list the rr_list to push to ++ * \param[in] push_list the rr_list to push ++ * \return false on error, otherwise true ++ */ ++bool ldns_rr_list_push_rr_list(ldns_rr_list *rr_list, const ldns_rr_list *push_list); ++ ++/** ++ * pops the last rr from an rrlist. ++ * \param[in] rr_list the rr_list to pop from ++ * \return NULL if nothing to pop. Otherwise the popped RR ++ */ ++ldns_rr* ldns_rr_list_pop_rr(ldns_rr_list *rr_list); ++ ++/** ++ * pops an rr_list of size s from an rrlist. ++ * \param[in] rr_list the rr_list to pop from ++ * \param[in] size the number of rr's to pop ++ * \return NULL if nothing to pop. Otherwise the popped rr_list ++ */ ++ldns_rr_list* ldns_rr_list_pop_rr_list(ldns_rr_list *rr_list, size_t size); ++ ++/** ++ * returns true if the given rr is one of the rrs in the ++ * list, or if it is equal to one ++ * \param[in] rr_list the rr_list to check ++ * \param[in] rr the rr to check ++ * \return true if rr_list contains rr, false otherwise ++ */ ++bool ldns_rr_list_contains_rr(const ldns_rr_list *rr_list, ldns_rr *rr); ++ ++/** ++ * checks if an rr_list is a rrset. ++ * \param[in] rr_list the rr_list to check ++ * \return true if it is an rrset otherwise false ++ */ ++bool ldns_is_rrset(ldns_rr_list *rr_list); ++ ++/** ++ * pushes an rr to an rrset (which really are rr_list's). ++ * \param[in] *rr_list the rrset to push the rr to ++ * \param[in] *rr the rr to push ++ * \return true if the push succeeded otherwise false ++ */ ++bool ldns_rr_set_push_rr(ldns_rr_list *rr_list, ldns_rr *rr); ++ ++/** ++ * pops the last rr from an rrset. This function is there only ++ * for the symmetry. ++ * \param[in] rr_list the rr_list to pop from ++ * \return NULL if nothing to pop. Otherwise the popped RR ++ * ++ */ ++ldns_rr* ldns_rr_set_pop_rr(ldns_rr_list *rr_list); ++ ++/** ++ * pops the first rrset from the list, ++ * the list must be sorted, so that all rr's from each rrset ++ * are next to each other ++ */ ++ldns_rr_list *ldns_rr_list_pop_rrset(ldns_rr_list *rr_list); ++ ++ ++/** ++ * retrieves a rrtype by looking up its name. ++ * \param[in] name a string with the name ++ * \return the type which corresponds with the name ++ */ ++ldns_rr_type ldns_get_rr_type_by_name(const char *name); ++ ++/** ++ * retrieves a class by looking up its name. ++ * \param[in] name string with the name ++ * \return the cass which corresponds with the name ++ */ ++ldns_rr_class ldns_get_rr_class_by_name(const char *name); ++ ++/** ++ * clones a rr and all its data ++ * \param[in] rr the rr to clone ++ * \return the new rr or NULL on failure ++ */ ++ldns_rr* ldns_rr_clone(const ldns_rr *rr); ++ ++/** ++ * clones an rrlist. ++ * \param[in] rrlist the rrlist to clone ++ * \return the cloned rr list ++ */ ++ldns_rr_list* ldns_rr_list_clone(const ldns_rr_list *rrlist); ++ ++/** ++ * sorts an rr_list (canonical wire format). the sorting is done inband. ++ * \param[in] unsorted the rr_list to be sorted ++ * \return void ++ */ ++void ldns_rr_list_sort(ldns_rr_list *unsorted); ++ ++/** ++ * compares two rrs. The TTL is not looked at. ++ * \param[in] rr1 the first one ++ * \param[in] rr2 the second one ++ * \return 0 if equal ++ * -1 if rr1 comes before rr2 ++ * +1 if rr2 comes before rr1 ++ */ ++int ldns_rr_compare(const ldns_rr *rr1, const ldns_rr *rr2); ++ ++/** ++ * compares two rrs, up to the rdata. ++ * \param[in] rr1 the first one ++ * \param[in] rr2 the second one ++ * \return 0 if equal ++ * -1 if rr1 comes before rr2 ++ * +1 if rr2 comes before rr1 ++ */ ++int ldns_rr_compare_no_rdata(const ldns_rr *rr1, const ldns_rr *rr2); ++ ++/** ++ * compares the wireformat of two rrs, contained in the given buffers. ++ * \param[in] rr1_buf the first one ++ * \param[in] rr2_buf the second one ++ * \return 0 if equal ++ * -1 if rr1_buf comes before rr2_buf ++ * +1 if rr2_buf comes before rr1_buf ++ */ ++int ldns_rr_compare_wire(ldns_buffer *rr1_buf, ldns_buffer *rr2_buf); ++ ++/** ++ * returns true of the given rr's are equal. ++ * Also returns true if one record is a DS that represents the ++ * same DNSKEY record as the other record ++ * \param[in] rr1 the first rr ++ * \param[in] rr2 the second rr ++ * \return true if equal otherwise false ++ */ ++bool ldns_rr_compare_ds(const ldns_rr *rr1, const ldns_rr *rr2); ++ ++/** ++ * compares two rr listss. ++ * \param[in] rrl1 the first one ++ * \param[in] rrl2 the second one ++ * \return 0 if equal ++ * -1 if rrl1 comes before rrl2 ++ * +1 if rrl2 comes before rrl1 ++ */ ++int ldns_rr_list_compare(const ldns_rr_list *rrl1, const ldns_rr_list *rrl2); ++ ++/** ++ * calculates the uncompressed size of an RR. ++ * \param[in] r the rr to operate on ++ * \return size of the rr ++ */ ++size_t ldns_rr_uncompressed_size(const ldns_rr *r); ++ ++/** ++ * converts each dname in a rr to its canonical form. ++ * \param[in] rr the rr to work on ++ * \return void ++ */ ++void ldns_rr2canonical(ldns_rr *rr); ++ ++/** ++ * converts each dname in each rr in a rr_list to its canonical form. ++ * \param[in] rr_list the rr_list to work on ++ * \return void ++ */ ++void ldns_rr_list2canonical(ldns_rr_list *rr_list); ++ ++/** ++ * counts the number of labels of the ownername. ++ * \param[in] rr count the labels of this rr ++ * \return the number of labels ++ */ ++uint8_t ldns_rr_label_count(ldns_rr *rr); ++ ++/** ++ * returns the resource record descriptor for the given rr type. ++ * ++ * \param[in] type the type value of the rr type ++ *\return the ldns_rr_descriptor for this type ++ */ ++const ldns_rr_descriptor *ldns_rr_descript(uint16_t type); ++ ++/** ++ * returns the minimum number of rdata fields of the rr type this descriptor describes. ++ * ++ * \param[in] descriptor for an rr type ++ * \return the minimum number of rdata fields ++ */ ++size_t ldns_rr_descriptor_minimum(const ldns_rr_descriptor *descriptor); ++ ++/** ++ * returns the maximum number of rdata fields of the rr type this descriptor describes. ++ * ++ * \param[in] descriptor for an rr type ++ * \return the maximum number of rdata fields ++ */ ++size_t ldns_rr_descriptor_maximum(const ldns_rr_descriptor *descriptor); ++ ++/** ++ * returns the rdf type for the given rdata field number of the rr type for the given descriptor. ++ * ++ * \param[in] descriptor for an rr type ++ * \param[in] field the field number ++ * \return the rdf type for the field ++ */ ++ldns_rdf_type ldns_rr_descriptor_field_type(const ldns_rr_descriptor *descriptor, size_t field); ++ ++/** ++ * Return the rr_list which matches the rdf at position field. Think ++ * type-covered stuff for RRSIG ++ * ++ * \param[in] l the rr_list to look in ++ * \param[in] r the rdf to use for the comparison ++ * \param[in] pos at which position can we find the rdf ++ * ++ * \return a new rr list with only the RRs that match ++ * ++ */ ++ldns_rr_list *ldns_rr_list_subtype_by_rdf(ldns_rr_list *l, ldns_rdf *r, size_t pos); ++ ++/** ++ * convert an rdf of type LDNS_RDF_TYPE_TYPE to an actual ++ * LDNS_RR_TYPE. This is usefull in the case when inspecting ++ * the rrtype covered field of an RRSIG. ++ * \param[in] rd the rdf to look at ++ * \return a ldns_rr_type with equivalent LDNS_RR_TYPE ++ * ++ */ ++ldns_rr_type ldns_rdf2rr_type(const ldns_rdf *rd); ++ ++/** ++ * Returns the type of the first element of the RR ++ * If there are no elements present, 0 is returned ++ * ++ * \param[in] rr_list The rr list ++ * \return rr_type of the first element, or 0 if the list is empty ++ */ ++ldns_rr_type ++ldns_rr_list_type(const ldns_rr_list *rr_list); ++ ++/** ++ * Returns the owner domain name rdf of the first element of the RR ++ * If there are no elements present, NULL is returned ++ * ++ * \param[in] rr_list The rr list ++ * \return dname of the first element, or NULL if the list is empty ++ */ ++ldns_rdf * ++ldns_rr_list_owner(const ldns_rr_list *rr_list); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* LDNS_RR_H */ +diff --git a/ldns/include/ldns/rr_functions.h b/ldns/include/ldns/rr_functions.h +new file mode 100644 +index 0000000..09a28dd +--- /dev/null ++++ b/ldns/include/ldns/rr_functions.h +@@ -0,0 +1,363 @@ ++/* ++ * rr_functions.h ++ * ++ * the .h file with defs for the per rr ++ * functions ++ * ++ * a Net::DNS like library for C ++ * ++ * (c) NLnet Labs, 2005-2006 ++ * ++ * See the file LICENSE for the license ++ */ ++#ifndef LDNS_RR_FUNCTIONS_H ++#define LDNS_RR_FUNCTIONS_H ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/** ++ * \file ++ * ++ * Defines some extra convenience functions for ldns_rr structures ++ */ ++ ++/* A / AAAA */ ++/** ++ * returns the address of a LDNS_RR_TYPE_A rr ++ * \param[in] r the resource record ++ * \return a ldns_rdf* with the address or NULL on failure ++ */ ++ldns_rdf* ldns_rr_a_address(const ldns_rr *r); ++ ++/** ++ * sets the address of a LDNS_RR_TYPE_A rr ++ * \param[in] r the rr to use ++ * \param[in] f the address to set ++ * \return true on success, false otherwise ++ */ ++bool ldns_rr_a_set_address(ldns_rr *r, ldns_rdf *f); ++ ++/* NS */ ++/** ++ * returns the name of a LDNS_RR_TYPE_NS rr ++ * \param[in] r the resource record ++ * \return a ldns_rdf* with the name or NULL on failure ++ */ ++ldns_rdf* ldns_rr_ns_nsdname(const ldns_rr *r); ++ ++/* MX */ ++/** ++ * returns the mx pref. of a LDNS_RR_TYPE_MX rr ++ * \param[in] r the resource record ++ * \return a ldns_rdf* with the preference or NULL on failure ++ */ ++ldns_rdf* ldns_rr_mx_preference(const ldns_rr *r); ++/** ++ * returns the mx host of a LDNS_RR_TYPE_MX rr ++ * \param[in] r the resource record ++ * \return a ldns_rdf* with the name of the MX host or NULL on failure ++ */ ++ldns_rdf* ldns_rr_mx_exchange(const ldns_rr *r); ++ ++/* RRSIG */ ++/** ++ * returns the type covered of a LDNS_RR_TYPE_RRSIG rr ++ * \param[in] r the resource record ++ * \return a ldns_rdf* with the type covered or NULL on failure ++ */ ++ldns_rdf* ldns_rr_rrsig_typecovered(const ldns_rr *r); ++/** ++ * sets the typecovered of a LDNS_RR_TYPE_RRSIG rr ++ * \param[in] r the rr to use ++ * \param[in] f the typecovered to set ++ * \return true on success, false otherwise ++ */ ++bool ldns_rr_rrsig_set_typecovered(ldns_rr *r, ldns_rdf *f); ++/** ++ * returns the algorithm of a LDNS_RR_TYPE_RRSIG RR ++ * \param[in] r the resource record ++ * \return a ldns_rdf* with the algorithm or NULL on failure ++ */ ++ldns_rdf* ldns_rr_rrsig_algorithm(const ldns_rr *r); ++/** ++ * sets the algorithm of a LDNS_RR_TYPE_RRSIG rr ++ * \param[in] r the rr to use ++ * \param[in] f the algorithm to set ++ * \return true on success, false otherwise ++ */ ++bool ldns_rr_rrsig_set_algorithm(ldns_rr *r, ldns_rdf *f); ++/** ++ * returns the number of labels of a LDNS_RR_TYPE_RRSIG RR ++ * \param[in] r the resource record ++ * \return a ldns_rdf* with the number of labels or NULL on failure ++ */ ++ldns_rdf *ldns_rr_rrsig_labels(const ldns_rr *r); ++/** ++ * sets the number of labels of a LDNS_RR_TYPE_RRSIG rr ++ * \param[in] r the rr to use ++ * \param[in] f the number of labels to set ++ * \return true on success, false otherwise ++ */ ++bool ldns_rr_rrsig_set_labels(ldns_rr *r, ldns_rdf *f); ++/** ++ * returns the original TTL of a LDNS_RR_TYPE_RRSIG RR ++ * \param[in] r the resource record ++ * \return a ldns_rdf* with the original TTL or NULL on failure ++ */ ++ldns_rdf* ldns_rr_rrsig_origttl(const ldns_rr *r); ++/** ++ * sets the original TTL of a LDNS_RR_TYPE_RRSIG rr ++ * \param[in] r the rr to use ++ * \param[in] f the original TTL to set ++ * \return true on success, false otherwise ++ */ ++bool ldns_rr_rrsig_set_origttl(ldns_rr *r, ldns_rdf *f); ++/** ++ * returns the expiration time of a LDNS_RR_TYPE_RRSIG RR ++ * \param[in] r the resource record ++ * \return a ldns_rdf* with the expiration time or NULL on failure ++ */ ++ldns_rdf* ldns_rr_rrsig_expiration(const ldns_rr *r); ++/** ++ * sets the expireation date of a LDNS_RR_TYPE_RRSIG rr ++ * \param[in] r the rr to use ++ * \param[in] f the expireation date to set ++ * \return true on success, false otherwise ++ */ ++bool ldns_rr_rrsig_set_expiration(ldns_rr *r, ldns_rdf *f); ++/** ++ * returns the inception time of a LDNS_RR_TYPE_RRSIG RR ++ * \param[in] r the resource record ++ * \return a ldns_rdf* with the inception time or NULL on failure ++ */ ++ldns_rdf* ldns_rr_rrsig_inception(const ldns_rr *r); ++/** ++ * sets the inception date of a LDNS_RR_TYPE_RRSIG rr ++ * \param[in] r the rr to use ++ * \param[in] f the inception date to set ++ * \return true on success, false otherwise ++ */ ++bool ldns_rr_rrsig_set_inception(ldns_rr *r, ldns_rdf *f); ++/** ++ * returns the keytag of a LDNS_RR_TYPE_RRSIG RR ++ * \param[in] r the resource record ++ * \return a ldns_rdf* with the keytag or NULL on failure ++ */ ++ldns_rdf* ldns_rr_rrsig_keytag(const ldns_rr *r); ++/** ++ * sets the keytag of a LDNS_RR_TYPE_RRSIG rr ++ * \param[in] r the rr to use ++ * \param[in] f the keytag to set ++ * \return true on success, false otherwise ++ */ ++bool ldns_rr_rrsig_set_keytag(ldns_rr *r, ldns_rdf *f); ++/** ++ * returns the signers name of a LDNS_RR_TYPE_RRSIG RR ++ * \param[in] r the resource record ++ * \return a ldns_rdf* with the signers name or NULL on failure ++ */ ++ldns_rdf* ldns_rr_rrsig_signame(const ldns_rr *r); ++/** ++ * sets the signers name of a LDNS_RR_TYPE_RRSIG rr ++ * \param[in] r the rr to use ++ * \param[in] f the signers name to set ++ * \return true on success, false otherwise ++ */ ++bool ldns_rr_rrsig_set_signame(ldns_rr *r, ldns_rdf *f); ++/** ++ * returns the signature data of a LDNS_RR_TYPE_RRSIG RR ++ * \param[in] r the resource record ++ * \return a ldns_rdf* with the signature data or NULL on failure ++ */ ++ldns_rdf* ldns_rr_rrsig_sig(const ldns_rr *r); ++/** ++ * sets the signature data of a LDNS_RR_TYPE_RRSIG rr ++ * \param[in] r the rr to use ++ * \param[in] f the signature data to set ++ * \return true on success, false otherwise ++ */ ++bool ldns_rr_rrsig_set_sig(ldns_rr *r, ldns_rdf *f); ++ ++/* DNSKEY */ ++/** ++ * returns the flags of a LDNS_RR_TYPE_DNSKEY rr ++ * \param[in] r the resource record ++ * \return a ldns_rdf* with the flags or NULL on failure ++ */ ++ldns_rdf* ldns_rr_dnskey_flags(const ldns_rr *r); ++/** ++ * sets the flags of a LDNS_RR_TYPE_DNSKEY rr ++ * \param[in] r the rr to use ++ * \param[in] f the flags to set ++ * \return true on success, false otherwise ++ */ ++bool ldns_rr_dnskey_set_flags(ldns_rr *r, ldns_rdf *f); ++/** ++ * returns the protocol of a LDNS_RR_TYPE_DNSKEY rr ++ * \param[in] r the resource record ++ * \return a ldns_rdf* with the protocol or NULL on failure ++ */ ++ldns_rdf* ldns_rr_dnskey_protocol(const ldns_rr *r); ++/** ++ * sets the protocol of a LDNS_RR_TYPE_DNSKEY rr ++ * \param[in] r the rr to use ++ * \param[in] f the protocol to set ++ * \return true on success, false otherwise ++ */ ++bool ldns_rr_dnskey_set_protocol(ldns_rr *r, ldns_rdf *f); ++/** ++ * returns the algorithm of a LDNS_RR_TYPE_DNSKEY rr ++ * \param[in] r the resource record ++ * \return a ldns_rdf* with the algorithm or NULL on failure ++ */ ++ldns_rdf* ldns_rr_dnskey_algorithm(const ldns_rr *r); ++/** ++ * sets the algorithm of a LDNS_RR_TYPE_DNSKEY rr ++ * \param[in] r the rr to use ++ * \param[in] f the algorithm to set ++ * \return true on success, false otherwise ++ */ ++bool ldns_rr_dnskey_set_algorithm(ldns_rr *r, ldns_rdf *f); ++/** ++ * returns the key data of a LDNS_RR_TYPE_DNSKEY rr ++ * \param[in] r the resource record ++ * \return a ldns_rdf* with the key data or NULL on failure ++ */ ++ldns_rdf* ldns_rr_dnskey_key(const ldns_rr *r); ++/** ++ * sets the key data of a LDNS_RR_TYPE_DNSKEY rr ++ * \param[in] r the rr to use ++ * \param[in] f the key data to set ++ * \return true on success, false otherwise ++ */ ++bool ldns_rr_dnskey_set_key(ldns_rr *r, ldns_rdf *f); ++ ++/** ++ * get the length of the keydata in bits ++ * \param[in] keydata the raw key data ++ * \param[in] len the length of the keydata ++ * \param[in] alg the cryptographic algorithm this is a key for ++ * \return the keysize in bits, or 0 on error ++ */ ++size_t ldns_rr_dnskey_key_size_raw(const unsigned char *keydata, ++ const size_t len, ++ const ldns_algorithm alg); ++ ++/** ++ * get the length of the keydata in bits ++ * \param[in] key the key rr to use ++ * \return the keysize in bits ++ */ ++size_t ldns_rr_dnskey_key_size(const ldns_rr *key); ++ ++/** ++ * The type of function to be passed to ldns_rr_soa_increment_func, ++ * ldns_rr_soa_increment_func_data or ldns_rr_soa_increment_int. ++ * The function will be called with as the first argument the current serial ++ * number of the SOA RR to be updated, and as the second argument a value ++ * given when calling ldns_rr_soa_increment_func_data or ++ * ldns_rr_soa_increment_int. With ldns_rr_soa_increment_int the pointer ++ * value holds the integer value passed to ldns_rr_soa_increment_int, ++ * and it should be cast to intptr_t to be used as an integer by the ++ * serial modifying function. ++ */ ++typedef uint32_t (*ldns_soa_serial_increment_func_t)(uint32_t, void*); ++ ++/** ++ * Function to be used with dns_rr_soa_increment_func_int, to set the soa ++ * serial number. ++ * \param[in] unused the (unused) current serial number. ++ * \param[in] data the serial number to be set. ++ */ ++uint32_t ldns_soa_serial_identity(uint32_t unused, void *data); ++ ++/** ++ * Function to be used with dns_rr_soa_increment_func, to increment the soa ++ * serial number with one. ++ * \param[in] s the current serial number. ++ * \param[in] unused unused. ++ */ ++uint32_t ldns_soa_serial_increment(uint32_t s, void *unused); ++ ++/** ++ * Function to be used with dns_rr_soa_increment_func_int, to increment the soa ++ * serial number with a certain amount. ++ * \param[in] s the current serial number. ++ * \param[in] data the amount to add to the current serial number. ++ */ ++uint32_t ldns_soa_serial_increment_by(uint32_t s, void *data); ++ ++/** ++ * Function to be used with ldns_rr_soa_increment_func or ++ * ldns_rr_soa_increment_func_int to set the soa serial to the number of ++ * seconds since unix epoch (1-1-1970 00:00). ++ * When data is given (i.e. the function is called via ++ * ldns_rr_soa_increment_func_int), it is used as the current time. ++ * When the resulting serial number is smaller than the current serial number, ++ * the current serial number is increased by one. ++ * \param[in] s the current serial number. ++ * \param[in] data the time in seconds since 1-1-1970 00:00 ++ */ ++uint32_t ldns_soa_serial_unixtime(uint32_t s, void *data); ++ ++/** ++ * Function to be used with ldns_rr_soa_increment_func or ++ * ldns_rr_soa_increment_func_int to set the soa serial to the current date ++ * succeeded by a two digit iteration (datecounter). ++ * When data is given (i.e. the function is called via ++ * ldns_rr_soa_increment_func_int), it is used as the current time. ++ * When the resulting serial number is smaller than the current serial number, ++ * the current serial number is increased by one. ++ * \param[in] s the current serial number. ++ * \param[in] data the time in seconds since 1-1-1970 00:00 ++ */ ++uint32_t ldns_soa_serial_datecounter(uint32_t s, void *data); ++ ++/** ++ * Increment the serial number of the given SOA by one. ++ * \param[in] soa The soa rr to be incremented ++ */ ++void ldns_rr_soa_increment( ++ ldns_rr *soa); ++ ++/** ++ * Increment the serial number of the given SOA with the given function. ++ * Included functions to be used here are: ldns_rr_soa_increment, ++ * ldns_soa_serial_unixtime and ldns_soa_serial_datecounter. ++ * \param[in] soa The soa rr to be incremented ++ * \param[in] f the function to use to increment the soa rr. ++ */ ++void ldns_rr_soa_increment_func( ++ ldns_rr *soa, ldns_soa_serial_increment_func_t f); ++ ++/** ++ * Increment the serial number of the given SOA with the given function ++ * passing it the given data argument. ++ * \param[in] soa The soa rr to be incremented ++ * \param[in] f the function to use to increment the soa rr. ++ * \param[in] data this argument will be passed to f as the second argument. ++ */ ++void ldns_rr_soa_increment_func_data( ++ ldns_rr *soa, ldns_soa_serial_increment_func_t f, void *data); ++ ++/** ++ * Increment the serial number of the given SOA with the given function ++ * using data as an argument for the function. ++ * Included functions to be used here are: ldns_soa_serial_identity, ++ * ldns_rr_soa_increment_by, ldns_soa_serial_unixtime and ++ * ldns_soa_serial_datecounter. ++ * \param[in] soa The soa rr to be incremented ++ * \param[in] f the function to use to increment the soa rr. ++ * \param[in] data this argument will be passed to f as the second argument ++ * (by casting it to void*). ++ */ ++void ldns_rr_soa_increment_func_int( ++ ldns_rr *soa, ldns_soa_serial_increment_func_t f, int data); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* LDNS_RR_FUNCTIONS_H */ +diff --git a/ldns/include/ldns/sha1.h b/ldns/include/ldns/sha1.h +new file mode 100644 +index 0000000..d5b1082 +--- /dev/null ++++ b/ldns/include/ldns/sha1.h +@@ -0,0 +1,38 @@ ++#ifndef LDNS_SHA1_H ++#define LDNS_SHA1_H ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#define LDNS_SHA1_BLOCK_LENGTH 64 ++#define LDNS_SHA1_DIGEST_LENGTH 20 ++ ++typedef struct { ++ uint32_t state[5]; ++ uint64_t count; ++ unsigned char buffer[LDNS_SHA1_BLOCK_LENGTH]; ++} ldns_sha1_ctx; ++ ++void ldns_sha1_init(ldns_sha1_ctx * context); ++void ldns_sha1_transform(uint32_t state[5], const unsigned char buffer[LDNS_SHA1_BLOCK_LENGTH]); ++void ldns_sha1_update(ldns_sha1_ctx *context, const unsigned char *data, unsigned int len); ++void ldns_sha1_final(unsigned char digest[LDNS_SHA1_DIGEST_LENGTH], ldns_sha1_ctx *context); ++ ++/** ++ * Convenience function to digest a fixed block of data at once. ++ * ++ * \param[in] data the data to digest ++ * \param[in] data_len the length of data in bytes ++ * \param[out] digest the length of data in bytes ++ * This pointer MUST have LDNS_SHA1_DIGEST_LENGTH bytes ++ * available ++ * \return the SHA1 digest of the given data ++ */ ++unsigned char *ldns_sha1(unsigned char *data, unsigned int data_len, unsigned char *digest); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* LDNS_SHA1_H */ +diff --git a/ldns/include/ldns/sha2.h b/ldns/include/ldns/sha2.h +new file mode 100644 +index 0000000..238767a +--- /dev/null ++++ b/ldns/include/ldns/sha2.h +@@ -0,0 +1,149 @@ ++/* ++ * FILE: sha2.h ++ * AUTHOR: Aaron D. Gifford - http://www.aarongifford.com/ ++ * ++ * Copyright (c) 2000-2001, Aaron D. Gifford ++ * All rights reserved. ++ * ++ * Modified by Jelte Jansen to fit in ldns, and not clash with any ++ * system-defined SHA code. ++ * Changes: ++ * - Renamed (external) functions and constants to fit ldns style ++ * - Removed uintXX vs. u_intXX smartness, since ldns needs uintXX ++ * anyway ++ * - BYTE ORDER check replaced by simple ifdef as defined or not by ++ * configure.ac ++ * - Removed _End and _Data functions ++ * - Added ldns_shaX(data, len, digest) functions ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. Neither the name of the copyright holder nor the names of contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTOR(S) BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ * $Id: sha2.h,v 1.1 2001/11/08 00:02:01 adg Exp adg $ ++ */ ++ ++#ifndef __LDNS_SHA2_H__ ++#define __LDNS_SHA2_H__ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++ ++/* ++ * Import u_intXX_t size_t type definitions from system headers. You ++ * may need to change this, or define these things yourself in this ++ * file. ++ */ ++#include <sys/types.h> ++ ++#if LDNS_BUILD_CONFIG_HAVE_INTTYPES_H ++ ++#include <inttypes.h> ++ ++#endif /* LDNS_BUILD_CONFIG_HAVE_INTTYPES_H */ ++ ++ ++/*** SHA-256/384/512 Various Length Definitions ***********************/ ++#define LDNS_SHA256_BLOCK_LENGTH 64 ++#define LDNS_SHA256_DIGEST_LENGTH 32 ++#define LDNS_SHA256_DIGEST_STRING_LENGTH (LDNS_SHA256_DIGEST_LENGTH * 2 + 1) ++#define LDNS_SHA384_BLOCK_LENGTH 128 ++#define LDNS_SHA384_DIGEST_LENGTH 48 ++#define LDNS_SHA384_DIGEST_STRING_LENGTH (LDNS_SHA384_DIGEST_LENGTH * 2 + 1) ++#define LDNS_SHA512_BLOCK_LENGTH 128 ++#define LDNS_SHA512_DIGEST_LENGTH 64 ++#define LDNS_SHA512_DIGEST_STRING_LENGTH (LDNS_SHA512_DIGEST_LENGTH * 2 + 1) ++ ++ ++/*** SHA-256/384/512 Context Structures *******************************/ ++ ++typedef struct _ldns_sha256_CTX { ++ uint32_t state[8]; ++ uint64_t bitcount; ++ uint8_t buffer[LDNS_SHA256_BLOCK_LENGTH]; ++} ldns_sha256_CTX; ++typedef struct _ldns_sha512_CTX { ++ uint64_t state[8]; ++ uint64_t bitcount[2]; ++ uint8_t buffer[LDNS_SHA512_BLOCK_LENGTH]; ++} ldns_sha512_CTX; ++ ++typedef ldns_sha512_CTX ldns_sha384_CTX; ++ ++ ++/*** SHA-256/384/512 Function Prototypes ******************************/ ++void ldns_sha256_init(ldns_sha256_CTX *); ++void ldns_sha256_update(ldns_sha256_CTX*, const uint8_t*, size_t); ++void ldns_sha256_final(uint8_t[LDNS_SHA256_DIGEST_LENGTH], ldns_sha256_CTX*); ++ ++void ldns_sha384_init(ldns_sha384_CTX*); ++void ldns_sha384_update(ldns_sha384_CTX*, const uint8_t*, size_t); ++void ldns_sha384_final(uint8_t[LDNS_SHA384_DIGEST_LENGTH], ldns_sha384_CTX*); ++ ++void ldns_sha512_init(ldns_sha512_CTX*); ++void ldns_sha512_update(ldns_sha512_CTX*, const uint8_t*, size_t); ++void ldns_sha512_final(uint8_t[LDNS_SHA512_DIGEST_LENGTH], ldns_sha512_CTX*); ++ ++/** ++ * Convenience function to digest a fixed block of data at once. ++ * ++ * \param[in] data the data to digest ++ * \param[in] data_len the length of data in bytes ++ * \param[out] digest the length of data in bytes ++ * This pointer MUST have LDNS_SHA256_DIGEST_LENGTH bytes ++ * available ++ * \return the SHA1 digest of the given data ++ */ ++unsigned char *ldns_sha256(unsigned char *data, unsigned int data_len, unsigned char *digest); ++ ++/** ++ * Convenience function to digest a fixed block of data at once. ++ * ++ * \param[in] data the data to digest ++ * \param[in] data_len the length of data in bytes ++ * \param[out] digest the length of data in bytes ++ * This pointer MUST have LDNS_SHA384_DIGEST_LENGTH bytes ++ * available ++ * \return the SHA1 digest of the given data ++ */ ++unsigned char *ldns_sha384(unsigned char *data, unsigned int data_len, unsigned char *digest); ++ ++/** ++ * Convenience function to digest a fixed block of data at once. ++ * ++ * \param[in] data the data to digest ++ * \param[in] data_len the length of data in bytes ++ * \param[out] digest the length of data in bytes ++ * This pointer MUST have LDNS_SHA512_DIGEST_LENGTH bytes ++ * available ++ * \return the SHA1 digest of the given data ++ */ ++unsigned char *ldns_sha512(unsigned char *data, unsigned int data_len, unsigned char *digest); ++ ++#ifdef __cplusplus ++} ++#endif /* __cplusplus */ ++ ++#endif /* __LDNS_SHA2_H__ */ +diff --git a/ldns/include/ldns/str2host.h b/ldns/include/ldns/str2host.h +new file mode 100644 +index 0000000..d639970 +--- /dev/null ++++ b/ldns/include/ldns/str2host.h +@@ -0,0 +1,319 @@ ++/** ++ * str2host.h - conversion from str to the host fmt ++ * ++ * a Net::DNS like library for C ++ * ++ * (c) NLnet Labs, 2005-2006 ++ * ++ * See the file LICENSE for the license ++ */ ++ ++#ifndef LDNS_2HOST_H ++#define LDNS_2HOST_H ++ ++#include <ldns/common.h> ++#include <ldns/error.h> ++#include <ldns/rr.h> ++#include <ldns/rdata.h> ++#include <ldns/packet.h> ++#include <ldns/buffer.h> ++#include <ctype.h> ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/** ++ * \file ++ * ++ * Defines functions to convert dns data in presentation format or text files ++ * to internal structures. ++ */ ++ ++/** ++ * convert a byte into wireformat ++ * \param[in] rd the rdf where to put the data ++ * \param[in] bytestr the string to be converted ++ * \return ldns_status ++ */ ++ldns_status ldns_str2rdf_int8(ldns_rdf **rd, const char *bytestr); ++ ++/** ++ * convert a string to a int16 in wireformat ++ * \param[in] rd the rdf where to put the data ++ * \param[in] shortstr the string to be converted ++ * \return ldns_status ++ */ ++ldns_status ldns_str2rdf_int16(ldns_rdf **rd, const char *shortstr); ++ ++/** ++ * convert a strings into a 4 byte int in wireformat ++ * \param[in] rd the rdf where to put the data ++ * \param[in] longstr the string to be converted ++ * \return ldns_status ++ */ ++ldns_status ldns_str2rdf_int32(ldns_rdf **rd, const char *longstr); ++ ++/** ++ * convert a time string to a time value in wireformat ++ * \param[in] rd the rdf where to put the data ++ * \param[in] time the string to be converted ++ * \return ldns_status ++ */ ++ldns_status ldns_str2rdf_time(ldns_rdf **rd, const char *time); ++ ++/* convert string with NSEC3 salt to wireformat) ++ * \param[in] rd the rdf where to put the data ++ * \param[in] str the string to be converted ++ * return ldns_status ++ */ ++ldns_status ldns_str2rdf_nsec3_salt(ldns_rdf **rd, const char *nsec3_salt); ++ ++/* convert a time period (think TTL's) to wireformat) ++ * \param[in] rd the rdf where to put the data ++ * \param[in] str the string to be converted ++ * return ldns_status ++ */ ++ldns_status ldns_str2rdf_period(ldns_rdf **rd, const char *str); ++ ++/** ++ * convert str with an A record into wireformat ++ * \param[in] rd the rdf where to put the data ++ * \param[in] str the string to be converted ++ * \return ldns_status ++ */ ++ldns_status ldns_str2rdf_a(ldns_rdf **rd, const char *str); ++ ++/** ++ * convert the str with an AAAA record into wireformat ++ * \param[in] rd the rdf where to put the data ++ * \param[in] str the string to be converted ++ * \return ldns_status ++ */ ++ldns_status ldns_str2rdf_aaaa(ldns_rdf **rd, const char *str); ++ ++/** ++ * convert a string into wireformat (think txt record) ++ * \param[in] rd the rdf where to put the data ++ * \param[in] str the string to be converted (NULL terminated) ++ * \return ldns_status ++ */ ++ldns_status ldns_str2rdf_str(ldns_rdf **rd, const char *str); ++ ++/** ++ * convert str with the apl record into wireformat ++ * \param[in] rd the rdf where to put the data ++ * \param[in] str the string to be converted ++ * \return ldns_status ++ */ ++ldns_status ldns_str2rdf_apl(ldns_rdf **rd, const char *str); ++ ++/** ++ * convert the string with the b64 data into wireformat ++ * \param[in] rd the rdf where to put the data ++ * \param[in] str the string to be converted ++ * \return ldns_status ++ */ ++ldns_status ldns_str2rdf_b64(ldns_rdf **rd, const char *str); ++ ++/** ++ * convert the string with the b32 ext hex data into wireformat ++ * \param[in] rd the rdf where to put the data ++ * \param[in] str the string to be converted ++ * \return ldns_status ++ */ ++ldns_status ldns_str2rdf_b32_ext(ldns_rdf **rd, const char *str); ++ ++/** ++ * convert a hex value into wireformat ++ * \param[in] rd the rdf where to put the data ++ * \param[in] str the string to be converted ++ * \return ldns_status ++ */ ++ldns_status ldns_str2rdf_hex(ldns_rdf **rd, const char *str); ++ ++/** ++ * convert string with nsec into wireformat ++ * \param[in] rd the rdf where to put the data ++ * \param[in] str the string to be converted ++ * \return ldns_status ++ */ ++ldns_status ldns_str2rdf_nsec(ldns_rdf **rd, const char *str); ++ ++/** ++ * convert a rrtype into wireformat ++ * \param[in] rd the rdf where to put the data ++ * \param[in] str the string to be converted ++ * \return ldns_status ++ */ ++ldns_status ldns_str2rdf_type(ldns_rdf **rd, const char *str); ++ ++/** ++ * convert string with a classname into wireformat ++ * \param[in] rd the rdf where to put the data ++ * \param[in] str the string to be converted ++ * \return ldns_status ++ */ ++ldns_status ldns_str2rdf_class(ldns_rdf **rd, const char *str); ++ ++/** ++ * convert an certificate algorithm value into wireformat ++ * \param[in] rd the rdf where to put the data ++ * \param[in] str the string to be converted ++ * \return ldns_status ++ */ ++ldns_status ldns_str2rdf_cert_alg(ldns_rdf **rd, const char *str); ++ ++/** ++ * convert an algorithm value into wireformat ++ * \param[in] rd the rdf where to put the data ++ * \param[in] str the string to be converted ++ * \return ldns_status ++ */ ++ldns_status ldns_str2rdf_alg(ldns_rdf **rd, const char *str); ++ ++/** ++ * convert a tlsa certificate usage value into wireformat ++ * \param[in] rd the rdf where to put the data ++ * \param[in] str the string to be converted ++ * \return ldns_status ++ */ ++ldns_status ldns_str2rdf_certificate_usage(ldns_rdf **rd, const char *str); ++ ++/** ++ * convert a tlsa selector value into wireformat ++ * \param[in] rd the rdf where to put the data ++ * \param[in] str the string to be converted ++ * \return ldns_status ++ */ ++ldns_status ldns_str2rdf_selector(ldns_rdf **rd, const char *str); ++ ++/** ++ * convert a tlsa matching type value into wireformat ++ * \param[in] rd the rdf where to put the data ++ * \param[in] str the string to be converted ++ * \return ldns_status ++ */ ++ldns_status ldns_str2rdf_matching_type(ldns_rdf **rd, const char *str); ++ ++/** ++ * convert a string with a unknown RR into wireformat ++ * \param[in] rd the rdf where to put the data ++ * \param[in] str the string to be converted ++ * \return ldns_status ++ */ ++ldns_status ldns_str2rdf_unknown(ldns_rdf **rd, const char *str); ++ ++/** ++ * convert string with a protocol service into wireformat ++ * \param[in] rd the rdf where to put the data ++ * \param[in] str the string to be converted ++ * \return ldns_status ++ */ ++ldns_status ldns_str2rdf_service(ldns_rdf **rd, const char *str); ++ ++/** ++ * convert a string with a LOC RR into wireformat ++ * \param[in] rd the rdf where to put the data ++ * \param[in] str the string to be converted ++ * \return ldns_status ++ */ ++ldns_status ldns_str2rdf_loc(ldns_rdf **rd, const char *str); ++ ++/** ++ * convert string with a WKS RR into wireformat ++ * \param[in] rd the rdf where to put the data ++ * \param[in] str the string to be converted ++ * \return ldns_status ++ */ ++ldns_status ldns_str2rdf_wks(ldns_rdf **rd, const char *str); ++ ++/** ++ * convert a str with a NSAP RR into wireformat ++ * \param[in] rd the rdf where to put the data ++ * \param[in] str the string to be converted ++ * \return ldns_status ++ */ ++ldns_status ldns_str2rdf_nsap(ldns_rdf **rd, const char *str); ++ ++/** ++ * convert a str with a ATMA RR into wireformat ++ * \param[in] rd the rdf where to put the data ++ * \param[in] str the string to be converted ++ * \return ldns_status ++ */ ++ldns_status ldns_str2rdf_atma(ldns_rdf **rd, const char *str); ++ ++/** ++ * convert a str with a IPSECKEY RR into wireformat ++ * \param[in] rd the rdf where to put the data ++ * \param[in] str the string to be converted ++ * \return ldns_status ++ */ ++ldns_status ldns_str2rdf_ipseckey(ldns_rdf **rd, const char *str); ++ ++/** ++ * convert a dname string into wireformat ++ * \param[in] rd the rdf where to put the data ++ * \param[in] str the string to be converted ++ * \return ldns_status ++ */ ++ldns_status ldns_str2rdf_dname(ldns_rdf **rd, const char *str); ++ ++/** ++ * convert 4 * 16bit hex separated by colons into wireformat ++ * \param[in] rd the rdf where to put the data ++ * \param[in] str the string to be converted ++ * \return ldns_status ++ */ ++ldns_status ldns_str2rdf_ilnp64(ldns_rdf **rd, const char *str); ++ ++/** ++ * convert 6 hex bytes separated by dashes into wireformat ++ * \param[in] rd the rdf where to put the data ++ * \param[in] str the string to be converted ++ * \return ldns_status ++ */ ++ldns_status ldns_str2rdf_eui48(ldns_rdf **rd, const char *str); ++ ++/** ++ * convert 8 hex bytes separated by dashes into wireformat ++ * \param[in] rd the rdf where to put the data ++ * \param[in] str the string to be converted ++ * \return ldns_status ++ */ ++ldns_status ldns_str2rdf_eui64(ldns_rdf **rd, const char *str); ++ ++/** ++ * Convert a non-zero sequence of US-ASCII letters and numbers into wireformat ++ * \param[in] rd the rdf where to put the data ++ * \param[in] str the string to be converted ++ * \return ldns_status ++ */ ++ldns_status ldns_str2rdf_tag(ldns_rdf **rd, const char *str); ++ ++/** ++ * Convert a <character-string> encoding of the value field as specified ++ * [RFC1035], Section 5.1., encoded as one bug chunk of data. ++ * \param[in] rd the rdf where to put the data ++ * \param[in] str the string to be converted ++ * \return ldns_status ++ */ ++ldns_status ldns_str2rdf_long_str(ldns_rdf **rd, const char *str); ++ ++/** ++ * Convert a "<algorithm> <hit> <pk>" encoding of the value field as specified ++ * in Section 6. of [RFC5205], encoded as wireformat as specified in Section 5. ++ * of [RFC5205]. ++ * \param[in] rd the rdf where to put the data ++ * \param[in] str the string to be converted ++ * \return ldns_status ++ */ ++ldns_status ldns_str2rdf_hip(ldns_rdf **rd, const char *str); ++ ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* LDNS_2HOST_H */ +diff --git a/ldns/include/ldns/tsig.h b/ldns/include/ldns/tsig.h +new file mode 100644 +index 0000000..676045f +--- /dev/null ++++ b/ldns/include/ldns/tsig.h +@@ -0,0 +1,101 @@ ++/* ++ * tsig.h -- defines for TSIG [RFC2845] ++ * ++ * Copyright (c) 2005-2008, NLnet Labs. All rights reserved. ++ * ++ * See LICENSE for the license. ++ */ ++ ++#ifndef LDNS_TSIG_H ++#define LDNS_TSIG_H ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/** ++ * \file ++ * ++ * Defines functions for TSIG usage ++ */ ++ ++ ++/** ++ * Contains credentials for TSIG ++*/ ++typedef struct ldns_tsig_credentials_struct ++{ ++ char *algorithm; ++ char *keyname; ++ char *keydata; ++ /* XXX More eventually. */ ++} ldns_tsig_credentials; ++ ++char *ldns_tsig_algorithm(ldns_tsig_credentials *); ++char *ldns_tsig_keyname(ldns_tsig_credentials *); ++char *ldns_tsig_keydata(ldns_tsig_credentials *); ++char *ldns_tsig_keyname_clone(ldns_tsig_credentials *); ++char *ldns_tsig_keydata_clone(ldns_tsig_credentials *); ++ ++/** ++ * verifies the tsig rr for the given packet and key. ++ * The wire must be given too because tsig does not sign normalized packets. ++ * \param[in] pkt the packet to verify ++ * \param[in] wire needed to verify the mac ++ * \param[in] wire_size size of wire ++ * \param[in] key_name the name of the shared key ++ * \param[in] key_data the key in base 64 format ++ * \param[in] mac original mac ++ * \return true if tsig is correct, false if not, or if tsig is not set ++ */ ++bool ldns_pkt_tsig_verify(ldns_pkt *pkt, uint8_t *wire, size_t wire_size, const char *key_name, const char *key_data, ldns_rdf *mac); ++ ++/** ++ * verifies the tsig rr for the given packet and key. ++ * The wire must be given too because tsig does not sign normalized packets. ++ * \param[in] pkt the packet to verify ++ * \param[in] wire needed to verify the mac ++ * \param[in] wire_size size of wire ++ * \param[in] key_name the name of the shared key ++ * \param[in] key_data the key in base 64 format ++ * \param[in] mac original mac ++ * \param[in] tsig_timers_only must be zero for the first packet and positive for subsequent packets. If zero, all digest ++ components are used to verify the _mac. If non-zero, only the TSIG timers are used to verify the mac. ++ * \return true if tsig is correct, false if not, or if tsig is not set ++ */ ++bool ldns_pkt_tsig_verify_next(ldns_pkt *pkt, uint8_t *wire, size_t wire_size, const char *key_name, const char *key_data, ldns_rdf *mac, ++ int tsig_timers_only); ++ ++/** ++ * creates a tsig rr for the given packet and key. ++ * \param[in] pkt the packet to sign ++ * \param[in] key_name the name of the shared key ++ * \param[in] key_data the key in base 64 format ++ * \param[in] fudge seconds of error permitted in time signed ++ * \param[in] algorithm_name the name of the algorithm used ++ * \param[in] query_mac is added to the digest if not NULL (so NULL is for signing queries, not NULL is for signing answers) ++ * \return status (OK if success) ++ */ ++ldns_status ldns_pkt_tsig_sign(ldns_pkt *pkt, const char *key_name, const char *key_data, uint16_t fudge, ++ const char *algorithm_name, ldns_rdf *query_mac); ++ ++/** ++ * creates a tsig rr for the given packet and key. ++ * \param[in] pkt the packet to sign ++ * \param[in] key_name the name of the shared key ++ * \param[in] key_data the key in base 64 format ++ * \param[in] fudge seconds of error permitted in time signed ++ * \param[in] algorithm_name the name of the algorithm used ++ * \param[in] query_mac is added to the digest if not NULL (so NULL is for signing queries, not NULL is for signing answers) ++ * \param[in] tsig_timers_only must be zero for the first packet and positive for subsequent packets. If zero, all digest ++ components are used to create the query_mac. If non-zero, only the TSIG timers are used to create the query_mac. ++ * \return status (OK if success) ++ */ ++ldns_status ldns_pkt_tsig_sign_next(ldns_pkt *pkt, const char *key_name, const char *key_data, uint16_t fudge, ++ const char *algorithm_name, ldns_rdf *query_mac, int tsig_timers_only); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* LDNS_TSIG_H */ +diff --git a/ldns/include/ldns/update.h b/ldns/include/ldns/update.h +new file mode 100644 +index 0000000..d3459d3 +--- /dev/null ++++ b/ldns/include/ldns/update.h +@@ -0,0 +1,115 @@ ++/* ++ * update.h ++ * ++ * Functions for RFC 2136 Dynamic Update ++ * ++ * Copyright (c) 2005-2008, NLnet Labs. All rights reserved. ++ * ++ * See LICENSE for the license. ++ */ ++ ++/** ++ * \file ++ * ++ * Defines functions to perform UPDATE queries ++ */ ++ ++ ++#ifndef LDNS_UPDATE_H ++#define LDNS_UPDATE_H ++ ++#include <ldns/resolver.h> ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/** ++ * create an update packet from zone name, class and the rr lists ++ * \param[in] zone_rdf name of the zone ++ * \param[in] clas zone class ++ * \param[in] pr_rrlist list of Prerequisite Section RRs ++ * \param[in] up_rrlist list of Updates Section RRs ++ * \param[in] ad_rrlist list of Additional Data Section RRs (currently unused) ++ * \return the new packet ++ */ ++ldns_pkt *ldns_update_pkt_new(ldns_rdf *zone_rdf, ldns_rr_class clas, ldns_rr_list *pr_rrlist, ldns_rr_list *up_rrlist, ldns_rr_list *ad_rrlist); ++ ++/** ++ * add tsig credentials to ++ * a packet from a resolver ++ * \param[in] p packet to copy to ++ * \param[in] r resolver to copy from ++ * ++ * \return status wether successfull or not ++ */ ++ldns_status ldns_update_pkt_tsig_add(ldns_pkt *p, ldns_resolver *r); ++ ++/* access functions */ ++ ++/** ++ * Get the zo count ++ * \param[in] p the packet ++ * \return the zo count ++ */ ++uint16_t ldns_update_zocount(const ldns_pkt *p); ++/** ++ * Get the zo count ++ * \param[in] p the packet ++ * \return the pr count ++ */ ++uint16_t ldns_update_prcount(const ldns_pkt *p); ++/** ++ * Get the zo count ++ * \param[in] p the packet ++ * \return the up count ++ */ ++uint16_t ldns_update_upcount(const ldns_pkt *p); ++/** ++ * Get the zo count ++ * \param[in] p the packet ++ * \return the ad count ++ */ ++uint16_t ldns_update_ad(const ldns_pkt *p); ++/** ++ * Set the zo count ++ * \param[in] p the packet ++ * \param[in] c the zo count to set ++ */ ++void ldns_update_set_zo(ldns_pkt *p, uint16_t c); ++/** ++ * Set the pr count ++ * \param[in] p the packet ++ * \param[in] c the pr count to set ++ */ ++void ldns_update_set_prcount(ldns_pkt *p, uint16_t c); ++/** ++ * Set the up count ++ * \param[in] p the packet ++ * \param[in] c the up count to set ++ */ ++void ldns_update_set_upcount(ldns_pkt *p, uint16_t c); ++/** ++ * Set the ad count ++ * \param[in] p the packet ++ * \param[in] c the ad count to set ++ */ ++void ldns_update_set_adcount(ldns_pkt *p, uint16_t c); ++ ++/* soa functions that need to be configured */ ++/* ++ * Not sure if we want to keep these like this, therefore ++ * not documented ++ */ ++ldns_status ldns_update_soa_mname(ldns_rdf *zone, ldns_resolver *r, ldns_rr_class c, ldns_rdf **mname); ++/* ++ * Not sure if we want to keep these like this, therefore ++ * not documented ++ */ ++ldns_status ldns_update_soa_zone_mname(const char *fqdn, ldns_resolver *r, ldns_rr_class c, ldns_rdf **zone_rdf, ldns_rdf **mname_rdf); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* LDNS_UPDATE_H */ +diff --git a/ldns/include/ldns/util.h b/ldns/include/ldns/util.h +new file mode 100644 +index 0000000..86848eb +--- /dev/null ++++ b/ldns/include/ldns/util.h +@@ -0,0 +1,392 @@ ++/* ++ * util.h ++ * ++ * helper function header file ++ * ++ * a Net::DNS like library for C ++ * ++ * (c) NLnet Labs, 2004 ++ * ++ * See the file LICENSE for the license ++ */ ++ ++#ifndef _UTIL_H ++#define _UTIL_H ++ ++#include "EXTERN.h" ++#include "perl.h" ++#include <ldns/common.h> ++#include <time.h> ++#include <stdio.h> ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#define dprintf(X,Y) fprintf(stderr, (X), (Y)) ++/* #define dprintf(X, Y) */ ++ ++#define LDNS_VERSION "1.6.18" ++#define LDNS_REVISION ((1<<16)|(6<<8)|(18)) ++ ++/** ++ * splint static inline workaround ++ */ ++#ifdef S_SPLINT_S ++# define INLINE ++#else ++# ifdef SWIG ++# define INLINE static ++# else ++# define INLINE static inline ++# endif ++#endif ++ ++/** ++ * Memory management macros ++ */ ++#define LDNS_MALLOC(type) LDNS_XMALLOC(type, 1) ++ ++#define LDNS_XMALLOC(type, count) ((type *) malloc((count) * sizeof(type))) ++ ++#define LDNS_CALLOC(type, count) ((type *) calloc((count), sizeof(type))) ++ ++#define LDNS_REALLOC(ptr, type) LDNS_XREALLOC((ptr), type, 1) ++ ++#define LDNS_XREALLOC(ptr, type, count) \ ++ ((type *) realloc((ptr), (count) * sizeof(type))) ++ ++#define LDNS_FREE(ptr) \ ++ do { free((ptr)); (ptr) = NULL; } while (0) ++ ++#define LDNS_DEP printf("DEPRECATED FUNCTION!\n"); ++ ++/* ++ * Copy data allowing for unaligned accesses in network byte order ++ * (big endian). ++ */ ++INLINE uint16_t ++ldns_read_uint16(const void *src) ++{ ++#ifdef ALLOW_UNALIGNED_ACCESSES ++ return ntohs(*(const uint16_t *) src); ++#else ++ const uint8_t *p = (const uint8_t *) src; ++ return ((uint16_t) p[0] << 8) | (uint16_t) p[1]; ++#endif ++} ++ ++INLINE uint32_t ++ldns_read_uint32(const void *src) ++{ ++#ifdef ALLOW_UNALIGNED_ACCESSES ++ return ntohl(*(const uint32_t *) src); ++#else ++ const uint8_t *p = (const uint8_t *) src; ++ return ( ((uint32_t) p[0] << 24) ++ | ((uint32_t) p[1] << 16) ++ | ((uint32_t) p[2] << 8) ++ | (uint32_t) p[3]); ++#endif ++} ++ ++/* ++ * Copy data allowing for unaligned accesses in network byte order ++ * (big endian). ++ */ ++INLINE void ++ldns_write_uint16(void *dst, uint16_t data) ++{ ++#ifdef ALLOW_UNALIGNED_ACCESSES ++ * (uint16_t *) dst = htons(data); ++#else ++ uint8_t *p = (uint8_t *) dst; ++ p[0] = (uint8_t) ((data >> 8) & 0xff); ++ p[1] = (uint8_t) (data & 0xff); ++#endif ++} ++ ++INLINE void ++ldns_write_uint32(void *dst, uint32_t data) ++{ ++#ifdef ALLOW_UNALIGNED_ACCESSES ++ * (uint32_t *) dst = htonl(data); ++#else ++ uint8_t *p = (uint8_t *) dst; ++ p[0] = (uint8_t) ((data >> 24) & 0xff); ++ p[1] = (uint8_t) ((data >> 16) & 0xff); ++ p[2] = (uint8_t) ((data >> 8) & 0xff); ++ p[3] = (uint8_t) (data & 0xff); ++#endif ++} ++ ++/* warning. */ ++INLINE void ++ldns_write_uint64_as_uint48(void *dst, uint64_t data) ++{ ++ uint8_t *p = (uint8_t *) dst; ++ p[0] = (uint8_t) ((data >> 40) & 0xff); ++ p[1] = (uint8_t) ((data >> 32) & 0xff); ++ p[2] = (uint8_t) ((data >> 24) & 0xff); ++ p[3] = (uint8_t) ((data >> 16) & 0xff); ++ p[4] = (uint8_t) ((data >> 8) & 0xff); ++ p[5] = (uint8_t) (data & 0xff); ++} ++ ++ ++/** ++ * Structure to do a Schwartzian-like transformation, for instance when ++ * sorting. If you need a transformation on the objects that are sorted, ++ * you can sue this to store the transformed values, so you do not ++ * need to do the transformation again for each comparison ++ */ ++struct ldns_schwartzian_compare_struct { ++ void *original_object; ++ void *transformed_object; ++}; ++ ++/** A general purpose lookup table ++ * ++ * Lookup tables are arrays of (id, name) pairs, ++ * So you can for instance lookup the RCODE 3, which is "NXDOMAIN", ++ * and vice versa. The lookup tables themselves are defined wherever needed, ++ * for instance in \ref host2str.c ++ */ ++struct ldns_struct_lookup_table { ++ int id; ++ const char *name; ++}; ++typedef struct ldns_struct_lookup_table ldns_lookup_table; ++ ++/** ++ * Looks up the table entry by name, returns NULL if not found. ++ * \param[in] table the lookup table to search in ++ * \param[in] name what to search for ++ * \return the item found ++ */ ++ldns_lookup_table *ldns_lookup_by_name(ldns_lookup_table table[], ++ const char *name); ++ ++/** ++ * Looks up the table entry by id, returns NULL if not found. ++ * \param[in] table the lookup table to search in ++ * \param[in] id what to search for ++ * \return the item found ++ */ ++ldns_lookup_table *ldns_lookup_by_id(ldns_lookup_table table[], int id); ++ ++/** ++ * Returns the value of the specified bit ++ * The bits are counted from left to right, so bit #0 is the ++ * left most bit. ++ * \param[in] bits array holding the bits ++ * \param[in] index to the wanted bit ++ * \return ++ */ ++int ldns_get_bit(uint8_t bits[], size_t index); ++ ++ ++/** ++ * Returns the value of the specified bit ++ * The bits are counted from right to left, so bit #0 is the ++ * right most bit. ++ * \param[in] bits array holding the bits ++ * \param[in] index to the wanted bit ++ * \return 1 or 0 depending no the bit state ++ */ ++int ldns_get_bit_r(uint8_t bits[], size_t index); ++ ++/** ++ * sets the specified bit in the specified byte to ++ * 1 if value is true, 0 if false ++ * The bits are counted from right to left, so bit #0 is the ++ * right most bit. ++ * \param[in] byte the bit to set the bit in ++ * \param[in] bit_nr the bit to set (0 <= n <= 7) ++ * \param[in] value whether to set the bit to 1 or 0 ++ * \return 1 or 0 depending no the bit state ++ */ ++void ldns_set_bit(uint8_t *byte, int bit_nr, bool value); ++ ++/** ++ * Returns the value of a to the power of b ++ * (or 1 of b < 1) ++ */ ++/*@unused@*/ ++INLINE long ++ldns_power(long a, long b) { ++ long result = 1; ++ while (b > 0) { ++ if (b & 1) { ++ result *= a; ++ if (b == 1) { ++ return result; ++ } ++ } ++ a *= a; ++ b /= 2; ++ } ++ return result; ++} ++ ++/** ++ * Returns the int value of the given (hex) digit ++ * \param[in] ch the hex char to convert ++ * \return the converted decimal value ++ */ ++int ldns_hexdigit_to_int(char ch); ++ ++/** ++ * Returns the char (hex) representation of the given int ++ * \param[in] ch the int to convert ++ * \return the converted hex char ++ */ ++char ldns_int_to_hexdigit(int ch); ++ ++/** ++ * Converts a hex string to binary data ++ * ++ * \param[out] data The binary result is placed here. ++ * At least strlen(str)/2 bytes should be allocated ++ * \param[in] str The hex string to convert. ++ * This string should not contain spaces ++ * \return The number of bytes of converted data, or -1 if one of the arguments * is NULL, or -2 if the string length is not an even number ++ */ ++int ++ldns_hexstring_to_data(uint8_t *data, const char *str); ++ ++/** ++ * Show the internal library version ++ * \return a string with the version in it ++ */ ++const char * ldns_version(void); ++ ++/** ++ * Convert TM to seconds since epoch (midnight, January 1st, 1970). ++ * Like timegm(3), which is not always available. ++ * \param[in] tm a struct tm* with the date ++ * \return the seconds since epoch ++ */ ++time_t ldns_mktime_from_utc(const struct tm *tm); ++ ++time_t mktime_from_utc(const struct tm *tm); ++ ++/** ++ * The function interprets time as the number of seconds since epoch ++ * with respect to now using serial arithmitics (rfc1982). ++ * That number of seconds is then converted to broken-out time information. ++ * This is especially usefull when converting the inception and expiration ++ * fields of RRSIG records. ++ * ++ * \param[in] time number of seconds since epoch (midnight, January 1st, 1970) ++ * to be intepreted as a serial arithmitics number relative to now. ++ * \param[in] now number of seconds since epoch (midnight, January 1st, 1970) ++ * to which the time value is compared to determine the final value. ++ * \param[out] result the struct with the broken-out time information ++ * \return result on success or NULL on error ++ */ ++struct tm * ldns_serial_arithmitics_gmtime_r(int32_t time, time_t now, struct tm *result); ++ ++/** ++ * Seed the random function. ++ * If the file descriptor is specified, the random generator is seeded with ++ * data from that file. If not, /dev/urandom is used. ++ * ++ * applications should call this if they need entropy data within ldns ++ * If openSSL is available, it is automatically seeded from /dev/urandom ++ * or /dev/random. ++ * ++ * If you need more entropy, or have no openssl available, this function ++ * MUST be called at the start of the program ++ * ++ * If openssl *is* available, this function just adds more entropy ++ * ++ * \param[in] fd a file providing entropy data for the seed ++ * \param[in] size the number of bytes to use as entropy data. If this is 0, ++ * only the minimal amount is taken (usually 4 bytes) ++ * \return 0 if seeding succeeds, 1 if it fails ++ */ ++int ldns_init_random(FILE *fd, unsigned int size); ++ ++/** ++ * Get random number. ++ * \return random number. ++ * ++ */ ++uint16_t ldns_get_random(void); ++ ++/** ++ * Encode data as BubbleBabble ++ * ++ * \param[in] data a pointer to data to be encoded ++ * \param[in] len size the number of bytes of data ++ * \return a string of BubbleBabble ++ */ ++char *ldns_bubblebabble(uint8_t *data, size_t len); ++ ++ ++INLINE time_t ldns_time(time_t *t) { return time(t); } ++ ++ ++/** ++ * calculates the size needed to store the result of b32_ntop ++ */ ++/*@unused@*/ ++INLINE size_t ldns_b32_ntop_calculate_size(size_t src_data_length) ++{ ++ return src_data_length == 0 ? 0 : ((src_data_length - 1) / 5 + 1) * 8; ++} ++ ++INLINE size_t ldns_b32_ntop_calculate_size_no_padding(size_t src_data_length) ++{ ++ return ((src_data_length + 3) * 8 / 5) - 4; ++} ++ ++int ldns_b32_ntop(const uint8_t* src_data, size_t src_data_length, ++ char* target_text_buffer, size_t target_text_buffer_size); ++ ++int ldns_b32_ntop_extended_hex(const uint8_t* src_data, size_t src_data_length, ++ char* target_text_buffer, size_t target_text_buffer_size); ++ ++#if ! LDNS_BUILD_CONFIG_HAVE_B32_NTOP ++ ++int b32_ntop(const uint8_t* src_data, size_t src_data_length, ++ char* target_text_buffer, size_t target_text_buffer_size); ++ ++int b32_ntop_extended_hex(const uint8_t* src_data, size_t src_data_length, ++ char* target_text_buffer, size_t target_text_buffer_size); ++ ++#endif /* ! LDNS_BUILD_CONFIG_HAVE_B32_NTOP */ ++ ++ ++/** ++ * calculates the size needed to store the result of b32_pton ++ */ ++/*@unused@*/ ++INLINE size_t ldns_b32_pton_calculate_size(size_t src_text_length) ++{ ++ return src_text_length * 5 / 8; ++} ++ ++int ldns_b32_pton(const char* src_text, size_t src_text_length, ++ uint8_t* target_data_buffer, size_t target_data_buffer_size); ++ ++int ldns_b32_pton_extended_hex(const char* src_text, size_t src_text_length, ++ uint8_t* target_data_buffer, size_t target_data_buffer_size); ++ ++#if ! LDNS_BUILD_CONFIG_HAVE_B32_PTON ++ ++int b32_pton(const char* src_text, size_t src_text_length, ++ uint8_t* target_data_buffer, size_t target_data_buffer_size); ++ ++int b32_pton_extended_hex(const char* src_text, size_t src_text_length, ++ uint8_t* target_data_buffer, size_t target_data_buffer_size); ++ ++#endif /* ! LDNS_BUILD_CONFIG_HAVE_B32_PTON */ ++ ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* !_UTIL_H */ +diff --git a/ldns/include/ldns/wire2host.h b/ldns/include/ldns/wire2host.h +new file mode 100644 +index 0000000..53155b3 +--- /dev/null ++++ b/ldns/include/ldns/wire2host.h +@@ -0,0 +1,197 @@ ++/* ++ * wire2host.h - from wire conversion routines ++ * ++ * a Net::DNS like library for C ++ * ++ * (c) NLnet Labs, 2005-2006 ++ * ++ * See the file LICENSE for the license ++ */ ++ ++/** ++ * \file ++ * ++ * Contains functions that translate dns data from the wire format (as sent ++ * by servers and clients) to the internal structures. ++ */ ++ ++#ifndef LDNS_WIRE2HOST_H ++#define LDNS_WIRE2HOST_H ++ ++#include <ldns/rdata.h> ++#include <ldns/common.h> ++#include <ldns/error.h> ++#include <ldns/rr.h> ++#include <ldns/packet.h> ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/* The length of the header */ ++#define LDNS_HEADER_SIZE 12 ++ ++/* First octet of flags */ ++#define LDNS_RD_MASK 0x01U ++#define LDNS_RD_SHIFT 0 ++#define LDNS_RD_WIRE(wirebuf) (*(wirebuf+2) & LDNS_RD_MASK) ++#define LDNS_RD_SET(wirebuf) (*(wirebuf+2) |= LDNS_RD_MASK) ++#define LDNS_RD_CLR(wirebuf) (*(wirebuf+2) &= ~LDNS_RD_MASK) ++ ++#define LDNS_TC_MASK 0x02U ++#define LDNS_TC_SHIFT 1 ++#define LDNS_TC_WIRE(wirebuf) (*(wirebuf+2) & LDNS_TC_MASK) ++#define LDNS_TC_SET(wirebuf) (*(wirebuf+2) |= LDNS_TC_MASK) ++#define LDNS_TC_CLR(wirebuf) (*(wirebuf+2) &= ~LDNS_TC_MASK) ++ ++#define LDNS_AA_MASK 0x04U ++#define LDNS_AA_SHIFT 2 ++#define LDNS_AA_WIRE(wirebuf) (*(wirebuf+2) & LDNS_AA_MASK) ++#define LDNS_AA_SET(wirebuf) (*(wirebuf+2) |= LDNS_AA_MASK) ++#define LDNS_AA_CLR(wirebuf) (*(wirebuf+2) &= ~LDNS_AA_MASK) ++ ++#define LDNS_OPCODE_MASK 0x78U ++#define LDNS_OPCODE_SHIFT 3 ++#define LDNS_OPCODE_WIRE(wirebuf) ((*(wirebuf+2) & LDNS_OPCODE_MASK) >> LDNS_OPCODE_SHIFT) ++#define LDNS_OPCODE_SET(wirebuf, opcode) \ ++ (*(wirebuf+2) = ((*(wirebuf+2)) & ~LDNS_OPCODE_MASK) | ((opcode) << LDNS_OPCODE_SHIFT)) ++ ++#define LDNS_QR_MASK 0x80U ++#define LDNS_QR_SHIFT 7 ++#define LDNS_QR_WIRE(wirebuf) (*(wirebuf+2) & LDNS_QR_MASK) ++#define LDNS_QR_SET(wirebuf) (*(wirebuf+2) |= LDNS_QR_MASK) ++#define LDNS_QR_CLR(wirebuf) (*(wirebuf+2) &= ~LDNS_QR_MASK) ++ ++/* Second octet of flags */ ++#define LDNS_RCODE_MASK 0x0fU ++#define LDNS_RCODE_SHIFT 0 ++#define LDNS_RCODE_WIRE(wirebuf) (*(wirebuf+3) & LDNS_RCODE_MASK) ++#define LDNS_RCODE_SET(wirebuf, rcode) \ ++ (*(wirebuf+3) = ((*(wirebuf+3)) & ~LDNS_RCODE_MASK) | (rcode)) ++ ++#define LDNS_CD_MASK 0x10U ++#define LDNS_CD_SHIFT 4 ++#define LDNS_CD_WIRE(wirebuf) (*(wirebuf+3) & LDNS_CD_MASK) ++#define LDNS_CD_SET(wirebuf) (*(wirebuf+3) |= LDNS_CD_MASK) ++#define LDNS_CD_CLR(wirebuf) (*(wirebuf+3) &= ~LDNS_CD_MASK) ++ ++#define LDNS_AD_MASK 0x20U ++#define LDNS_AD_SHIFT 5 ++#define LDNS_AD_WIRE(wirebuf) (*(wirebuf+3) & LDNS_AD_MASK) ++#define LDNS_AD_SET(wirebuf) (*(wirebuf+3) |= LDNS_AD_MASK) ++#define LDNS_AD_CLR(wirebuf) (*(wirebuf+3) &= ~LDNS_AD_MASK) ++ ++#define LDNS_Z_MASK 0x40U ++#define LDNS_Z_SHIFT 6 ++#define LDNS_Z_WIRE(wirebuf) (*(wirebuf+3) & LDNS_Z_MASK) ++#define LDNS_Z_SET(wirebuf) (*(wirebuf+3) |= LDNS_Z_MASK) ++#define LDNS_Z_CLR(wirebuf) (*(wirebuf+3) &= ~LDNS_Z_MASK) ++ ++#define LDNS_RA_MASK 0x80U ++#define LDNS_RA_SHIFT 7 ++#define LDNS_RA_WIRE(wirebuf) (*(wirebuf+3) & LDNS_RA_MASK) ++#define LDNS_RA_SET(wirebuf) (*(wirebuf+3) |= LDNS_RA_MASK) ++#define LDNS_RA_CLR(wirebuf) (*(wirebuf+3) &= ~LDNS_RA_MASK) ++ ++/* Query ID */ ++#define LDNS_ID_WIRE(wirebuf) (ldns_read_uint16(wirebuf)) ++#define LDNS_ID_SET(wirebuf, id) (ldns_write_uint16(wirebuf, id)) ++ ++/* Counter of the question section */ ++#define LDNS_QDCOUNT_OFF 4 ++/* ++#define QDCOUNT(wirebuf) (ntohs(*(uint16_t *)(wirebuf+QDCOUNT_OFF))) ++*/ ++#define LDNS_QDCOUNT(wirebuf) (ldns_read_uint16(wirebuf+LDNS_QDCOUNT_OFF)) ++ ++/* Counter of the answer section */ ++#define LDNS_ANCOUNT_OFF 6 ++#define LDNS_ANCOUNT(wirebuf) (ldns_read_uint16(wirebuf+LDNS_ANCOUNT_OFF)) ++ ++/* Counter of the authority section */ ++#define LDNS_NSCOUNT_OFF 8 ++#define LDNS_NSCOUNT(wirebuf) (ldns_read_uint16(wirebuf+LDNS_NSCOUNT_OFF)) ++ ++/* Counter of the additional section */ ++#define LDNS_ARCOUNT_OFF 10 ++#define LDNS_ARCOUNT(wirebuf) (ldns_read_uint16(wirebuf+LDNS_ARCOUNT_OFF)) ++ ++/** ++ * converts the data on the uint8_t bytearray (in wire format) to a DNS packet. ++ * This function will initialize and allocate memory space for the packet ++ * structure. ++ * ++ * \param[in] packet pointer to the structure to hold the packet ++ * \param[in] data pointer to the buffer with the data ++ * \param[in] len the length of the data buffer (in bytes) ++ * \return LDNS_STATUS_OK if everything succeeds, error otherwise ++ */ ++ldns_status ldns_wire2pkt(ldns_pkt **packet, const uint8_t *data, size_t len); ++ ++/** ++ * converts the data on the uint8_t bytearray (in wire format) to a DNS packet. ++ * This function will initialize and allocate memory space for the packet ++ * structure. ++ * ++ * \param[in] packet pointer to the structure to hold the packet ++ * \param[in] buffer the buffer with the data ++ * \return LDNS_STATUS_OK if everything succeeds, error otherwise ++ */ ++ldns_status ldns_buffer2pkt_wire(ldns_pkt **packet, ldns_buffer *buffer); ++ ++/** ++ * converts the data on the uint8_t bytearray (in wire format) to a DNS ++ * dname rdata field. This function will initialize and allocate memory ++ * space for the dname structure. The length of the wiredata of this rdf ++ * is added to the *pos value. ++ * ++ * \param[in] dname pointer to the structure to hold the rdata value ++ * \param[in] wire pointer to the buffer with the data ++ * \param[in] max the length of the data buffer (in bytes) ++ * \param[in] pos the position of the rdf in the buffer (ie. the number of bytes ++ * from the start of the buffer) ++ * \return LDNS_STATUS_OK if everything succeeds, error otherwise ++ */ ++ldns_status ldns_wire2dname(ldns_rdf **dname, const uint8_t *wire, size_t max, size_t *pos); ++ ++/** ++ * converts the data on the uint8_t bytearray (in wire format) to DNS ++ * rdata fields, and adds them to the list of rdfs of the given rr. ++ * This function will initialize and allocate memory space for the dname ++ * structures. ++ * The length of the wiredata of these rdfs is added to the *pos value. ++ * ++ * All rdfs belonging to the RR are read; the rr should have no rdfs ++ * yet. An error is returned if the format cannot be parsed. ++ * ++ * \param[in] rr pointer to the ldns_rr structure to hold the rdata value ++ * \param[in] wire pointer to the buffer with the data ++ * \param[in] max the length of the data buffer (in bytes) ++ * \param[in] pos the position of the rdf in the buffer (ie. the number of bytes ++ * from the start of the buffer) ++ * \return LDNS_STATUS_OK if everything succeeds, error otherwise ++ */ ++ldns_status ldns_wire2rdf(ldns_rr *rr, const uint8_t *wire, size_t max, size_t *pos); ++ ++/** ++ * converts the data on the uint8_t bytearray (in wire format) to a DNS ++ * resource record. ++ * This function will initialize and allocate memory space for the rr ++ * structure. ++ * The length of the wiredata of this rr is added to the *pos value. ++ * ++ * \param[in] rr pointer to the structure to hold the rdata value ++ * \param[in] wire pointer to the buffer with the data ++ * \param[in] max the length of the data buffer (in bytes) ++ * \param[in] pos the position of the rr in the buffer (ie. the number of bytes ++ * from the start of the buffer) ++ * \param[in] section the section in the packet the rr is meant for ++ * \return LDNS_STATUS_OK if everything succeeds, error otherwise ++ */ ++ldns_status ldns_wire2rr(ldns_rr **rr, const uint8_t *wire, size_t max, size_t *pos, ldns_pkt_section section); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* LDNS_WIRE2HOST_H */ +diff --git a/ldns/include/ldns/zone.h b/ldns/include/ldns/zone.h +new file mode 100644 +index 0000000..0d129a0 +--- /dev/null ++++ b/ldns/include/ldns/zone.h +@@ -0,0 +1,176 @@ ++/** ++ * zone.h ++ * ++ * zone definitions ++ * - what is it ++ * - get_glue function ++ * - search etc ++ * ++ * a Net::DNS like library for C ++ * ++ * (c) NLnet Labs, 2005-2006 ++ * ++ * See the file LICENSE for the license ++ */ ++ ++/** ++ * \file ++ * ++ * Defines the ldns_zone structure and functions to manipulate it. ++ */ ++ ++ ++#ifndef LDNS_ZONE_H ++#define LDNS_ZONE_H ++ ++#include <ldns/common.h> ++#include <ldns/rdata.h> ++#include <ldns/rr.h> ++#include <ldns/error.h> ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/** ++ * DNS Zone ++ * ++ * A list of RR's with some ++ * extra information which comes from the SOA RR ++ * Note: nothing has been done to make this efficient (yet). ++ */ ++struct ldns_struct_zone ++{ ++ /** the soa defines a zone */ ++ ldns_rr *_soa; ++ /* basicly a zone is a list of rr's */ ++ ldns_rr_list *_rrs; ++ /* we could change this to be a b-tree etc etc todo */ ++}; ++typedef struct ldns_struct_zone ldns_zone; ++ ++/** ++ * create a new ldns_zone structure ++ * \return a pointer to a ldns_zone structure ++ */ ++ldns_zone * ldns_zone_new(void); ++ ++/** ++ * Return the soa record of a zone ++ * \param[in] z the zone to read from ++ * \return the soa record in the zone ++ */ ++ldns_rr * ldns_zone_soa(const ldns_zone *z); ++ ++/** ++ * Returns the number of resource records in the zone, NOT counting the SOA record ++ * \param[in] z the zone to read from ++ * \return the number of rr's in the zone ++ */ ++size_t ldns_zone_rr_count(const ldns_zone *z); ++ ++/** ++ * Set the zone's soa record ++ * \param[in] z the zone to put the new soa in ++ * \param[in] soa the soa to set ++ */ ++void ldns_zone_set_soa(ldns_zone *z, ldns_rr *soa); ++ ++/** ++ * Get a list of a zone's content. Note that the SOA ++ * isn't included in this list. You need to get the ++ * with ldns_zone_soa. ++ * \param[in] z the zone to read from ++ * \return the rrs from this zone ++ */ ++ldns_rr_list * ldns_zone_rrs(const ldns_zone *z); ++ ++/** ++ * Set the zone's contents ++ * \param[in] z the zone to put the new soa in ++ * \param[in] rrlist the rrlist to use ++ */ ++void ldns_zone_set_rrs(ldns_zone *z, ldns_rr_list *rrlist); ++ ++/** ++ * push an rrlist to a zone structure. This function use pointer ++ * copying, so the rr_list structure inside z is modified! ++ * \param[in] z the zone to add to ++ * \param[in] list the list to add ++ * \return a true on succes otherwise falsed ++ */ ++bool ldns_zone_push_rr_list(ldns_zone *z, ldns_rr_list *list); ++ ++/** ++ * push an single rr to a zone structure. This function use pointer ++ * copying, so the rr_list structure inside z is modified! ++ * \param[in] z the zone to add to ++ * \param[in] rr the rr to add ++ * \return a true on succes otherwise falsed ++ */ ++bool ldns_zone_push_rr(ldns_zone *z, ldns_rr *rr); ++ ++/** ++ * Retrieve all resource records from the zone that are glue ++ * records. The resulting list does are pointer references ++ * to the zone's data. ++ * ++ * Due to the current zone implementation (as a list of rr's), this ++ * function is extremely slow. Another (probably better) way to do this ++ * is to use an ldns_dnssec_zone structure and the ++ * ldns_dnssec_mark_and_get_glue() function. ++ * ++ * \param[in] z the zone to look for glue ++ * \return the rr_list with the glue ++ */ ++ldns_rr_list *ldns_zone_glue_rr_list(const ldns_zone *z); ++ ++/** ++ * Create a new zone from a file ++ * \param[out] z the new zone ++ * \param[in] *fp the filepointer to use ++ * \param[in] *origin the zones' origin ++ * \param[in] ttl default ttl to use ++ * \param[in] c default class to use (IN) ++ * ++ * \return ldns_status mesg with an error or LDNS_STATUS_OK ++ */ ++ldns_status ldns_zone_new_frm_fp(ldns_zone **z, FILE *fp, ldns_rdf *origin, uint32_t ttl, ldns_rr_class c); ++ ++/** ++ * Create a new zone from a file, keep track of the line numbering ++ * \param[out] z the new zone ++ * \param[in] *fp the filepointer to use ++ * \param[in] *origin the zones' origin ++ * \param[in] ttl default ttl to use ++ * \param[in] c default class to use (IN) ++ * \param[out] line_nr used for error msg, to get to the line number ++ * ++ * \return ldns_status mesg with an error or LDNS_STATUS_OK ++ */ ++ldns_status ldns_zone_new_frm_fp_l(ldns_zone **z, FILE *fp, ldns_rdf *origin, uint32_t ttl, ldns_rr_class c, int *line_nr); ++ ++/** ++ * Frees the allocated memory for the zone, and the rr_list structure in it ++ * \param[in] zone the zone to free ++ */ ++void ldns_zone_free(ldns_zone *zone); ++ ++/** ++ * Frees the allocated memory for the zone, the soa rr in it, ++ * and the rr_list structure in it, including the rr's in that. etc. ++ * \param[in] zone the zone to free ++ */ ++void ldns_zone_deep_free(ldns_zone *zone); ++ ++/** ++ * Sort the rrs in a zone, with the current impl. this is slow ++ * \param[in] zone the zone to sort ++ */ ++void ldns_zone_sort(ldns_zone *zone); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* LDNS_ZONE_H */ +diff --git a/ldns/src/buffer.c b/ldns/src/buffer.c +new file mode 100644 +index 0000000..fc6c17e +--- /dev/null ++++ b/ldns/src/buffer.c +@@ -0,0 +1,177 @@ ++/* ++ * buffer.c -- generic memory buffer . ++ * ++ * Copyright (c) 2001-2008, NLnet Labs. All rights reserved. ++ * ++ * See LICENSE for the license. ++ * ++ */ ++ ++#include <ldns/config.h> ++ ++#include <ldns/ldns.h> ++#include <ldns/buffer.h> ++ ++ldns_buffer * ++ldns_buffer_new(size_t capacity) ++{ ++ ldns_buffer *buffer = LDNS_MALLOC(ldns_buffer); ++ ++ if (!buffer) { ++ return NULL; ++ } ++ ++ buffer->_data = (uint8_t *) LDNS_XMALLOC(uint8_t, capacity); ++ if (!buffer->_data) { ++ LDNS_FREE(buffer); ++ return NULL; ++ } ++ ++ buffer->_position = 0; ++ buffer->_limit = buffer->_capacity = capacity; ++ buffer->_fixed = 0; ++ buffer->_status = LDNS_STATUS_OK; ++ ++ ldns_buffer_invariant(buffer); ++ ++ return buffer; ++} ++ ++void ++ldns_buffer_new_frm_data(ldns_buffer *buffer, void *data, size_t size) ++{ ++ assert(data != NULL); ++ ++ buffer->_position = 0; ++ buffer->_limit = buffer->_capacity = size; ++ buffer->_fixed = 0; ++ buffer->_data = LDNS_XMALLOC(uint8_t, size); ++ if(!buffer->_data) { ++ buffer->_status = LDNS_STATUS_MEM_ERR; ++ return; ++ } ++ memcpy(buffer->_data, data, size); ++ buffer->_status = LDNS_STATUS_OK; ++ ++ ldns_buffer_invariant(buffer); ++} ++ ++bool ++ldns_buffer_set_capacity(ldns_buffer *buffer, size_t capacity) ++{ ++ void *data; ++ ++ ldns_buffer_invariant(buffer); ++ assert(buffer->_position <= capacity); ++ ++ data = (uint8_t *) LDNS_XREALLOC(buffer->_data, uint8_t, capacity); ++ if (!data) { ++ buffer->_status = LDNS_STATUS_MEM_ERR; ++ return false; ++ } else { ++ buffer->_data = data; ++ buffer->_limit = buffer->_capacity = capacity; ++ return true; ++ } ++} ++ ++bool ++ldns_buffer_reserve(ldns_buffer *buffer, size_t amount) ++{ ++ ldns_buffer_invariant(buffer); ++ assert(!buffer->_fixed); ++ if (buffer->_capacity < buffer->_position + amount) { ++ size_t new_capacity = buffer->_capacity * 3 / 2; ++ ++ if (new_capacity < buffer->_position + amount) { ++ new_capacity = buffer->_position + amount; ++ } ++ if (!ldns_buffer_set_capacity(buffer, new_capacity)) { ++ buffer->_status = LDNS_STATUS_MEM_ERR; ++ return false; ++ } ++ } ++ buffer->_limit = buffer->_capacity; ++ return true; ++} ++ ++int ++ldns_buffer_printf(ldns_buffer *buffer, const char *format, ...) ++{ ++ va_list args; ++ int written = 0; ++ size_t remaining; ++ ++ if (ldns_buffer_status_ok(buffer)) { ++ ldns_buffer_invariant(buffer); ++ assert(buffer->_limit == buffer->_capacity); ++ ++ remaining = ldns_buffer_remaining(buffer); ++ va_start(args, format); ++ written = vsnprintf((char *) ldns_buffer_current(buffer), remaining, ++ format, args); ++ va_end(args); ++ if (written == -1) { ++ buffer->_status = LDNS_STATUS_INTERNAL_ERR; ++ return -1; ++ } else if ((size_t) written >= remaining) { ++ if (!ldns_buffer_reserve(buffer, (size_t) written + 1)) { ++ buffer->_status = LDNS_STATUS_MEM_ERR; ++ return -1; ++ } ++ va_start(args, format); ++ written = vsnprintf((char *) ldns_buffer_current(buffer), ++ ldns_buffer_remaining(buffer), format, args); ++ va_end(args); ++ if (written == -1) { ++ buffer->_status = LDNS_STATUS_INTERNAL_ERR; ++ return -1; ++ } ++ } ++ buffer->_position += written; ++ } ++ return written; ++} ++ ++void ++ldns_buffer_free(ldns_buffer *buffer) ++{ ++ if (!buffer) { ++ return; ++ } ++ ++ if (!buffer->_fixed) ++ LDNS_FREE(buffer->_data); ++ ++ LDNS_FREE(buffer); ++} ++ ++void * ++ldns_buffer_export(ldns_buffer *buffer) ++{ ++ buffer->_fixed = 1; ++ return buffer->_data; ++} ++ ++int ++ldns_bgetc(ldns_buffer *buffer) ++{ ++ if (!ldns_buffer_available_at(buffer, buffer->_position, sizeof(uint8_t))) { ++ ldns_buffer_set_position(buffer, ldns_buffer_limit(buffer)); ++ /* ldns_buffer_rewind(buffer);*/ ++ return EOF; ++ } ++ return (int)ldns_buffer_read_u8(buffer); ++} ++ ++void ++ldns_buffer_copy(ldns_buffer* result, ldns_buffer* from) ++{ ++ size_t tocopy = ldns_buffer_limit(from); ++ ++ if(tocopy > ldns_buffer_capacity(result)) ++ tocopy = ldns_buffer_capacity(result); ++ ldns_buffer_clear(result); ++ ldns_buffer_write(result, ldns_buffer_begin(from), tocopy); ++ ldns_buffer_flip(result); ++} +diff --git a/ldns/src/compat/b64_ntop.c b/ldns/src/compat/b64_ntop.c +new file mode 100644 +index 0000000..6895aca +--- /dev/null ++++ b/ldns/src/compat/b64_ntop.c +@@ -0,0 +1,185 @@ ++/* ++ * Copyright (c) 1996, 1998 by Internet Software Consortium. ++ * ++ * Permission to use, copy, modify, and distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS ++ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES ++ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE ++ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL ++ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR ++ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ++ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS ++ * SOFTWARE. ++ */ ++ ++/* ++ * Portions Copyright (c) 1995 by International Business Machines, Inc. ++ * ++ * International Business Machines, Inc. (hereinafter called IBM) grants ++ * permission under its copyrights to use, copy, modify, and distribute this ++ * Software with or without fee, provided that the above copyright notice and ++ * all paragraphs of this notice appear in all copies, and that the name of IBM ++ * not be used in connection with the marketing of any product incorporating ++ * the Software or modifications thereof, without specific, written prior ++ * permission. ++ * ++ * To the extent it has a right to do so, IBM grants an immunity from suit ++ * under its patents, if any, for the use, sale or manufacture of products to ++ * the extent that such products are used for performing Domain Name System ++ * dynamic updates in TCP/IP networks by means of the Software. No immunity is ++ * granted for any product per se or for any other function of any product. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES, ++ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A ++ * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, ++ * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING ++ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN ++ * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES. ++ */ ++#include <ldns/config.h> ++#include <ctype.h> ++#include <stdlib.h> ++#include <string.h> ++ ++static const char Base64[] = ++ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; ++static const char Pad64 = '='; ++ ++/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt) ++ The following encoding technique is taken from RFC 1521 by Borenstein ++ and Freed. It is reproduced here in a slightly edited form for ++ convenience. ++ ++ A 65-character subset of US-ASCII is used, enabling 6 bits to be ++ represented per printable character. (The extra 65th character, "=", ++ is used to signify a special processing function.) ++ ++ The encoding process represents 24-bit groups of input bits as output ++ strings of 4 encoded characters. Proceeding from left to right, a ++ 24-bit input group is formed by concatenating 3 8-bit input groups. ++ These 24 bits are then treated as 4 concatenated 6-bit groups, each ++ of which is translated into a single digit in the base64 alphabet. ++ ++ Each 6-bit group is used as an index into an array of 64 printable ++ characters. The character referenced by the index is placed in the ++ output string. ++ ++ Table 1: The Base64 Alphabet ++ ++ Value Encoding Value Encoding Value Encoding Value Encoding ++ 0 A 17 R 34 i 51 z ++ 1 B 18 S 35 j 52 0 ++ 2 C 19 T 36 k 53 1 ++ 3 D 20 U 37 l 54 2 ++ 4 E 21 V 38 m 55 3 ++ 5 F 22 W 39 n 56 4 ++ 6 G 23 X 40 o 57 5 ++ 7 H 24 Y 41 p 58 6 ++ 8 I 25 Z 42 q 59 7 ++ 9 J 26 a 43 r 60 8 ++ 10 K 27 b 44 s 61 9 ++ 11 L 28 c 45 t 62 + ++ 12 M 29 d 46 u 63 / ++ 13 N 30 e 47 v ++ 14 O 31 f 48 w (pad) = ++ 15 P 32 g 49 x ++ 16 Q 33 h 50 y ++ ++ Special processing is performed if fewer than 24 bits are available ++ at the end of the data being encoded. A full encoding quantum is ++ always completed at the end of a quantity. When fewer than 24 input ++ bits are available in an input group, zero bits are added (on the ++ right) to form an integral number of 6-bit groups. Padding at the ++ end of the data is performed using the '=' character. ++ ++ Since all base64 input is an integral number of octets, only the ++ ------------------------------------------------- ++ following cases can arise: ++ ++ (1) the final quantum of encoding input is an integral ++ multiple of 24 bits; here, the final unit of encoded ++ output will be an integral multiple of 4 characters ++ with no "=" padding, ++ (2) the final quantum of encoding input is exactly 8 bits; ++ here, the final unit of encoded output will be two ++ characters followed by two "=" padding characters, or ++ (3) the final quantum of encoding input is exactly 16 bits; ++ here, the final unit of encoded output will be three ++ characters followed by one "=" padding character. ++ */ ++ ++int ++ldns_b64_ntop(uint8_t const *src, size_t srclength, char *target, size_t targsize) { ++ size_t datalength = 0; ++ uint8_t input[3]; ++ uint8_t output[4]; ++ size_t i; ++ ++ if (srclength == 0) { ++ if (targsize > 0) { ++ target[0] = '\0'; ++ return 0; ++ } else { ++ return -1; ++ } ++ } ++ ++ while (2 < srclength) { ++ input[0] = *src++; ++ input[1] = *src++; ++ input[2] = *src++; ++ srclength -= 3; ++ ++ output[0] = input[0] >> 2; ++ output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); ++ output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); ++ output[3] = input[2] & 0x3f; ++ assert(output[0] < 64); ++ assert(output[1] < 64); ++ assert(output[2] < 64); ++ assert(output[3] < 64); ++ ++ if (datalength + 4 > targsize) { ++ return (-1); ++ } ++ target[datalength++] = Base64[output[0]]; ++ target[datalength++] = Base64[output[1]]; ++ target[datalength++] = Base64[output[2]]; ++ target[datalength++] = Base64[output[3]]; ++ } ++ ++ /* Now we worry about padding. */ ++ if (0 != srclength) { ++ /* Get what's left. */ ++ input[0] = input[1] = input[2] = (uint8_t) '\0'; ++ for (i = 0; i < srclength; i++) ++ input[i] = *src++; ++ ++ output[0] = input[0] >> 2; ++ output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); ++ output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); ++ assert(output[0] < 64); ++ assert(output[1] < 64); ++ assert(output[2] < 64); ++ ++ if (datalength + 4 > targsize) { ++ return (-2); ++ } ++ target[datalength++] = Base64[output[0]]; ++ target[datalength++] = Base64[output[1]]; ++ if (srclength == 1) { ++ target[datalength++] = Pad64; ++ } else { ++ target[datalength++] = Base64[output[2]]; ++ } ++ target[datalength++] = Pad64; ++ } ++ if (datalength >= targsize) { ++ return (-3); ++ } ++ target[datalength] = '\0'; /* Returned value doesn't count \0. */ ++ return (int) (datalength); ++} +diff --git a/ldns/src/compat/b64_pton.c b/ldns/src/compat/b64_pton.c +new file mode 100644 +index 0000000..18d8c8e +--- /dev/null ++++ b/ldns/src/compat/b64_pton.c +@@ -0,0 +1,244 @@ ++/* ++ * Copyright (c) 1996, 1998 by Internet Software Consortium. ++ * ++ * Permission to use, copy, modify, and distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS ++ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES ++ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE ++ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL ++ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR ++ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ++ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS ++ * SOFTWARE. ++ */ ++ ++/* ++ * Portions Copyright (c) 1995 by International Business Machines, Inc. ++ * ++ * International Business Machines, Inc. (hereinafter called IBM) grants ++ * permission under its copyrights to use, copy, modify, and distribute this ++ * Software with or without fee, provided that the above copyright notice and ++ * all paragraphs of this notice appear in all copies, and that the name of IBM ++ * not be used in connection with the marketing of any product incorporating ++ * the Software or modifications thereof, without specific, written prior ++ * permission. ++ * ++ * To the extent it has a right to do so, IBM grants an immunity from suit ++ * under its patents, if any, for the use, sale or manufacture of products to ++ * the extent that such products are used for performing Domain Name System ++ * dynamic updates in TCP/IP networks by means of the Software. No immunity is ++ * granted for any product per se or for any other function of any product. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES, ++ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A ++ * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, ++ * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING ++ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN ++ * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES. ++ */ ++#include <ldns/config.h> ++#include <ctype.h> ++#include <stdlib.h> ++#include <string.h> ++ ++static const char Base64[] = ++ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; ++static const char Pad64 = '='; ++ ++/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt) ++ The following encoding technique is taken from RFC 1521 by Borenstein ++ and Freed. It is reproduced here in a slightly edited form for ++ convenience. ++ ++ A 65-character subset of US-ASCII is used, enabling 6 bits to be ++ represented per printable character. (The extra 65th character, "=", ++ is used to signify a special processing function.) ++ ++ The encoding process represents 24-bit groups of input bits as output ++ strings of 4 encoded characters. Proceeding from left to right, a ++ 24-bit input group is formed by concatenating 3 8-bit input groups. ++ These 24 bits are then treated as 4 concatenated 6-bit groups, each ++ of which is translated into a single digit in the base64 alphabet. ++ ++ Each 6-bit group is used as an index into an array of 64 printable ++ characters. The character referenced by the index is placed in the ++ output string. ++ ++ Table 1: The Base64 Alphabet ++ ++ Value Encoding Value Encoding Value Encoding Value Encoding ++ 0 A 17 R 34 i 51 z ++ 1 B 18 S 35 j 52 0 ++ 2 C 19 T 36 k 53 1 ++ 3 D 20 U 37 l 54 2 ++ 4 E 21 V 38 m 55 3 ++ 5 F 22 W 39 n 56 4 ++ 6 G 23 X 40 o 57 5 ++ 7 H 24 Y 41 p 58 6 ++ 8 I 25 Z 42 q 59 7 ++ 9 J 26 a 43 r 60 8 ++ 10 K 27 b 44 s 61 9 ++ 11 L 28 c 45 t 62 + ++ 12 M 29 d 46 u 63 / ++ 13 N 30 e 47 v ++ 14 O 31 f 48 w (pad) = ++ 15 P 32 g 49 x ++ 16 Q 33 h 50 y ++ ++ Special processing is performed if fewer than 24 bits are available ++ at the end of the data being encoded. A full encoding quantum is ++ always completed at the end of a quantity. When fewer than 24 input ++ bits are available in an input group, zero bits are added (on the ++ right) to form an integral number of 6-bit groups. Padding at the ++ end of the data is performed using the '=' character. ++ ++ Since all base64 input is an integral number of octets, only the ++ ------------------------------------------------- ++ following cases can arise: ++ ++ (1) the final quantum of encoding input is an integral ++ multiple of 24 bits; here, the final unit of encoded ++ output will be an integral multiple of 4 characters ++ with no "=" padding, ++ (2) the final quantum of encoding input is exactly 8 bits; ++ here, the final unit of encoded output will be two ++ characters followed by two "=" padding characters, or ++ (3) the final quantum of encoding input is exactly 16 bits; ++ here, the final unit of encoded output will be three ++ characters followed by one "=" padding character. ++ */ ++ ++/* skips all whitespace anywhere. ++ converts characters, four at a time, starting at (or after) ++ src from base - 64 numbers into three 8 bit bytes in the target area. ++ it returns the number of data bytes stored at the target, or -1 on error. ++ */ ++ ++int ++ldns_b64_pton(char const *origsrc, uint8_t *target, size_t targsize) ++{ ++ unsigned char const* src = (unsigned char*)origsrc; ++ int tarindex, state, ch; ++ char *pos; ++ ++ state = 0; ++ tarindex = 0; ++ ++ if (strlen(origsrc) == 0) { ++ return 0; ++ } ++ ++ while ((ch = *src++) != '\0') { ++ if (isspace((unsigned char)ch)) /* Skip whitespace anywhere. */ ++ continue; ++ ++ if (ch == Pad64) ++ break; ++ ++ pos = strchr(Base64, ch); ++ if (pos == 0) { ++ /* A non-base64 character. */ ++ return (-1); ++ } ++ ++ switch (state) { ++ case 0: ++ if (target) { ++ if ((size_t)tarindex >= targsize) ++ return (-1); ++ target[tarindex] = (pos - Base64) << 2; ++ } ++ state = 1; ++ break; ++ case 1: ++ if (target) { ++ if ((size_t)tarindex + 1 >= targsize) ++ return (-1); ++ target[tarindex] |= (pos - Base64) >> 4; ++ target[tarindex+1] = ((pos - Base64) & 0x0f) ++ << 4 ; ++ } ++ tarindex++; ++ state = 2; ++ break; ++ case 2: ++ if (target) { ++ if ((size_t)tarindex + 1 >= targsize) ++ return (-1); ++ target[tarindex] |= (pos - Base64) >> 2; ++ target[tarindex+1] = ((pos - Base64) & 0x03) ++ << 6; ++ } ++ tarindex++; ++ state = 3; ++ break; ++ case 3: ++ if (target) { ++ if ((size_t)tarindex >= targsize) ++ return (-1); ++ target[tarindex] |= (pos - Base64); ++ } ++ tarindex++; ++ state = 0; ++ break; ++ default: ++ abort(); ++ } ++ } ++ ++ /* ++ * We are done decoding Base-64 chars. Let's see if we ended ++ * on a byte boundary, and/or with erroneous trailing characters. ++ */ ++ ++ if (ch == Pad64) { /* We got a pad char. */ ++ ch = *src++; /* Skip it, get next. */ ++ switch (state) { ++ case 0: /* Invalid = in first position */ ++ case 1: /* Invalid = in second position */ ++ return (-1); ++ ++ case 2: /* Valid, means one byte of info */ ++ /* Skip any number of spaces. */ ++ for ((void)NULL; ch != '\0'; ch = *src++) ++ if (!isspace((unsigned char)ch)) ++ break; ++ /* Make sure there is another trailing = sign. */ ++ if (ch != Pad64) ++ return (-1); ++ ch = *src++; /* Skip the = */ ++ /* Fall through to "single trailing =" case. */ ++ /* FALLTHROUGH */ ++ ++ case 3: /* Valid, means two bytes of info */ ++ /* ++ * We know this char is an =. Is there anything but ++ * whitespace after it? ++ */ ++ for ((void)NULL; ch != '\0'; ch = *src++) ++ if (!isspace((unsigned char)ch)) ++ return (-1); ++ ++ /* ++ * Now make sure for cases 2 and 3 that the "extra" ++ * bits that slopped past the last full byte were ++ * zeros. If we don't check them, they become a ++ * subliminal channel. ++ */ ++ if (target && target[tarindex] != 0) ++ return (-1); ++ } ++ } else { ++ /* ++ * We ended by seeing the end of the string. Make sure we ++ * have no partial bytes lying around. ++ */ ++ if (state != 0) ++ return (-1); ++ } ++ ++ return (tarindex); ++} +diff --git a/ldns/src/compat/strlcpy.c b/ldns/src/compat/strlcpy.c +new file mode 100644 +index 0000000..d6c34c1 +--- /dev/null ++++ b/ldns/src/compat/strlcpy.c +@@ -0,0 +1,57 @@ ++/* from openssh 4.3p2 compat/strlcpy.c */ ++/* ++ * Copyright (c) 1998 Todd C. Miller <Todd.Miller@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 |