summaryrefslogtreecommitdiffstats
path: root/src/lib/dns
diff options
context:
space:
mode:
authorMukund Sivaraman <muks@isc.org>2014-02-20 04:07:25 +0100
committerMukund Sivaraman <muks@isc.org>2014-02-20 04:07:25 +0100
commitcdcedf7fadf4f3021b86be152a6b009f3be8fcc0 (patch)
treed5233d90d66f985d21b539e98849ede767beabc7 /src/lib/dns
parent[2534] Support some minor cases for quoted character strings (compatibility w... (diff)
parentMerge branch 'trac2000' (diff)
downloadkea-cdcedf7fadf4f3021b86be152a6b009f3be8fcc0.tar.xz
kea-cdcedf7fadf4f3021b86be152a6b009f3be8fcc0.zip
Merge branch 'master' into trac2534
Diffstat (limited to 'src/lib/dns')
-rw-r--r--src/lib/dns/Makefile.am7
-rw-r--r--src/lib/dns/exceptions.h29
-rwxr-xr-xsrc/lib/dns/gen-rdatacode.py.in4
-rw-r--r--src/lib/dns/labelsequence.cc17
-rw-r--r--src/lib/dns/master_lexer.h6
-rw-r--r--src/lib/dns/master_loader.cc541
-rw-r--r--src/lib/dns/message.cc21
-rw-r--r--src/lib/dns/message.h56
-rw-r--r--src/lib/dns/name.h11
-rw-r--r--src/lib/dns/nsec3hash.cc52
-rw-r--r--src/lib/dns/nsec3hash.h23
-rw-r--r--src/lib/dns/python/message_python.cc8
-rw-r--r--src/lib/dns/python/name_python.cc2
-rw-r--r--src/lib/dns/python/name_python.h2
-rw-r--r--src/lib/dns/python/pydnspp.cc70
-rw-r--r--src/lib/dns/python/pydnspp_common.cc6
-rw-r--r--src/lib/dns/python/pydnspp_common.h4
-rw-r--r--src/lib/dns/python/rdata_python.cc5
-rw-r--r--src/lib/dns/python/rrset_python.cc17
-rw-r--r--src/lib/dns/python/tests/Makefile.am1
-rw-r--r--src/lib/dns/python/tests/message_python_test.py7
-rw-r--r--src/lib/dns/python/tests/name_python_test.py12
-rw-r--r--src/lib/dns/python/tests/pydnspp_python_test.py34
-rw-r--r--src/lib/dns/python/tests/rrset_python_test.py18
-rw-r--r--src/lib/dns/python/tsig_python.cc11
-rw-r--r--src/lib/dns/python/tsig_python.h6
-rw-r--r--src/lib/dns/rdata.cc142
-rw-r--r--src/lib/dns/rdata.h31
-rw-r--r--src/lib/dns/rdata/generic/caa_257.cc306
-rw-r--r--src/lib/dns/rdata/generic/caa_257.h72
-rw-r--r--src/lib/dns/rdata/generic/detail/char_string.cc84
-rw-r--r--src/lib/dns/rdata/generic/detail/char_string.h37
-rw-r--r--src/lib/dns/rdata/generic/opt_41.cc182
-rw-r--r--src/lib/dns/rdata/generic/opt_41.h57
-rw-r--r--src/lib/dns/rdata/generic/sshfp_44.cc30
-rw-r--r--src/lib/dns/rdata/generic/sshfp_44.h4
-rw-r--r--src/lib/dns/rdata/generic/tlsa_52.cc350
-rw-r--r--src/lib/dns/rdata/generic/tlsa_52.h65
-rw-r--r--src/lib/dns/rdata_pimpl_holder.h60
-rw-r--r--src/lib/dns/rrclass-placeholder.h10
-rw-r--r--src/lib/dns/rrparamregistry.h10
-rw-r--r--src/lib/dns/rrset.cc64
-rw-r--r--src/lib/dns/rrset.h58
-rw-r--r--src/lib/dns/rrttl.cc44
-rw-r--r--src/lib/dns/rrttl.h10
-rw-r--r--src/lib/dns/rrtype-placeholder.h10
-rw-r--r--src/lib/dns/tests/Makefile.am5
-rw-r--r--src/lib/dns/tests/dns_exceptions_unittest.cc69
-rw-r--r--src/lib/dns/tests/edns_unittest.cc28
-rw-r--r--src/lib/dns/tests/labelsequence_unittest.cc10
-rw-r--r--src/lib/dns/tests/master_loader_unittest.cc496
-rw-r--r--src/lib/dns/tests/message_unittest.cc73
-rw-r--r--src/lib/dns/tests/messagerenderer_unittest.cc55
-rw-r--r--src/lib/dns/tests/name_unittest.cc78
-rw-r--r--src/lib/dns/tests/nsec3hash_unittest.cc33
-rw-r--r--src/lib/dns/tests/question_unittest.cc12
-rw-r--r--src/lib/dns/tests/rdata_afsdb_unittest.cc24
-rw-r--r--src/lib/dns/tests/rdata_caa_unittest.cc327
-rw-r--r--src/lib/dns/tests/rdata_char_string_data_unittest.cc187
-rw-r--r--src/lib/dns/tests/rdata_cname_unittest.cc20
-rw-r--r--src/lib/dns/tests/rdata_dhcid_unittest.cc12
-rw-r--r--src/lib/dns/tests/rdata_dname_unittest.cc20
-rw-r--r--src/lib/dns/tests/rdata_dnskey_unittest.cc15
-rw-r--r--src/lib/dns/tests/rdata_ds_like_unittest.cc12
-rw-r--r--src/lib/dns/tests/rdata_hinfo_unittest.cc15
-rw-r--r--src/lib/dns/tests/rdata_in_a_unittest.cc14
-rw-r--r--src/lib/dns/tests/rdata_in_aaaa_unittest.cc14
-rw-r--r--src/lib/dns/tests/rdata_minfo_unittest.cc25
-rw-r--r--src/lib/dns/tests/rdata_mx_unittest.cc12
-rw-r--r--src/lib/dns/tests/rdata_naptr_unittest.cc15
-rw-r--r--src/lib/dns/tests/rdata_ns_unittest.cc20
-rw-r--r--src/lib/dns/tests/rdata_nsec3param_like_unittest.cc9
-rw-r--r--src/lib/dns/tests/rdata_nsec3param_unittest.cc15
-rw-r--r--src/lib/dns/tests/rdata_nsec_unittest.cc10
-rw-r--r--src/lib/dns/tests/rdata_nsecbitmap_unittest.cc15
-rw-r--r--src/lib/dns/tests/rdata_opt_unittest.cc143
-rw-r--r--src/lib/dns/tests/rdata_pimpl_holder_unittest.cc62
-rw-r--r--src/lib/dns/tests/rdata_ptr_unittest.cc20
-rw-r--r--src/lib/dns/tests/rdata_rp_unittest.cc14
-rw-r--r--src/lib/dns/tests/rdata_rrsig_unittest.cc51
-rw-r--r--src/lib/dns/tests/rdata_soa_unittest.cc16
-rw-r--r--src/lib/dns/tests/rdata_srv_unittest.cc26
-rw-r--r--src/lib/dns/tests/rdata_sshfp_unittest.cc55
-rw-r--r--src/lib/dns/tests/rdata_tlsa_unittest.cc282
-rw-r--r--src/lib/dns/tests/rdata_tsig_unittest.cc49
-rw-r--r--src/lib/dns/tests/rdata_txt_like_unittest.cc58
-rw-r--r--src/lib/dns/tests/rdata_unittest.cc29
-rw-r--r--src/lib/dns/tests/rdata_unittest.h4
-rw-r--r--src/lib/dns/tests/rdatafields_unittest.cc51
-rw-r--r--src/lib/dns/tests/rrclass_unittest.cc12
-rw-r--r--src/lib/dns/tests/rrset_unittest.cc116
-rw-r--r--src/lib/dns/tests/rrttl_unittest.cc12
-rw-r--r--src/lib/dns/tests/rrtype_unittest.cc12
-rw-r--r--src/lib/dns/tests/testdata/.gitignore10
-rw-r--r--src/lib/dns/tests/testdata/Makefile.am18
-rw-r--r--src/lib/dns/tests/testdata/rdata_caa_fromWire1.spec6
-rw-r--r--src/lib/dns/tests/testdata/rdata_caa_fromWire2.spec7
-rw-r--r--src/lib/dns/tests/testdata/rdata_caa_fromWire3.spec7
-rw-r--r--src/lib/dns/tests/testdata/rdata_caa_fromWire4.spec7
-rw-r--r--src/lib/dns/tests/testdata/rdata_caa_fromWire56
-rw-r--r--src/lib/dns/tests/testdata/rdata_caa_fromWire64
-rw-r--r--src/lib/dns/tests/testdata/rdata_opt_fromWire16
-rw-r--r--src/lib/dns/tests/testdata/rdata_opt_fromWire115
-rw-r--r--src/lib/dns/tests/testdata/rdata_opt_fromWire24
-rw-r--r--src/lib/dns/tests/testdata/rdata_opt_fromWire38
-rw-r--r--src/lib/dns/tests/testdata/rdata_opt_fromWire49
-rw-r--r--src/lib/dns/tests/testdata/rdata_tlsa_fromWire4
-rw-r--r--src/lib/dns/tests/testdata/rdata_tlsa_fromWire106
-rw-r--r--src/lib/dns/tests/testdata/rdata_tlsa_fromWire114
-rw-r--r--src/lib/dns/tests/testdata/rdata_tlsa_fromWire124
-rw-r--r--src/lib/dns/tests/testdata/rdata_tlsa_fromWire24
-rw-r--r--src/lib/dns/tests/testdata/rdata_tlsa_fromWire3.spec7
-rw-r--r--src/lib/dns/tests/testdata/rdata_tlsa_fromWire4.spec7
-rw-r--r--src/lib/dns/tests/testdata/rdata_tlsa_fromWire5.spec7
-rw-r--r--src/lib/dns/tests/testdata/rdata_tlsa_fromWire6.spec7
-rw-r--r--src/lib/dns/tests/testdata/rdata_tlsa_fromWire7.spec9
-rw-r--r--src/lib/dns/tests/testdata/rdata_tlsa_fromWire8.spec7
-rw-r--r--src/lib/dns/tests/testdata/rdata_tlsa_fromWire97
-rw-r--r--src/lib/dns/tests/tsig_unittest.cc15
-rw-r--r--src/lib/dns/tests/tsigkey_unittest.cc30
-rw-r--r--src/lib/dns/tests/tsigrecord_unittest.cc17
-rw-r--r--src/lib/dns/tests/unittest_util.cc27
-rw-r--r--src/lib/dns/tests/unittest_util.h22
-rw-r--r--src/lib/dns/tsig.cc30
-rw-r--r--src/lib/dns/tsigkey.cc2
125 files changed, 4728 insertions, 853 deletions
diff --git a/src/lib/dns/Makefile.am b/src/lib/dns/Makefile.am
index bda4e85333..7691d31324 100644
--- a/src/lib/dns/Makefile.am
+++ b/src/lib/dns/Makefile.am
@@ -70,12 +70,16 @@ EXTRA_DIST += rdata/generic/spf_99.cc
EXTRA_DIST += rdata/generic/spf_99.h
EXTRA_DIST += rdata/generic/sshfp_44.cc
EXTRA_DIST += rdata/generic/sshfp_44.h
+EXTRA_DIST += rdata/generic/tlsa_52.cc
+EXTRA_DIST += rdata/generic/tlsa_52.h
EXTRA_DIST += rdata/generic/txt_16.cc
EXTRA_DIST += rdata/generic/txt_16.h
EXTRA_DIST += rdata/generic/minfo_14.cc
EXTRA_DIST += rdata/generic/minfo_14.h
EXTRA_DIST += rdata/generic/afsdb_18.cc
EXTRA_DIST += rdata/generic/afsdb_18.h
+EXTRA_DIST += rdata/generic/caa_257.cc
+EXTRA_DIST += rdata/generic/caa_257.h
EXTRA_DIST += rdata/hs_4/a_1.cc
EXTRA_DIST += rdata/hs_4/a_1.h
EXTRA_DIST += rdata/in_1/a_1.cc
@@ -135,6 +139,7 @@ libb10_dns___la_SOURCES += master_loader.h
libb10_dns___la_SOURCES += rrset_collection_base.h
libb10_dns___la_SOURCES += rrset_collection.h rrset_collection.cc
libb10_dns___la_SOURCES += zone_checker.h zone_checker.cc
+libb10_dns___la_SOURCES += rdata_pimpl_holder.h
libb10_dns___la_SOURCES += rdata/generic/detail/char_string.h
libb10_dns___la_SOURCES += rdata/generic/detail/char_string.cc
libb10_dns___la_SOURCES += rdata/generic/detail/nsec_bitmap.h
@@ -158,7 +163,7 @@ rrclass.h: rrclass-placeholder.h
rrtype.h: rrtype-placeholder.h
rrparamregistry.cc: rrparamregistry-placeholder.cc
-s-rdatacode: Makefile
+s-rdatacode: Makefile $(EXTRA_DIST)
$(PYTHON) ./gen-rdatacode.py
touch $@
diff --git a/src/lib/dns/exceptions.h b/src/lib/dns/exceptions.h
index 070b152c2b..21030b49c2 100644
--- a/src/lib/dns/exceptions.h
+++ b/src/lib/dns/exceptions.h
@@ -30,10 +30,34 @@ namespace dns {
///
class Rcode; // forward declaration
-class DNSProtocolError : public isc::Exception {
+class Exception : public isc::Exception {
public:
- DNSProtocolError(const char* file, size_t line, const char* what) :
+ Exception(const char* file, size_t line, const char* what) :
isc::Exception(file, line, what) {}
+};
+
+///
+/// \brief Base class for all sorts of text parse errors.
+///
+class DNSTextError : public isc::dns::Exception {
+public:
+ DNSTextError(const char* file, size_t line, const char* what) :
+ isc::dns::Exception(file, line, what) {}
+};
+
+///
+/// \brief Base class for name parser exceptions.
+///
+class NameParserException : public DNSTextError {
+public:
+ NameParserException(const char* file, size_t line, const char* what) :
+ DNSTextError(file, line, what) {}
+};
+
+class DNSProtocolError : public isc::dns::Exception {
+public:
+ DNSProtocolError(const char* file, size_t line, const char* what) :
+ isc::dns::Exception(file, line, what) {}
virtual const Rcode& getRcode() const = 0;
};
@@ -50,6 +74,7 @@ public:
DNSProtocolError(file, line, what) {}
virtual const Rcode& getRcode() const;
};
+
}
}
#endif // DNS_EXCEPTIONS_H
diff --git a/src/lib/dns/gen-rdatacode.py.in b/src/lib/dns/gen-rdatacode.py.in
index 3fd3b33112..1cb1e37da1 100755
--- a/src/lib/dns/gen-rdatacode.py.in
+++ b/src/lib/dns/gen-rdatacode.py.in
@@ -41,9 +41,9 @@ meta_types = {
'10': 'null', '11': 'wks', '19': 'x25', '21': 'rt', '22': 'nsap',
'23': 'nsap-ptr', '24': 'sig', '20': 'isdn', '25': 'key', '26': 'px',
'27': 'gpos', '29': 'loc', '36': 'kx', '37': 'cert', '42': 'apl',
- '45': 'ipseckey', '52': 'tlsa', '55': 'hip', '103': 'unspec',
+ '45': 'ipseckey', '55': 'hip', '103': 'unspec',
'104': 'nid', '105': 'l32', '106': 'l64', '107': 'lp', '249': 'tkey',
- '253': 'mailb', '256': 'uri', '257': 'caa'
+ '253': 'mailb', '256': 'uri'
}
# Classes that don't have any known types. This is a dict from type code
# values (as string) to textual mnemonic.
diff --git a/src/lib/dns/labelsequence.cc b/src/lib/dns/labelsequence.cc
index f5f6a95a1b..91af63372d 100644
--- a/src/lib/dns/labelsequence.cc
+++ b/src/lib/dns/labelsequence.cc
@@ -1,4 +1,4 @@
-// Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2012-2014 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
@@ -12,6 +12,8 @@
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
+#include <config.h>
+
#include <dns/labelsequence.h>
#include <dns/name_internal.h>
#include <exceptions/exceptions.h>
@@ -24,24 +26,34 @@ namespace isc {
namespace dns {
LabelSequence::LabelSequence(const void* buf) {
+#ifdef ENABLE_DEBUG
+ // In non-debug mode, derefencing the NULL pointer further below
+ // will lead to a crash, so disabling this check is not
+ // unsafe. Except for a programming mistake, this case should not
+ // happen.
if (buf == NULL) {
isc_throw(BadValue,
"Null pointer passed to LabelSequence constructor");
}
+#endif
const uint8_t* bp = reinterpret_cast<const uint8_t*>(buf);
-
first_label_ = 0;
const uint8_t offsets_len = *bp++;
+
+#ifdef ENABLE_DEBUG
if (offsets_len == 0 || offsets_len > Name::MAX_LABELS) {
isc_throw(BadValue,
"Bad offsets len in serialized LabelSequence data: "
<< static_cast<unsigned int>(offsets_len));
}
+#endif
+
last_label_ = offsets_len - 1;
offsets_ = bp;
data_ = bp + offsets_len;
+#ifdef ENABLE_DEBUG
// Check the integrity on the offsets and the name data
const uint8_t* dp = data_;
for (size_t cur_offset = 0; cur_offset < offsets_len; ++cur_offset) {
@@ -52,6 +64,7 @@ LabelSequence::LabelSequence(const void* buf) {
}
dp += (1 + *dp);
}
+#endif
}
LabelSequence::LabelSequence(const LabelSequence& src,
diff --git a/src/lib/dns/master_lexer.h b/src/lib/dns/master_lexer.h
index 650368181c..33c0567b08 100644
--- a/src/lib/dns/master_lexer.h
+++ b/src/lib/dns/master_lexer.h
@@ -15,7 +15,7 @@
#ifndef MASTER_LEXER_H
#define MASTER_LEXER_H 1
-#include <exceptions/exceptions.h>
+#include <dns/exceptions.h>
#include <istream>
#include <string>
@@ -325,10 +325,10 @@ public:
///
/// The \c token_ member variable (read-only) is set to a \c MasterToken
/// object of type ERROR indicating the reason for the error.
- class LexerError : public Exception {
+ class LexerError : public isc::dns::Exception {
public:
LexerError(const char* file, size_t line, MasterToken error_token) :
- Exception(file, line, error_token.getErrorText().c_str()),
+ isc::dns::Exception(file, line, error_token.getErrorText().c_str()),
token_(error_token)
{}
const MasterToken token_;
diff --git a/src/lib/dns/master_loader.cc b/src/lib/dns/master_loader.cc
index 6b6e091489..80b1053432 100644
--- a/src/lib/dns/master_loader.cc
+++ b/src/lib/dns/master_loader.cc
@@ -1,4 +1,4 @@
-// Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2012-2014 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
@@ -21,14 +21,16 @@
#include <dns/rrtype.h>
#include <dns/rdata.h>
-#include <boost/scoped_ptr.hpp>
+#include <boost/format.hpp>
#include <boost/algorithm/string/predicate.hpp> // for iequals
+#include <boost/scoped_ptr.hpp>
+#include <boost/shared_ptr.hpp>
#include <string>
#include <memory>
#include <vector>
-#include <boost/algorithm/string/predicate.hpp> // for iequals
-#include <boost/shared_ptr.hpp>
+
+#include <cstdio> // for sscanf()
using std::string;
using std::auto_ptr;
@@ -54,9 +56,34 @@ public:
} // end unnamed namespace
+/// \brief Private implementation class for the \c MasterLoader
+///
+/// This class is used internally by the \c MasterLoader and is not
+/// publicly visible. It is present to avoid polluting the public API
+/// with internal implementation details of the \c MasterLoader.
// cppcheck-suppress noConstructor
class MasterLoader::MasterLoaderImpl {
public:
+ /// \brief Constructor.
+ ///
+ /// \param master_file Path to the file to load.
+ /// \param zone_origin The origin of zone to be expected inside
+ /// the master file. Currently unused, but it is expected to
+ /// be used for some validation.
+ /// \param zone_class The class of zone to be expected inside the
+ /// master file.
+ /// \param callbacks The callbacks by which it should report problems.
+ /// Usually, the callback carries a filename and line number of the
+ /// input where the problem happens. There's a special case of empty
+ /// filename and zero line in case the opening of the top-level master
+ /// file fails.
+ /// \param add_callback The callback which would be called with each
+ /// loaded RR.
+ /// \param options Options for the parsing, which is bitwise-or of
+ /// the Options values or DEFAULT. If the MANY_ERRORS option is
+ /// included, the parser tries to continue past errors. If it
+ /// is not included, it stops at first encountered error.
+ /// \throw std::bad_alloc when there's not enough memory.
MasterLoaderImpl(const char* master_file,
const Name& zone_origin,
const RRClass& zone_class,
@@ -81,6 +108,16 @@ public:
rr_count_(0)
{}
+ /// \brief Wrapper around \c MasterLexer::pushSource() (file version)
+ ///
+ /// This method is used as a wrapper around the lexer's
+ /// \c pushSource() to also save the current origin and the last
+ /// seen name (to be restored upon \c popSource()). It also calls
+ /// \c pushSource(). See \c doInclude() implementation for more
+ /// details.
+ ///
+ /// \param filename Path to the file to push as a new source.
+ /// \param current_origin The current origin name to save.
void pushSource(const std::string& filename, const Name& current_origin) {
std::string error;
if (!lexer_.pushSource(filename.c_str(), &error)) {
@@ -98,17 +135,35 @@ public:
previous_name_ = false;
}
+ /// \brief Wrapper around \c MasterLexer::pushSource() (stream version)
+ ///
+ /// Similar to \c pushSource(). This method need not save the
+ /// current origin as it is not used with $INCLUDE processing.
+ ///
+ /// \param stream The input stream to use as a new source.
void pushStreamSource(std::istream& stream) {
lexer_.pushSource(stream);
initialized_ = true;
}
+ /// \brief Implementation of \c MasterLoader::loadIncremental()
+ ///
+ /// See \c MasterLoader::loadIncremental() for details.
bool loadIncremental(size_t count_limit);
+ /// \brief Return the total size of the input sources pushed so
+ /// far. See \c MasterLexer::getTotalSourceSize().
size_t getSize() const { return (lexer_.getTotalSourceSize()); }
+
+ /// \brief Return the line number being parsed in the pushed input
+ /// sources. See \c MasterLexer::getPosition().
size_t getPosition() const { return (lexer_.getPosition()); }
private:
+ /// \brief Report an error using the callbacks that were supplied
+ /// during \c MasterLoader construction. Note that this method also
+ /// throws \c MasterLoaderError exception if necessary, so the
+ /// caller need not throw it.
void reportError(const std::string& filename, size_t line,
const std::string& reason)
{
@@ -123,6 +178,12 @@ private:
}
}
+ /// \brief Wrapper around \c MasterLexer::popSource()
+ ///
+ /// This method is used as a wrapper around the lexer's
+ /// \c popSource() to also restore the current origin and the last
+ /// seen name (at time of push). It also calls \c popSource(). See
+ /// \c doInclude() implementation for more details.
bool popSource() {
if (lexer_.getSourceCount() == 1) {
return (false);
@@ -141,14 +202,43 @@ private:
return (true);
}
- // Get a string token. Handle it as error if it is not string.
+ /// \brief Get a string token. Handle it as error if it is not string.
const string getString() {
lexer_.getNextToken(MasterToken::STRING).getString(string_token_);
return (string_token_);
}
+ /// \brief Parse the initial token at the beginning of a line in a
+ /// master file (or stream).
+ ///
+ /// A helper method of \c loadIncremental(), parsing the first token
+ /// of a new line. If it looks like an RR, detect its owner name
+ /// and return a string token for the next field of the RR.
+ ///
+ /// Otherwise, return either \c END_OF_LINE or \c END_OF_FILE token
+ /// depending on whether the loader continues to the next line or
+ /// completes the load, respectively. Other corner cases including
+ /// $-directive handling is done here.
+ ///
+ /// For unexpected errors, it throws an exception, which will be
+ /// handled in \c loadIncremental().
MasterToken handleInitialToken();
+ /// \brief Helper method for \c doGenerate().
+ ///
+ /// This is a helper method for \c doGenerate() that processes the
+ /// LHS or RHS for a single iteration in the range that is requested
+ /// by the $GENERATE directive and returns a generated string (that
+ /// is used to build a name (LHS) or RDATA (RHS) for an RR). See the
+ /// commented implementation for details.
+ std::string generateForIter(const std::string& str, const int it);
+
+ /// \brief Process the $GENERATE directive.
+ ///
+ /// See the commented implementation for details.
+ void doGenerate();
+
+ /// \brief Process the $ORIGIN directive.
void doOrigin(bool is_optional) {
// Parse and create the new origin. It is relative to the previous
// one.
@@ -181,6 +271,7 @@ private:
}
}
+ /// \brief Process the $INCLUDE directive.
void doInclude() {
// First, get the filename to include
const string
@@ -201,11 +292,16 @@ private:
pushSource(filename, current_origin);
}
- // A helper method for loadIncremental(). It parses part of an RR
- // until it finds the RR type field. If TTL or RR class is
- // specified before the RR type, it also recognizes and validates
- // them. explicit_ttl will be set to true if this method finds a
- // valid TTL field.
+ /// \brief Parse RR fields (TTL, CLASS and TYPE).
+ ///
+ /// A helper method for \c loadIncremental(). It parses part of an
+ /// RR until it finds the RR type field. If TTL or RR class is
+ /// specified before the RR type, it also recognizes and validates
+ /// them.
+ ///
+ /// \param explicit_ttl will be set to true if this method finds a
+ /// valid TTL field.
+ /// \param rrparam_token Pass the current (parsed) token here.
RRType parseRRParams(bool& explicit_ttl, MasterToken rrparam_token) {
// Find TTL, class and type. Both TTL and class are
// optional and may occur in any order if they exist. TTL
@@ -245,20 +341,25 @@ private:
return (RRType(rrparam_token.getString()));
}
- // Upper limit check when recognizing a specific TTL value from the
- // zone file ($TTL, the RR's TTL field, or the SOA minimum). RFC2181
- // Section 8 limits the range of TTL values to 2^31-1 (0x7fffffff),
- // and prohibits transmitting a TTL field exceeding this range. We
- // guarantee that by limiting the value at the time of zone
- // parsing/loading, following what BIND 9 does. Resetting it to 0
- // at this point may not be exactly what the RFC states (depending on
- // the meaning of 'received'), but the end result would be the same (i.e.,
- // the guarantee on transmission). Again, we follow the BIND 9's behavior
- // here.
- //
- // post_parsing is true iff this method is called after parsing the entire
- // RR and the lexer is positioned at the next line. It's just for
- // calculating the accurate source line when callback is necessary.
+ /// \brief Check and limit TTL to maximum value.
+ ///
+ /// Upper limit check when recognizing a specific TTL value from the
+ /// zone file ($TTL, the RR's TTL field, or the SOA minimum). RFC2181
+ /// Section 8 limits the range of TTL values to 2^31-1 (0x7fffffff),
+ /// and prohibits transmitting a TTL field exceeding this range. We
+ /// guarantee that by limiting the value at the time of zone
+ /// parsing/loading, following what BIND 9 does. Resetting it to 0
+ /// at this point may not be exactly what the RFC states (depending on
+ /// the meaning of 'received'), but the end result would be the same (i.e.,
+ /// the guarantee on transmission). Again, we follow the BIND 9's behavior
+ /// here.
+ ///
+ /// \param ttl the TTL to check. If it is larger than the maximum
+ /// allowed, it is set to 0.
+ /// \param post_parsing should be true iff this method is called
+ /// after parsing the entire RR and the lexer is positioned at the
+ /// next line. It's just for calculating the accurate source line
+ /// when callback is necessary.
void limitTTL(RRTTL& ttl, bool post_parsing) {
if (ttl > RRTTL::MAX_TTL()) {
const size_t src_line = lexer_.getSourceLine() -
@@ -270,19 +371,25 @@ private:
}
}
- // Set/reset the default TTL. This should be from either $TTL or SOA
- // minimum TTL (it's the caller's responsibility; this method doesn't
- // care about where it comes from). see LimitTTL() for parameter
- // post_parsing.
+ /// \brief Set/reset the default TTL.
+ ///
+ /// This should be from either $TTL or SOA minimum TTL (it's the
+ /// caller's responsibility; this method doesn't care about where it
+ /// comes from). See \c limitTTL() for parameter post_parsing.
void setDefaultTTL(const RRTTL& ttl, bool post_parsing) {
assignTTL(default_ttl_, ttl);
limitTTL(*default_ttl_, post_parsing);
}
- // Try to set/reset the current TTL from candidate TTL text. It's possible
- // it does not actually represent a TTL (which is not immediately
- // considered an error). Return true iff it's recognized as a valid TTL
- // (and only in which case the current TTL is set).
+ /// \brief Try to set/reset the current TTL from candidate TTL text.
+ ///
+ /// It's possible it that the text does not actually represent a TTL
+ /// (which is not immediately considered an error). Returns \c true
+ /// iff it's recognized as a valid TTL (and only in which case the
+ /// current TTL is set).
+ ///
+ /// \param ttl_txt The text to parse as a TTL.
+ /// \return true if a TTL was parsed (and set as the current TTL).
bool setCurrentTTL(const string& ttl_txt) {
// We use the factory version instead of RRTTL constructor as we
// need to expect cases where ttl_txt does not actually represent a TTL
@@ -296,14 +403,15 @@ private:
return (false);
}
- // Determine the TTL of the current RR based on the given parsing context.
- //
- // explicit_ttl is true iff the TTL is explicitly specified for that RR
- // (in which case current_ttl_ is set to that TTL).
- // rrtype is the type of the current RR, and rdata is its RDATA. They
- // only matter if the type is SOA and no available TTL is known. In this
- // case the minimum TTL of the SOA will be used as the TTL of that SOA
- // and the default TTL for subsequent RRs.
+ /// \brief Determine the TTL of the current RR based on the given
+ /// parsing context.
+ ///
+ /// \c explicit_ttl is true iff the TTL is explicitly specified for that RR
+ /// (in which case current_ttl_ is set to that TTL).
+ /// \c rrtype is the type of the current RR, and \c rdata is its RDATA. They
+ /// only matter if the type is SOA and no available TTL is known. In this
+ /// case the minimum TTL of the SOA will be used as the TTL of that SOA
+ /// and the default TTL for subsequent RRs.
const RRTTL& getCurrentTTL(bool explicit_ttl, const RRType& rrtype,
const rdata::ConstRdataPtr& rdata) {
// We've completed parsing the full of RR, and the lexer is already
@@ -342,12 +450,19 @@ private:
return (*current_ttl_);
}
+ /// \brief Handle a $DIRECTIVE
+ ///
+ /// This method is called when a $DIRECTIVE is encountered in the
+ /// input stream.
void handleDirective(const char* directive, size_t length) {
if (iequals(directive, "INCLUDE")) {
doInclude();
} else if (iequals(directive, "ORIGIN")) {
doOrigin(false);
eatUntilEOL(true);
+ } else if (iequals(directive, "GENERATE")) {
+ doGenerate();
+ eatUntilEOL(true);
} else if (iequals(directive, "TTL")) {
setDefaultTTL(RRTTL(getString()), false);
eatUntilEOL(true);
@@ -357,6 +472,7 @@ private:
}
}
+ /// \brief Skip tokens until end-of-line.
void eatUntilEOL(bool reportExtra) {
// We want to continue. Try to read until the end of line
for (;;) {
@@ -437,15 +553,320 @@ public:
size_t rr_count_; // number of RRs successfully loaded
};
-// A helper method of loadIncremental, parsing the first token of a new line.
-// If it looks like an RR, detect its owner name and return a string token for
-// the next field of the RR.
-// Otherwise, return either END_OF_LINE or END_OF_FILE token depending on
-// whether the loader continues to the next line or completes the load,
-// respectively. Other corner cases including $-directive handling is done
-// here.
-// For unexpected errors, it throws an exception, which will be handled in
-// loadIncremental.
+namespace { // begin unnamed namespace
+
+/// \brief Generate a dotted nibble sequence.
+///
+/// This method generates a dotted nibble sequence and returns it as a
+/// string. The nibbles are appended from the least significant digit
+/// (in hex representation of \c num) to the most significant digit with
+/// dots ('.') to separate the digits. If \c width is non-zero and the
+/// dotted nibble sequence has not filled the requested width, the rest
+/// of the width is filled with a dotted nibble sequence of 0 nibbles.
+///
+/// Some sample representations:
+///
+/// num = 0x1234, width = 0
+/// "4.3.2.1"
+///
+/// num = 0x1234, width = 1
+/// "4.3.2.1"
+///
+/// num = 0x1234, width = 8
+/// "4.3.2.1"
+///
+/// num = 0x1234, width = 9
+/// "4.3.2.1."
+///
+/// num = 0x1234, width = 10
+/// "4.3.2.1.0"
+///
+/// num = 0x1234, width = 11
+/// "4.3.2.1.0."
+///
+/// num = 0xabcd, width = 0, uppercase = true
+/// "D.C.B.A"
+///
+/// num = 0, width = 0
+/// "0"
+///
+/// num = 0, width = 1
+/// "0"
+///
+/// num = 0, width = 2
+/// "0."
+///
+/// num = 0, width = 3
+/// "0.0"
+///
+/// \param num The number for which the dotted nibble sequence should be
+/// generated.
+/// \param width The width of the generated string. This is only
+/// meaningful when it is larger than the dotted nibble sequence
+/// representation of \c num.
+/// \param uppercase Whether to use uppercase characters in nibble
+/// sequence.
+/// \return A string containing the dotted nibble sequence.
+std::string
+genNibbles(int num, unsigned int width, bool uppercase) {
+ static const char *hex = "0123456789abcdef0123456789ABCDEF";
+ std::string rstr;
+
+ do {
+ char ch = hex[(num & 0x0f) + (uppercase ? 16 : 0)];
+ num >>= 4;
+ rstr.push_back(ch);
+
+ if (width > 0) {
+ --width;
+ }
+
+ // If width is non zero then we need to add a label separator.
+ // If value is non zero then we need to add another label and
+ // that requires a label separator.
+ if (width > 0 || num != 0) {
+ rstr.push_back('.');
+
+ if (width > 0) {
+ --width;
+ }
+ }
+ } while ((num != 0) || (width > 0));
+
+ return (rstr);
+}
+
+} // end unnamed namespace
+
+std::string
+MasterLoader::MasterLoaderImpl::generateForIter(const std::string& str,
+ const int num)
+{
+ std::string rstr;
+
+ for (std::string::const_iterator it = str.begin(); it != str.end();) {
+ switch (*it) {
+ case '$':
+ // This is the case when the '$' character is encountered in
+ // the LHS or RHS. A computed value is added in its place in
+ // the generated string.
+ ++it;
+ if ((it != str.end()) && (*it == '$')) {
+ rstr.push_back('$');
+ ++it;
+ continue;
+ }
+
+ // 'it' can be equal to str.end() here, but it is handled
+ // correctly.
+ if (*it != '{') {
+ // There is no modifier (between {}), so just copy the
+ // passed number into the generated string.
+ rstr += boost::str(boost::format("%d") % num);
+ } else {
+ // There is a modifier (between {}). Parse it and handle
+ // the various cases below.
+ const char* scan_str =
+ str.c_str() + std::distance(str.begin(), it);
+ int offset = 0;
+ unsigned int width;
+ char base[2] = {'d', 0}; // char plus null byte
+ // cppcheck-suppress invalidscanf
+ const int n = sscanf(scan_str, "{%d,%u,%1[doxXnN]}",
+ &offset, &width, base);
+ switch (n) {
+ case 1:
+ // Only 1 item was matched (the offset). Copy (num +
+ // offset) into the generated string.
+ rstr += boost::str(boost::format("%d") % (num + offset));
+ break;
+
+ case 2: {
+ // 2 items were matched (the offset and width). Copy
+ // (num + offset) and format it according to the width
+ // into the generated string.
+ const std::string fmt =
+ boost::str(boost::format("%%0%ud") % width);
+ rstr += boost::str(boost::format(fmt) % (num + offset));
+ break;
+ }
+
+ case 3:
+ // 3 items were matched (offset, width and base).
+ if ((base[0] == 'n') || (base[0] == 'N')) {
+ // The base is requesting nibbles. Format it
+ // specially (see genNibbles() documentation).
+ rstr += genNibbles(num + offset, width, (base[0] == 'N'));
+ } else {
+ // The base is not requesting nibbles. Copy (num +
+ // offset) and format it according to the width
+ // and base into the generated string.
+ const std::string fmt =
+ boost::str(boost::format("%%0%u%c") % width % base[0]);
+ rstr += boost::str(boost::format(fmt) % (num + offset));
+ }
+ break;
+
+ default:
+ // Any other case in the modifiers is an error.
+ reportError(lexer_.getSourceName(), lexer_.getSourceLine(),
+ "Invalid $GENERATE format modifiers");
+ return ("");
+ }
+
+ // Find the closing brace. Careful that 'it' can be equal
+ // to str.end() here.
+ while ((it != str.end()) && (*it != '}')) {
+ ++it;
+ }
+ // Skip past the closing brace (if there is one).
+ if (it != str.end()) {
+ ++it;
+ }
+ }
+ break;
+
+ case '\\':
+ // This is the case when the '\' character is encountered in
+ // the LHS or RHS. The '\' and the following character are
+ // copied as-is into the generated string. This is usually
+ // used for escaping the $ character.
+ rstr.push_back(*it);
+ ++it;
+ if (it == str.end()) {
+ continue;
+ }
+ rstr.push_back(*it);
+ ++it;
+ break;
+
+ default:
+ // This is the default case that handles all other
+ // characters. They are copied as-is into the generated
+ // string.
+ rstr.push_back(*it);
+ ++it;
+ break;
+ }
+ }
+
+ return (rstr);
+}
+
+void
+MasterLoader::MasterLoaderImpl::doGenerate() {
+ // Parse the range token
+ const MasterToken& range_token = lexer_.getNextToken(MasterToken::STRING);
+ if (range_token.getType() != MasterToken::STRING) {
+ reportError(lexer_.getSourceName(), lexer_.getSourceLine(),
+ "Invalid $GENERATE syntax");
+ return;
+ }
+ const std::string range = range_token.getString();
+
+ // Parse the LHS token
+ const MasterToken& lhs_token = lexer_.getNextToken(MasterToken::STRING);
+ if (lhs_token.getType() != MasterToken::STRING) {
+ reportError(lexer_.getSourceName(), lexer_.getSourceLine(),
+ "Invalid $GENERATE syntax");
+ return;
+ }
+ const std::string lhs = lhs_token.getString();
+
+ // Parse the TTL, RR class and RR type tokens. Note that TTL and RR
+ // class may come in any order, or may be missing (either or
+ // both). If TTL is missing, we expect that it was either specified
+ // explicitly using $TTL, or is implicitly known from a previous RR,
+ // or that this is the SOA RR from which the MINIMUM field is
+ // used. It's unlikely that $GENERATE will be used with an SOA RR,
+ // but it's possible. The parsing happens within the parseRRParams()
+ // helper method which is called below.
+ const MasterToken& param_token = lexer_.getNextToken(MasterToken::STRING);
+ if (param_token.getType() != MasterToken::STRING) {
+ reportError(lexer_.getSourceName(), lexer_.getSourceLine(),
+ "Invalid $GENERATE syntax");
+ return;
+ }
+
+ bool explicit_ttl = false;
+ const RRType rrtype = parseRRParams(explicit_ttl, param_token);
+
+ // Parse the RHS token. It can be a quoted string.
+ const MasterToken& rhs_token = lexer_.getNextToken(MasterToken::QSTRING);
+ if ((rhs_token.getType() != MasterToken::QSTRING) &&
+ (rhs_token.getType() != MasterToken::STRING))
+ {
+ reportError(lexer_.getSourceName(), lexer_.getSourceLine(),
+ "Invalid $GENERATE syntax");
+ return;
+ }
+ const std::string rhs = rhs_token.getString();
+
+ // Range can be one of two forms: start-stop or start-stop/step. If
+ // the first form is used, then step is set to 1. All of start, stop
+ // and step must be positive.
+ unsigned int start;
+ unsigned int stop;
+ unsigned int step;
+ // cppcheck-suppress invalidscanf
+ const int n = sscanf(range.c_str(), "%u-%u/%u", &start, &stop, &step);
+ if ((n < 2) || (stop < start)) {
+ reportError(lexer_.getSourceName(), lexer_.getSourceLine(),
+ "$GENERATE: invalid range: " + range);
+ return;
+ }
+
+ if (n == 2) {
+ step = 1;
+ }
+
+ // Generate and add the records.
+ for (int i = start; i <= stop; i += step) {
+ // Get generated strings for LHS and RHS. LHS goes to form the
+ // name, RHS goes to form the RDATA of the RR.
+ const std::string generated_name = generateForIter(lhs, i);
+ const std::string generated_rdata = generateForIter(rhs, i);
+ if (generated_name.empty() || generated_rdata.empty()) {
+ // The error should have been sent to the callbacks already
+ // by generateForIter().
+ reportError(lexer_.getSourceName(), lexer_.getSourceLine(),
+ "$GENERATE error");
+ return;
+ }
+
+ // generateForIter() can return a string with a trailing '.' in
+ // case of a nibble representation. So we cannot use the
+ // relative Name constructor. We use concatenate() which is
+ // expensive, but keeps the generated LHS-based Name within the
+ // active origin.
+ last_name_.reset
+ (new Name(Name(generated_name).concatenate(active_origin_)));
+ previous_name_ = true;
+
+ const rdata::RdataPtr rdata =
+ rdata::createRdata(rrtype, zone_class_, generated_rdata);
+ // In case we get NULL, it means there was error creating the
+ // Rdata. The errors should have been reported by callbacks_
+ // already. We need to decide if we want to continue or not.
+ if (rdata) {
+ add_callback_(*last_name_, zone_class_, rrtype,
+ getCurrentTTL(explicit_ttl, rrtype, rdata),
+ rdata);
+ // Good, we added another one
+ ++rr_count_;
+ } else {
+ seen_error_ = true;
+ if (!many_errors_) {
+ ok_ = false;
+ complete_ = true;
+ // We don't have the exact error here, but it was
+ // reported by the error callback.
+ isc_throw(MasterLoaderError, "Invalid RR data");
+ }
+ }
+ }
+}
+
MasterToken
MasterLoader::MasterLoaderImpl::handleInitialToken() {
const MasterToken& initial_token =
@@ -576,15 +997,19 @@ MasterLoader::MasterLoaderImpl::loadIncremental(size_t count_limit) {
isc_throw(MasterLoaderError, "Invalid RR data");
}
}
- } catch (const MasterLoaderError&) {
- // This is a hack. We exclude the MasterLoaderError from the
- // below case. Once we restrict the below to some smaller
- // exception, we should remove this.
- throw;
- } catch (const isc::Exception& e) {
- // TODO: Once we do #2518, catch only the DNSTextError here,
- // not isc::Exception. The rest should be just simply
- // propagated.
+ } catch (const isc::dns::DNSTextError& e) {
+ reportError(lexer_.getSourceName(), lexer_.getSourceLine(),
+ e.what());
+ eatUntilEOL(false);
+ } catch (const MasterLexer::ReadError& e) {
+ reportError(lexer_.getSourceName(), lexer_.getSourceLine(),
+ e.what());
+ eatUntilEOL(false);
+ } catch (const MasterLexer::LexerError& e) {
+ reportError(lexer_.getSourceName(), lexer_.getSourceLine(),
+ e.what());
+ eatUntilEOL(false);
+ } catch (const InternalException& e) {
reportError(lexer_.getSourceName(), lexer_.getSourceLine(),
e.what());
eatUntilEOL(false);
diff --git a/src/lib/dns/message.cc b/src/lib/dns/message.cc
index 2bc337ad6f..33cd07b2dc 100644
--- a/src/lib/dns/message.cc
+++ b/src/lib/dns/message.cc
@@ -604,13 +604,8 @@ Message::addQuestion(const Question& question) {
}
void
-Message::toWire(AbstractMessageRenderer& renderer) {
- impl_->toWire(renderer, NULL);
-}
-
-void
-Message::toWire(AbstractMessageRenderer& renderer, TSIGContext& tsig_ctx) {
- impl_->toWire(renderer, &tsig_ctx);
+Message::toWire(AbstractMessageRenderer& renderer, TSIGContext* tsig_ctx) {
+ impl_->toWire(renderer, tsig_ctx);
}
void
@@ -620,6 +615,10 @@ Message::parseHeader(InputBuffer& buffer) {
"Message parse attempted in non parse mode");
}
+ if (impl_->header_parsed_) {
+ return;
+ }
+
if ((buffer.getLength() - buffer.getPosition()) < HEADERLEN) {
isc_throw(MessageTooShort, "Malformed DNS message (short length): "
<< buffer.getLength() - buffer.getPosition());
@@ -645,9 +644,11 @@ Message::fromWire(InputBuffer& buffer, ParseOptions options) {
"Message parse attempted in non parse mode");
}
- if (!impl_->header_parsed_) {
- parseHeader(buffer);
- }
+ // Clear any old parsed data
+ clear(Message::PARSE);
+
+ buffer.setPosition(0);
+ parseHeader(buffer);
impl_->counts_[SECTION_QUESTION] = impl_->parseQuestion(buffer);
impl_->counts_[SECTION_ANSWER] =
diff --git a/src/lib/dns/message.h b/src/lib/dns/message.h
index aaa0d76982..3afad1f27a 100644
--- a/src/lib/dns/message.h
+++ b/src/lib/dns/message.h
@@ -21,7 +21,7 @@
#include <string>
#include <ostream>
-#include <exceptions/exceptions.h>
+#include <dns/exceptions.h>
#include <dns/edns.h>
#include <dns/question.h>
@@ -41,10 +41,10 @@ class TSIGRecord;
/// message parser encounters a short length of data that don't even contain
/// the full header section.
///
-class MessageTooShort : public Exception {
+class MessageTooShort : public isc::dns::Exception {
public:
MessageTooShort(const char* file, size_t line, const char* what) :
- isc::Exception(file, line, what) {}
+ isc::dns::Exception(file, line, what) {}
};
///
@@ -52,10 +52,10 @@ public:
/// is being constructed for an incompatible section. Specifically, this
/// happens RRset iterator is being constructed for a Question section.
///
-class InvalidMessageSection : public Exception {
+class InvalidMessageSection : public isc::dns::Exception {
public:
InvalidMessageSection(const char* file, size_t line, const char* what) :
- isc::Exception(file, line, what) {}
+ isc::dns::Exception(file, line, what) {}
};
///
@@ -63,10 +63,10 @@ public:
/// class method is called that is prohibited for the current mode of
/// the message.
///
-class InvalidMessageOperation : public Exception {
+class InvalidMessageOperation : public isc::dns::Exception {
public:
InvalidMessageOperation(const char* file, size_t line, const char* what) :
- isc::Exception(file, line, what) {}
+ isc::dns::Exception(file, line, what) {}
};
///
@@ -74,10 +74,10 @@ public:
/// smaller than the standard default maximum (DEFAULT_MAX_UDPSIZE) is
/// being specified for the message.
///
-class InvalidMessageUDPSize : public Exception {
+class InvalidMessageUDPSize : public isc::dns::Exception {
public:
InvalidMessageUDPSize(const char* file, size_t line, const char* what) :
- isc::Exception(file, line, what) {}
+ isc::dns::Exception(file, line, what) {}
};
typedef uint16_t qid_t;
@@ -550,29 +550,18 @@ public:
std::string toText() const;
/// \brief Render the message in wire formant into a message renderer
- /// object.
+ /// object with (or without) TSIG.
///
/// This \c Message must be in the \c RENDER mode and both \c Opcode and
/// \c Rcode must have been set beforehand; otherwise, an exception of
/// class \c InvalidMessageOperation will be thrown.
///
- /// \note The renderer's internal buffers and data are automatically
- /// cleared, keeping the length limit and the compression mode intact.
- /// In case truncation is triggered, the renderer is cleared completely.
- ///
- /// \param renderer DNS message rendering context that encapsulates the
- /// output buffer and name compression information.
- void toWire(AbstractMessageRenderer& renderer);
-
- /// \brief Render the message in wire formant into a message renderer
- /// object with TSIG.
- ///
- /// This method is similar to the other version of \c toWire(), but
- /// it will also add a TSIG RR with (in many cases) the TSIG MAC for
- /// the message along with the given TSIG context (\c tsig_ctx).
- /// The TSIG RR will be placed at the end of \c renderer.
- /// \c tsig_ctx will be updated based on the fact it was used for signing
- /// and with the latest MAC.
+ /// If a non-NULL \c tsig_ctx is passed, it will also add a TSIG RR
+ /// with (in many cases) the TSIG MAC for the message along with the
+ /// given TSIG context (\c tsig_ctx). The TSIG RR will be placed at
+ /// the end of \c renderer. The \c TSIGContext at \c tsig_ctx will
+ /// be updated based on the fact it was used for signing and with
+ /// the latest MAC.
///
/// \exception InvalidMessageOperation The message is not in the Render
/// mode, or either Rcode or Opcode is not set.
@@ -589,10 +578,12 @@ public:
/// cleared, keeping the length limit and the compression mode intact.
/// In case truncation is triggered, the renderer is cleared completely.
///
- /// \param renderer See the other version
+ /// \param renderer DNS message rendering context that encapsulates the
+ /// output buffer and name compression information.
/// \param tsig_ctx A TSIG context that is to be used for signing the
/// message
- void toWire(AbstractMessageRenderer& renderer, TSIGContext& tsig_ctx);
+ void toWire(AbstractMessageRenderer& renderer,
+ TSIGContext* tsig_ctx = NULL);
/// Parse options.
///
@@ -607,6 +598,10 @@ public:
};
/// \brief Parse the header section of the \c Message.
+ ///
+ /// NOTE: If the header has already been parsed by a previous call
+ /// to this method, this method simply returns (i.e., it does not
+ /// read from the \c buffer).
void parseHeader(isc::util::InputBuffer& buffer);
/// \brief (Re)build a \c Message object from wire-format data.
@@ -642,7 +637,8 @@ public:
/// \exception std::bad_alloc Memory allocation failure
/// \exception Others \c Name, \c Rdata, and \c EDNS classes can also throw
///
- /// \param buffer A input buffer object that stores the wire data
+ /// \param buffer A input buffer object that stores the wire
+ /// data. This method reads from position 0 in the passed buffer.
/// \param options Parse options
void fromWire(isc::util::InputBuffer& buffer, ParseOptions options
= PARSE_DEFAULT);
diff --git a/src/lib/dns/name.h b/src/lib/dns/name.h
index 02c868f039..7c750e3afc 100644
--- a/src/lib/dns/name.h
+++ b/src/lib/dns/name.h
@@ -20,7 +20,7 @@
#include <string>
#include <vector>
-#include <exceptions/exceptions.h>
+#include <dns/exceptions.h>
namespace isc {
namespace util {
@@ -32,15 +32,6 @@ namespace dns {
class AbstractMessageRenderer;
///
-/// \brief Base class for name parser exceptions.
-///
-class NameParserException : public Exception {
-public:
- NameParserException(const char* file, size_t line, const char* what) :
- isc::Exception(file, line, what) {}
-};
-
-///
/// \brief A standard DNS module exception that is thrown if the name parser
/// encounters an empty label in the middle of a name.
///
diff --git a/src/lib/dns/nsec3hash.cc b/src/lib/dns/nsec3hash.cc
index 0e03798268..4e6fea1ee7 100644
--- a/src/lib/dns/nsec3hash.cc
+++ b/src/lib/dns/nsec3hash.cc
@@ -29,8 +29,10 @@
#include <util/hash/sha1.h>
#include <dns/name.h>
+#include <dns/labelsequence.h>
#include <dns/nsec3hash.h>
#include <dns/rdataclass.h>
+#include <dns/name_internal.h>
using namespace std;
using namespace isc::util;
@@ -84,6 +86,7 @@ public:
}
virtual std::string calculate(const Name& name) const;
+ virtual std::string calculate(const LabelSequence& ls) const;
virtual bool match(const generic::NSEC3& nsec3) const;
virtual bool match(const generic::NSEC3PARAM& nsec3param) const;
@@ -91,6 +94,8 @@ public:
const vector<uint8_t>& salt) const;
private:
+ std::string calculateForWiredata(const uint8_t* data, size_t length) const;
+
const uint8_t algorithm_;
const uint16_t iterations_;
uint8_t* salt_data_;
@@ -116,19 +121,33 @@ iterateSHA1(SHA1Context* ctx, const uint8_t* input, size_t inlength,
}
string
-NSEC3HashRFC5155::calculate(const Name& name) const {
+NSEC3HashRFC5155::calculateForWiredata(const uint8_t* data,
+ size_t length) const
+{
// We first need to normalize the name by converting all upper case
// characters in the labels to lower ones.
- obuf_.clear();
- Name name_copy(name);
- name_copy.downcase();
- name_copy.toWire(obuf_);
+
+ uint8_t name_buf[256];
+ assert(length < sizeof (name_buf));
+
+ const uint8_t *p1 = data;
+ uint8_t *p2 = name_buf;
+ while (*p1 != 0) {
+ char len = *p1;
+
+ *p2++ = *p1++;
+ while (len--) {
+ *p2++ = isc::dns::name::internal::maptolower[*p1++];
+ }
+ }
+
+ *p2 = *p1;
uint8_t* const digest = &digest_[0];
assert(digest_.size() == SHA1_HASHSIZE);
- iterateSHA1(&sha1_ctx_, static_cast<const uint8_t*>(obuf_.getData()),
- obuf_.getLength(), salt_data_, salt_length_, digest);
+ iterateSHA1(&sha1_ctx_, name_buf, length,
+ salt_data_, salt_length_, digest);
for (unsigned int n = 0; n < iterations_; ++n) {
iterateSHA1(&sha1_ctx_, digest, SHA1_HASHSIZE,
salt_data_, salt_length_, digest);
@@ -137,6 +156,25 @@ NSEC3HashRFC5155::calculate(const Name& name) const {
return (encodeBase32Hex(digest_));
}
+string
+NSEC3HashRFC5155::calculate(const Name& name) const {
+ obuf_.clear();
+ name.toWire(obuf_);
+
+ return (calculateForWiredata(static_cast<const uint8_t*>(obuf_.getData()),
+ obuf_.getLength()));
+}
+
+string
+NSEC3HashRFC5155::calculate(const LabelSequence& ls) const {
+ assert(ls.isAbsolute());
+
+ size_t length;
+ const uint8_t* data = ls.getData(&length);
+
+ return (calculateForWiredata(data, length));
+}
+
bool
NSEC3HashRFC5155::match(uint8_t algorithm, uint16_t iterations,
const vector<uint8_t>& salt) const
diff --git a/src/lib/dns/nsec3hash.h b/src/lib/dns/nsec3hash.h
index f1ca1a3c2c..b58f0c9417 100644
--- a/src/lib/dns/nsec3hash.h
+++ b/src/lib/dns/nsec3hash.h
@@ -23,6 +23,7 @@
namespace isc {
namespace dns {
class Name;
+class LabelSequence;
namespace rdata {
namespace generic {
@@ -122,26 +123,40 @@ public:
/// (SHA-1) is supported
/// \param iterations the number of iterations
/// \param salt_data the salt data as a byte array
- /// \param salt_data_length the length of the salt data
+ /// \param salt_length the length of the salt data
static NSEC3Hash* create(uint8_t algorithm, uint16_t iterations,
const uint8_t* salt_data, size_t salt_length);
/// \brief The destructor.
virtual ~NSEC3Hash() {}
- /// \brief Calculate the NSEC3 hash.
+ /// \brief Calculate the NSEC3 hash (Name variant).
///
/// This method calculates the NSEC3 hash value for the given \c name
/// with the hash parameters (algorithm, iterations and salt) given at
/// construction, and returns the value as a base32hex-encoded string
/// (without containing any white spaces). All US-ASCII letters in the
- /// string will be upper cased.
+ /// string will be lower cased.
///
/// \param name The domain name for which the hash value is to be
/// calculated.
/// \return Base32hex-encoded string of the hash value.
virtual std::string calculate(const Name& name) const = 0;
+ /// \brief Calculate the NSEC3 hash (LabelSequence variant).
+ ///
+ /// This method calculates the NSEC3 hash value for the given
+ /// absolute LabelSequence \c ls with the hash parameters
+ /// (algorithm, iterations and salt) given at construction, and
+ /// returns the value as a base32hex-encoded string (without
+ /// containing any white spaces). All US-ASCII letters in the
+ /// string will be lower cased.
+ ///
+ /// \param ls The absolute label sequence for which the hash value
+ /// is to be calculated.
+ /// \return Base32hex-encoded string of the hash value.
+ virtual std::string calculate(const LabelSequence& ls) const = 0;
+
/// \brief Match given NSEC3 parameters with that of the hash.
///
/// This method compares NSEC3 parameters used for hash calculation
@@ -233,7 +248,7 @@ public:
/// (SHA-1) is supported
/// \param iterations the number of iterations
/// \param salt_data the salt data as a byte array
- /// \param salt_data_length the length of the salt data
+ /// \param salt_length the length of the salt data
virtual NSEC3Hash* create(uint8_t algorithm, uint16_t iterations,
const uint8_t* salt_data, size_t salt_length)
const = 0;
diff --git a/src/lib/dns/python/message_python.cc b/src/lib/dns/python/message_python.cc
index 4dfee249b6..d86754b8e8 100644
--- a/src/lib/dns/python/message_python.cc
+++ b/src/lib/dns/python/message_python.cc
@@ -696,10 +696,10 @@ Message_toWire(s_Message* self, PyObject* args) {
PyObject* mr;
PyObject* tsig_ctx = NULL;
- if (PyArg_ParseTuple(args, "O!|O!", &messagerenderer_type, &mr,
- &tsigcontext_type, &tsig_ctx)) {
+ if (PyArg_ParseTuple(args, "O!|O", &messagerenderer_type, &mr,
+ &tsig_ctx)) {
try {
- if (tsig_ctx == NULL) {
+ if ((tsig_ctx == NULL) || (tsig_ctx == Py_None)) {
self->cppobj->toWire(PyMessageRenderer_ToMessageRenderer(mr));
} else {
self->cppobj->toWire(PyMessageRenderer_ToMessageRenderer(mr),
@@ -726,7 +726,7 @@ Message_toWire(s_Message* self, PyObject* args) {
}
PyErr_Clear();
PyErr_SetString(PyExc_TypeError,
- "toWire argument must be a MessageRenderer");
+ "Bad to_wire() arguments were passed");
return (NULL);
}
diff --git a/src/lib/dns/python/name_python.cc b/src/lib/dns/python/name_python.cc
index 2799db9fde..ecdae841c3 100644
--- a/src/lib/dns/python/name_python.cc
+++ b/src/lib/dns/python/name_python.cc
@@ -537,6 +537,7 @@ namespace python {
// Initialization and addition of these go in the module init at the
// end
//
+PyObject* po_NameParserException;
PyObject* po_EmptyLabel;
PyObject* po_TooLongName;
PyObject* po_TooLongLabel;
@@ -544,7 +545,6 @@ PyObject* po_BadLabelType;
PyObject* po_BadEscape;
PyObject* po_IncompleteName;
PyObject* po_InvalidBufferPosition;
-PyObject* po_DNSMessageFORMERR;
//
// Definition of enums
diff --git a/src/lib/dns/python/name_python.h b/src/lib/dns/python/name_python.h
index d18c0d9385..2cce9994cc 100644
--- a/src/lib/dns/python/name_python.h
+++ b/src/lib/dns/python/name_python.h
@@ -23,6 +23,7 @@ class Name;
namespace python {
+extern PyObject* po_NameParserException;
extern PyObject* po_EmptyLabel;
extern PyObject* po_TooLongName;
extern PyObject* po_TooLongLabel;
@@ -30,7 +31,6 @@ extern PyObject* po_BadLabelType;
extern PyObject* po_BadEscape;
extern PyObject* po_IncompleteName;
extern PyObject* po_InvalidBufferPosition;
-extern PyObject* po_DNSMessageFORMERR;
//
// Declaration of enums
diff --git a/src/lib/dns/python/pydnspp.cc b/src/lib/dns/python/pydnspp.cc
index 30dc09089c..b0bda22c4b 100644
--- a/src/lib/dns/python/pydnspp.cc
+++ b/src/lib/dns/python/pydnspp.cc
@@ -28,6 +28,7 @@
#include <Python.h>
#include <structmember.h>
+#include <dns/exceptions.h>
#include <dns/message.h>
#include <dns/opcode.h>
#include <dns/tsig.h>
@@ -152,8 +153,14 @@ initModulePart_Message(PyObject* mod) {
PyErr_NewException("pydnspp.InvalidMessageUDPSize", NULL, NULL);
PyObjectContainer(po_InvalidMessageUDPSize).installToModule(
mod, "InvalidMessageUDPSize");
+ po_DNSMessageFORMERR =
+ PyErr_NewException("pydnspp.DNSMessageFORMERR",
+ po_DNSProtocolError, NULL);
+ PyObjectContainer(po_DNSMessageFORMERR).installToModule(
+ mod, "DNSMessageFORMERR");
po_DNSMessageBADVERS =
- PyErr_NewException("pydnspp.DNSMessageBADVERS", NULL, NULL);
+ PyErr_NewException("pydnspp.DNSMessageBADVERS",
+ po_DNSProtocolError, NULL);
PyObjectContainer(po_DNSMessageBADVERS).installToModule(
mod, "DNSMessageBADVERS");
po_UnknownNSEC3HashAlgorithm =
@@ -243,36 +250,40 @@ initModulePart_Name(PyObject* mod) {
// Add the exceptions to the module
try {
- po_EmptyLabel = PyErr_NewException("pydnspp.EmptyLabel", NULL, NULL);
+ po_NameParserException =
+ PyErr_NewException("pydnspp.NameParserException",
+ po_DNSTextError, NULL);
+ PyObjectContainer(po_NameParserException)
+ .installToModule(mod, "NameParserException");
+
+ po_EmptyLabel = PyErr_NewException("pydnspp.EmptyLabel",
+ po_NameParserException, NULL);
PyObjectContainer(po_EmptyLabel).installToModule(mod, "EmptyLabel");
- po_TooLongName = PyErr_NewException("pydnspp.TooLongName", NULL, NULL);
+ po_TooLongName = PyErr_NewException("pydnspp.TooLongName",
+ po_NameParserException, NULL);
PyObjectContainer(po_TooLongName).installToModule(mod, "TooLongName");
- po_TooLongLabel = PyErr_NewException("pydnspp.TooLongLabel", NULL, NULL);
+ po_TooLongLabel = PyErr_NewException("pydnspp.TooLongLabel",
+ po_NameParserException, NULL);
PyObjectContainer(po_TooLongLabel).installToModule(mod, "TooLongLabel");
- po_BadLabelType = PyErr_NewException("pydnspp.BadLabelType", NULL, NULL);
+ po_BadLabelType = PyErr_NewException("pydnspp.BadLabelType",
+ po_NameParserException, NULL);
PyObjectContainer(po_BadLabelType).installToModule(mod, "BadLabelType");
- po_BadEscape = PyErr_NewException("pydnspp.BadEscape", NULL, NULL);
+ po_BadEscape = PyErr_NewException("pydnspp.BadEscape",
+ po_NameParserException, NULL);
PyObjectContainer(po_BadEscape).installToModule(mod, "BadEscape");
- po_IncompleteName = PyErr_NewException("pydnspp.IncompleteName", NULL,
- NULL);
+ po_IncompleteName = PyErr_NewException("pydnspp.IncompleteName",
+ po_NameParserException, NULL);
PyObjectContainer(po_IncompleteName).installToModule(mod, "IncompleteName");
po_InvalidBufferPosition =
PyErr_NewException("pydnspp.InvalidBufferPosition", NULL, NULL);
PyObjectContainer(po_InvalidBufferPosition).installToModule(
mod, "InvalidBufferPosition");
-
- // This one could have gone into the message_python.cc file, but is
- // already needed here.
- po_DNSMessageFORMERR = PyErr_NewException("pydnspp.DNSMessageFORMERR",
- NULL, NULL);
- PyObjectContainer(po_DNSMessageFORMERR).installToModule(
- mod, "DNSMessageFORMERR");
} catch (const std::exception& ex) {
const std::string ex_what =
"Unexpected failure in Name initialization: " +
@@ -865,14 +876,31 @@ PyInit_pydnspp(void) {
PyObjectContainer(po_IscException).installToModule(mod, "IscException");
po_InvalidOperation = PyErr_NewException("pydnspp.InvalidOperation",
- NULL, NULL);
- PyObjectContainer(po_InvalidOperation).installToModule(
- mod, "InvalidOperation");
+ po_IscException, NULL);
+ PyObjectContainer(po_InvalidOperation)
+ .installToModule(mod, "InvalidOperation");
po_InvalidParameter = PyErr_NewException("pydnspp.InvalidParameter",
- NULL, NULL);
- PyObjectContainer(po_InvalidParameter).installToModule(
- mod, "InvalidParameter");
+ po_IscException, NULL);
+ PyObjectContainer(po_InvalidParameter)
+ .installToModule(mod, "InvalidParameter");
+
+ // Add DNS exceptions
+ po_DNSException = PyErr_NewException("pydnspp.DNSException",
+ po_IscException, NULL);
+ PyObjectContainer(po_DNSException)
+ .installToModule(mod, "DNSException");
+
+ po_DNSTextError = PyErr_NewException("pydnspp.DNSTextError",
+ po_DNSException, NULL);
+ PyObjectContainer(po_DNSTextError)
+ .installToModule(mod, "DNSTextError");
+
+ po_DNSProtocolError = PyErr_NewException("pydnspp.DNSProtocolError",
+ po_DNSException, NULL);
+ PyObjectContainer(po_DNSProtocolError)
+ .installToModule(mod, "DNSProtocolError");
+
} catch (const std::exception& ex) {
const std::string ex_what =
"Unexpected failure in pydnspp initialization: " +
diff --git a/src/lib/dns/python/pydnspp_common.cc b/src/lib/dns/python/pydnspp_common.cc
index 4250db7601..c95f87765e 100644
--- a/src/lib/dns/python/pydnspp_common.cc
+++ b/src/lib/dns/python/pydnspp_common.cc
@@ -50,7 +50,11 @@ PyObject* po_IscException;
PyObject* po_InvalidOperation;
PyObject* po_InvalidParameter;
-// For our own isc::dns::Exception
+// For DNS exceptions
+PyObject* po_DNSException;
+PyObject* po_DNSTextError;
+PyObject* po_DNSProtocolError;
+PyObject* po_DNSMessageFORMERR;
PyObject* po_DNSMessageBADVERS;
diff --git a/src/lib/dns/python/pydnspp_common.h b/src/lib/dns/python/pydnspp_common.h
index 9c27cfdae1..77191dc576 100644
--- a/src/lib/dns/python/pydnspp_common.h
+++ b/src/lib/dns/python/pydnspp_common.h
@@ -34,6 +34,10 @@ extern PyObject* po_InvalidOperation;
extern PyObject* po_InvalidParameter;
// For our own isc::dns::Exception
+extern PyObject* po_DNSException;
+extern PyObject* po_DNSTextError;
+extern PyObject* po_DNSProtocolError;
+extern PyObject* po_DNSMessageFORMERR;
extern PyObject* po_DNSMessageBADVERS;
// This function reads 'bytes' from a sequence
diff --git a/src/lib/dns/python/rdata_python.cc b/src/lib/dns/python/rdata_python.cc
index 20f67c8d7e..4b5200255f 100644
--- a/src/lib/dns/python/rdata_python.cc
+++ b/src/lib/dns/python/rdata_python.cc
@@ -25,6 +25,7 @@
#include "rrclass_python.h"
#include "messagerenderer_python.h"
#include "name_python.h"
+#include "pydnspp_common.h"
using namespace isc::dns;
using namespace isc::dns::python;
@@ -104,9 +105,9 @@ Rdata_init(PyObject* self_p, PyObject* args, PyObject*) {
const char* s;
const char* data;
Py_ssize_t len;
- s_Rdata* self(static_cast<s_Rdata*>(self_p));
-
try {
+ s_Rdata* self = static_cast<s_Rdata*>(self_p);
+
// Create from string
if (PyArg_ParseTuple(args, "O!O!s", &rrtype_type, &rrtype,
&rrclass_type, &rrclass,
diff --git a/src/lib/dns/python/rrset_python.cc b/src/lib/dns/python/rrset_python.cc
index de5925a431..4d864d1d8a 100644
--- a/src/lib/dns/python/rrset_python.cc
+++ b/src/lib/dns/python/rrset_python.cc
@@ -53,6 +53,7 @@ int RRset_init(s_RRset* self, PyObject* args);
void RRset_destroy(s_RRset* self);
PyObject* RRset_getRdataCount(PyObject* self, PyObject* args);
+PyObject* RRset_getLength(PyObject* self, PyObject* args);
PyObject* RRset_getName(PyObject* self, PyObject* args);
PyObject* RRset_getClass(PyObject* self, PyObject* args);
PyObject* RRset_getType(PyObject* self, PyObject* args);
@@ -70,6 +71,8 @@ PyObject* RRset_removeRRsig(PyObject* self, PyObject* args);
PyMethodDef RRset_methods[] = {
{ "get_rdata_count", RRset_getRdataCount, METH_NOARGS,
"Returns the number of rdata fields." },
+ { "get_length", RRset_getLength, METH_NOARGS,
+ "Returns the wire format length of the RRset." },
{ "get_name", RRset_getName, METH_NOARGS,
"Returns the name of the RRset, as a Name object." },
{ "get_class", RRset_getClass, METH_NOARGS,
@@ -136,6 +139,18 @@ RRset_getRdataCount(PyObject* self, PyObject*) {
}
PyObject*
+RRset_getLength(PyObject* self, PyObject*) {
+ try {
+ return (Py_BuildValue("H", static_cast<const s_RRset*>(self)->cppobj->
+ getLength()));
+ } catch (const EmptyRRset& ers) {
+ PyErr_Clear();
+ PyErr_SetString(po_EmptyRRset, ers.what());
+ return (NULL);
+ }
+}
+
+PyObject*
RRset_getName(PyObject* self, PyObject*) {
try {
return (createNameObject(static_cast<const s_RRset*>(self)->cppobj->
@@ -236,9 +251,9 @@ PyObject*
RRset_toWire(PyObject* self_p, PyObject* args) {
PyObject* bytes;
PyObject* mr;
- const s_RRset* self(static_cast<const s_RRset*>(self_p));
try {
+ const s_RRset* self = static_cast<const s_RRset*>(self_p);
if (PyArg_ParseTuple(args, "O", &bytes) && PySequence_Check(bytes)) {
PyObject* bytes_o = bytes;
diff --git a/src/lib/dns/python/tests/Makefile.am b/src/lib/dns/python/tests/Makefile.am
index 4574303408..8fe8bb7667 100644
--- a/src/lib/dns/python/tests/Makefile.am
+++ b/src/lib/dns/python/tests/Makefile.am
@@ -6,6 +6,7 @@ PYTESTS += name_python_test.py
PYTESTS += nsec3hash_python_test.py
PYTESTS += question_python_test.py
PYTESTS += opcode_python_test.py
+PYTESTS += pydnspp_python_test.py
PYTESTS += rcode_python_test.py
PYTESTS += rdata_python_test.py
PYTESTS += rrclass_python_test.py
diff --git a/src/lib/dns/python/tests/message_python_test.py b/src/lib/dns/python/tests/message_python_test.py
index 996ef8970c..6f017dfec3 100644
--- a/src/lib/dns/python/tests/message_python_test.py
+++ b/src/lib/dns/python/tests/message_python_test.py
@@ -371,6 +371,13 @@ class MessageTest(unittest.TestCase):
self.__common_tsigmessage_setup()
self.__common_tsig_checks("message_toWire2.wire")
+ def test_to_wire_with_tsig_none(self):
+ message_render = create_message()
+ renderer = MessageRenderer()
+ message_render.to_wire(renderer, None)
+ self.assertEqual(b'\x105\x85\x00\x00\x01\x00\x02\x00\x00\x00\x00\x04test\x07example\x03com\x00\x00\x01\x00\x01\xc0\x0c\x00\x01\x00\x01\x00\x00\x0e\x10\x00\x04\xc0\x00\x02\x01\xc0\x0c\x00\x01\x00\x01\x00\x00\x0e\x10\x00\x04\xc0\x00\x02\x02',
+ renderer.get_data())
+
def test_to_wire_with_edns_tsig(self):
fix_current_time(0x4db60d1f)
self.r.set_qid(0x6cd)
diff --git a/src/lib/dns/python/tests/name_python_test.py b/src/lib/dns/python/tests/name_python_test.py
index 8ea2e3520a..8160716896 100644
--- a/src/lib/dns/python/tests/name_python_test.py
+++ b/src/lib/dns/python/tests/name_python_test.py
@@ -14,7 +14,7 @@
# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#
-# Tests for the messagerenderer part of the pydnspp module
+# Tests for the name part of the pydnspp module
#
import unittest
@@ -97,6 +97,16 @@ class NameTest(unittest.TestCase):
self.assertRaises(DNSMessageFORMERR, Name, b, 0)
self.assertRaises(IndexError, Name, b, -1)
+ def test_exception_hierarchy(self):
+ self.assertTrue(isinstance(EmptyLabel(), NameParserException))
+ self.assertTrue(isinstance(TooLongLabel(), NameParserException))
+ self.assertTrue(isinstance(BadLabelType(), NameParserException))
+ self.assertTrue(isinstance(BadEscape(), NameParserException))
+ self.assertTrue(isinstance(TooLongName(), NameParserException))
+ self.assertTrue(isinstance(IncompleteName(), NameParserException))
+
+ self.assertTrue(isinstance(NameParserException(), DNSTextError))
+
def test_at(self):
self.assertEqual(7, self.name1.at(0))
self.assertEqual(101, self.name1.at(1))
diff --git a/src/lib/dns/python/tests/pydnspp_python_test.py b/src/lib/dns/python/tests/pydnspp_python_test.py
new file mode 100644
index 0000000000..574fc00e00
--- /dev/null
+++ b/src/lib/dns/python/tests/pydnspp_python_test.py
@@ -0,0 +1,34 @@
+# Copyright (C) 2014 Internet Systems 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 SYSTEMS CONSORTIUM
+# DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+# INTERNET SYSTEMS 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.
+
+#
+# Tests for the common part of the pydnspp module
+#
+
+import unittest
+import os
+from pydnspp import *
+
+class CommonTest(unittest.TestCase):
+ def test_exception_hierarchy(self):
+ self.assertTrue(isinstance(InvalidOperation(), IscException))
+ self.assertTrue(isinstance(InvalidParameter(), IscException))
+
+ self.assertTrue(isinstance(DNSException(), IscException))
+ self.assertTrue(isinstance(DNSTextError(), DNSException))
+ self.assertTrue(isinstance(DNSProtocolError(), DNSException))
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/src/lib/dns/python/tests/rrset_python_test.py b/src/lib/dns/python/tests/rrset_python_test.py
index 9592b42021..d848d278b6 100644
--- a/src/lib/dns/python/tests/rrset_python_test.py
+++ b/src/lib/dns/python/tests/rrset_python_test.py
@@ -45,6 +45,24 @@ class TestModuleSpec(unittest.TestCase):
self.assertEqual(i, self.rrset_a_empty.get_rdata_count())
self.rrset_a_empty.add_rdata(Rdata(RRType("A"), RRClass("IN"), "192.0.2.1"))
+ def test_get_length(self):
+ # Empty RRset should throw
+ self.assertRaises(EmptyRRset, self.rrset_a_empty.get_length);
+
+ # Unless it is type ANY or NONE:
+ # test.example.com = 1 + 4 + 1 + 7 + 1 + 3 + 1 = 18 octets
+ # TYPE field = 2 octets
+ # CLASS field = 2 octets
+ # TTL field = 4 octets
+ # RDLENGTH field = 2 octets
+ # Total = 18 + 2 + 2 + 4 + 2 = 28 octets
+ self.assertEqual(28, self.rrset_any_a_empty.get_length())
+
+ # Single A RR:
+ # 28 octets (above) + 4 octets (A RDATA) = 32 octets
+ # With 2 A RRs:
+ self.assertEqual(32 + 32, self.rrset_a.get_length())
+
def test_get_name(self):
self.assertEqual(self.test_name, self.rrset_a.get_name())
self.assertEqual(self.test_domain, self.rrset_ns.get_name())
diff --git a/src/lib/dns/python/tsig_python.cc b/src/lib/dns/python/tsig_python.cc
index abb77334f6..c5b5421dcc 100644
--- a/src/lib/dns/python/tsig_python.cc
+++ b/src/lib/dns/python/tsig_python.cc
@@ -334,14 +334,21 @@ PyTSIGContext_Check(PyObject* obj) {
return (PyObject_TypeCheck(obj, &tsigcontext_type));
}
-TSIGContext&
+TSIGContext*
PyTSIGContext_ToTSIGContext(PyObject* tsigcontext_obj) {
if (tsigcontext_obj == NULL) {
isc_throw(PyCPPWrapperException,
"obj argument NULL in TSIGContext PyObject conversion");
}
+
+ if (!PyTSIGContext_Check(tsigcontext_obj)) {
+ isc_throw(TSIGContextError,
+ "obj argument is of wrong type in TSIGContext "
+ "PyObject conversion");
+ }
+
s_TSIGContext* tsigcontext = static_cast<s_TSIGContext*>(tsigcontext_obj);
- return (*tsigcontext->cppobj);
+ return (tsigcontext->cppobj);
}
} // namespace python
diff --git a/src/lib/dns/python/tsig_python.h b/src/lib/dns/python/tsig_python.h
index 0bd57d70c0..bbef56be10 100644
--- a/src/lib/dns/python/tsig_python.h
+++ b/src/lib/dns/python/tsig_python.h
@@ -36,8 +36,8 @@ extern PyObject* po_TSIGContextError;
/// \return true if the object is of type TSIGContext, false otherwise
bool PyTSIGContext_Check(PyObject* obj);
-/// \brief Returns a reference to the TSIGContext object contained within the given
-/// Python object.
+/// \brief Returns a pointer to the TSIGContext object contained within
+/// the given Python object.
///
/// \note The given object MUST be of type TSIGContext; this can be checked with
/// either the right call to ParseTuple("O!"), or with PyTSIGContext_Check()
@@ -46,7 +46,7 @@ bool PyTSIGContext_Check(PyObject* obj);
/// may be destroyed, the caller must copy it itself.
///
/// \param tsigcontext_obj The tsigcontext object to convert
-TSIGContext& PyTSIGContext_ToTSIGContext(PyObject* tsigcontext_obj);
+TSIGContext* PyTSIGContext_ToTSIGContext(PyObject* tsigcontext_obj);
} // namespace python
diff --git a/src/lib/dns/rdata.cc b/src/lib/dns/rdata.cc
index f42c349f2d..a34f8870fe 100644
--- a/src/lib/dns/rdata.cc
+++ b/src/lib/dns/rdata.cc
@@ -15,6 +15,7 @@
#include <exceptions/exceptions.h>
#include <util/buffer.h>
+#include <util/encode/hex.h>
#include <dns/name.h>
#include <dns/messagerenderer.h>
@@ -46,6 +47,15 @@ namespace isc {
namespace dns {
namespace rdata {
+uint16_t
+Rdata::getLength() const {
+ OutputBuffer obuffer(0);
+
+ toWire(obuffer);
+
+ return (obuffer.getLength());
+}
+
// XXX: we need to specify std:: for string to help doxygen match the
// function signature with that given in the header file.
RdataPtr
@@ -211,94 +221,100 @@ Generic::Generic(isc::util::InputBuffer& buffer, size_t rdata_len) {
impl_ = new GenericImpl(data);
}
-void
-Generic::constructHelper(const std::string& rdata_string) {
- istringstream iss(rdata_string);
- string unknown_mark;
- iss >> unknown_mark;
- if (unknown_mark != "\\#") {
+GenericImpl*
+Generic::constructFromLexer(MasterLexer& lexer) {
+ const MasterToken& token = lexer.getNextToken(MasterToken::STRING);
+ if (token.getString() != "\\#") {
isc_throw(InvalidRdataText,
- "Missing the special token (\\#) for generic RDATA encoding");
+ "Missing the special token (\\#) for "
+ "unknown RDATA encoding");
}
- // RDLENGTH: read into a string so that we can easily reject invalid tokens
- string rdlen_txt;
- iss >> rdlen_txt;
- istringstream iss_rdlen(rdlen_txt);
- int32_t rdlen;
- iss_rdlen >> rdlen;
- if (iss_rdlen.rdstate() != ios::eofbit) {
- isc_throw(InvalidRdataText,
- "Invalid representation for a generic RDLENGTH");
+ // Initialize with an absurd value.
+ uint32_t rdlen = 65536;
+
+ try {
+ rdlen = lexer.getNextToken(MasterToken::NUMBER).getNumber();
+ } catch (const MasterLexer::LexerError& ex) {
+ isc_throw(InvalidRdataLength,
+ "Unknown RDATA length is invalid");
}
- if (rdlen < 0 || rdlen > 0xffff) {
- isc_throw(InvalidRdataLength, "RDATA length is out of range");
+
+ if (rdlen > 65535) {
+ isc_throw(InvalidRdataLength,
+ "Unknown RDATA length is out of range: " << rdlen);
}
- iss >> ws; // skip any white spaces
- // Hexadecimal encoding of RDATA: each segment must consist of an even
- // number of hex digits.
vector<uint8_t> data;
- while (!iss.eof() && data.size() < rdlen) {
- // extract two characters, which should compose a single byte of data.
- char buf[2];
- iss.read(buf, sizeof(buf));
- if ((iss.rdstate() & (ios::badbit | ios::failbit)) != 0) {
- isc_throw(InvalidRdataText,
- "Invalid hex encoding of generic RDATA");
+
+ if (rdlen > 0) {
+ string hex_txt;
+ string hex_part;
+ // Whitespace is allowed within hex data, so read to the end of input.
+ while (true) {
+ const MasterToken& token =
+ lexer.getNextToken(MasterToken::STRING, true);
+ if ((token.getType() == MasterToken::END_OF_FILE) ||
+ (token.getType() == MasterToken::END_OF_LINE)) {
+ // Unget the last read token as createRdata() expects us
+ // to leave it at the end-of-line or end-of-file when we
+ // return.
+ lexer.ungetToken();
+ break;
+ }
+ token.getString(hex_part);
+ hex_txt.append(hex_part);
}
- // convert it to a single byte integer as a hex digit.
- istringstream iss_byte(string(buf, sizeof(buf)));
- unsigned int ch;
- iss_byte >> hex >> ch;
- if (iss_byte.rdstate() != ios::eofbit) {
+ try {
+ isc::util::encode::decodeHex(hex_txt, data);
+ } catch (const isc::BadValue& ex) {
isc_throw(InvalidRdataText,
- "Invalid hex encoding of generic RDATA");
+ "Invalid hex encoding of generic RDATA: " << ex.what());
}
- data.push_back(ch);
- iss >> ws; // skip spaces
- }
-
- if (!iss.eof()) {
- isc_throw(InvalidRdataLength,
- "RDLENGTH is too small for generic RDATA");
}
if (data.size() != rdlen) {
isc_throw(InvalidRdataLength,
- "Generic RDATA code doesn't match RDLENGTH");
+ "Size of unknown RDATA hex data doesn't match RDLENGTH: "
+ << data.size() << " vs. " << rdlen);
}
- impl_ = new GenericImpl(data);
-}
-
-Generic::Generic(const std::string& rdata_string) {
- constructHelper(rdata_string);
+ return (new GenericImpl(data));
}
-Generic::Generic(MasterLexer& lexer, const Name*,
- MasterLoader::Options,
- MasterLoaderCallbacks&)
+Generic::Generic(const std::string& rdata_string) :
+ impl_(NULL)
{
- std::string s;
+ // We use auto_ptr here because if there is an exception in this
+ // constructor, the destructor is not called and there could be a
+ // leak of the GenericImpl that constructFromLexer() returns.
+ std::auto_ptr<GenericImpl> impl_ptr(NULL);
- while (true) {
- const MasterToken& token = lexer.getNextToken();
- if ((token.getType() == MasterToken::END_OF_FILE) ||
- (token.getType() == MasterToken::END_OF_LINE)) {
- lexer.ungetToken(); // let the upper layer handle the end-of token
- break;
- }
+ try {
+ std::istringstream ss(rdata_string);
+ MasterLexer lexer;
+ lexer.pushSource(ss);
- if (!s.empty()) {
- s += " ";
- }
+ impl_ptr.reset(constructFromLexer(lexer));
- s += token.getString();
+ if (lexer.getNextToken().getType() != MasterToken::END_OF_FILE) {
+ isc_throw(InvalidRdataText, "extra input text for unknown RDATA: "
+ << rdata_string);
+ }
+ } catch (const MasterLexer::LexerError& ex) {
+ isc_throw(InvalidRdataText, "Failed to construct unknown RDATA "
+ "from '" << rdata_string << "': " << ex.what());
}
- constructHelper(s);
+ impl_ = impl_ptr.release();
+}
+
+Generic::Generic(MasterLexer& lexer, const Name*,
+ MasterLoader::Options,
+ MasterLoaderCallbacks&) :
+ impl_(constructFromLexer(lexer))
+{
}
Generic::~Generic() {
diff --git a/src/lib/dns/rdata.h b/src/lib/dns/rdata.h
index 3fe0c74dd2..eb07937650 100644
--- a/src/lib/dns/rdata.h
+++ b/src/lib/dns/rdata.h
@@ -19,7 +19,7 @@
#include <dns/master_loader.h>
#include <dns/master_loader_callbacks.h>
-#include <exceptions/exceptions.h>
+#include <dns/exceptions.h>
#include <boost/shared_ptr.hpp>
@@ -42,20 +42,20 @@ namespace rdata {
/// \brief A standard DNS module exception that is thrown if RDATA parser
/// encounters an invalid or inconsistent data length.
///
-class InvalidRdataLength : public Exception {
+class InvalidRdataLength : public DNSTextError {
public:
InvalidRdataLength(const char* file, size_t line, const char* what) :
- isc::Exception(file, line, what) {}
+ DNSTextError(file, line, what) {}
};
///
/// \brief A standard DNS module exception that is thrown if RDATA parser
/// fails to recognize a given textual representation.
///
-class InvalidRdataText : public Exception {
+class InvalidRdataText : public DNSTextError {
public:
InvalidRdataText(const char* file, size_t line, const char* what) :
- isc::Exception(file, line, what) {}
+ DNSTextError(file, line, what) {}
};
///
@@ -63,10 +63,10 @@ public:
/// encounters a character-string (as defined in RFC1035) exceeding
/// the maximum allowable length (\c MAX_CHARSTRING_LEN).
///
-class CharStringTooLong : public Exception {
+class CharStringTooLong : public DNSTextError {
public:
CharStringTooLong(const char* file, size_t line, const char* what) :
- isc::Exception(file, line, what) {}
+ DNSTextError(file, line, what) {}
};
// Forward declaration to define RdataPtr.
@@ -221,6 +221,21 @@ public:
/// \return > 0 if \c this would be sorted after \c other.
virtual int compare(const Rdata& other) const = 0;
//@}
+
+ /// \brief Get the wire format length of an Rdata.
+ ///
+ /// IMPLEMENTATION NOTE: Currently this base class implementation is
+ /// non-optimal as it renders the wire data to a buffer and returns
+ /// the buffer's length. What would perform better is to add
+ /// implementations of \c getLength() method to every RDATA
+ /// type. This is why this method is virtual. Once all Rdata types
+ /// have \c getLength() implementations, this base class
+ /// implementation must be removed and the method should become a
+ /// pure interface.
+ ///
+ /// \return The length of the wire format representation of the
+ /// RDATA.
+ virtual uint16_t getLength() const;
};
namespace generic {
@@ -378,7 +393,7 @@ public:
//@}
private:
- void constructHelper(const std::string& rdata_string);
+ GenericImpl* constructFromLexer(MasterLexer& lexer);
GenericImpl* impl_;
};
diff --git a/src/lib/dns/rdata/generic/caa_257.cc b/src/lib/dns/rdata/generic/caa_257.cc
new file mode 100644
index 0000000000..7d46a57662
--- /dev/null
+++ b/src/lib/dns/rdata/generic/caa_257.cc
@@ -0,0 +1,306 @@
+// Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or 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 ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS. IN NO EVENT SHALL ISC 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.
+
+#include <config.h>
+
+#include <boost/lexical_cast.hpp>
+#include <boost/algorithm/string.hpp>
+
+#include <exceptions/exceptions.h>
+
+#include <util/buffer.h>
+#include <dns/name.h>
+#include <dns/messagerenderer.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+
+#include <dns/rdata/generic/detail/char_string.h>
+
+using namespace std;
+using boost::lexical_cast;
+using namespace isc::util;
+
+// BEGIN_ISC_NAMESPACE
+// BEGIN_RDATA_NAMESPACE
+
+struct CAAImpl {
+ // straightforward representation of CAA RDATA fields
+ CAAImpl(uint8_t flags, const std::string& tag,
+ const detail::CharStringData& value) :
+ flags_(flags),
+ tag_(tag),
+ value_(value)
+ {
+ if ((sizeof(flags) + 1 + tag_.size() + value_.size()) > 65535) {
+ isc_throw(InvalidRdataLength,
+ "CAA Value field is too large: " << value_.size());
+ }
+ }
+
+ uint8_t flags_;
+ const std::string tag_;
+ const detail::CharStringData value_;
+};
+
+// helper function for string and lexer constructors
+CAAImpl*
+CAA::constructFromLexer(MasterLexer& lexer) {
+ const uint32_t flags =
+ lexer.getNextToken(MasterToken::NUMBER).getNumber();
+ if (flags > 255) {
+ isc_throw(InvalidRdataText,
+ "CAA flags field out of range");
+ }
+
+ // Tag field must not be empty.
+ const std::string tag =
+ lexer.getNextToken(MasterToken::STRING).getString();
+ if (tag.empty()) {
+ isc_throw(InvalidRdataText, "CAA tag field is empty");
+ } else if (tag.size() > 255) {
+ isc_throw(InvalidRdataText,
+ "CAA tag field is too large: " << tag.size());
+ }
+
+ // Value field may be empty.
+ detail::CharStringData value;
+ MasterToken token = lexer.getNextToken(MasterToken::QSTRING, true);
+ if ((token.getType() != MasterToken::END_OF_FILE) &&
+ (token.getType() != MasterToken::END_OF_LINE))
+ {
+ detail::stringToCharStringData(token.getStringRegion(), value);
+ }
+
+ return (new CAAImpl(flags, tag, value));
+}
+
+/// \brief Constructor from string.
+///
+/// The given string must represent a valid CAA RDATA. There can be
+/// extra space characters at the beginning or end of the text (which
+/// are simply ignored), but other extra text, including a new line,
+/// will make the construction fail with an exception.
+///
+/// The Flags, Tag and Value fields must be within their valid ranges,
+/// but are not constrained to the values defined in RFC6844. The Tag
+/// field must not be empty.
+///
+/// \throw InvalidRdataText if any fields are missing, out of their
+/// valid ranges, incorrect, or empty.
+///
+/// \param caa_str A string containing the RDATA to be created
+CAA::CAA(const string& caa_str) :
+ impl_(NULL)
+{
+ // We use auto_ptr here because if there is an exception in this
+ // constructor, the destructor is not called and there could be a
+ // leak of the CAAImpl that constructFromLexer() returns.
+ std::auto_ptr<CAAImpl> impl_ptr(NULL);
+
+ try {
+ std::istringstream ss(caa_str);
+ MasterLexer lexer;
+ lexer.pushSource(ss);
+
+ impl_ptr.reset(constructFromLexer(lexer));
+
+ if (lexer.getNextToken().getType() != MasterToken::END_OF_FILE) {
+ isc_throw(InvalidRdataText, "extra input text for CAA: "
+ << caa_str);
+ }
+ } catch (const MasterLexer::LexerError& ex) {
+ isc_throw(InvalidRdataText, "Failed to construct CAA from '" <<
+ caa_str << "': " << ex.what());
+ }
+
+ impl_ = impl_ptr.release();
+}
+
+/// \brief Constructor with a context of MasterLexer.
+///
+/// The \c lexer should point to the beginning of valid textual
+/// representation of an CAA RDATA.
+///
+/// \throw MasterLexer::LexerError General parsing error such as missing
+/// field.
+/// \throw InvalidRdataText Fields are out of their valid ranges,
+/// incorrect, or empty.
+///
+/// \param lexer A \c MasterLexer object parsing a master file for the
+/// RDATA to be created
+CAA::CAA(MasterLexer& lexer, const Name*,
+ MasterLoader::Options, MasterLoaderCallbacks&) :
+ impl_(constructFromLexer(lexer))
+{
+}
+
+/// \brief Constructor from InputBuffer.
+///
+/// The passed buffer must contain a valid CAA RDATA.
+///
+/// The Flags, Tag and Value fields must be within their valid ranges,
+/// but are not constrained to the values defined in RFC6844. The Tag
+/// field must not be empty.
+CAA::CAA(InputBuffer& buffer, size_t rdata_len) {
+ if (rdata_len < 2) {
+ isc_throw(InvalidRdataLength, "CAA record too short");
+ }
+
+ const uint8_t flags = buffer.readUint8();
+ const uint8_t tag_length = buffer.readUint8();
+ rdata_len -= 2;
+ if (tag_length == 0) {
+ isc_throw(InvalidRdataText, "CAA tag field is empty");
+ }
+
+ if (rdata_len < tag_length) {
+ isc_throw(InvalidRdataLength,
+ "RDATA is too short for CAA tag field");
+ }
+
+ std::vector<uint8_t> tag_vec(tag_length);
+ buffer.readData(&tag_vec[0], tag_length);
+ std::string tag(tag_vec.begin(), tag_vec.end());
+ rdata_len -= tag_length;
+
+ detail::CharStringData value;
+ value.resize(rdata_len);
+ if (rdata_len > 0) {
+ buffer.readData(&value[0], rdata_len);
+ }
+
+ impl_ = new CAAImpl(flags, tag, value);
+}
+
+CAA::CAA(uint8_t flags, const std::string& tag, const std::string& value) :
+ impl_(NULL)
+{
+ if (tag.empty()) {
+ isc_throw(isc::InvalidParameter,
+ "CAA tag field is empty");
+ } else if (tag.size() > 255) {
+ isc_throw(isc::InvalidParameter,
+ "CAA tag field is too large: " << tag.size());
+ }
+
+ MasterToken::StringRegion region;
+ region.beg = &value[0]; // note std ensures this works even if str is empty
+ region.len = value.size();
+
+ detail::CharStringData value_vec;
+ detail::stringToCharStringData(region, value_vec);
+
+ impl_ = new CAAImpl(flags, tag, value_vec);
+}
+
+CAA::CAA(const CAA& other) :
+ Rdata(), impl_(new CAAImpl(*other.impl_))
+{}
+
+CAA&
+CAA::operator=(const CAA& source) {
+ if (this == &source) {
+ return (*this);
+ }
+
+ CAAImpl* newimpl = new CAAImpl(*source.impl_);
+ delete impl_;
+ impl_ = newimpl;
+
+ return (*this);
+}
+
+CAA::~CAA() {
+ delete impl_;
+}
+
+void
+CAA::toWire(OutputBuffer& buffer) const {
+ buffer.writeUint8(impl_->flags_);
+
+ // The constructors must ensure that the tag field is not empty.
+ assert(!impl_->tag_.empty());
+ buffer.writeUint8(impl_->tag_.size());
+ buffer.writeData(&impl_->tag_[0], impl_->tag_.size());
+
+ if (!impl_->value_.empty()) {
+ buffer.writeData(&impl_->value_[0],
+ impl_->value_.size());
+ }
+}
+
+void
+CAA::toWire(AbstractMessageRenderer& renderer) const {
+ renderer.writeUint8(impl_->flags_);
+
+ // The constructors must ensure that the tag field is not empty.
+ assert(!impl_->tag_.empty());
+ renderer.writeUint8(impl_->tag_.size());
+ renderer.writeData(&impl_->tag_[0], impl_->tag_.size());
+
+ if (!impl_->value_.empty()) {
+ renderer.writeData(&impl_->value_[0],
+ impl_->value_.size());
+ }
+}
+
+std::string
+CAA::toText() const {
+ std::string result;
+
+ result = lexical_cast<std::string>(static_cast<int>(impl_->flags_));
+ result += " " + impl_->tag_;
+ result += " \"" + detail::charStringDataToString(impl_->value_) + "\"";
+
+ return (result);
+}
+
+int
+CAA::compare(const Rdata& other) const {
+ const CAA& other_caa = dynamic_cast<const CAA&>(other);
+
+ if (impl_->flags_ < other_caa.impl_->flags_) {
+ return (-1);
+ } else if (impl_->flags_ > other_caa.impl_->flags_) {
+ return (1);
+ }
+
+ // Do a case-insensitive compare of the tag strings.
+ const int result = boost::ilexicographical_compare
+ <std::string, std::string>(impl_->tag_, other_caa.impl_->tag_);
+ if (result != 0) {
+ return (result);
+ }
+
+ return (detail::compareCharStringDatas(impl_->value_,
+ other_caa.impl_->value_));
+}
+
+uint8_t
+CAA::getFlags() const {
+ return (impl_->flags_);
+}
+
+const std::string&
+CAA::getTag() const {
+ return (impl_->tag_);
+}
+
+const std::vector<uint8_t>&
+CAA::getValue() const {
+ return (impl_->value_);
+}
+
+// END_RDATA_NAMESPACE
+// END_ISC_NAMESPACE
diff --git a/src/lib/dns/rdata/generic/caa_257.h b/src/lib/dns/rdata/generic/caa_257.h
new file mode 100644
index 0000000000..47a1369c97
--- /dev/null
+++ b/src/lib/dns/rdata/generic/caa_257.h
@@ -0,0 +1,72 @@
+// Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or 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 ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS. IN NO EVENT SHALL ISC 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.
+
+// BEGIN_HEADER_GUARD
+
+#include <stdint.h>
+
+#include <dns/name.h>
+#include <dns/rdata.h>
+
+#include <string>
+#include <vector>
+
+// BEGIN_ISC_NAMESPACE
+
+// BEGIN_COMMON_DECLARATIONS
+// END_COMMON_DECLARATIONS
+
+// BEGIN_RDATA_NAMESPACE
+
+struct CAAImpl;
+
+class CAA : public Rdata {
+public:
+ // BEGIN_COMMON_MEMBERS
+ // END_COMMON_MEMBERS
+
+ CAA(uint8_t flags, const std::string& tag, const std::string& value);
+ CAA& operator=(const CAA& source);
+ ~CAA();
+
+ ///
+ /// Specialized methods
+ ///
+
+ /// \brief Return the Flags field of the CAA RDATA.
+ uint8_t getFlags() const;
+
+ /// \brief Return the Tag field of the CAA RDATA.
+ const std::string& getTag() const;
+
+ /// \brief Return the Value field of the CAA RDATA.
+ ///
+ /// Note: The const reference which is returned is valid only during
+ /// the lifetime of this \c generic::CAA object. It should not be
+ /// used afterwards.
+ const std::vector<uint8_t>& getValue() const;
+
+private:
+ CAAImpl* constructFromLexer(MasterLexer& lexer);
+
+ CAAImpl* impl_;
+};
+
+// END_RDATA_NAMESPACE
+// END_ISC_NAMESPACE
+// END_HEADER_GUARD
+
+// Local Variables:
+// mode: c++
+// End:
diff --git a/src/lib/dns/rdata/generic/detail/char_string.cc b/src/lib/dns/rdata/generic/detail/char_string.cc
index 4c8965a10b..328fa7b406 100644
--- a/src/lib/dns/rdata/generic/detail/char_string.cc
+++ b/src/lib/dns/rdata/generic/detail/char_string.cc
@@ -93,6 +93,39 @@ stringToCharString(const MasterToken::StringRegion& str_region,
result[0] = result.size() - 1;
}
+void
+stringToCharStringData(const MasterToken::StringRegion& str_region,
+ CharStringData& result)
+{
+ bool escape = false;
+ const char* s = str_region.beg;
+ const char* const s_end = str_region.beg + str_region.len;
+
+ for (size_t n = str_region.len; n != 0; --n, ++s) {
+ int c = (*s & 0xff);
+ if (escape && std::isdigit(c) != 0) {
+ c = decimalToNumber(s, s_end);
+ // decimalToNumber() already throws if (s_end - s) is less
+ // than 3, so the following assertion is unnecessary. But we
+ // assert it anyway. 'n' is an unsigned type (size_t) and
+ // can underflow.
+ assert(n >= 3);
+ // 'n' and 's' are also updated by 1 in the for statement's
+ // expression, so we update them by 2 instead of 3 here.
+ n -= 2;
+ s += 2;
+ } else if (!escape && c == '\\') {
+ escape = true;
+ continue;
+ }
+ escape = false;
+ result.push_back(c);
+ }
+ if (escape) { // terminated by non-escaped '\'
+ isc_throw(InvalidRdataText, "character-string ends with '\\'");
+ }
+}
+
std::string
charStringToString(const CharString& char_string) {
std::string s;
@@ -116,6 +149,29 @@ charStringToString(const CharString& char_string) {
return (s);
}
+std::string
+charStringDataToString(const CharStringData& char_string) {
+ std::string s;
+ for (CharString::const_iterator it = char_string.begin();
+ it != char_string.end(); ++it) {
+ const uint8_t ch = *it;
+ if ((ch < 0x20) || (ch >= 0x7f)) {
+ // convert to escaped \xxx (decimal) format
+ s.push_back('\\');
+ s.push_back('0' + ((ch / 100) % 10));
+ s.push_back('0' + ((ch / 10) % 10));
+ s.push_back('0' + (ch % 10));
+ continue;
+ }
+ if ((ch == '"') || (ch == ';') || (ch == '\\')) {
+ s.push_back('\\');
+ }
+ s.push_back(ch);
+ }
+
+ return (s);
+}
+
int compareCharStrings(const detail::CharString& self,
const detail::CharString& other) {
if (self.size() == 0 && other.size() == 0) {
@@ -144,6 +200,34 @@ int compareCharStrings(const detail::CharString& self,
}
}
+int compareCharStringDatas(const detail::CharStringData& self,
+ const detail::CharStringData& other) {
+ if (self.size() == 0 && other.size() == 0) {
+ return (0);
+ }
+ if (self.size() == 0) {
+ return (-1);
+ }
+ if (other.size() == 0) {
+ return (1);
+ }
+ const size_t self_len = self.size();
+ const size_t other_len = other.size();
+ const size_t cmp_len = std::min(self_len, other_len);
+ const int cmp = std::memcmp(&self[0], &other[0], cmp_len);
+ if (cmp < 0) {
+ return (-1);
+ } else if (cmp > 0) {
+ return (1);
+ } else if (self_len < other_len) {
+ return (-1);
+ } else if (self_len > other_len) {
+ return (1);
+ } else {
+ return (0);
+ }
+}
+
size_t
bufferToCharString(isc::util::InputBuffer& buffer, size_t rdata_len,
CharString& target) {
diff --git a/src/lib/dns/rdata/generic/detail/char_string.h b/src/lib/dns/rdata/generic/detail/char_string.h
index 8e3e2944d0..01fccadc59 100644
--- a/src/lib/dns/rdata/generic/detail/char_string.h
+++ b/src/lib/dns/rdata/generic/detail/char_string.h
@@ -34,6 +34,9 @@ namespace detail {
/// be the bare char basis.
typedef std::vector<uint8_t> CharString;
+/// \brief Type for DNS character string without the length prefix.
+typedef std::vector<uint8_t> CharStringData;
+
/// \brief Convert a DNS character-string into corresponding binary data.
///
/// This helper function takes a string object that is expected to be a
@@ -53,6 +56,20 @@ typedef std::vector<uint8_t> CharString;
void stringToCharString(const MasterToken::StringRegion& str_region,
CharString& result);
+/// \brief Convert a DNS character-string into corresponding binary data.
+///
+/// This method functions similar to \c stringToCharString() except it
+/// does not include the 1-octet length prefix in the \c result, and the
+/// result is not limited to MAX_CHARSTRING_LEN octets.
+///
+/// \throw InvalidRdataText Upon syntax errors.
+///
+/// \brief str_region A string that represents a character-string.
+/// \brief result A placeholder vector where the resulting data are to be
+/// stored. Expected to be empty, but it's not checked.
+void stringToCharStringData(const MasterToken::StringRegion& str_region,
+ CharStringData& result);
+
/// \brief Convert a CharString into a textual DNS character-string.
///
/// This method converts a binary 8-bit representation of a DNS
@@ -67,6 +84,15 @@ void stringToCharString(const MasterToken::StringRegion& str_region,
/// \return A string representation of \c char_string.
std::string charStringToString(const CharString& char_string);
+/// \brief Convert a CharStringData into a textual DNS character-string.
+///
+/// Reverse of \c stringToCharStringData(). See \c stringToCharString()
+/// vs. \c stringToCharStringData().
+///
+/// \param char_string The \c CharStringData to convert.
+/// \return A string representation of \c char_string.
+std::string charStringDataToString(const CharStringData& char_string);
+
/// \brief Compare two CharString objects
///
/// \param self The CharString field to compare
@@ -77,6 +103,17 @@ std::string charStringToString(const CharString& char_string);
/// 0 if \c self and \c other are equal
int compareCharStrings(const CharString& self, const CharString& other);
+/// \brief Compare two CharStringData objects
+///
+/// \param self The CharStringData field to compare
+/// \param other The CharStringData field to compare to
+///
+/// \return -1 if \c self would be sorted before \c other
+/// 1 if \c self would be sorted after \c other
+/// 0 if \c self and \c other are equal
+int compareCharStringDatas(const CharStringData& self,
+ const CharStringData& other);
+
/// \brief Convert a buffer containing a character-string to CharString
///
/// This method reads one character-string from the given buffer (in wire
diff --git a/src/lib/dns/rdata/generic/opt_41.cc b/src/lib/dns/rdata/generic/opt_41.cc
index 136bdf931a..6b292e9fa1 100644
--- a/src/lib/dns/rdata/generic/opt_41.cc
+++ b/src/lib/dns/rdata/generic/opt_41.cc
@@ -14,25 +14,68 @@
#include <config.h>
-#include <string>
-
#include <util/buffer.h>
#include <dns/messagerenderer.h>
#include <dns/rdata.h>
#include <dns/rdataclass.h>
+#include <boost/foreach.hpp>
+
+#include <string>
+#include <string.h>
+
using namespace std;
using namespace isc::util;
// BEGIN_ISC_NAMESPACE
// BEGIN_RDATA_NAMESPACE
+/// \brief Constructor.
+OPT::PseudoRR::PseudoRR(uint16_t code,
+ boost::shared_ptr<std::vector<uint8_t> >& data) :
+ code_(code),
+ data_(data)
+{
+}
+
+uint16_t
+OPT::PseudoRR::getCode() const {
+ return (code_);
+}
+
+const uint8_t*
+OPT::PseudoRR::getData() const {
+ return (&(*data_)[0]);
+}
+
+uint16_t
+OPT::PseudoRR::getLength() const {
+ return (data_->size());
+}
+
+struct OPTImpl {
+ OPTImpl() :
+ rdlength_(0)
+ {}
+
+ uint16_t rdlength_;
+ std::vector<OPT::PseudoRR> pseudo_rrs_;
+};
+
+/// \brief Default constructor.
+OPT::OPT() :
+ impl_(new OPTImpl)
+{
+}
+
/// \brief Constructor from string.
///
/// This constructor cannot be used, and always throws an exception.
///
/// \throw InvalidRdataText OPT RR cannot be constructed from text.
-OPT::OPT(const std::string&) {
+OPT::OPT(const std::string&) :
+ impl_(NULL)
+{
isc_throw(InvalidRdataText, "OPT RR cannot be constructed from text");
}
@@ -42,50 +85,141 @@ OPT::OPT(const std::string&) {
///
/// \throw InvalidRdataText OPT RR cannot be constructed from text.
OPT::OPT(MasterLexer&, const Name*,
- MasterLoader::Options, MasterLoaderCallbacks&)
+ MasterLoader::Options, MasterLoaderCallbacks&) :
+ impl_(NULL)
{
isc_throw(InvalidRdataText, "OPT RR cannot be constructed from text");
}
-OPT::OPT(InputBuffer& buffer, size_t rdata_len) {
- // setPosition() will throw against a short buffer anyway, but it's safer
- // to check it explicitly here.
- if (buffer.getLength() - buffer.getPosition() < rdata_len) {
- isc_throw(InvalidRdataLength, "RDLEN of OPT is too large");
+OPT::OPT(InputBuffer& buffer, size_t rdata_len) :
+ impl_(NULL)
+{
+ std::auto_ptr<OPTImpl> impl_ptr(new OPTImpl);
+
+ while (true) {
+ if (rdata_len == 0) {
+ break;
+ }
+
+ if (rdata_len < 4) {
+ isc_throw(InvalidRdataLength,
+ "Pseudo OPT RR record too short: "
+ << rdata_len << " bytes");
+ }
+
+ const uint16_t option_code = buffer.readUint16();
+ const uint16_t option_length = buffer.readUint16();
+ rdata_len -= 4;
+
+ if (static_cast<uint16_t>(impl_ptr->rdlength_ + option_length) <
+ impl_ptr->rdlength_)
+ {
+ isc_throw(InvalidRdataText,
+ "Option length " << option_length
+ << " would overflow OPT RR RDLEN (currently "
+ << impl_ptr->rdlength_ << ").");
+ }
+
+ if (rdata_len < option_length) {
+ isc_throw(InvalidRdataLength, "Corrupt pseudo OPT RR record");
+ }
+
+ boost::shared_ptr<std::vector<uint8_t> >
+ option_data(new std::vector<uint8_t>(option_length));
+ buffer.readData(&(*option_data)[0], option_length);
+ impl_ptr->pseudo_rrs_.push_back(PseudoRR(option_code, option_data));
+ impl_ptr->rdlength_ += option_length;
+ rdata_len -= option_length;
+ }
+
+ impl_ = impl_ptr.release();
+}
+
+OPT::OPT(const OPT& other) :
+ Rdata(), impl_(new OPTImpl(*other.impl_))
+{
+}
+
+OPT&
+OPT::operator=(const OPT& source) {
+ if (this == &source) {
+ return (*this);
}
- // This simple implementation ignores any options
- buffer.setPosition(buffer.getPosition() + rdata_len);
+ OPTImpl* newimpl = new OPTImpl(*source.impl_);
+ delete impl_;
+ impl_ = newimpl;
+
+ return (*this);
}
-OPT::OPT(const OPT&) : Rdata() {
- // there's nothing to copy in this simple implementation.
+OPT::~OPT() {
+ delete impl_;
}
std::string
OPT::toText() const {
- // OPT records do not have a text format.
- return ("");
+ isc_throw(isc::InvalidOperation,
+ "OPT RRs do not have a presentation format");
}
void
-OPT::toWire(OutputBuffer&) const {
- // nothing to do, as this simple version doesn't support any options.
+OPT::toWire(OutputBuffer& buffer) const {
+ BOOST_FOREACH(const PseudoRR& pseudo_rr, impl_->pseudo_rrs_) {
+ buffer.writeUint16(pseudo_rr.getCode());
+ const uint16_t length = pseudo_rr.getLength();
+ buffer.writeUint16(length);
+ if (length > 0) {
+ buffer.writeData(pseudo_rr.getData(), length);
+ }
+ }
}
void
-OPT::toWire(AbstractMessageRenderer&) const {
- // nothing to do, as this simple version doesn't support any options.
+OPT::toWire(AbstractMessageRenderer& renderer) const {
+ BOOST_FOREACH(const PseudoRR& pseudo_rr, impl_->pseudo_rrs_) {
+ renderer.writeUint16(pseudo_rr.getCode());
+ const uint16_t length = pseudo_rr.getLength();
+ renderer.writeUint16(length);
+ if (length > 0) {
+ renderer.writeData(pseudo_rr.getData(), length);
+ }
+ }
}
int
-OPT::compare(const Rdata& other) const {
- //const OPT& other_opt = dynamic_cast<const OPT&>(other);
- // right now we don't need other_opt:
- static_cast<void>(dynamic_cast<const OPT&>(other));
-
+OPT::compare(const Rdata&) const {
+ isc_throw(isc::InvalidOperation,
+ "It is meaningless to compare a set of OPT pseudo RRs; "
+ "they have unspecified order");
return (0);
}
+void
+OPT::appendPseudoRR(uint16_t code, const uint8_t* data, uint16_t length) {
+ // See if it overflows 16-bit length field. We only worry about the
+ // pseudo-RR length here, not the whole message length (which should
+ // be checked and enforced elsewhere).
+ if (static_cast<uint16_t>(impl_->rdlength_ + length) <
+ impl_->rdlength_)
+ {
+ isc_throw(isc::InvalidParameter,
+ "Option length " << length
+ << " would overflow OPT RR RDLEN (currently "
+ << impl_->rdlength_ << ").");
+ }
+
+ boost::shared_ptr<std::vector<uint8_t> >
+ option_data(new std::vector<uint8_t>(length));
+ std::memcpy(&(*option_data)[0], data, length);
+ impl_->pseudo_rrs_.push_back(PseudoRR(code, option_data));
+ impl_->rdlength_ += length;
+}
+
+const std::vector<OPT::PseudoRR>&
+OPT::getPseudoRRs() const {
+ return (impl_->pseudo_rrs_);
+}
+
// END_RDATA_NAMESPACE
// END_ISC_NAMESPACE
diff --git a/src/lib/dns/rdata/generic/opt_41.h b/src/lib/dns/rdata/generic/opt_41.h
index 0cb7043cca..cc51977e3a 100644
--- a/src/lib/dns/rdata/generic/opt_41.h
+++ b/src/lib/dns/rdata/generic/opt_41.h
@@ -18,6 +18,10 @@
#include <dns/rdata.h>
+#include <boost/shared_ptr.hpp>
+
+#include <vector>
+
// BEGIN_ISC_NAMESPACE
// BEGIN_COMMON_DECLARATIONS
@@ -25,15 +29,64 @@
// BEGIN_RDATA_NAMESPACE
+struct OPTImpl;
+
class OPT : public Rdata {
public:
// BEGIN_COMMON_MEMBERS
// END_COMMON_MEMBERS
// The default constructor makes sense for OPT as it can be empty.
- OPT() {}
+ OPT();
+ OPT& operator=(const OPT& source);
+ ~OPT();
+
+ /// \brief A class representing a pseudo RR (or option) within an
+ /// OPT RR (see RFC 6891).
+ class PseudoRR {
+ public:
+ /// \brief Constructor.
+ /// \param code The OPTION-CODE field of the pseudo RR.
+ /// \param data The OPTION-DATA field of the pseudo
+ /// RR. OPTION-LENGTH is set to the length of this vector.
+ PseudoRR(uint16_t code,
+ boost::shared_ptr<std::vector<uint8_t> >& data);
+
+ /// \brief Return the option code of this pseudo RR.
+ uint16_t getCode() const;
+
+ /// \brief Return the option data of this pseudo RR.
+ const uint8_t* getData() const;
+
+ /// \brief Return the length of the option data of this
+ /// pseudo RR.
+ uint16_t getLength() const;
+
+ private:
+ uint16_t code_;
+ boost::shared_ptr<std::vector<uint8_t> > data_;
+ };
+
+ /// \brief Append a pseudo RR (option) in this OPT RR.
+ ///
+ /// \param code The OPTION-CODE field of the pseudo RR.
+ /// \param data The OPTION-DATA field of the pseudo RR.
+ /// \param length The size of the \c data argument. OPTION-LENGTH is
+ /// set to this size.
+ /// \throw \c isc::InvalidParameter if this pseudo RR would cause
+ /// the OPT RDATA to overflow its RDLENGTH.
+ void appendPseudoRR(uint16_t code, const uint8_t* data, uint16_t length);
+
+ /// \brief Return a vector of the pseudo RRs (options) in this
+ /// OPT RR.
+ ///
+ /// Note: The returned reference is only valid during the lifetime
+ /// of this \c generic::OPT object. It should not be used
+ /// afterwards.
+ const std::vector<PseudoRR>& getPseudoRRs() const;
+
private:
- // RR-type specific members are here.
+ OPTImpl* impl_;
};
// END_RDATA_NAMESPACE
diff --git a/src/lib/dns/rdata/generic/sshfp_44.cc b/src/lib/dns/rdata/generic/sshfp_44.cc
index 2865ed18c8..4c1e83274a 100644
--- a/src/lib/dns/rdata/generic/sshfp_44.cc
+++ b/src/lib/dns/rdata/generic/sshfp_44.cc
@@ -14,8 +14,6 @@
#include <config.h>
-#include <string>
-
#include <boost/lexical_cast.hpp>
#include <exceptions/exceptions.h>
@@ -38,7 +36,7 @@ using namespace isc::util::encode;
struct SSHFPImpl {
// straightforward representation of SSHFP RDATA fields
SSHFPImpl(uint8_t algorithm, uint8_t fingerprint_type,
- vector<uint8_t>& fingerprint) :
+ const vector<uint8_t>& fingerprint) :
algorithm_(algorithm),
fingerprint_type_(fingerprint_type),
fingerprint_(fingerprint)
@@ -82,7 +80,11 @@ SSHFP::constructFromLexer(MasterLexer& lexer) {
// If fingerprint is missing, it's OK. See the API documentation of the
// constructor.
if (fingerprint_str.size() > 0) {
- decodeHex(fingerprint_str, fingerprint);
+ try {
+ decodeHex(fingerprint_str, fingerprint);
+ } catch (const isc::BadValue& e) {
+ isc_throw(InvalidRdataText, "Bad SSHFP fingerprint: " << e.what());
+ }
}
return (new SSHFPImpl(algorithm, fingerprint_type, fingerprint));
@@ -102,8 +104,9 @@ SSHFP::constructFromLexer(MasterLexer& lexer) {
/// valid hex encoding of the fingerprint. For compatibility with BIND 9,
/// whitespace is allowed in the hex text (RFC4255 is silent on the matter).
///
-/// \throw InvalidRdataText if any fields are missing, out of their valid
-/// ranges, or incorrect.
+/// \throw InvalidRdataText if any fields are missing, are out of their
+/// valid ranges or are incorrect, or if the fingerprint is not a valid
+/// hex string.
///
/// \param sshfp_str A string containing the RDATA to be created
SSHFP::SSHFP(const string& sshfp_str) :
@@ -128,9 +131,6 @@ SSHFP::SSHFP(const string& sshfp_str) :
} catch (const MasterLexer::LexerError& ex) {
isc_throw(InvalidRdataText, "Failed to construct SSHFP from '" <<
sshfp_str << "': " << ex.what());
- } catch (const isc::BadValue& e) {
- isc_throw(InvalidRdataText,
- "Bad SSHFP fingerprint: " << e.what());
}
impl_ = impl_ptr.release();
@@ -142,9 +142,8 @@ SSHFP::SSHFP(const string& sshfp_str) :
/// of an SSHFP RDATA.
///
/// \throw MasterLexer::LexerError General parsing error such as missing field.
-/// \throw InvalidRdataText Fields are out of their valid range, or are
-/// incorrect.
-/// \throw BadValue Fingerprint is not a valid hex string.
+/// \throw InvalidRdataText Fields are out of their valid range or are
+/// incorrect, or if the fingerprint is not a valid hex string.
///
/// \param lexer A \c MasterLexer object parsing a master file for the
/// RDATA to be created
@@ -293,8 +292,13 @@ SSHFP::getFingerprintType() const {
return (impl_->fingerprint_type_);
}
+const std::vector<uint8_t>&
+SSHFP::getFingerprint() const {
+ return (impl_->fingerprint_);
+}
+
size_t
-SSHFP::getFingerprintLen() const {
+SSHFP::getFingerprintLength() const {
return (impl_->fingerprint_.size());
}
diff --git a/src/lib/dns/rdata/generic/sshfp_44.h b/src/lib/dns/rdata/generic/sshfp_44.h
index 28ce0f3d22..85ae8067c5 100644
--- a/src/lib/dns/rdata/generic/sshfp_44.h
+++ b/src/lib/dns/rdata/generic/sshfp_44.h
@@ -17,6 +17,7 @@
#include <stdint.h>
#include <string>
+#include <vector>
#include <dns/name.h>
#include <dns/rdata.h>
@@ -45,7 +46,8 @@ public:
///
uint8_t getAlgorithmNumber() const;
uint8_t getFingerprintType() const;
- size_t getFingerprintLen() const;
+ const std::vector<uint8_t>& getFingerprint() const;
+ size_t getFingerprintLength() const;
private:
SSHFPImpl* constructFromLexer(MasterLexer& lexer);
diff --git a/src/lib/dns/rdata/generic/tlsa_52.cc b/src/lib/dns/rdata/generic/tlsa_52.cc
new file mode 100644
index 0000000000..774bdef6cf
--- /dev/null
+++ b/src/lib/dns/rdata/generic/tlsa_52.cc
@@ -0,0 +1,350 @@
+// Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or 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 ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS. IN NO EVENT SHALL ISC 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.
+
+#include <config.h>
+
+#include <boost/lexical_cast.hpp>
+
+#include <exceptions/exceptions.h>
+
+#include <util/buffer.h>
+#include <util/encode/hex.h>
+#include <dns/name.h>
+#include <dns/messagerenderer.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rdata_pimpl_holder.h>
+
+using namespace std;
+using boost::lexical_cast;
+using namespace isc::util;
+using namespace isc::util::encode;
+
+// BEGIN_ISC_NAMESPACE
+// BEGIN_RDATA_NAMESPACE
+
+struct TLSAImpl {
+ // straightforward representation of TLSA RDATA fields
+ TLSAImpl(uint8_t certificate_usage, uint8_t selector,
+ uint8_t matching_type, const vector<uint8_t>& data) :
+ certificate_usage_(certificate_usage),
+ selector_(selector),
+ matching_type_(matching_type),
+ data_(data)
+ {}
+
+ uint8_t certificate_usage_;
+ uint8_t selector_;
+ uint8_t matching_type_;
+ const vector<uint8_t> data_;
+};
+
+// helper function for string and lexer constructors
+TLSAImpl*
+TLSA::constructFromLexer(MasterLexer& lexer) {
+ const uint32_t certificate_usage =
+ lexer.getNextToken(MasterToken::NUMBER).getNumber();
+ if (certificate_usage > 255) {
+ isc_throw(InvalidRdataText,
+ "TLSA certificate usage field out of range");
+ }
+
+ const uint32_t selector =
+ lexer.getNextToken(MasterToken::NUMBER).getNumber();
+ if (selector > 255) {
+ isc_throw(InvalidRdataText,
+ "TLSA selector field out of range");
+ }
+
+ const uint32_t matching_type =
+ lexer.getNextToken(MasterToken::NUMBER).getNumber();
+ if (matching_type > 255) {
+ isc_throw(InvalidRdataText,
+ "TLSA matching type field out of range");
+ }
+
+ std::string certificate_assoc_data;
+ std::string data_substr;
+ while (true) {
+ const MasterToken& token =
+ lexer.getNextToken(MasterToken::STRING, true);
+ if ((token.getType() == MasterToken::END_OF_FILE) ||
+ (token.getType() == MasterToken::END_OF_LINE)) {
+ break;
+ }
+
+ token.getString(data_substr);
+ certificate_assoc_data.append(data_substr);
+ }
+ lexer.ungetToken();
+
+ if (certificate_assoc_data.empty()) {
+ isc_throw(InvalidRdataText, "Empty TLSA certificate association data");
+ }
+
+ vector<uint8_t> data;
+ try {
+ decodeHex(certificate_assoc_data, data);
+ } catch (const isc::BadValue& e) {
+ isc_throw(InvalidRdataText,
+ "Bad TLSA certificate association data: " << e.what());
+ }
+
+ return (new TLSAImpl(certificate_usage, selector, matching_type, data));
+}
+
+/// \brief Constructor from string.
+///
+/// The given string must represent a valid TLSA RDATA. There can be
+/// extra space characters at the beginning or end of the text (which
+/// are simply ignored), but other extra text, including a new line,
+/// will make the construction fail with an exception.
+///
+/// The Certificate Usage, Selector and Matching Type fields must be
+/// within their valid ranges, but are not constrained to the values
+/// defined in RFC6698.
+///
+/// The Certificate Association Data Field field may be absent, but if
+/// present it must contain a valid hex encoding of the data. Whitespace
+/// is allowed in the hex text.
+///
+/// \throw InvalidRdataText if any fields are missing, out of their
+/// valid ranges, or are incorrect, or Certificate Association Data is
+/// not a valid hex string.
+///
+/// \param tlsa_str A string containing the RDATA to be created
+TLSA::TLSA(const string& tlsa_str) :
+ impl_(NULL)
+{
+ // We use a smart pointer here because if there is an exception in
+ // this constructor, the destructor is not called and there could be
+ // a leak of the TLSAImpl that constructFromLexer() returns.
+ RdataPimplHolder<TLSAImpl> impl_ptr;
+
+ try {
+ std::istringstream ss(tlsa_str);
+ MasterLexer lexer;
+ lexer.pushSource(ss);
+
+ impl_ptr.reset(constructFromLexer(lexer));
+
+ if (lexer.getNextToken().getType() != MasterToken::END_OF_FILE) {
+ isc_throw(InvalidRdataText, "extra input text for TLSA: "
+ << tlsa_str);
+ }
+ } catch (const MasterLexer::LexerError& ex) {
+ isc_throw(InvalidRdataText, "Failed to construct TLSA from '" <<
+ tlsa_str << "': " << ex.what());
+ }
+
+ impl_ = impl_ptr.release();
+}
+
+/// \brief Constructor with a context of MasterLexer.
+///
+/// The \c lexer should point to the beginning of valid textual representation
+/// of an TLSA RDATA.
+///
+/// \throw MasterLexer::LexerError General parsing error such as missing field.
+/// \throw InvalidRdataText Fields are out of their valid range, or are
+/// incorrect, or Certificate Association Data is not a valid hex string.
+///
+/// \param lexer A \c MasterLexer object parsing a master file for the
+/// RDATA to be created
+TLSA::TLSA(MasterLexer& lexer, const Name*,
+ MasterLoader::Options, MasterLoaderCallbacks&) :
+ impl_(constructFromLexer(lexer))
+{
+}
+
+/// \brief Constructor from InputBuffer.
+///
+/// The passed buffer must contain a valid TLSA RDATA.
+///
+/// The Certificate Usage, Selector and Matching Type fields must be
+/// within their valid ranges, but are not constrained to the values
+/// defined in RFC6698. It is okay for the certificate association data
+/// to be missing (see the description of the constructor from string).
+TLSA::TLSA(InputBuffer& buffer, size_t rdata_len) {
+ if (rdata_len < 3) {
+ isc_throw(InvalidRdataLength, "TLSA record too short");
+ }
+
+ const uint8_t certificate_usage = buffer.readUint8();
+ const uint8_t selector = buffer.readUint8();
+ const uint8_t matching_type = buffer.readUint8();
+
+ vector<uint8_t> data;
+ rdata_len -= 3;
+
+ if (rdata_len == 0) {
+ isc_throw(InvalidRdataLength,
+ "Empty TLSA certificate association data");
+ }
+
+ data.resize(rdata_len);
+ buffer.readData(&data[0], rdata_len);
+
+ impl_ = new TLSAImpl(certificate_usage, selector, matching_type, data);
+}
+
+TLSA::TLSA(uint8_t certificate_usage, uint8_t selector,
+ uint8_t matching_type, const std::string& certificate_assoc_data) :
+ impl_(NULL)
+{
+ if (certificate_assoc_data.empty()) {
+ isc_throw(InvalidRdataText, "Empty TLSA certificate association data");
+ }
+
+ vector<uint8_t> data;
+ try {
+ decodeHex(certificate_assoc_data, data);
+ } catch (const isc::BadValue& e) {
+ isc_throw(InvalidRdataText,
+ "Bad TLSA certificate association data: " << e.what());
+ }
+
+ impl_ = new TLSAImpl(certificate_usage, selector, matching_type, data);
+}
+
+TLSA::TLSA(const TLSA& other) :
+ Rdata(), impl_(new TLSAImpl(*other.impl_))
+{}
+
+TLSA&
+TLSA::operator=(const TLSA& source) {
+ if (this == &source) {
+ return (*this);
+ }
+
+ TLSAImpl* newimpl = new TLSAImpl(*source.impl_);
+ delete impl_;
+ impl_ = newimpl;
+
+ return (*this);
+}
+
+TLSA::~TLSA() {
+ delete impl_;
+}
+
+void
+TLSA::toWire(OutputBuffer& buffer) const {
+ buffer.writeUint8(impl_->certificate_usage_);
+ buffer.writeUint8(impl_->selector_);
+ buffer.writeUint8(impl_->matching_type_);
+
+ // The constructors must ensure that the certificate association
+ // data field is not empty.
+ assert(!impl_->data_.empty());
+ buffer.writeData(&impl_->data_[0], impl_->data_.size());
+}
+
+void
+TLSA::toWire(AbstractMessageRenderer& renderer) const {
+ renderer.writeUint8(impl_->certificate_usage_);
+ renderer.writeUint8(impl_->selector_);
+ renderer.writeUint8(impl_->matching_type_);
+
+ // The constructors must ensure that the certificate association
+ // data field is not empty.
+ assert(!impl_->data_.empty());
+ renderer.writeData(&impl_->data_[0], impl_->data_.size());
+}
+
+string
+TLSA::toText() const {
+ // The constructors must ensure that the certificate association
+ // data field is not empty.
+ assert(!impl_->data_.empty());
+
+ return (lexical_cast<string>(static_cast<int>(impl_->certificate_usage_)) + " " +
+ lexical_cast<string>(static_cast<int>(impl_->selector_)) + " " +
+ lexical_cast<string>(static_cast<int>(impl_->matching_type_)) + " " +
+ encodeHex(impl_->data_));
+}
+
+int
+TLSA::compare(const Rdata& other) const {
+ const TLSA& other_tlsa = dynamic_cast<const TLSA&>(other);
+
+ if (impl_->certificate_usage_ < other_tlsa.impl_->certificate_usage_) {
+ return (-1);
+ } else if (impl_->certificate_usage_ >
+ other_tlsa.impl_->certificate_usage_) {
+ return (1);
+ }
+
+ if (impl_->selector_ < other_tlsa.impl_->selector_) {
+ return (-1);
+ } else if (impl_->selector_ > other_tlsa.impl_->selector_) {
+ return (1);
+ }
+
+ if (impl_->matching_type_ < other_tlsa.impl_->matching_type_) {
+ return (-1);
+ } else if (impl_->matching_type_ >
+ other_tlsa.impl_->matching_type_) {
+ return (1);
+ }
+
+ const size_t this_len = impl_->data_.size();
+ const size_t other_len = other_tlsa.impl_->data_.size();
+ const size_t cmplen = min(this_len, other_len);
+
+ if (cmplen > 0) {
+ const int cmp = memcmp(&impl_->data_[0],
+ &other_tlsa.impl_->data_[0],
+ cmplen);
+ if (cmp != 0) {
+ return (cmp);
+ }
+ }
+
+ if (this_len == other_len) {
+ return (0);
+ } else if (this_len < other_len) {
+ return (-1);
+ } else {
+ return (1);
+ }
+}
+
+uint8_t
+TLSA::getCertificateUsage() const {
+ return (impl_->certificate_usage_);
+}
+
+uint8_t
+TLSA::getSelector() const {
+ return (impl_->selector_);
+}
+
+uint8_t
+TLSA::getMatchingType() const {
+ return (impl_->matching_type_);
+}
+
+const std::vector<uint8_t>&
+TLSA::getData() const {
+ return (impl_->data_);
+}
+
+size_t
+TLSA::getDataLength() const {
+ return (impl_->data_.size());
+}
+
+// END_RDATA_NAMESPACE
+// END_ISC_NAMESPACE
diff --git a/src/lib/dns/rdata/generic/tlsa_52.h b/src/lib/dns/rdata/generic/tlsa_52.h
new file mode 100644
index 0000000000..7d8c69a3d1
--- /dev/null
+++ b/src/lib/dns/rdata/generic/tlsa_52.h
@@ -0,0 +1,65 @@
+// Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or 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 ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS. IN NO EVENT SHALL ISC 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.
+
+// BEGIN_HEADER_GUARD
+
+#include <stdint.h>
+
+#include <dns/name.h>
+#include <dns/rdata.h>
+
+#include <string>
+#include <vector>
+
+// BEGIN_ISC_NAMESPACE
+
+// BEGIN_COMMON_DECLARATIONS
+// END_COMMON_DECLARATIONS
+
+// BEGIN_RDATA_NAMESPACE
+
+struct TLSAImpl;
+
+class TLSA : public Rdata {
+public:
+ // BEGIN_COMMON_MEMBERS
+ // END_COMMON_MEMBERS
+
+ TLSA(uint8_t certificate_usage, uint8_t selector,
+ uint8_t matching_type, const std::string& certificate_assoc_data);
+ TLSA& operator=(const TLSA& source);
+ ~TLSA();
+
+ ///
+ /// Specialized methods
+ ///
+ uint8_t getCertificateUsage() const;
+ uint8_t getSelector() const;
+ uint8_t getMatchingType() const;
+ const std::vector<uint8_t>& getData() const;
+ size_t getDataLength() const;
+
+private:
+ TLSAImpl* constructFromLexer(MasterLexer& lexer);
+
+ TLSAImpl* impl_;
+};
+
+// END_RDATA_NAMESPACE
+// END_ISC_NAMESPACE
+// END_HEADER_GUARD
+
+// Local Variables:
+// mode: c++
+// End:
diff --git a/src/lib/dns/rdata_pimpl_holder.h b/src/lib/dns/rdata_pimpl_holder.h
new file mode 100644
index 0000000000..2705dd854d
--- /dev/null
+++ b/src/lib/dns/rdata_pimpl_holder.h
@@ -0,0 +1,60 @@
+// Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or 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 ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS. IN NO EVENT SHALL ISC 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.
+
+#ifndef DNS_RDATA_PIMPL_HOLDER_H
+#define DNS_RDATA_PIMPL_HOLDER_H 1
+
+#include <boost/noncopyable.hpp>
+
+#include <cstddef> // for NULL
+
+namespace isc {
+namespace dns {
+namespace rdata {
+
+template <typename T>
+class RdataPimplHolder : boost::noncopyable {
+public:
+ RdataPimplHolder(T* obj = NULL) :
+ obj_(obj)
+ {}
+
+ ~RdataPimplHolder() {
+ delete obj_;
+ }
+
+ void reset(T* obj = NULL) {
+ delete obj_;
+ obj_ = obj;
+ }
+
+ T* get() {
+ return (obj_);
+ }
+
+ T* release() {
+ T* obj = obj_;
+ obj_ = NULL;
+ return (obj);
+ }
+
+private:
+ T* obj_;
+};
+
+} // namespace rdata
+} // namespace dns
+} // namespace isc
+
+#endif // DNS_RDATA_PIMPL_HOLDER_H
diff --git a/src/lib/dns/rrclass-placeholder.h b/src/lib/dns/rrclass-placeholder.h
index b4f1851aa4..709057e818 100644
--- a/src/lib/dns/rrclass-placeholder.h
+++ b/src/lib/dns/rrclass-placeholder.h
@@ -20,7 +20,7 @@
#include <string>
#include <ostream>
-#include <exceptions/exceptions.h>
+#include <dns/exceptions.h>
#include <boost/optional.hpp>
@@ -39,20 +39,20 @@ class AbstractMessageRenderer;
/// \brief A standard DNS module exception that is thrown if an RRClass object
/// is being constructed from an unrecognized string.
///
-class InvalidRRClass : public Exception {
+class InvalidRRClass : public DNSTextError {
public:
InvalidRRClass(const char* file, size_t line, const char* what) :
- isc::Exception(file, line, what) {}
+ DNSTextError(file, line, what) {}
};
///
/// \brief A standard DNS module exception that is thrown if an RRClass object
/// is being constructed from a incomplete (too short) wire-format data.
///
-class IncompleteRRClass : public Exception {
+class IncompleteRRClass : public isc::dns::Exception {
public:
IncompleteRRClass(const char* file, size_t line, const char* what) :
- isc::Exception(file, line, what) {}
+ isc::dns::Exception(file, line, what) {}
};
///
diff --git a/src/lib/dns/rrparamregistry.h b/src/lib/dns/rrparamregistry.h
index 1d59e019db..3e30a360e5 100644
--- a/src/lib/dns/rrparamregistry.h
+++ b/src/lib/dns/rrparamregistry.h
@@ -21,7 +21,7 @@
#include <boost/shared_ptr.hpp>
-#include <exceptions/exceptions.h>
+#include <dns/exceptions.h>
#include <dns/rdata.h>
@@ -35,20 +35,20 @@ struct RRParamRegistryImpl;
/// \brief A standard DNS module exception that is thrown if a new RR type is
/// being registered with a different type string.
///
-class RRTypeExists : public Exception {
+class RRTypeExists : public isc::dns::Exception {
public:
RRTypeExists(const char* file, size_t line, const char* what) :
- isc::Exception(file, line, what) {}
+ isc::dns::Exception(file, line, what) {}
};
///
/// \brief A standard DNS module exception that is thrown if a new RR class is
/// being registered with a different type string.
///
-class RRClassExists : public Exception {
+class RRClassExists : public isc::dns::Exception {
public:
RRClassExists(const char* file, size_t line, const char* what) :
- isc::Exception(file, line, what) {}
+ isc::dns::Exception(file, line, what) {}
};
namespace rdata {
diff --git a/src/lib/dns/rrset.cc b/src/lib/dns/rrset.cc
index 8dfe884dac..b3da32c9de 100644
--- a/src/lib/dns/rrset.cc
+++ b/src/lib/dns/rrset.cc
@@ -254,6 +254,11 @@ BasicRRset::addRdata(const Rdata& rdata) {
AbstractRRset::addRdata(rdata);
}
+void
+BasicRRset::addRdata(const std::string& rdata_str) {
+ addRdata(createRdata(getType(), getClass(), rdata_str));
+}
+
unsigned int
BasicRRset::getRdataCount() const {
return (impl_->rdatalist_.size());
@@ -289,6 +294,50 @@ BasicRRset::toText() const {
return (AbstractRRset::toText());
}
+uint16_t
+BasicRRset::getLength() const {
+ uint16_t length = 0;
+ RdataIteratorPtr it = getRdataIterator();
+
+ if (it->isLast()) {
+ // empty rrsets are only allowed for classes ANY and NONE
+ if (getClass() != RRClass::ANY() &&
+ getClass() != RRClass::NONE()) {
+ isc_throw(EmptyRRset, "getLength() is attempted for an empty RRset");
+ }
+
+ // For an empty RRset, write the name, type, class and TTL once,
+ // followed by empty rdata.
+ length += getName().getLength();
+ length += 2; // TYPE field
+ length += 2; // CLASS field
+ length += 4; // TTL field
+ length += 2; // RDLENGTH field (=0 in wire format)
+
+ return (length);
+ }
+
+ do {
+ // This is a size_t as some of the following additions may
+ // overflow due to a programming mistake somewhere.
+ size_t rrlen = 0;
+
+ rrlen += getName().getLength();
+ rrlen += 2; // TYPE field
+ rrlen += 2; // CLASS field
+ rrlen += 4; // TTL field
+ rrlen += 2; // RDLENGTH field
+ rrlen += it->getCurrent().getLength();
+
+ assert(length + rrlen < 65536);
+ length += rrlen;
+
+ it->next();
+ } while (!it->isLast());
+
+ return (length);
+}
+
unsigned int
BasicRRset::toWire(OutputBuffer& buffer) const {
return (AbstractRRset::toWire(buffer));
@@ -322,6 +371,21 @@ RRset::getRRsigDataCount() const {
}
}
+uint16_t
+RRset::getLength() const {
+ uint16_t length = BasicRRset::getLength();
+
+ if (rrsig_) {
+ const uint16_t rrsigs_length = rrsig_->getLength();
+ // the uint16_ts are promoted to ints during addition below, so
+ // it won't overflow a 16-bit register.
+ assert(length + rrsigs_length < 65536);
+ length += rrsigs_length;
+ }
+
+ return (length);
+}
+
unsigned int
RRset::toWire(OutputBuffer& buffer) const {
unsigned int rrs_written = BasicRRset::toWire(buffer);
diff --git a/src/lib/dns/rrset.h b/src/lib/dns/rrset.h
index eb8fa6ed0c..c474ac6427 100644
--- a/src/lib/dns/rrset.h
+++ b/src/lib/dns/rrset.h
@@ -20,7 +20,7 @@
#include <boost/shared_ptr.hpp>
-#include <exceptions/exceptions.h>
+#include <dns/exceptions.h>
#include <dns/rdata.h>
#include <dns/rrtype.h>
@@ -36,10 +36,10 @@ namespace dns {
/// \brief A standard DNS module exception that is thrown if an RRset object
/// does not contain any RDATA where required.
///
-class EmptyRRset : public Exception {
+class EmptyRRset : public isc::dns::Exception {
public:
EmptyRRset(const char* file, size_t line, const char* what) :
- isc::Exception(file, line, what) {}
+ isc::dns::Exception(file, line, what) {}
};
// forward declarations
@@ -206,6 +206,20 @@ public:
/// \return The number of \c Rdata objects contained.
virtual unsigned int getRdataCount() const = 0;
+ /// \brief Get the wire format length of the \c AbstractRRset.
+ ///
+ /// This method returns the wire format length of the
+ /// \c AbstractRRset, which is calculated by summing the individual
+ /// lengths of the various fields that make up each RR.
+ ///
+ /// NOTE: When including name lengths, the allocation for
+ /// uncompressed name wire format representation is used.
+ ///
+ /// \return The length of the wire format representation of the
+ /// \c AbstractRRset.
+ /// \throw \c EmptyRRset if the \c AbstractRRset is empty.
+ virtual uint16_t getLength() const = 0;
+
/// \brief Returns the owner name of the \c RRset.
///
/// \return A reference to a \c Name class object corresponding to the
@@ -376,10 +390,27 @@ public:
/// Still, this version would offer a more intuitive interface and is
/// provided as such.
///
+ /// NOTE: Because a new Rdata object is constructed, this method can
+ /// throw a std::bad_cast exception if this RRset's class is NONE,
+ /// or if some other error occurs. If you want to be able to add
+ /// RDATA to an RRset whose class is NONE, please use the other
+ /// variant of \c addRdata() which accepts a \c ConstRdataPtr
+ /// argument.
+ ///
/// \param rdata A reference to a \c rdata::RdataPtr (derived) class
/// object, a copy of which is to be added to the \c RRset.
virtual void addRdata(const rdata::Rdata& rdata) = 0;
+ /// \brief Add an RDATA to the RRset (string version).
+ ///
+ /// This method constructs an Rdata object from the the given
+ /// \c rdata_str in presentation format and adds it to the \c RRset.
+ ///
+ /// \param rdata_str RDATA string in presentation format.
+ /// \throw InvalidRdataText if the \c rdata_str is invalid for this
+ /// \c RRset.
+ virtual void addRdata(const std::string& rdata_str) = 0;
+
/// \brief Return an iterator to go through all RDATA stored in the
/// \c RRset.
///
@@ -642,6 +673,13 @@ public:
/// \return The number of \c Rdata objects contained.
virtual unsigned int getRdataCount() const;
+ /// \brief Get the wire format length of the \c BasicRRset.
+ ///
+ /// \return The length of the wire format representation of the
+ /// \c BasicRRset.
+ /// \throw \c EmptyRRset if the \c BasicRRset is empty.
+ virtual uint16_t getLength() const;
+
/// \brief Returns the owner name of the \c RRset.
///
/// This method never throws an exception.
@@ -727,6 +765,13 @@ public:
/// See \c AbstractRRset::addRdata(const rdata::Rdata&).
virtual void addRdata(const rdata::Rdata& rdata);
+ /// \brief Add an RDATA to the RRset (string version).
+ ///
+ /// \param rdata_str RDATA string in presentation format.
+ /// \throw InvalidRdataText if the \c rdata_str is invalid for this
+ /// \c RRset.
+ virtual void addRdata(const std::string& rdata_str);
+
/// \brief Return an iterator to go through all RDATA stored in the
/// \c BasicRRset.
///
@@ -813,6 +858,13 @@ public:
virtual ~RRset();
+ /// \brief Get the wire format length of the \c RRset.
+ ///
+ /// \return The length of the wire format representation of the
+ /// \c RRset.
+ /// \throw \c EmptyRRset if the \c RRset is empty.
+ virtual uint16_t getLength() const;
+
/// \brief Render the RRset in the wire format with name compression and
/// truncation handling.
///
diff --git a/src/lib/dns/rrttl.cc b/src/lib/dns/rrttl.cc
index 73ac2599de..e6ce007bac 100644
--- a/src/lib/dns/rrttl.cc
+++ b/src/lib/dns/rrttl.cc
@@ -42,14 +42,15 @@ myIsalpha(char c) {
struct Unit {
char unit;
uint32_t multiply;
+ uint32_t max_allowed;
};
Unit units[] = {
- { 'S', 1 },
- { 'M', 60 },
- { 'H', 60 * 60 },
- { 'D', 24 * 60 * 60 },
- { 'W', 7 * 24 * 60 * 60 }
+ { 'S', 1, 0xffffffff / 1 },
+ { 'M', 60, 0xffffffff / 60 },
+ { 'H', 60 * 60, 0xffffffff / (60 * 60) },
+ { 'D', 24 * 60 * 60, 0xffffffff / (24 * 60 * 60) },
+ { 'W', 7 * 24 * 60 * 60, 0xffffffff / (7 * 24 * 60 * 60) }
};
}
@@ -66,11 +67,9 @@ parseTTLString(const string& ttlstr, uint32_t& ttlval, string* error_txt) {
}
return (false);
}
- // We use a larger data type during the computation. This is because
- // some compilers don't fail when out of range, so we check the range
- // ourselves later.
- int64_t val = 0;
+ // We use a larger data type to handle negative number cases.
+ uint64_t val = 0;
const string::const_iterator end = ttlstr.end();
string::const_iterator pos = ttlstr.begin();
@@ -92,7 +91,7 @@ parseTTLString(const string& ttlstr, uint32_t& ttlval, string* error_txt) {
} else {
// Case without any units at all. Just convert and store
// it.
- val = boost::lexical_cast<int64_t>(ttlstr);
+ val = boost::lexical_cast<uint64_t>(ttlstr);
break;
}
}
@@ -100,11 +99,13 @@ parseTTLString(const string& ttlstr, uint32_t& ttlval, string* error_txt) {
units_mode = true;
// Find the unit and get the size.
uint32_t multiply = 1; // initialize to silence compiler warnings
+ uint32_t max_allowed = 0xffffffff;
bool found = false;
for (size_t i = 0; i < sizeof(units) / sizeof(*units); ++i) {
if (toupper(*unit) == units[i].unit) {
found = true;
multiply = units[i].multiply;
+ max_allowed = units[i].max_allowed;
break;
}
}
@@ -122,15 +123,25 @@ parseTTLString(const string& ttlstr, uint32_t& ttlval, string* error_txt) {
}
return (false);
}
- const int64_t value = boost::lexical_cast<int64_t>(string(pos,
- unit));
+ const uint64_t value =
+ boost::lexical_cast<uint64_t>(string(pos, unit));
+ if (value > max_allowed) {
+ if (error_txt != NULL) {
+ *error_txt = "Part of TTL out of range: " + ttlstr;
+ }
+ return (false);
+ }
+
+ // seconds cannot be out of range at this point.
+ const uint64_t seconds = value * multiply;
+ assert(seconds <= 0xffffffff);
+
// Add what we found
- val += multiply * value;
+ val += seconds;
// Check the partial value is still in range (the value can only
// grow, so if we get out of range now, it won't get better, so
// there's no need to continue).
- if (value < 0 || value > 0xffffffff || val < 0 ||
- val > 0xffffffff) {
+ if (val < seconds || val > 0xffffffff) {
if (error_txt != NULL) {
*error_txt = "Part of TTL out of range: " + ttlstr;
}
@@ -146,9 +157,10 @@ parseTTLString(const string& ttlstr, uint32_t& ttlval, string* error_txt) {
return (false);
}
- if (val >= 0 && val <= 0xffffffff) {
+ if (val <= 0xffffffff) {
ttlval = val;
} else {
+ // This could be due to negative numbers in input, etc.
if (error_txt != NULL) {
*error_txt = "TTL out of range: " + ttlstr;
}
diff --git a/src/lib/dns/rrttl.h b/src/lib/dns/rrttl.h
index 35403b6294..ffa3467970 100644
--- a/src/lib/dns/rrttl.h
+++ b/src/lib/dns/rrttl.h
@@ -15,7 +15,7 @@
#ifndef RRTTL_H
#define RRTTL_H 1
-#include <exceptions/exceptions.h>
+#include <dns/exceptions.h>
#include <boost/optional.hpp>
@@ -36,20 +36,20 @@ class AbstractMessageRenderer;
/// \brief A standard DNS module exception that is thrown if an RRTTL object
/// is being constructed from an unrecognized string.
///
-class InvalidRRTTL : public Exception {
+class InvalidRRTTL : public DNSTextError {
public:
InvalidRRTTL(const char* file, size_t line, const char* what) :
- isc::Exception(file, line, what) {}
+ DNSTextError(file, line, what) {}
};
///
/// \brief A standard DNS module exception that is thrown if an RRTTL object
/// is being constructed from a incomplete (too short) wire-format data.
///
-class IncompleteRRTTL : public Exception {
+class IncompleteRRTTL : public isc::dns::Exception {
public:
IncompleteRRTTL(const char* file, size_t line, const char* what) :
- isc::Exception(file, line, what) {}
+ isc::dns::Exception(file, line, what) {}
};
///
diff --git a/src/lib/dns/rrtype-placeholder.h b/src/lib/dns/rrtype-placeholder.h
index 5541635caa..46167e45dc 100644
--- a/src/lib/dns/rrtype-placeholder.h
+++ b/src/lib/dns/rrtype-placeholder.h
@@ -20,7 +20,7 @@
#include <string>
#include <ostream>
-#include <exceptions/exceptions.h>
+#include <dns/exceptions.h>
// Solaris x86 defines DS in <sys/regset.h>, which gets pulled in by Boost
#if defined(__sun) && defined(DS)
@@ -42,20 +42,20 @@ class AbstractMessageRenderer;
/// \brief A standard DNS module exception that is thrown if an RRType object
/// is being constructed from an unrecognized string.
///
-class InvalidRRType : public Exception {
+class InvalidRRType : public DNSTextError {
public:
InvalidRRType(const char* file, size_t line, const char* what) :
- isc::Exception(file, line, what) {}
+ DNSTextError(file, line, what) {}
};
///
/// \brief A standard DNS module exception that is thrown if an RRType object
/// is being constructed from a incomplete (too short) wire-format data.
///
-class IncompleteRRType : public Exception {
+class IncompleteRRType : public isc::dns::Exception {
public:
IncompleteRRType(const char* file, size_t line, const char* what) :
- isc::Exception(file, line, what) {}
+ isc::dns::Exception(file, line, what) {}
};
///
diff --git a/src/lib/dns/tests/Makefile.am b/src/lib/dns/tests/Makefile.am
index 5029681a32..415700a5f1 100644
--- a/src/lib/dns/tests/Makefile.am
+++ b/src/lib/dns/tests/Makefile.am
@@ -21,6 +21,7 @@ TESTS =
if HAVE_GTEST
TESTS += run_unittests
run_unittests_SOURCES = unittest_util.h unittest_util.cc
+run_unittests_SOURCES += dns_exceptions_unittest.cc
run_unittests_SOURCES += edns_unittest.cc
run_unittests_SOURCES += master_lexer_inputsource_unittest.cc
run_unittests_SOURCES += labelsequence_unittest.cc
@@ -38,7 +39,9 @@ run_unittests_SOURCES += opcode_unittest.cc
run_unittests_SOURCES += rcode_unittest.cc
run_unittests_SOURCES += rdata_unittest.h rdata_unittest.cc
run_unittests_SOURCES += rdatafields_unittest.cc
+run_unittests_SOURCES += rdata_pimpl_holder_unittest.cc
run_unittests_SOURCES += rdata_char_string_unittest.cc
+run_unittests_SOURCES += rdata_char_string_data_unittest.cc
run_unittests_SOURCES += rdata_in_a_unittest.cc rdata_in_aaaa_unittest.cc
run_unittests_SOURCES += rdata_ns_unittest.cc rdata_soa_unittest.cc
run_unittests_SOURCES += rdata_txt_like_unittest.cc
@@ -59,10 +62,12 @@ run_unittests_SOURCES += rdata_nsec3param_like_unittest.cc
run_unittests_SOURCES += rdata_rrsig_unittest.cc
run_unittests_SOURCES += rdata_rp_unittest.cc
run_unittests_SOURCES += rdata_srv_unittest.cc
+run_unittests_SOURCES += rdata_tlsa_unittest.cc
run_unittests_SOURCES += rdata_minfo_unittest.cc
run_unittests_SOURCES += rdata_tsig_unittest.cc
run_unittests_SOURCES += rdata_naptr_unittest.cc
run_unittests_SOURCES += rdata_hinfo_unittest.cc
+run_unittests_SOURCES += rdata_caa_unittest.cc
run_unittests_SOURCES += rrset_unittest.cc
run_unittests_SOURCES += question_unittest.cc
run_unittests_SOURCES += rrparamregistry_unittest.cc
diff --git a/src/lib/dns/tests/dns_exceptions_unittest.cc b/src/lib/dns/tests/dns_exceptions_unittest.cc
new file mode 100644
index 0000000000..905e2caa76
--- /dev/null
+++ b/src/lib/dns/tests/dns_exceptions_unittest.cc
@@ -0,0 +1,69 @@
+// Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or 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 ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS. IN NO EVENT SHALL ISC 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.
+
+#include <dns/exceptions.h>
+
+#include <gtest/gtest.h>
+
+namespace { // begin unnamed namespace
+
+TEST(DNSExceptionsTest, checkExceptionsHierarchy) {
+ EXPECT_NO_THROW({
+ const isc::dns::Exception exception("", 0, "");
+ const isc::Exception& exception_cast =
+ dynamic_cast<const isc::Exception&>(exception);
+ // to avoid compiler warning
+ exception_cast.what();
+ });
+
+ EXPECT_NO_THROW({
+ const isc::dns::DNSTextError exception("", 0, "");
+ const isc::dns::Exception& exception_cast =
+ dynamic_cast<const isc::dns::Exception&>(exception);
+ // to avoid compiler warning
+ exception_cast.what();
+ });
+
+ EXPECT_NO_THROW({
+ const isc::dns::NameParserException exception("", 0, "");
+ const isc::dns::DNSTextError& exception_cast =
+ dynamic_cast<const isc::dns::DNSTextError&>(exception);
+ // to avoid compiler warning
+ exception_cast.what();
+ });
+
+ EXPECT_NO_THROW({
+ const isc::dns::DNSMessageFORMERR exception("", 0, "");
+ const isc::dns::DNSProtocolError& exception_cast =
+ dynamic_cast<const isc::dns::DNSProtocolError&>(exception);
+ const isc::dns::Exception& exception_cast2 =
+ dynamic_cast<const isc::dns::Exception&>(exception);
+ // to avoid compiler warning
+ exception_cast.what();
+ exception_cast2.what();
+ });
+
+ EXPECT_NO_THROW({
+ const isc::dns::DNSMessageBADVERS exception("", 0, "");
+ const isc::dns::DNSProtocolError& exception_cast =
+ dynamic_cast<const isc::dns::DNSProtocolError&>(exception);
+ const isc::dns::Exception& exception_cast2 =
+ dynamic_cast<const isc::dns::Exception&>(exception);
+ // to avoid compiler warning
+ exception_cast.what();
+ exception_cast2.what();
+ });
+}
+
+} // end unnamed namespace
diff --git a/src/lib/dns/tests/edns_unittest.cc b/src/lib/dns/tests/edns_unittest.cc
index de2d2447dd..3fffc6ff4f 100644
--- a/src/lib/dns/tests/edns_unittest.cc
+++ b/src/lib/dns/tests/edns_unittest.cc
@@ -31,12 +31,14 @@
#include <gtest/gtest.h>
#include <dns/tests/unittest_util.h>
+#include <util/unittests/wiredata.h>
-using isc::UnitTestUtil;
using namespace std;
using namespace isc::dns;
using namespace isc::util;
using namespace isc::dns::rdata;
+using isc::UnitTestUtil;
+using isc::util::unittests::matchWireData;
const uint8_t EDNS::SUPPORTED_VERSION;
@@ -159,8 +161,8 @@ TEST_F(EDNSTest, toWireRenderer) {
EXPECT_EQ(1, edns_base.toWire(renderer,
Rcode::NOERROR().getExtendedCode()));
UnitTestUtil::readWireData("edns_toWire1.wire", wiredata);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, renderer.getData(),
- renderer.getLength(), &wiredata[0], wiredata.size());
+ matchWireData(&wiredata[0], wiredata.size(),
+ renderer.getData(), renderer.getLength());
// Typical case, enabling DNSSEC
renderer.clear();
@@ -169,8 +171,8 @@ TEST_F(EDNSTest, toWireRenderer) {
EXPECT_EQ(1, edns_base.toWire(renderer,
Rcode::NOERROR().getExtendedCode()));
UnitTestUtil::readWireData("edns_toWire2.wire", wiredata);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, renderer.getData(),
- renderer.getLength(), &wiredata[0], wiredata.size());
+ matchWireData(&wiredata[0], wiredata.size(),
+ renderer.getData(), renderer.getLength());
// Non-0 extended Rcode
renderer.clear();
@@ -179,8 +181,8 @@ TEST_F(EDNSTest, toWireRenderer) {
EXPECT_EQ(1, edns_base.toWire(renderer,
Rcode::BADVERS().getExtendedCode()));
UnitTestUtil::readWireData("edns_toWire3.wire", wiredata);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, renderer.getData(),
- renderer.getLength(), &wiredata[0], wiredata.size());
+ matchWireData(&wiredata[0], wiredata.size(),
+ renderer.getData(), renderer.getLength());
// Uncommon UDP buffer size
renderer.clear();
@@ -190,8 +192,8 @@ TEST_F(EDNSTest, toWireRenderer) {
EXPECT_EQ(1, edns_base.toWire(renderer,
Rcode::NOERROR().getExtendedCode()));
UnitTestUtil::readWireData("edns_toWire4.wire", wiredata);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, renderer.getData(),
- renderer.getLength(), &wiredata[0], wiredata.size());
+ matchWireData(&wiredata[0], wiredata.size(),
+ renderer.getData(), renderer.getLength());
// From RR with unknown flag. If used for toWire(), the unknown flag
// should disappear.
@@ -201,8 +203,8 @@ TEST_F(EDNSTest, toWireRenderer) {
*opt_rdata).toWire(renderer,
Rcode::NOERROR().getExtendedCode()));
UnitTestUtil::readWireData("edns_toWire2.wire", wiredata);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, renderer.getData(),
- renderer.getLength(), &wiredata[0], wiredata.size());
+ matchWireData(&wiredata[0], wiredata.size(),
+ renderer.getData(), renderer.getLength());
// If the available length in the renderer is not sufficient for the OPT
// RR, it shouldn't be inserted.
@@ -222,8 +224,8 @@ TEST_F(EDNSTest, toWireBuffer) {
EXPECT_EQ(1, edns_base.toWire(obuffer,
Rcode::NOERROR().getExtendedCode()));
UnitTestUtil::readWireData("edns_toWire1.wire", wiredata);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, obuffer.getData(),
- obuffer.getLength(), &wiredata[0], wiredata.size());
+ matchWireData(&wiredata[0], wiredata.size(),
+ obuffer.getData(), obuffer.getLength());
}
TEST_F(EDNSTest, createFromRR) {
diff --git a/src/lib/dns/tests/labelsequence_unittest.cc b/src/lib/dns/tests/labelsequence_unittest.cc
index a3ac767b4f..c211a4b897 100644
--- a/src/lib/dns/tests/labelsequence_unittest.cc
+++ b/src/lib/dns/tests/labelsequence_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2012-2014 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
@@ -12,6 +12,8 @@
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
+#include <config.h>
+
#include <util/buffer.h>
#include <dns/labelsequence.h>
@@ -853,6 +855,10 @@ TEST_F(LabelSequenceTest, serialize) {
isc::BadValue);
}
+#ifdef ENABLE_DEBUG
+
+// These checks are enabled only in debug mode in the LabelSequence
+// class.
TEST_F(LabelSequenceTest, badDeserialize) {
EXPECT_THROW(LabelSequence(NULL), isc::BadValue);
const uint8_t zero_offsets[] = { 0 };
@@ -879,6 +885,8 @@ TEST_F(LabelSequenceTest, badDeserialize) {
EXPECT_THROW(LabelSequence ls(offsets_noincrease), isc::BadValue);
}
+#endif
+
namespace {
// Helper function; repeatedly calls
diff --git a/src/lib/dns/tests/master_loader_unittest.cc b/src/lib/dns/tests/master_loader_unittest.cc
index 4caa3a1988..09fc3529ac 100644
--- a/src/lib/dns/tests/master_loader_unittest.cc
+++ b/src/lib/dns/tests/master_loader_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2012-2014 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
@@ -123,7 +123,9 @@ public:
EXPECT_EQ(rrttl, current->getTTL());
ASSERT_EQ(1, current->getRdataCount());
EXPECT_EQ(0, isc::dns::rdata::createRdata(type, RRClass::IN(), data)->
- compare(current->getRdataIterator()->getCurrent()));
+ compare(current->getRdataIterator()->getCurrent()))
+ << data << " vs. "
+ << current->getRdataIterator()->getCurrent().toText();
}
void checkBasicRRs() {
@@ -307,6 +309,481 @@ TEST_F(MasterLoaderTest, origin) {
}
}
+TEST_F(MasterLoaderTest, generate) {
+ // Various forms of the directive
+ const char* generates[] = {
+ "$generate",
+ "$GENERATE",
+ "$Generate",
+ "$GeneratE",
+ "\"$GENERATE\"",
+ NULL
+ };
+ for (const char** generate = generates; *generate != NULL; ++generate) {
+ SCOPED_TRACE(*generate);
+
+ clear();
+ const string directive = *generate;
+ const string input =
+ "$ORIGIN example.org.\n"
+ "before.example.org. 3600 IN A 192.0.2.0\n" +
+ directive + " 3-5 host$ A 192.0.2.$\n" +
+ "after.example.org. 3600 IN A 192.0.2.255\n";
+ stringstream ss(input);
+ setLoader(ss, Name("example.org."), RRClass::IN(),
+ MasterLoader::MANY_ERRORS);
+
+ loader_->load();
+ EXPECT_TRUE(loader_->loadedSucessfully());
+ EXPECT_TRUE(errors_.empty());
+
+ // The "before" and "after" scaffolding below checks that no
+ // extra records are added by $GENERATE outside the requested
+ // range.
+ checkRR("before.example.org", RRType::A(), "192.0.2.0");
+ checkRR("host3.example.org", RRType::A(), "192.0.2.3");
+ checkRR("host4.example.org", RRType::A(), "192.0.2.4");
+ checkRR("host5.example.org", RRType::A(), "192.0.2.5");
+ checkRR("after.example.org", RRType::A(), "192.0.2.255");
+ }
+}
+
+TEST_F(MasterLoaderTest, generateRelativeLHS) {
+ const string input =
+ "$ORIGIN example.org.\n"
+ "$GENERATE 1-2 @ 3600 NS ns$.example.org.\n";
+ stringstream ss(input);
+ setLoader(ss, Name("example.org."), RRClass::IN(),
+ MasterLoader::MANY_ERRORS);
+
+ loader_->load();
+ EXPECT_TRUE(loader_->loadedSucessfully());
+ EXPECT_TRUE(errors_.empty());
+
+ checkRR("example.org", RRType::NS(), "ns1.example.org.");
+ checkRR("example.org", RRType::NS(), "ns2.example.org.");
+}
+
+TEST_F(MasterLoaderTest, generateInFront) {
+ // $ is in the front
+ const string input =
+ "$ORIGIN example.org.\n"
+ "$GENERATE 9-10 $host 3600 TXT \"$ pomegranate\"\n";
+ stringstream ss(input);
+ setLoader(ss, Name("example.org."), RRClass::IN(),
+ MasterLoader::MANY_ERRORS);
+
+ loader_->load();
+ EXPECT_TRUE(loader_->loadedSucessfully());
+ EXPECT_TRUE(errors_.empty());
+
+ checkRR("9host.example.org", RRType::TXT(), "9 pomegranate");
+ checkRR("10host.example.org", RRType::TXT(), "10 pomegranate");
+}
+
+TEST_F(MasterLoaderTest, generateInMiddle) {
+ // $ is in the middle
+ const string input =
+ "$ORIGIN example.org.\n"
+ "$GENERATE 9-10 num$-host 3600 TXT \"This is $ pomegranate\"\n";
+ stringstream ss(input);
+ setLoader(ss, Name("example.org."), RRClass::IN(),
+ MasterLoader::MANY_ERRORS);
+
+ loader_->load();
+ EXPECT_TRUE(loader_->loadedSucessfully());
+ EXPECT_TRUE(errors_.empty());
+
+ checkRR("num9-host.example.org", RRType::TXT(), "This is 9 pomegranate");
+ checkRR("num10-host.example.org", RRType::TXT(), "This is 10 pomegranate");
+}
+
+TEST_F(MasterLoaderTest, generateAtEnd) {
+ // $ is at the end
+ const string input =
+ "$ORIGIN example.org.\n"
+ "$GENERATE 9-10 num$-host 3600 TXT Pomegranate$\n";
+ stringstream ss(input);
+ setLoader(ss, Name("example.org."), RRClass::IN(),
+ MasterLoader::MANY_ERRORS);
+
+ loader_->load();
+ EXPECT_TRUE(loader_->loadedSucessfully());
+ EXPECT_TRUE(errors_.empty());
+
+ checkRR("num9-host.example.org", RRType::TXT(), "Pomegranate9");
+ checkRR("num10-host.example.org", RRType::TXT(), "Pomegranate10");
+}
+
+TEST_F(MasterLoaderTest, generateStripsQuotes) {
+ const string input =
+ "$ORIGIN example.org.\n"
+ "$GENERATE 1-2 @ 3600 MX \"$ mx$.example.org.\"\n";
+ stringstream ss(input);
+ setLoader(ss, Name("example.org."), RRClass::IN(),
+ MasterLoader::MANY_ERRORS);
+
+ loader_->load();
+ EXPECT_TRUE(loader_->loadedSucessfully());
+ EXPECT_TRUE(errors_.empty());
+
+ checkRR("example.org", RRType::MX(), "1 mx1.example.org.");
+ checkRR("example.org", RRType::MX(), "2 mx2.example.org.");
+}
+
+TEST_F(MasterLoaderTest, generateWithDoublePlaceholder) {
+ const string input =
+ "$ORIGIN example.org.\n"
+ "$GENERATE 9-10 host$ 3600 TXT \"This is $$ pomegranate\"\n";
+ stringstream ss(input);
+ setLoader(ss, Name("example.org."), RRClass::IN(),
+ MasterLoader::MANY_ERRORS);
+
+ loader_->load();
+ EXPECT_TRUE(loader_->loadedSucessfully());
+ EXPECT_TRUE(errors_.empty());
+
+ checkRR("host9.example.org", RRType::TXT(), "This is $ pomegranate");
+ checkRR("host10.example.org", RRType::TXT(), "This is $ pomegranate");
+}
+
+TEST_F(MasterLoaderTest, generateWithEscape) {
+ const string input =
+ "$ORIGIN example.org.\n"
+ "$GENERATE 9-10 host$ 3600 TXT \"This is \\$\\pomegranate\"\n";
+ stringstream ss(input);
+ setLoader(ss, Name("example.org."), RRClass::IN(),
+ MasterLoader::MANY_ERRORS);
+
+ loader_->load();
+ EXPECT_TRUE(loader_->loadedSucessfully());
+ EXPECT_TRUE(errors_.empty());
+
+ checkRR("host9.example.org", RRType::TXT(), "This is \\$\\pomegranate");
+ checkRR("host10.example.org", RRType::TXT(), "This is \\$\\pomegranate");
+}
+
+TEST_F(MasterLoaderTest, generateWithParams) {
+ const string input =
+ "$ORIGIN example.org.\n"
+ "$TTL 3600\n"
+ "$GENERATE 2-3 host$ A 192.0.2.$\n"
+ "$GENERATE 5-6 host$ 3600 A 192.0.2.$\n"
+ "$GENERATE 8-9 host$ IN A 192.0.2.$\n"
+ "$GENERATE 11-12 host$ IN 3600 A 192.0.2.$\n"
+ "$GENERATE 14-15 host$ 3600 IN A 192.0.2.$\n";
+ stringstream ss(input);
+ setLoader(ss, Name("example.org."), RRClass::IN(),
+ MasterLoader::MANY_ERRORS);
+
+ loader_->load();
+ EXPECT_TRUE(loader_->loadedSucessfully());
+ EXPECT_TRUE(errors_.empty());
+
+ checkRR("host2.example.org", RRType::A(), "192.0.2.2");
+ checkRR("host3.example.org", RRType::A(), "192.0.2.3");
+
+ checkRR("host5.example.org", RRType::A(), "192.0.2.5");
+ checkRR("host6.example.org", RRType::A(), "192.0.2.6");
+
+ checkRR("host8.example.org", RRType::A(), "192.0.2.8");
+ checkRR("host9.example.org", RRType::A(), "192.0.2.9");
+
+ checkRR("host11.example.org", RRType::A(), "192.0.2.11");
+ checkRR("host12.example.org", RRType::A(), "192.0.2.12");
+
+ checkRR("host14.example.org", RRType::A(), "192.0.2.14");
+ checkRR("host15.example.org", RRType::A(), "192.0.2.15");
+}
+
+TEST_F(MasterLoaderTest, generateWithStep) {
+ const string input =
+ "$ORIGIN example.org.\n"
+ "$GENERATE 2-9/2 host$ 3600 A 192.0.2.$\n"
+ "$GENERATE 12-21/3 host$ 3600 A 192.0.2.$\n"
+ "$GENERATE 30-31/1 host$ 3600 A 192.0.2.$\n";
+ stringstream ss(input);
+ setLoader(ss, Name("example.org."), RRClass::IN(),
+ MasterLoader::MANY_ERRORS);
+
+ loader_->load();
+ EXPECT_TRUE(loader_->loadedSucessfully());
+ EXPECT_TRUE(errors_.empty());
+
+ checkRR("host2.example.org", RRType::A(), "192.0.2.2");
+ checkRR("host4.example.org", RRType::A(), "192.0.2.4");
+ checkRR("host6.example.org", RRType::A(), "192.0.2.6");
+ checkRR("host8.example.org", RRType::A(), "192.0.2.8");
+
+ checkRR("host12.example.org", RRType::A(), "192.0.2.12");
+ checkRR("host15.example.org", RRType::A(), "192.0.2.15");
+ checkRR("host18.example.org", RRType::A(), "192.0.2.18");
+ checkRR("host21.example.org", RRType::A(), "192.0.2.21");
+
+ checkRR("host30.example.org", RRType::A(), "192.0.2.30");
+ checkRR("host31.example.org", RRType::A(), "192.0.2.31");
+}
+
+TEST_F(MasterLoaderTest, generateWithModifiers) {
+ const string input =
+ "$ORIGIN example.org.\n"
+ "$TTL 3600\n"
+
+ // Use a positive delta of 1 in the LHS and a negative delta of
+ // -1 in the RHS
+ "$GENERATE 2-9/2 host${1} A 192.0.2.${-1}\n"
+
+ "$GENERATE 10-12 host${0,4} A 192.0.2.$\n"
+ "$GENERATE 14-15 host${0,4,d} A 192.0.2.$\n"
+
+ // Names are case-insensitive, so we use TXT's RDATA to check
+ // case with hex representation.
+ "$GENERATE 30-31 host$ TXT \"Value ${0,4,x}\"\n"
+ "$GENERATE 42-43 host$ TXT \"Value ${0,4,X}\"\n"
+
+ // Octal does not use any alphabets
+ "$GENERATE 45-46 host${0,4,o} A 192.0.2.$\n"
+
+ // Here, the LHS has a trailing dot (which would result in an
+ // out-of-zone name), but that should be handled as a relative
+ // name.
+ "$GENERATE 90-92 ${0,8,n} A 192.0.2.$\n"
+
+ // Here, the LHS has no trailing dot, and results in the same
+ // number of labels as width=8 above.
+ "$GENERATE 94-96 ${0,7,n} A 192.0.2.$\n"
+
+ // Names are case-insensitive, so we use TXT's RDATA to check
+ // case with nibble representation.
+ "$GENERATE 106-107 host$ TXT \"Value ${0,9,n}\"\n"
+ "$GENERATE 109-110 host$ TXT \"Value ${0,9,N}\"\n"
+
+ // Junk type will not parse and 'd' is assumed. No error is
+ // generated (this is to match BIND 9 behavior).
+ "$GENERATE 200-201 host${0,4,j} A 192.0.2.$\n";
+ stringstream ss(input);
+ setLoader(ss, Name("example.org."), RRClass::IN(),
+ MasterLoader::MANY_ERRORS);
+
+ loader_->load();
+ EXPECT_TRUE(loader_->loadedSucessfully());
+ EXPECT_TRUE(errors_.empty());
+
+ checkRR("host3.example.org", RRType::A(), "192.0.2.1");
+ checkRR("host5.example.org", RRType::A(), "192.0.2.3");
+ checkRR("host7.example.org", RRType::A(), "192.0.2.5");
+ checkRR("host9.example.org", RRType::A(), "192.0.2.7");
+
+ checkRR("host0010.example.org", RRType::A(), "192.0.2.10");
+ checkRR("host0011.example.org", RRType::A(), "192.0.2.11");
+ checkRR("host0012.example.org", RRType::A(), "192.0.2.12");
+
+ checkRR("host0014.example.org", RRType::A(), "192.0.2.14");
+ checkRR("host0015.example.org", RRType::A(), "192.0.2.15");
+
+ checkRR("host30.example.org", RRType::TXT(), "Value 001e");
+ checkRR("host31.example.org", RRType::TXT(), "Value 001f");
+
+ checkRR("host42.example.org", RRType::TXT(), "Value 002A");
+ checkRR("host43.example.org", RRType::TXT(), "Value 002B");
+
+ checkRR("host0055.example.org", RRType::A(), "192.0.2.45");
+ checkRR("host0056.example.org", RRType::A(), "192.0.2.46");
+
+ checkRR("a.5.0.0.example.org", RRType::A(), "192.0.2.90");
+ checkRR("b.5.0.0.example.org", RRType::A(), "192.0.2.91");
+ checkRR("c.5.0.0.example.org", RRType::A(), "192.0.2.92");
+
+ checkRR("e.5.0.0.example.org", RRType::A(), "192.0.2.94");
+ checkRR("f.5.0.0.example.org", RRType::A(), "192.0.2.95");
+ checkRR("0.6.0.0.example.org", RRType::A(), "192.0.2.96");
+
+ checkRR("host106.example.org", RRType::TXT(), "Value a.6.0.0.0");
+ checkRR("host107.example.org", RRType::TXT(), "Value b.6.0.0.0");
+ checkRR("host109.example.org", RRType::TXT(), "Value D.6.0.0.0");
+ checkRR("host110.example.org", RRType::TXT(), "Value E.6.0.0.0");
+
+ checkRR("host0200.example.org", RRType::A(), "192.0.2.200");
+ checkRR("host0201.example.org", RRType::A(), "192.0.2.201");
+}
+
+TEST_F(MasterLoaderTest, generateWithNoModifiers) {
+ const string input =
+ "$ORIGIN example.org.\n"
+ "$TTL 3600\n"
+ "$GENERATE 10-12 host${} A 192.0.2.$\n";
+ stringstream ss(input);
+ setLoader(ss, Name("example.org."), RRClass::IN(),
+ MasterLoader::MANY_ERRORS);
+
+ loader_->load();
+ EXPECT_FALSE(loader_->loadedSucessfully());
+ ASSERT_EQ(2, errors_.size()); // For the broken GENERATE
+ EXPECT_TRUE(warnings_.empty());
+
+ checkCallbackMessage(errors_.at(0),
+ "Invalid $GENERATE format modifiers", 3);
+ checkCallbackMessage(errors_.at(1),
+ "$GENERATE error", 3);
+}
+
+TEST_F(MasterLoaderTest, generateWithBadModifiers) {
+ const string input =
+ "$ORIGIN example.org.\n"
+ "$TTL 3600\n"
+ "$GENERATE 10-12 host${GARBAGE} A 192.0.2.$\n";
+ stringstream ss(input);
+ setLoader(ss, Name("example.org."), RRClass::IN(),
+ MasterLoader::MANY_ERRORS);
+
+ loader_->load();
+ EXPECT_FALSE(loader_->loadedSucessfully());
+ ASSERT_EQ(2, errors_.size()); // For the broken GENERATE
+ EXPECT_TRUE(warnings_.empty());
+
+ checkCallbackMessage(errors_.at(0),
+ "Invalid $GENERATE format modifiers", 3);
+ checkCallbackMessage(errors_.at(1),
+ "$GENERATE error", 3);
+}
+
+TEST_F(MasterLoaderTest, generateMissingRange) {
+ const string input =
+ "$ORIGIN example.org.\n"
+ "$GENERATE\n";
+ stringstream ss(input);
+ setLoader(ss, Name("example.org."), RRClass::IN(),
+ MasterLoader::MANY_ERRORS);
+
+ loader_->load();
+ EXPECT_FALSE(loader_->loadedSucessfully());
+ EXPECT_EQ(1, errors_.size()); // For the broken GENERATE
+ EXPECT_TRUE(warnings_.empty());
+
+ checkCallbackMessage(errors_.at(0),
+ "unexpected end of input", 2);
+}
+
+TEST_F(MasterLoaderTest, generateMissingLHS) {
+ const string input =
+ "$ORIGIN example.org.\n"
+ "$GENERATE 2-4\n";
+ stringstream ss(input);
+ setLoader(ss, Name("example.org."), RRClass::IN(),
+ MasterLoader::MANY_ERRORS);
+
+ loader_->load();
+ EXPECT_FALSE(loader_->loadedSucessfully());
+ EXPECT_EQ(1, errors_.size()); // For the broken GENERATE
+ EXPECT_TRUE(warnings_.empty());
+
+ checkCallbackMessage(errors_.at(0),
+ "unexpected end of input", 2);
+}
+
+TEST_F(MasterLoaderTest, generateMissingType) {
+ const string input =
+ "$ORIGIN example.org.\n"
+ "$GENERATE 2-4 host$\n";
+ stringstream ss(input);
+ setLoader(ss, Name("example.org."), RRClass::IN(),
+ MasterLoader::MANY_ERRORS);
+
+ loader_->load();
+ EXPECT_FALSE(loader_->loadedSucessfully());
+ EXPECT_EQ(1, errors_.size()); // For the broken GENERATE
+ EXPECT_TRUE(warnings_.empty());
+
+ checkCallbackMessage(errors_.at(0),
+ "unexpected end of input", 2);
+}
+
+TEST_F(MasterLoaderTest, generateMissingRHS) {
+ const string input =
+ "$ORIGIN example.org.\n"
+ "$GENERATE 2-4 host$ A\n";
+ stringstream ss(input);
+ setLoader(ss, Name("example.org."), RRClass::IN(),
+ MasterLoader::MANY_ERRORS);
+
+ loader_->load();
+ EXPECT_FALSE(loader_->loadedSucessfully());
+ EXPECT_EQ(1, errors_.size()); // For the broken GENERATE
+ EXPECT_TRUE(warnings_.empty());
+
+ checkCallbackMessage(errors_.at(0),
+ "unexpected end of input", 2);
+}
+
+TEST_F(MasterLoaderTest, generateWithBadRangeSyntax) {
+ const string input =
+ "$ORIGIN example.org.\n"
+ "$GENERATE ABCD host$ 3600 A 192.0.2.$\n";
+ stringstream ss(input);
+ setLoader(ss, Name("example.org."), RRClass::IN(),
+ MasterLoader::MANY_ERRORS);
+
+ loader_->load();
+ EXPECT_FALSE(loader_->loadedSucessfully());
+ EXPECT_EQ(1, errors_.size()); // For the broken GENERATE
+ EXPECT_TRUE(warnings_.empty());
+
+ checkCallbackMessage(errors_.at(0),
+ "$GENERATE: invalid range: ABCD", 2);
+}
+
+TEST_F(MasterLoaderTest, generateWithInvalidRange) {
+ // start > stop
+ const string input =
+ "$ORIGIN example.org.\n"
+ "$GENERATE 2-1 host$ 3600 A 192.0.2.$\n";
+ stringstream ss(input);
+ setLoader(ss, Name("example.org."), RRClass::IN(),
+ MasterLoader::MANY_ERRORS);
+
+ loader_->load();
+ EXPECT_FALSE(loader_->loadedSucessfully());
+ EXPECT_EQ(1, errors_.size()); // For the broken GENERATE
+ EXPECT_TRUE(warnings_.empty());
+
+ checkCallbackMessage(errors_.at(0),
+ "$GENERATE: invalid range: 2-1", 2);
+}
+
+TEST_F(MasterLoaderTest, generateWithInvalidClass) {
+ const string input =
+ "$ORIGIN example.org.\n"
+ "$GENERATE 1-2 host$ 3600 CH A 192.0.2.$\n";
+ stringstream ss(input);
+ setLoader(ss, Name("example.org."), RRClass::IN(),
+ MasterLoader::MANY_ERRORS);
+
+ loader_->load();
+ EXPECT_FALSE(loader_->loadedSucessfully());
+ EXPECT_EQ(1, errors_.size()); // For the broken GENERATE
+ EXPECT_TRUE(warnings_.empty());
+
+ checkCallbackMessage(errors_.at(0),
+ "Class mismatch: CH vs. IN", 2);
+}
+
+TEST_F(MasterLoaderTest, generateWithNoAvailableTTL) {
+ const string input =
+ "$ORIGIN example.org.\n"
+ "$GENERATE 1-2 host$ A 192.0.2.$\n";
+ stringstream ss(input);
+ setLoader(ss, Name("example.org."), RRClass::IN(),
+ MasterLoader::MANY_ERRORS);
+
+ loader_->load();
+ EXPECT_FALSE(loader_->loadedSucessfully());
+ EXPECT_EQ(1, errors_.size()); // For the broken GENERATE
+ EXPECT_TRUE(warnings_.empty());
+
+ checkCallbackMessage(errors_.at(0),
+ "no TTL specified; load rejected", 2);
+}
+
// Test the source is correctly popped even after error
TEST_F(MasterLoaderTest, popAfterError) {
const string include_str = "$include " TEST_DATA_SRCDIR
@@ -952,4 +1429,19 @@ TEST_F(MasterLoaderTest, previousInInclude) {
checkARR("www.example.org");
}
+TEST_F(MasterLoaderTest, numericOwnerName) {
+ const string input("$ORIGIN example.org.\n"
+ "1 3600 IN A 192.0.2.1\n");
+ stringstream ss(input);
+ setLoader(ss, Name("example.org."), RRClass::IN(),
+ MasterLoader::MANY_ERRORS);
+
+ loader_->load();
+ EXPECT_TRUE(loader_->loadedSucessfully());
+ EXPECT_TRUE(errors_.empty());
+ EXPECT_TRUE(warnings_.empty());
+
+ checkRR("1.example.org", RRType::A(), "192.0.2.1");
+}
+
}
diff --git a/src/lib/dns/tests/message_unittest.cc b/src/lib/dns/tests/message_unittest.cc
index 8aaebaa183..00b8a5bd5f 100644
--- a/src/lib/dns/tests/message_unittest.cc
+++ b/src/lib/dns/tests/message_unittest.cc
@@ -41,13 +41,15 @@
#include <gtest/gtest.h>
#include <dns/tests/unittest_util.h>
+#include <util/unittests/wiredata.h>
-using isc::UnitTestUtil;
using namespace std;
using namespace isc;
using namespace isc::dns;
using namespace isc::util;
using namespace isc::dns::rdata;
+using isc::UnitTestUtil;
+using isc::util::unittests::matchWireData;
//
// Note: we need more tests, including:
@@ -217,10 +219,9 @@ TEST_F(MessageTest, fromWireWithTSIG) {
EXPECT_EQ(TSIGKey::HMACMD5_NAME(), tsig_rr->getRdata().getAlgorithm());
EXPECT_EQ(0x4da8877a, tsig_rr->getRdata().getTimeSigned());
EXPECT_EQ(TSIGContext::DEFAULT_FUDGE, tsig_rr->getRdata().getFudge());
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- tsig_rr->getRdata().getMAC(),
- tsig_rr->getRdata().getMACSize(),
- expected_mac, sizeof(expected_mac));
+ matchWireData(expected_mac, sizeof(expected_mac),
+ tsig_rr->getRdata().getMAC(),
+ tsig_rr->getRdata().getMACSize());
EXPECT_EQ(0, tsig_rr->getRdata().getError());
EXPECT_EQ(0, tsig_rr->getRdata().getOtherLen());
EXPECT_EQ(static_cast<void*>(NULL), tsig_rr->getRdata().getOtherData());
@@ -572,12 +573,10 @@ TEST_F(MessageTest, parseHeader) {
message_parse.endSection(Message::SECTION_ADDITIONAL));
}
-TEST_F(MessageTest, fromWire) {
- // fromWire() isn't allowed in the render mode.
- EXPECT_THROW(factoryFromFile(message_render, "message_fromWire1"),
- InvalidMessageOperation);
-
- factoryFromFile(message_parse, "message_fromWire1");
+void
+checkMessageFromWire(const Message& message_parse,
+ const Name& test_name)
+{
EXPECT_EQ(0x1035, message_parse.getQid());
EXPECT_EQ(Opcode::QUERY(), message_parse.getOpcode());
EXPECT_EQ(Rcode::NOERROR(), message_parse.getRcode());
@@ -608,6 +607,37 @@ TEST_F(MessageTest, fromWire) {
EXPECT_TRUE(it->isLast());
}
+
+TEST_F(MessageTest, fromWire) {
+ // fromWire() isn't allowed in the render mode.
+ EXPECT_THROW(factoryFromFile(message_render, "message_fromWire1"),
+ InvalidMessageOperation);
+
+ factoryFromFile(message_parse, "message_fromWire1");
+ checkMessageFromWire(message_parse, test_name);
+}
+
+TEST_F(MessageTest, fromWireMultiple) {
+ // Parse from wire multiple times.
+ factoryFromFile(message_parse, "message_fromWire1");
+ factoryFromFile(message_parse, "message_fromWire1");
+ factoryFromFile(message_parse, "message_fromWire1");
+ factoryFromFile(message_parse, "message_fromWire1");
+ checkMessageFromWire(message_parse, test_name);
+
+ // Calling parseHeader() directly before fromWire() should not cause
+ // any problems.
+ received_data.clear();
+ UnitTestUtil::readWireData("message_fromWire1", received_data);
+
+ InputBuffer buffer(&received_data[0], received_data.size());
+ message_parse.parseHeader(buffer);
+ message_parse.fromWire(buffer);
+ message_parse.parseHeader(buffer);
+ message_parse.fromWire(buffer);
+ checkMessageFromWire(message_parse, test_name);
+}
+
TEST_F(MessageTest, fromWireShortBuffer) {
// We trim a valid message (ending with an SOA RR) for one byte.
// fromWire() should throw an exception while parsing the trimmed RR.
@@ -729,8 +759,8 @@ TEST_F(MessageTest, toWire) {
message_render.toWire(renderer);
vector<unsigned char> data;
UnitTestUtil::readWireData("message_toWire1", data);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, renderer.getData(),
- renderer.getLength(), &data[0], data.size());
+ matchWireData(&data[0], data.size(),
+ renderer.getData(), renderer.getLength());
}
TEST_F(MessageTest, toWireSigned) {
@@ -766,8 +796,8 @@ TEST_F(MessageTest, toWireSigned) {
message_render.toWire(renderer);
vector<unsigned char> data;
UnitTestUtil::readWireData("message_toWire6", data);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, renderer.getData(),
- renderer.getLength(), &data[0], data.size());
+ matchWireData(&data[0], data.size(),
+ renderer.getData(), renderer.getLength());
}
TEST_F(MessageTest, toWireSignedAndTruncated) {
@@ -810,8 +840,8 @@ TEST_F(MessageTest, toWireSignedAndTruncated) {
message_render.toWire(renderer);
vector<unsigned char> data;
UnitTestUtil::readWireData("message_toWire7", data);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, renderer.getData(),
- renderer.getLength(), &data[0], data.size());
+ matchWireData(&data[0], data.size(),
+ renderer.getData(), renderer.getLength());
}
TEST_F(MessageTest, toWireInParseMode) {
@@ -864,12 +894,11 @@ commonTSIGToWireCheck(Message& message, MessageRenderer& renderer,
message.addRRset(Message::SECTION_ANSWER, ans_rrset);
}
- message.toWire(renderer, tsig_ctx);
+ message.toWire(renderer, &tsig_ctx);
vector<unsigned char> expected_data;
UnitTestUtil::readWireData(expected_file, expected_data);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, renderer.getData(),
- renderer.getLength(),
- &expected_data[0], expected_data.size());
+ matchWireData(&expected_data[0], expected_data.size(),
+ renderer.getData(), renderer.getLength());
}
TEST_F(MessageTest, toWireWithTSIG) {
@@ -997,7 +1026,7 @@ TEST_F(MessageTest, toWireTSIGTruncation3) {
message_render.addQuestion(Question(Name("www.example.com"),
RRClass::IN(), RRType(i)));
}
- message_render.toWire(renderer, tsig_ctx);
+ message_render.toWire(renderer, &tsig_ctx);
// Check the rendered data by parsing it. We only check it has the
// TC bit on, has the correct number of questions, and has a TSIG RR.
diff --git a/src/lib/dns/tests/messagerenderer_unittest.cc b/src/lib/dns/tests/messagerenderer_unittest.cc
index 582c164b6c..2b4da59ca1 100644
--- a/src/lib/dns/tests/messagerenderer_unittest.cc
+++ b/src/lib/dns/tests/messagerenderer_unittest.cc
@@ -19,6 +19,7 @@
#include <dns/messagerenderer.h>
#include <dns/tests/unittest_util.h>
+#include <util/unittests/wiredata.h>
#include <gtest/gtest.h>
@@ -33,6 +34,7 @@ using isc::dns::LabelSequence;
using isc::dns::MessageRenderer;
using isc::util::OutputBuffer;
using boost::lexical_cast;
+using isc::util::unittests::matchWireData;
namespace {
class MessageRendererTest : public ::testing::Test {
@@ -56,8 +58,8 @@ TEST_F(MessageRendererTest, writeIntger) {
renderer.writeUint16(data16);
expected_size += sizeof(data16);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, renderer.getData(),
- renderer.getLength(), &testdata[1], sizeof(data16));
+ matchWireData(&testdata[1], sizeof(data16),
+ renderer.getData(), renderer.getLength());
}
TEST_F(MessageRendererTest, writeName) {
@@ -65,8 +67,8 @@ TEST_F(MessageRendererTest, writeName) {
renderer.writeName(Name("a.example.com."));
renderer.writeName(Name("b.example.com."));
renderer.writeName(Name("a.example.org."));
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, renderer.getData(),
- renderer.getLength(), &data[0], data.size());
+ matchWireData(&data[0], data.size(),
+ renderer.getData(), renderer.getLength());
}
TEST_F(MessageRendererTest, writeNameInLargeBuffer) {
@@ -77,11 +79,9 @@ TEST_F(MessageRendererTest, writeNameInLargeBuffer) {
renderer.writeName(Name("a.example.com."));
renderer.writeName(Name("a.example.com."));
renderer.writeName(Name("b.example.com."));
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- static_cast<const uint8_t*>(renderer.getData()) +
- offset,
- renderer.getLength() - offset,
- &data[0], data.size());
+ matchWireData(&data[0], data.size(),
+ static_cast<const uint8_t*>(renderer.getData()) + offset,
+ renderer.getLength() - offset);
}
TEST_F(MessageRendererTest, writeNameWithUncompressed) {
@@ -89,8 +89,8 @@ TEST_F(MessageRendererTest, writeNameWithUncompressed) {
renderer.writeName(Name("a.example.com."));
renderer.writeName(Name("b.example.com."), false);
renderer.writeName(Name("b.example.com."));
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, renderer.getData(),
- renderer.getLength(), &data[0], data.size());
+ matchWireData(&data[0], data.size(),
+ renderer.getData(), renderer.getLength());
}
TEST_F(MessageRendererTest, writeNamePointerChain) {
@@ -98,8 +98,8 @@ TEST_F(MessageRendererTest, writeNamePointerChain) {
renderer.writeName(Name("a.example.com."));
renderer.writeName(Name("b.example.com."));
renderer.writeName(Name("b.example.com."));
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, renderer.getData(),
- renderer.getLength(), &data[0], data.size());
+ matchWireData(&data[0], data.size(),
+ renderer.getData(), renderer.getLength());
}
TEST_F(MessageRendererTest, compressMode) {
@@ -126,8 +126,8 @@ TEST_F(MessageRendererTest, writeNameCaseCompress) {
// this should match the first name in terms of compression:
renderer.writeName(Name("b.exAmple.CoM."));
renderer.writeName(Name("a.example.org."));
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, renderer.getData(),
- renderer.getLength(), &data[0], data.size());
+ matchWireData(&data[0], data.size(),
+ renderer.getData(), renderer.getLength());
}
TEST_F(MessageRendererTest, writeNameCaseSensitiveCompress) {
@@ -138,8 +138,8 @@ TEST_F(MessageRendererTest, writeNameCaseSensitiveCompress) {
renderer.writeName(Name("a.example.com."));
renderer.writeName(Name("b.eXample.com."));
renderer.writeName(Name("c.eXample.com."));
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, renderer.getData(),
- renderer.getLength(), &data[0], data.size());
+ matchWireData(&data[0], data.size(),
+ renderer.getData(), renderer.getLength());
}
TEST_F(MessageRendererTest, writeNameMixedCaseCompress) {
@@ -171,11 +171,10 @@ TEST_F(MessageRendererTest, writeRootName) {
renderer.writeName(Name("."));
renderer.writeName(example_name);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- static_cast<const uint8_t*>(renderer.getData()),
- renderer.getLength(),
- static_cast<const uint8_t*>(expected.getData()),
- expected.getLength());
+ matchWireData(static_cast<const uint8_t*>(expected.getData()),
+ expected.getLength(),
+ static_cast<const uint8_t*>(renderer.getData()),
+ renderer.getLength());
}
TEST_F(MessageRendererTest, writeNameLabelSequence1) {
@@ -192,8 +191,8 @@ TEST_F(MessageRendererTest, writeNameLabelSequence1) {
// example.com.
renderer.writeName(ls1);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, renderer.getData(),
- renderer.getLength(), &data[0], data.size());
+ matchWireData(&data[0], data.size(),
+ renderer.getData(), renderer.getLength());
}
TEST_F(MessageRendererTest, writeNameLabelSequence2) {
@@ -207,8 +206,8 @@ TEST_F(MessageRendererTest, writeNameLabelSequence2) {
// a.example.com (without root .)
renderer.writeName(ls1);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, renderer.getData(),
- renderer.getLength(), &data[0], data.size());
+ matchWireData(&data[0], data.size(),
+ renderer.getData(), renderer.getLength());
}
TEST_F(MessageRendererTest, writeNameLabelSequence3) {
@@ -235,8 +234,8 @@ TEST_F(MessageRendererTest, writeNameLabelSequence3) {
// example
renderer.writeName(ls1);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, renderer.getData(),
- renderer.getLength(), &data[0], data.size());
+ matchWireData(&data[0], data.size(),
+ renderer.getData(), renderer.getLength());
}
TEST_F(MessageRendererTest, setBuffer) {
diff --git a/src/lib/dns/tests/name_unittest.cc b/src/lib/dns/tests/name_unittest.cc
index 10d1e550cc..bb8320e543 100644
--- a/src/lib/dns/tests/name_unittest.cc
+++ b/src/lib/dns/tests/name_unittest.cc
@@ -25,6 +25,7 @@
#include <dns/messagerenderer.h>
#include <dns/tests/unittest_util.h>
+#include <util/unittests/wiredata.h>
#include <gtest/gtest.h>
@@ -32,6 +33,7 @@ using namespace std;
using namespace isc;
using namespace isc::dns;
using namespace isc::util;
+using isc::util::unittests::matchWireData;
//
// XXX: these are defined as class static constants, but some compilers
@@ -137,9 +139,8 @@ NameTest::compareInWireFormat(const Name& name_actual,
name_actual.toWire(buffer_actual);
name_expected.toWire(buffer_expected);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- buffer_actual.getData(), buffer_actual.getLength(),
- buffer_expected.getData(), buffer_expected.getLength());
+ matchWireData(buffer_expected.getData(), buffer_expected.getLength(),
+ buffer_actual.getData(), buffer_actual.getLength());
}
TEST_F(NameTest, nonlocalObject) {
@@ -164,6 +165,64 @@ checkBadTextName(const string& txt) {
NameParserException);
}
+TEST_F(NameTest, checkExceptionsHierarchy) {
+ EXPECT_NO_THROW({
+ const isc::dns::EmptyLabel exception("", 0, "");
+ const isc::dns::NameParserException& exception_cast =
+ dynamic_cast<const isc::dns::NameParserException&>(exception);
+ // to avoid compiler warning
+ exception_cast.what();
+ });
+
+ EXPECT_NO_THROW({
+ const isc::dns::TooLongName exception("", 0, "");
+ const isc::dns::NameParserException& exception_cast =
+ dynamic_cast<const isc::dns::NameParserException&>(exception);
+ // to avoid compiler warning
+ exception_cast.what();
+ });
+
+ EXPECT_NO_THROW({
+ const isc::dns::TooLongLabel exception("", 0, "");
+ const isc::dns::NameParserException& exception_cast =
+ dynamic_cast<const isc::dns::NameParserException&>(exception);
+ // to avoid compiler warning
+ exception_cast.what();
+ });
+
+ EXPECT_NO_THROW({
+ const isc::dns::BadLabelType exception("", 0, "");
+ const isc::dns::NameParserException& exception_cast =
+ dynamic_cast<const isc::dns::NameParserException&>(exception);
+ // to avoid compiler warning
+ exception_cast.what();
+ });
+
+ EXPECT_NO_THROW({
+ const isc::dns::BadEscape exception("", 0, "");
+ const isc::dns::NameParserException& exception_cast =
+ dynamic_cast<const isc::dns::NameParserException&>(exception);
+ // to avoid compiler warning
+ exception_cast.what();
+ });
+
+ EXPECT_NO_THROW({
+ const isc::dns::IncompleteName exception("", 0, "");
+ const isc::dns::NameParserException& exception_cast =
+ dynamic_cast<const isc::dns::NameParserException&>(exception);
+ // to avoid compiler warning
+ exception_cast.what();
+ });
+
+ EXPECT_NO_THROW({
+ const isc::dns::MissingNameOrigin exception("", 0, "");
+ const isc::dns::NameParserException& exception_cast =
+ dynamic_cast<const isc::dns::NameParserException&>(exception);
+ // to avoid compiler warning
+ exception_cast.what();
+ });
+}
+
TEST_F(NameTest, fromText) {
vector<string> strnames;
strnames.push_back("www.example.com");
@@ -454,8 +513,8 @@ TEST_F(NameTest, toWireBuffer) {
UnitTestUtil::readWireData(string("01610376697803636f6d00"), data);
Name("a.vix.com.").toWire(buffer);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, &data[0], data.size(),
- buffer.getData(), buffer.getLength());
+ matchWireData(&data[0], data.size(),
+ buffer.getData(), buffer.getLength());
}
//
@@ -468,8 +527,8 @@ TEST_F(NameTest, toWireRenderer) {
UnitTestUtil::readWireData(string("01610376697803636f6d00"), data);
Name("a.vix.com.").toWire(renderer);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, &data[0], data.size(),
- renderer.getData(), renderer.getLength());
+ matchWireData(&data[0], data.size(),
+ renderer.getData(), renderer.getLength());
}
//
@@ -628,9 +687,8 @@ TEST_F(NameTest, at) {
}
example_name.toWire(buffer_expected);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- &data[0], data.size(), buffer_expected.getData(),
- buffer_expected.getLength());
+ matchWireData(&data[0], data.size(),
+ buffer_expected.getData(), buffer_expected.getLength());
// Out-of-range access: should trigger an exception.
EXPECT_THROW(example_name.at(example_name.getLength()), OutOfRange);
diff --git a/src/lib/dns/tests/nsec3hash_unittest.cc b/src/lib/dns/tests/nsec3hash_unittest.cc
index 4ef0c7b70c..44f8096ae4 100644
--- a/src/lib/dns/tests/nsec3hash_unittest.cc
+++ b/src/lib/dns/tests/nsec3hash_unittest.cc
@@ -19,6 +19,7 @@
#include <boost/scoped_ptr.hpp>
#include <dns/nsec3hash.h>
+#include <dns/labelsequence.h>
#include <dns/rdataclass.h>
#include <util/encode/hex.h>
@@ -92,6 +93,18 @@ calculateCheck(NSEC3Hash& hash) {
// Check case-insensitiveness
EXPECT_EQ("0P9MHAVEQVM6T7VBL5LOP2U3T2RP3TOM",
hash.calculate(Name("EXAMPLE")));
+
+ // Repeat for the LabelSequence variant.
+
+ // A couple of normal cases from the RFC5155 example.
+ EXPECT_EQ("0P9MHAVEQVM6T7VBL5LOP2U3T2RP3TOM",
+ hash.calculate(LabelSequence(Name("example"))));
+ EXPECT_EQ("35MTHGPGCU1QG68FAB165KLNSNK3DPVL",
+ hash.calculate(LabelSequence(Name("a.example"))));
+
+ // Check case-insensitiveness
+ EXPECT_EQ("0P9MHAVEQVM6T7VBL5LOP2U3T2RP3TOM",
+ hash.calculate(LabelSequence(Name("EXAMPLE"))));
}
TEST_F(NSEC3HashTest, calculate) {
@@ -113,13 +126,16 @@ TEST_F(NSEC3HashTest, calculate) {
EXPECT_EQ("CK0POJMG874LJREF7EFN8430QVIT8BSM",
NSEC3HashPtr(NSEC3Hash::create(generic::NSEC3PARAM("1 0 0 -")))
->calculate(Name("com")));
+ EXPECT_EQ("CK0POJMG874LJREF7EFN8430QVIT8BSM",
+ NSEC3HashPtr(NSEC3Hash::create(generic::NSEC3PARAM("1 0 0 -")))
+ ->calculate(LabelSequence(Name("com"))));
// Using unusually large iterations, something larger than the 8-bit range.
// (expected hash value generated by BIND 9's dnssec-signzone)
EXPECT_EQ("COG6A52MJ96MNMV3QUCAGGCO0RHCC2Q3",
NSEC3HashPtr(NSEC3Hash::create(
generic::NSEC3PARAM("1 0 256 AABBCCDD")))
- ->calculate(Name("example.org")));
+ ->calculate(LabelSequence(Name("example.org"))));
}
// Common checks for match cases
@@ -169,6 +185,9 @@ class TestNSEC3Hash : public NSEC3Hash {
virtual string calculate(const Name&) const {
return ("00000000000000000000000000000000");
}
+ virtual string calculate(const LabelSequence&) const {
+ return ("00000000000000000000000000000000");
+ }
virtual bool match(const generic::NSEC3PARAM&) const {
return (true);
}
@@ -207,6 +226,8 @@ TEST_F(NSEC3HashTest, setCreator) {
// Re-check an existing case using the default creator/hash implementation
EXPECT_EQ("0P9MHAVEQVM6T7VBL5LOP2U3T2RP3TOM",
test_hash->calculate(Name("example")));
+ EXPECT_EQ("0P9MHAVEQVM6T7VBL5LOP2U3T2RP3TOM",
+ test_hash->calculate(LabelSequence(Name("example"))));
// Replace the creator, and confirm the hash values are faked
TestNSEC3HashCreator test_creator;
@@ -215,12 +236,16 @@ TEST_F(NSEC3HashTest, setCreator) {
test_hash.reset(NSEC3Hash::create(generic::NSEC3PARAM("1 0 12 aabbccdd")));
EXPECT_EQ("00000000000000000000000000000000",
test_hash->calculate(Name("example")));
+ EXPECT_EQ("00000000000000000000000000000000",
+ test_hash->calculate(LabelSequence(Name("example"))));
// Same for hash from NSEC3 RDATA
test_hash.reset(NSEC3Hash::create(generic::NSEC3
("1 0 12 aabbccdd " +
string(nsec3_common))));
EXPECT_EQ("00000000000000000000000000000000",
test_hash->calculate(Name("example")));
+ EXPECT_EQ("00000000000000000000000000000000",
+ test_hash->calculate(LabelSequence(Name("example"))));
// If we set a special flag big (0x80) on creation, it will act like the
// default creator.
@@ -228,17 +253,23 @@ TEST_F(NSEC3HashTest, setCreator) {
"1 128 12 aabbccdd")));
EXPECT_EQ("0P9MHAVEQVM6T7VBL5LOP2U3T2RP3TOM",
test_hash->calculate(Name("example")));
+ EXPECT_EQ("0P9MHAVEQVM6T7VBL5LOP2U3T2RP3TOM",
+ test_hash->calculate(LabelSequence(Name("example"))));
test_hash.reset(NSEC3Hash::create(generic::NSEC3
("1 128 12 aabbccdd " +
string(nsec3_common))));
EXPECT_EQ("0P9MHAVEQVM6T7VBL5LOP2U3T2RP3TOM",
test_hash->calculate(Name("example")));
+ EXPECT_EQ("0P9MHAVEQVM6T7VBL5LOP2U3T2RP3TOM",
+ test_hash->calculate(LabelSequence(Name("example"))));
// Reset the creator to default, and confirm that
setNSEC3HashCreator(NULL);
test_hash.reset(NSEC3Hash::create(generic::NSEC3PARAM("1 0 12 aabbccdd")));
EXPECT_EQ("0P9MHAVEQVM6T7VBL5LOP2U3T2RP3TOM",
test_hash->calculate(Name("example")));
+ EXPECT_EQ("0P9MHAVEQVM6T7VBL5LOP2U3T2RP3TOM",
+ test_hash->calculate(LabelSequence(Name("example"))));
}
} // end namespace
diff --git a/src/lib/dns/tests/question_unittest.cc b/src/lib/dns/tests/question_unittest.cc
index d1214a1238..8e1667f5c9 100644
--- a/src/lib/dns/tests/question_unittest.cc
+++ b/src/lib/dns/tests/question_unittest.cc
@@ -28,11 +28,13 @@
#include <gtest/gtest.h>
#include <dns/tests/unittest_util.h>
+#include <util/unittests/wiredata.h>
-using isc::UnitTestUtil;
using namespace std;
using namespace isc::dns;
using namespace isc::util;
+using isc::UnitTestUtil;
+using isc::util::unittests::matchWireData;
namespace {
class QuestionTest : public ::testing::Test {
@@ -100,16 +102,16 @@ TEST_F(QuestionTest, toWireBuffer) {
test_question1.toWire(obuffer);
test_question2.toWire(obuffer);
UnitTestUtil::readWireData("question_toWire1", wiredata);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, obuffer.getData(),
- obuffer.getLength(), &wiredata[0], wiredata.size());
+ matchWireData(&wiredata[0], wiredata.size(),
+ obuffer.getData(), obuffer.getLength());
}
TEST_F(QuestionTest, toWireRenderer) {
test_question1.toWire(renderer);
test_question2.toWire(renderer);
UnitTestUtil::readWireData("question_toWire2", wiredata);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, renderer.getData(),
- renderer.getLength(), &wiredata[0], wiredata.size());
+ matchWireData(&wiredata[0], wiredata.size(),
+ renderer.getData(), renderer.getLength());
}
TEST_F(QuestionTest, toWireTruncated) {
diff --git a/src/lib/dns/tests/rdata_afsdb_unittest.cc b/src/lib/dns/tests/rdata_afsdb_unittest.cc
index 9a628cd178..6e933f5d59 100644
--- a/src/lib/dns/tests/rdata_afsdb_unittest.cc
+++ b/src/lib/dns/tests/rdata_afsdb_unittest.cc
@@ -24,12 +24,14 @@
#include <dns/tests/unittest_util.h>
#include <dns/tests/rdata_unittest.h>
+#include <util/unittests/wiredata.h>
-using isc::UnitTestUtil;
using namespace std;
using namespace isc::dns;
using namespace isc::util;
using namespace isc::dns::rdata;
+using isc::UnitTestUtil;
+using isc::util::unittests::matchWireData;
const char* const afsdb_text = "1 afsdb.example.com.";
const char* const afsdb_text2 = "0 root.example.com.";
@@ -155,9 +157,8 @@ TEST_F(Rdata_AFSDB_Test, toWireBuffer) {
UnitTestUtil::readWireData("rdata_afsdb_toWire1.wire", expected_wire);
// then compare them
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- obuffer.getData(), obuffer.getLength(),
- &expected_wire[0], expected_wire.size());
+ matchWireData(&expected_wire[0], expected_wire.size(),
+ obuffer.getData(), obuffer.getLength());
// clear buffer for the next test
obuffer.clear();
@@ -170,9 +171,8 @@ TEST_F(Rdata_AFSDB_Test, toWireBuffer) {
UnitTestUtil::readWireData("rdata_afsdb_toWire2.wire", expected_wire);
// then compare them
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- obuffer.getData(), obuffer.getLength(),
- &expected_wire[0], expected_wire.size());
+ matchWireData(&expected_wire[0], expected_wire.size(),
+ obuffer.getData(), obuffer.getLength());
}
TEST_F(Rdata_AFSDB_Test, toWireRenderer) {
@@ -187,9 +187,8 @@ TEST_F(Rdata_AFSDB_Test, toWireRenderer) {
UnitTestUtil::readWireData("rdata_afsdb_toWire1.wire", expected_wire);
// then compare them
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- renderer.getData(), renderer.getLength(),
- &expected_wire[0], expected_wire.size());
+ matchWireData(&expected_wire[0], expected_wire.size(),
+ renderer.getData(), renderer.getLength());
// clear renderer for the next test
renderer.clear();
@@ -202,9 +201,8 @@ TEST_F(Rdata_AFSDB_Test, toWireRenderer) {
UnitTestUtil::readWireData("rdata_afsdb_toWire2.wire", expected_wire);
// then compare them
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- renderer.getData(), renderer.getLength(),
- &expected_wire[0], expected_wire.size());
+ matchWireData(&expected_wire[0], expected_wire.size(),
+ renderer.getData(), renderer.getLength());
}
TEST_F(Rdata_AFSDB_Test, toText) {
diff --git a/src/lib/dns/tests/rdata_caa_unittest.cc b/src/lib/dns/tests/rdata_caa_unittest.cc
new file mode 100644
index 0000000000..b88aba31e7
--- /dev/null
+++ b/src/lib/dns/tests/rdata_caa_unittest.cc
@@ -0,0 +1,327 @@
+// Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or 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 ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS. IN NO EVENT SHALL ISC 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.
+
+#include <algorithm>
+#include <string>
+
+#include <util/buffer.h>
+#include <dns/messagerenderer.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rrclass.h>
+#include <dns/rrtype.h>
+
+#include <gtest/gtest.h>
+
+#include <dns/tests/unittest_util.h>
+#include <dns/tests/rdata_unittest.h>
+#include <util/unittests/wiredata.h>
+
+#include <boost/algorithm/string.hpp>
+
+using namespace std;
+using namespace isc;
+using namespace isc::dns;
+using namespace isc::util;
+using namespace isc::dns::rdata;
+using isc::UnitTestUtil;
+using isc::util::unittests::matchWireData;
+
+namespace {
+class Rdata_CAA_Test : public RdataTest {
+protected:
+ Rdata_CAA_Test() :
+ caa_txt("0 issue \"ca.example.net\""),
+ rdata_caa(caa_txt)
+ {}
+
+ void checkFromText_None(const string& rdata_str) {
+ checkFromText<generic::CAA, isc::Exception, isc::Exception>(
+ rdata_str, rdata_caa, false, false);
+ }
+
+ void checkFromText_InvalidText(const string& rdata_str) {
+ checkFromText<generic::CAA, InvalidRdataText, InvalidRdataText>(
+ rdata_str, rdata_caa, true, true);
+ }
+
+ void checkFromText_LexerError(const string& rdata_str) {
+ checkFromText
+ <generic::CAA, InvalidRdataText, MasterLexer::LexerError>(
+ rdata_str, rdata_caa, true, true);
+ }
+
+ void checkFromText_BadString(const string& rdata_str) {
+ checkFromText
+ <generic::CAA, InvalidRdataText, isc::Exception>(
+ rdata_str, rdata_caa, true, false);
+ }
+
+ const string caa_txt;
+ const generic::CAA rdata_caa;
+};
+
+const uint8_t rdata_caa_wiredata[] = {
+ // flags
+ 0x00,
+ // tag length
+ 0x5,
+ // tag
+ 'i', 's', 's', 'u', 'e',
+ // value
+ 'c', 'a', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e',
+ '.', 'n', 'e', 't'
+};
+
+TEST_F(Rdata_CAA_Test, createFromText) {
+ // Basic test
+ checkFromText_None(caa_txt);
+
+ // With different spacing
+ checkFromText_None("0 issue \"ca.example.net\"");
+
+ // Combination of lowercase and uppercase
+ checkFromText_None("0 IssUE \"ca.example.net\"");
+
+ // string constructor throws if there's extra text,
+ // but lexer constructor doesn't
+ checkFromText_BadString(caa_txt + "\n" + caa_txt);
+
+ // Missing value field
+ EXPECT_NO_THROW(const generic::CAA rdata_caa2("0 issue"));
+}
+
+TEST_F(Rdata_CAA_Test, fields) {
+ // Some of these may not be RFC conformant, but we relax the check
+ // in our code to work with other field values that may show up in
+ // the future.
+ EXPECT_NO_THROW(const generic::CAA rdata_caa2("1 issue \"ca.example.net\""));
+ EXPECT_NO_THROW(const generic::CAA rdata_caa2("2 issue \"ca.example.net\""));
+ EXPECT_NO_THROW(const generic::CAA rdata_caa2("3 issue \"ca.example.net\""));
+ EXPECT_NO_THROW(const generic::CAA rdata_caa2("128 issue \"ca.example.net\""));
+ EXPECT_NO_THROW(const generic::CAA rdata_caa2("255 issue \"ca.example.net\""));
+
+ EXPECT_NO_THROW(const generic::CAA rdata_caa2("0 foo \"ca.example.net\""));
+ EXPECT_NO_THROW(const generic::CAA rdata_caa2("0 bar \"ca.example.net\""));
+ EXPECT_NO_THROW(const generic::CAA rdata_caa2("0 12345 \"ca.example.net\""));
+ EXPECT_NO_THROW(const generic::CAA rdata_caa2("0 w0x1y2z3 \"ca.example.net\""));
+ EXPECT_NO_THROW(const generic::CAA rdata_caa2("0 relaxed-too \"ca.example.net\""));
+ EXPECT_NO_THROW(const generic::CAA rdata_caa2("0 RELAXED.too \"ca.example.net\""));
+
+ // No value (this is redundant to the last test case in the
+ // .createFromText test
+ EXPECT_NO_THROW(const generic::CAA rdata_caa2("0 issue"));
+
+ // > 255 would be broken
+ EXPECT_THROW(const generic::CAA rdata_caa2("256 issue \"ca.example.net\""),
+ InvalidRdataText);
+
+ // Missing tag actually passes because it parses the value as tag
+ // and assumes that the value is empty instead.
+ EXPECT_NO_THROW(const generic::CAA rdata_caa2("0 \"ca.example.net\""));
+
+ // Tag is too long
+ const std::string tag(256, 'a');
+ const std::string rdata_txt("0 " + tag + " \"ca.example.net\"");
+ EXPECT_THROW(const generic::CAA rdata_caa2(rdata_txt), InvalidRdataText);
+}
+
+TEST_F(Rdata_CAA_Test, characterStringValue) {
+ const generic::CAA rdata_caa_unquoted("0 issue ca.example.net");
+ EXPECT_EQ(0, rdata_caa_unquoted.compare(rdata_caa));
+
+ const generic::CAA rdata_caa_escape_X("0 issue ca.e\\xample.net");
+ EXPECT_EQ(0, rdata_caa_escape_X.compare(rdata_caa));
+
+ const generic::CAA rdata_caa_escape_DDD("0 issue ca.e\\120ample.net");
+ EXPECT_EQ(0, rdata_caa_escape_DDD.compare(rdata_caa));
+
+ const generic::CAA rdata_caa_multiline("0 issue (\nca.example.net)");
+ EXPECT_EQ(0, rdata_caa_multiline.compare(rdata_caa));
+}
+
+TEST_F(Rdata_CAA_Test, badText) {
+ checkFromText_LexerError("0");
+ checkFromText_LexerError("ZERO issue \"ca.example.net\"");
+ EXPECT_THROW(const generic::CAA rdata_caa2(caa_txt + " extra text"),
+ InvalidRdataText);
+
+ // Yes, this is redundant to the last test cases in the .fields test
+ checkFromText_InvalidText("2345 issue \"ca.example.net\"");
+
+ // negative values are trapped in the lexer rather than the
+ // constructor
+ checkFromText_LexerError("-2 issue \"ca.example.net\"");
+}
+
+TEST_F(Rdata_CAA_Test, copyAndAssign) {
+ // Copy construct
+ generic::CAA rdata_caa2(rdata_caa);
+ EXPECT_EQ(0, rdata_caa.compare(rdata_caa2));
+
+ // Assignment, mainly to confirm it doesn't cause disruption.
+ rdata_caa2 = rdata_caa;
+ EXPECT_EQ(0, rdata_caa.compare(rdata_caa2));
+}
+
+TEST_F(Rdata_CAA_Test, createFromWire) {
+ // Basic test
+ EXPECT_EQ(0, rdata_caa.compare(
+ *rdataFactoryFromFile(RRType("CAA"), RRClass("IN"),
+ "rdata_caa_fromWire1.wire")));
+
+ // Combination of lowercase and uppercase
+ EXPECT_EQ(0, rdata_caa.compare(
+ *rdataFactoryFromFile(RRType("CAA"), RRClass("IN"),
+ "rdata_caa_fromWire2.wire")));
+
+ // Value field is empty
+ EXPECT_NO_THROW(rdataFactoryFromFile(RRType("CAA"), RRClass("IN"),
+ "rdata_caa_fromWire3.wire"));
+
+ // Tag field is empty
+ EXPECT_THROW(rdataFactoryFromFile(RRType("CAA"), RRClass("IN"),
+ "rdata_caa_fromWire4.wire"),
+ InvalidRdataText);
+
+ // Value field is shorter than rdata len
+ EXPECT_THROW(rdataFactoryFromFile(RRType("CAA"), RRClass("IN"),
+ "rdata_caa_fromWire5"),
+ InvalidBufferPosition);
+
+ // all RDATA is missing
+ EXPECT_THROW(rdataFactoryFromFile(RRType("CAA"), RRClass("IN"),
+ "rdata_caa_fromWire6"),
+ InvalidBufferPosition);
+}
+
+TEST_F(Rdata_CAA_Test, createFromParams) {
+ const generic::CAA rdata_caa2(0, "issue", "ca.example.net");
+ EXPECT_EQ(0, rdata_caa2.compare(rdata_caa));
+
+ const generic::CAA rdata_caa4(0, "issue", "ca.e\\xample.net");
+ EXPECT_EQ(0, rdata_caa4.compare(rdata_caa));
+
+ const generic::CAA rdata_caa5(0, "issue", "ca.e\\120ample.net");
+ EXPECT_EQ(0, rdata_caa5.compare(rdata_caa));
+
+ // Tag is empty
+ EXPECT_THROW(const generic::CAA rdata_caa3(0, "", "ca.example.net"),
+ isc::InvalidParameter);
+
+ // Tag is too long
+ const std::string tag(256, 'a');
+ EXPECT_THROW(const generic::CAA rdata_caa3(0, tag, "ca.example.net"),
+ isc::InvalidParameter);
+
+ // Value is too long
+ const std::string value(65536, 'a');
+ EXPECT_THROW(const generic::CAA rdata_caa3(0, "issue", value),
+ InvalidRdataLength);
+}
+
+TEST_F(Rdata_CAA_Test, toText) {
+ EXPECT_TRUE(boost::iequals(caa_txt, rdata_caa.toText()));
+
+ const string caa_txt2("1 issue \"\"");
+ const generic::CAA rdata_caa2(caa_txt2);
+ EXPECT_TRUE(boost::iequals(caa_txt2, rdata_caa2.toText()));
+}
+
+TEST_F(Rdata_CAA_Test, toWire) {
+ obuffer.clear();
+ rdata_caa.toWire(obuffer);
+
+ matchWireData(rdata_caa_wiredata, sizeof(rdata_caa_wiredata),
+ obuffer.getData(), obuffer.getLength());
+}
+
+TEST_F(Rdata_CAA_Test, compare) {
+ // Equality test is repeated from createFromWire tests above.
+ EXPECT_EQ(0, rdata_caa.compare(
+ *rdataFactoryFromFile(RRType("CAA"), RRClass("IN"),
+ "rdata_caa_fromWire1.wire")));
+
+ const generic::CAA rdata_caa2("1 issue \"ca.example.net\"");
+
+ EXPECT_EQ(1, rdata_caa2.compare(rdata_caa));
+ EXPECT_EQ(-1, rdata_caa.compare(rdata_caa2));
+}
+
+TEST_F(Rdata_CAA_Test, getFlags) {
+ EXPECT_EQ(0, rdata_caa.getFlags());
+}
+
+TEST_F(Rdata_CAA_Test, getTag) {
+ EXPECT_EQ("issue", rdata_caa.getTag());
+}
+
+TEST_F(Rdata_CAA_Test, getValue) {
+ const uint8_t value_data[] = {
+ 'c', 'a', '.',
+ 'e', 'x', 'a', 'm', 'p', 'l', 'e', '.',
+ 'n', 'e', 't'
+ };
+
+ const std::vector<uint8_t>& value = rdata_caa.getValue();
+ matchWireData(value_data, sizeof(value_data),
+ &value[0], value.size());
+}
+
+TEST_F(Rdata_CAA_Test, emptyValueFromWire) {
+ const uint8_t rdf_wiredata[] = {
+ // flags
+ 0x00,
+ // tag length
+ 0x5,
+ // tag
+ 'i', 's', 's', 'u', 'e'
+ };
+
+ const generic::CAA rdf =
+ dynamic_cast<const generic::CAA&>
+ (*rdataFactoryFromFile(RRType("CAA"), RRClass("IN"),
+ "rdata_caa_fromWire3.wire"));
+
+ EXPECT_EQ(0, rdf.getFlags());
+ EXPECT_EQ("issue", rdf.getTag());
+
+ obuffer.clear();
+ rdf.toWire(obuffer);
+
+ matchWireData(rdf_wiredata, sizeof(rdf_wiredata),
+ obuffer.getData(), obuffer.getLength());
+}
+
+TEST_F(Rdata_CAA_Test, emptyValueFromString) {
+ const generic::CAA rdata_caa2("0 issue");
+ const uint8_t rdata_caa2_wiredata[] = {
+ // flags
+ 0x00,
+ // tag length
+ 0x5,
+ // tag
+ 'i', 's', 's', 'u', 'e'
+ };
+
+ EXPECT_EQ(0, rdata_caa2.getFlags());
+ EXPECT_EQ("issue", rdata_caa2.getTag());
+
+ obuffer.clear();
+ rdata_caa2.toWire(obuffer);
+
+ matchWireData(rdata_caa2_wiredata, sizeof(rdata_caa2_wiredata),
+ obuffer.getData(), obuffer.getLength());
+}
+}
diff --git a/src/lib/dns/tests/rdata_char_string_data_unittest.cc b/src/lib/dns/tests/rdata_char_string_data_unittest.cc
new file mode 100644
index 0000000000..88a00a9b56
--- /dev/null
+++ b/src/lib/dns/tests/rdata_char_string_data_unittest.cc
@@ -0,0 +1,187 @@
+// Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or 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 ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS. IN NO EVENT SHALL ISC 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.
+
+#include <util/unittests/wiredata.h>
+
+#include <dns/exceptions.h>
+#include <dns/rdata.h>
+#include <dns/rdata/generic/detail/char_string.h>
+#include <util/buffer.h>
+
+#include <gtest/gtest.h>
+
+#include <string>
+#include <vector>
+
+using namespace isc::dns;
+using namespace isc::dns::rdata;
+using isc::dns::rdata::generic::detail::CharStringData;
+using isc::dns::rdata::generic::detail::stringToCharStringData;
+using isc::dns::rdata::generic::detail::charStringDataToString;
+using isc::dns::rdata::generic::detail::compareCharStringDatas;
+using isc::util::unittests::matchWireData;
+
+namespace {
+const uint8_t test_charstr[] = {
+ 'T', 'e', 's', 't', ' ', 'S', 't', 'r', 'i', 'n', 'g'
+};
+
+class CharStringDataTest : public ::testing::Test {
+protected:
+ CharStringDataTest() :
+ // char-string representation for test data using two types of escape
+ // ('r' = 114)
+ test_str("Test\\ St\\114ing")
+ {
+ str_region.beg = &test_str[0];
+ str_region.len = test_str.size();
+ }
+ CharStringData chstr; // place holder
+ const std::string test_str;
+ MasterToken::StringRegion str_region;
+};
+
+MasterToken::StringRegion
+createStringRegion(const std::string& str) {
+ MasterToken::StringRegion region;
+ region.beg = &str[0]; // note std ensures this works even if str is empty
+ region.len = str.size();
+ return (region);
+}
+
+TEST_F(CharStringDataTest, normalConversion) {
+ uint8_t tmp[3]; // placeholder for expected sequence
+
+ stringToCharStringData(str_region, chstr);
+ matchWireData(test_charstr, sizeof(test_charstr), &chstr[0], chstr.size());
+
+ // Empty string
+ chstr.clear();
+ stringToCharStringData(createStringRegion(""), chstr);
+ EXPECT_TRUE(chstr.empty());
+
+ // Possible largest char string
+ chstr.clear();
+ std::string long_str(255, 'x');
+ stringToCharStringData(createStringRegion(long_str), chstr);
+ std::vector<uint8_t> expected;
+ expected.insert(expected.end(), long_str.begin(), long_str.end());
+ matchWireData(&expected[0], expected.size(), &chstr[0], chstr.size());
+
+ // Escaped '\'
+ chstr.clear();
+ tmp[0] = '\\';
+ stringToCharStringData(createStringRegion("\\\\"), chstr);
+ matchWireData(tmp, 1, &chstr[0], chstr.size());
+
+ // Boundary values for \DDD
+ chstr.clear();
+ tmp[0] = 0;
+ stringToCharStringData(createStringRegion("\\000"), chstr);
+ matchWireData(tmp, 1, &chstr[0], chstr.size());
+
+ chstr.clear();
+ stringToCharStringData(createStringRegion("\\255"), chstr);
+ tmp[0] = 255;
+ matchWireData(tmp, 1, &chstr[0], chstr.size());
+
+ // Another digit follows DDD; it shouldn't cause confusion
+ chstr.clear();
+ stringToCharStringData(createStringRegion("\\2550"), chstr);
+ tmp[1] = '0';
+ matchWireData(tmp, 2, &chstr[0], chstr.size());
+}
+
+TEST_F(CharStringDataTest, badConversion) {
+ // input string ending with (non escaped) '\'
+ chstr.clear();
+ EXPECT_THROW(stringToCharStringData(createStringRegion("foo\\"), chstr),
+ InvalidRdataText);
+}
+
+TEST_F(CharStringDataTest, badDDD) {
+ // Check various type of bad form of \DDD
+
+ // Not a number
+ EXPECT_THROW(stringToCharStringData(createStringRegion("\\1a2"), chstr),
+ InvalidRdataText);
+ EXPECT_THROW(stringToCharStringData(createStringRegion("\\12a"), chstr),
+ InvalidRdataText);
+
+ // Not in the range of uint8_t
+ EXPECT_THROW(stringToCharStringData(createStringRegion("\\256"), chstr),
+ InvalidRdataText);
+
+ // Short buffer
+ EXPECT_THROW(stringToCharStringData(createStringRegion("\\42"), chstr),
+ InvalidRdataText);
+}
+
+const struct TestData {
+ const char *data;
+ const char *expected;
+} conversion_data[] = {
+ {"Test\"Test", "Test\\\"Test"},
+ {"Test;Test", "Test\\;Test"},
+ {"Test\\Test", "Test\\\\Test"},
+ {"Test\x1fTest", "Test\\031Test"},
+ {"Test ~ Test", "Test ~ Test"},
+ {"Test\x7fTest", "Test\\127Test"},
+ {NULL, NULL}
+};
+
+TEST_F(CharStringDataTest, charStringDataToString) {
+ for (const TestData* cur = conversion_data; cur->data != NULL; ++cur) {
+ uint8_t idata[32];
+ size_t length = std::strlen(cur->data);
+ ASSERT_LT(length, sizeof(idata));
+ std::memcpy(idata, cur->data, length);
+ const CharStringData test_data(idata, idata + length);
+ EXPECT_EQ(cur->expected, charStringDataToString(test_data));
+ }
+}
+
+TEST_F(CharStringDataTest, compareCharStringData) {
+ CharStringData charstr;
+ CharStringData charstr2;
+ CharStringData charstr_small1;
+ CharStringData charstr_small2;
+ CharStringData charstr_large1;
+ CharStringData charstr_large2;
+ CharStringData charstr_empty;
+
+ stringToCharStringData(createStringRegion("test string"), charstr);
+ stringToCharStringData(createStringRegion("test string"), charstr2);
+ stringToCharStringData(createStringRegion("test strin"), charstr_small1);
+ stringToCharStringData(createStringRegion("test strina"), charstr_small2);
+ stringToCharStringData(createStringRegion("test stringa"), charstr_large1);
+ stringToCharStringData(createStringRegion("test strinz"), charstr_large2);
+
+ EXPECT_EQ(0, compareCharStringDatas(charstr, charstr2));
+ EXPECT_EQ(0, compareCharStringDatas(charstr2, charstr));
+ EXPECT_EQ(1, compareCharStringDatas(charstr, charstr_small1));
+ EXPECT_EQ(1, compareCharStringDatas(charstr, charstr_small2));
+ EXPECT_EQ(-1, compareCharStringDatas(charstr, charstr_large1));
+ EXPECT_EQ(-1, compareCharStringDatas(charstr, charstr_large2));
+ EXPECT_EQ(-1, compareCharStringDatas(charstr_small1, charstr));
+ EXPECT_EQ(-1, compareCharStringDatas(charstr_small2, charstr));
+ EXPECT_EQ(1, compareCharStringDatas(charstr_large1, charstr));
+ EXPECT_EQ(1, compareCharStringDatas(charstr_large2, charstr));
+
+ EXPECT_EQ(-1, compareCharStringDatas(charstr_empty, charstr));
+ EXPECT_EQ(1, compareCharStringDatas(charstr, charstr_empty));
+ EXPECT_EQ(0, compareCharStringDatas(charstr_empty, charstr_empty));
+}
+
+} // unnamed namespace
diff --git a/src/lib/dns/tests/rdata_cname_unittest.cc b/src/lib/dns/tests/rdata_cname_unittest.cc
index 5f602f011e..6e706e0a8d 100644
--- a/src/lib/dns/tests/rdata_cname_unittest.cc
+++ b/src/lib/dns/tests/rdata_cname_unittest.cc
@@ -24,12 +24,14 @@
#include <dns/tests/unittest_util.h>
#include <dns/tests/rdata_unittest.h>
+#include <util/unittests/wiredata.h>
-using isc::UnitTestUtil;
using namespace std;
using namespace isc::dns;
using namespace isc::util;
using namespace isc::dns::rdata;
+using isc::UnitTestUtil;
+using isc::util::unittests::matchWireData;
namespace {
class Rdata_CNAME_Test : public RdataTest {
@@ -115,20 +117,18 @@ TEST_F(Rdata_CNAME_Test, createFromLexer) {
TEST_F(Rdata_CNAME_Test, toWireBuffer) {
rdata_cname.toWire(obuffer);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- obuffer.getData(), obuffer.getLength(),
- wiredata_cname, sizeof(wiredata_cname));
+ matchWireData(wiredata_cname, sizeof(wiredata_cname),
+ obuffer.getData(), obuffer.getLength());
}
TEST_F(Rdata_CNAME_Test, toWireRenderer) {
rdata_cname.toWire(renderer);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- renderer.getData(), renderer.getLength(),
- wiredata_cname, sizeof(wiredata_cname));
+ matchWireData(wiredata_cname, sizeof(wiredata_cname),
+ renderer.getData(), renderer.getLength());
+
rdata_cname2.toWire(renderer);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- renderer.getData(), renderer.getLength(),
- wiredata_cname2, sizeof(wiredata_cname2));
+ matchWireData(wiredata_cname2, sizeof(wiredata_cname2),
+ renderer.getData(), renderer.getLength());
}
TEST_F(Rdata_CNAME_Test, toText) {
diff --git a/src/lib/dns/tests/rdata_dhcid_unittest.cc b/src/lib/dns/tests/rdata_dhcid_unittest.cc
index 77baccd893..5bc1d1ef4f 100644
--- a/src/lib/dns/tests/rdata_dhcid_unittest.cc
+++ b/src/lib/dns/tests/rdata_dhcid_unittest.cc
@@ -22,14 +22,16 @@
#include <dns/tests/unittest_util.h>
#include <dns/tests/rdata_unittest.h>
+#include <util/unittests/wiredata.h>
-using isc::UnitTestUtil;
using namespace std;
using namespace isc;
using namespace isc::dns;
using namespace isc::util;
using namespace isc::util::encode;
using namespace isc::dns::rdata;
+using isc::UnitTestUtil;
+using isc::util::unittests::matchWireData;
namespace {
@@ -125,8 +127,8 @@ TEST_F(Rdata_DHCID_Test, toWireRenderer) {
vector<unsigned char> data;
UnitTestUtil::readWireData("rdata_dhcid_toWire", data);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, renderer.getData(),
- renderer.getLength(), &data[0], data.size());
+ matchWireData(&data[0], data.size(),
+ renderer.getData(), renderer.getLength());
}
TEST_F(Rdata_DHCID_Test, toWireBuffer) {
@@ -134,8 +136,8 @@ TEST_F(Rdata_DHCID_Test, toWireBuffer) {
vector<unsigned char> data;
UnitTestUtil::readWireData("rdata_dhcid_toWire", data);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, obuffer.getData(),
- obuffer.getLength(), &data[0], data.size());
+ matchWireData(&data[0], data.size(),
+ obuffer.getData(), obuffer.getLength());
}
TEST_F(Rdata_DHCID_Test, toText) {
diff --git a/src/lib/dns/tests/rdata_dname_unittest.cc b/src/lib/dns/tests/rdata_dname_unittest.cc
index 7209e36e61..9e13a168ca 100644
--- a/src/lib/dns/tests/rdata_dname_unittest.cc
+++ b/src/lib/dns/tests/rdata_dname_unittest.cc
@@ -24,12 +24,14 @@
#include <dns/tests/unittest_util.h>
#include <dns/tests/rdata_unittest.h>
+#include <util/unittests/wiredata.h>
-using isc::UnitTestUtil;
using namespace std;
using namespace isc::dns;
using namespace isc::util;
using namespace isc::dns::rdata;
+using isc::UnitTestUtil;
+using isc::util::unittests::matchWireData;
namespace {
class Rdata_DNAME_Test : public RdataTest {
@@ -117,20 +119,18 @@ TEST_F(Rdata_DNAME_Test, createFromLexer) {
TEST_F(Rdata_DNAME_Test, toWireBuffer) {
rdata_dname.toWire(obuffer);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- obuffer.getData(), obuffer.getLength(),
- wiredata_dname, sizeof(wiredata_dname));
+ matchWireData(wiredata_dname, sizeof(wiredata_dname),
+ obuffer.getData(), obuffer.getLength());
}
TEST_F(Rdata_DNAME_Test, toWireRenderer) {
rdata_dname.toWire(renderer);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- renderer.getData(), renderer.getLength(),
- wiredata_dname, sizeof(wiredata_dname));
+ matchWireData(wiredata_dname, sizeof(wiredata_dname),
+ renderer.getData(), renderer.getLength());
+
rdata_dname2.toWire(renderer);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- renderer.getData(), renderer.getLength(),
- wiredata_dname2, sizeof(wiredata_dname2));
+ matchWireData(wiredata_dname2, sizeof(wiredata_dname2),
+ renderer.getData(), renderer.getLength());
}
TEST_F(Rdata_DNAME_Test, toText) {
diff --git a/src/lib/dns/tests/rdata_dnskey_unittest.cc b/src/lib/dns/tests/rdata_dnskey_unittest.cc
index 872dc2af95..0c77735d17 100644
--- a/src/lib/dns/tests/rdata_dnskey_unittest.cc
+++ b/src/lib/dns/tests/rdata_dnskey_unittest.cc
@@ -27,13 +27,15 @@
#include <dns/tests/unittest_util.h>
#include <dns/tests/rdata_unittest.h>
+#include <util/unittests/wiredata.h>
-using isc::UnitTestUtil;
using namespace std;
using namespace isc;
using namespace isc::dns;
using namespace isc::util;
using namespace isc::dns::rdata;
+using isc::UnitTestUtil;
+using isc::util::unittests::matchWireData;
namespace {
class Rdata_DNSKEY_Test : public RdataTest {
@@ -155,9 +157,9 @@ TEST_F(Rdata_DNSKEY_Test, toWireRenderer) {
vector<unsigned char> data;
UnitTestUtil::readWireData("rdata_dnskey_fromWire.wire", data);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- static_cast<const uint8_t *>(renderer.getData()) + 2,
- renderer.getLength() - 2, &data[2], data.size() - 2);
+ matchWireData(&data[2], data.size() - 2,
+ static_cast<const uint8_t *>(renderer.getData()) + 2,
+ renderer.getLength() - 2);
}
TEST_F(Rdata_DNSKEY_Test, toWireBuffer) {
@@ -165,9 +167,8 @@ TEST_F(Rdata_DNSKEY_Test, toWireBuffer) {
vector<unsigned char> data;
UnitTestUtil::readWireData("rdata_dnskey_fromWire.wire", data);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- obuffer.getData(), obuffer.getLength(),
- &data[2], data.size() - 2);
+ matchWireData(&data[2], data.size() - 2,
+ obuffer.getData(), obuffer.getLength());
}
TEST_F(Rdata_DNSKEY_Test, createFromWire) {
diff --git a/src/lib/dns/tests/rdata_ds_like_unittest.cc b/src/lib/dns/tests/rdata_ds_like_unittest.cc
index ae6a360f5b..e278f1ffcb 100644
--- a/src/lib/dns/tests/rdata_ds_like_unittest.cc
+++ b/src/lib/dns/tests/rdata_ds_like_unittest.cc
@@ -26,12 +26,14 @@
#include <dns/tests/unittest_util.h>
#include <dns/tests/rdata_unittest.h>
+#include <util/unittests/wiredata.h>
-using isc::UnitTestUtil;
using namespace std;
using namespace isc::dns;
using namespace isc::util;
using namespace isc::dns::rdata;
+using isc::UnitTestUtil;
+using isc::util::unittests::matchWireData;
namespace {
// hacks to make templates work
@@ -148,11 +150,9 @@ TYPED_TEST(Rdata_DS_LIKE_Test, toWireRenderer) {
vector<unsigned char> data;
UnitTestUtil::readWireData("rdata_ds_fromWire", data);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- static_cast<const uint8_t*>
- (this->renderer.getData()) + 2,
- this->renderer.getLength() - 2,
- &data[2], data.size() - 2);
+ matchWireData(&data[2], data.size() - 2,
+ static_cast<const uint8_t*>(this->renderer.getData()) + 2,
+ this->renderer.getLength() - 2);
}
TYPED_TEST(Rdata_DS_LIKE_Test, toWireBuffer) {
diff --git a/src/lib/dns/tests/rdata_hinfo_unittest.cc b/src/lib/dns/tests/rdata_hinfo_unittest.cc
index 7be2cb6026..887848e2b2 100644
--- a/src/lib/dns/tests/rdata_hinfo_unittest.cc
+++ b/src/lib/dns/tests/rdata_hinfo_unittest.cc
@@ -24,13 +24,15 @@
#include <dns/tests/unittest_util.h>
#include <dns/tests/rdata_unittest.h>
+#include <util/unittests/wiredata.h>
-using isc::UnitTestUtil;
using namespace std;
using namespace isc::dns;
using namespace isc::util;
using namespace isc::dns::rdata;
using namespace isc::dns::rdata::generic;
+using isc::UnitTestUtil;
+using isc::util::unittests::matchWireData;
namespace {
class Rdata_HINFO_Test : public RdataTest {
@@ -113,19 +115,18 @@ TEST_F(Rdata_HINFO_Test, toText) {
TEST_F(Rdata_HINFO_Test, toWire) {
HINFO hinfo(hinfo_str);
- hinfo.toWire(obuffer);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, obuffer.getData(),
- obuffer.getLength(), hinfo_rdata, sizeof(hinfo_rdata));
+ hinfo.toWire(obuffer);
+ matchWireData(hinfo_rdata, sizeof (hinfo_rdata),
+ obuffer.getData(), obuffer.getLength());
}
TEST_F(Rdata_HINFO_Test, toWireRenderer) {
HINFO hinfo(hinfo_str);
hinfo.toWire(renderer);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, renderer.getData(),
- renderer.getLength(), hinfo_rdata,
- sizeof(hinfo_rdata));
+ matchWireData(hinfo_rdata, sizeof (hinfo_rdata),
+ renderer.getData(), renderer.getLength());
}
TEST_F(Rdata_HINFO_Test, compare) {
diff --git a/src/lib/dns/tests/rdata_in_a_unittest.cc b/src/lib/dns/tests/rdata_in_a_unittest.cc
index 3f65641f50..c940075409 100644
--- a/src/lib/dns/tests/rdata_in_a_unittest.cc
+++ b/src/lib/dns/tests/rdata_in_a_unittest.cc
@@ -27,17 +27,19 @@
#include <dns/tests/unittest_util.h>
#include <dns/tests/rdata_unittest.h>
+#include <util/unittests/wiredata.h>
#include <sstream>
#include <arpa/inet.h>
#include <sys/socket.h>
-using isc::UnitTestUtil;
using namespace std;
using namespace isc::dns;
using namespace isc::util;
using namespace isc::dns::rdata;
+using isc::UnitTestUtil;
+using isc::util::unittests::matchWireData;
namespace {
class Rdata_IN_A_Test : public RdataTest {
@@ -121,16 +123,14 @@ TEST_F(Rdata_IN_A_Test, createFromWire) {
TEST_F(Rdata_IN_A_Test, toWireBuffer) {
rdata_in_a.toWire(obuffer);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- obuffer.getData(), obuffer.getLength(),
- wiredata_in_a, sizeof(wiredata_in_a));
+ matchWireData(wiredata_in_a, sizeof (wiredata_in_a),
+ obuffer.getData(), obuffer.getLength());
}
TEST_F(Rdata_IN_A_Test, toWireRenderer) {
rdata_in_a.toWire(renderer);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- renderer.getData(), renderer.getLength(),
- wiredata_in_a, sizeof(wiredata_in_a));
+ matchWireData(wiredata_in_a, sizeof (wiredata_in_a),
+ renderer.getData(), renderer.getLength());
}
TEST_F(Rdata_IN_A_Test, toText) {
diff --git a/src/lib/dns/tests/rdata_in_aaaa_unittest.cc b/src/lib/dns/tests/rdata_in_aaaa_unittest.cc
index 82f75a897c..ff92d07d87 100644
--- a/src/lib/dns/tests/rdata_in_aaaa_unittest.cc
+++ b/src/lib/dns/tests/rdata_in_aaaa_unittest.cc
@@ -24,12 +24,14 @@
#include <dns/tests/unittest_util.h>
#include <dns/tests/rdata_unittest.h>
+#include <util/unittests/wiredata.h>
-using isc::UnitTestUtil;
using namespace std;
using namespace isc::dns;
using namespace isc::util;
using namespace isc::dns::rdata;
+using isc::UnitTestUtil;
+using isc::util::unittests::matchWireData;
namespace {
class Rdata_IN_AAAA_Test : public RdataTest {
@@ -117,16 +119,14 @@ TEST_F(Rdata_IN_AAAA_Test, createFromLexer) {
TEST_F(Rdata_IN_AAAA_Test, toWireBuffer) {
rdata_in_aaaa.toWire(obuffer);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- obuffer.getData(), obuffer.getLength(),
- wiredata_in_aaaa, sizeof(wiredata_in_aaaa));
+ matchWireData(wiredata_in_aaaa, sizeof (wiredata_in_aaaa),
+ obuffer.getData(), obuffer.getLength());
}
TEST_F(Rdata_IN_AAAA_Test, toWireRenderer) {
rdata_in_aaaa.toWire(renderer);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- renderer.getData(), renderer.getLength(),
- wiredata_in_aaaa, sizeof(wiredata_in_aaaa));
+ matchWireData(wiredata_in_aaaa, sizeof (wiredata_in_aaaa),
+ renderer.getData(), renderer.getLength());
}
TEST_F(Rdata_IN_AAAA_Test, toText) {
diff --git a/src/lib/dns/tests/rdata_minfo_unittest.cc b/src/lib/dns/tests/rdata_minfo_unittest.cc
index 3ce6a6cd49..8addb29c69 100644
--- a/src/lib/dns/tests/rdata_minfo_unittest.cc
+++ b/src/lib/dns/tests/rdata_minfo_unittest.cc
@@ -26,12 +26,14 @@
#include <dns/tests/unittest_util.h>
#include <dns/tests/rdata_unittest.h>
+#include <util/unittests/wiredata.h>
-using isc::UnitTestUtil;
using namespace std;
using namespace isc::util;
using namespace isc::dns;
using namespace isc::dns::rdata;
+using isc::UnitTestUtil;
+using isc::util::unittests::matchWireData;
namespace {
class Rdata_MINFO_Test : public RdataTest {
@@ -177,33 +179,30 @@ TEST_F(Rdata_MINFO_Test, toWireBuffer) {
rdata_minfo.toWire(obuffer);
vector<unsigned char> data;
UnitTestUtil::readWireData("rdata_minfo_toWireUncompressed1.wire", data);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- static_cast<const uint8_t *>(obuffer.getData()),
- obuffer.getLength(), &data[0], data.size());
+ matchWireData(&data[0], data.size(),
+ obuffer.getData(), obuffer.getLength());
obuffer.clear();
rdata_minfo2.toWire(obuffer);
vector<unsigned char> data2;
UnitTestUtil::readWireData("rdata_minfo_toWireUncompressed2.wire", data2);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- static_cast<const uint8_t *>(obuffer.getData()),
- obuffer.getLength(), &data2[0], data2.size());
+ matchWireData(&data2[0], data2.size(),
+ obuffer.getData(), obuffer.getLength());
}
TEST_F(Rdata_MINFO_Test, toWireRenderer) {
rdata_minfo.toWire(renderer);
vector<unsigned char> data;
UnitTestUtil::readWireData("rdata_minfo_toWire1.wire", data);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- static_cast<const uint8_t *>(renderer.getData()),
- renderer.getLength(), &data[0], data.size());
+ matchWireData(&data[0], data.size(),
+ renderer.getData(), renderer.getLength());
+
renderer.clear();
rdata_minfo2.toWire(renderer);
vector<unsigned char> data2;
UnitTestUtil::readWireData("rdata_minfo_toWire2.wire", data2);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- static_cast<const uint8_t *>(renderer.getData()),
- renderer.getLength(), &data2[0], data2.size());
+ matchWireData(&data2[0], data2.size(),
+ renderer.getData(), renderer.getLength());
}
TEST_F(Rdata_MINFO_Test, toText) {
diff --git a/src/lib/dns/tests/rdata_mx_unittest.cc b/src/lib/dns/tests/rdata_mx_unittest.cc
index 6e4eaba41f..926374aae0 100644
--- a/src/lib/dns/tests/rdata_mx_unittest.cc
+++ b/src/lib/dns/tests/rdata_mx_unittest.cc
@@ -23,12 +23,14 @@
#include <dns/tests/unittest_util.h>
#include <dns/tests/rdata_unittest.h>
+#include <util/unittests/wiredata.h>
-using isc::UnitTestUtil;
using namespace std;
using namespace isc::dns;
using namespace isc::util;
using namespace isc::dns::rdata;
+using isc::UnitTestUtil;
+using isc::util::unittests::matchWireData;
namespace {
class Rdata_MX_Test : public RdataTest {
@@ -101,8 +103,8 @@ TEST_F(Rdata_MX_Test, toWireRenderer) {
vector<unsigned char> data;
UnitTestUtil::readWireData("rdata_mx_toWire1", data);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, renderer.getData(),
- renderer.getLength(), &data[0], data.size());
+ matchWireData(&data[0], data.size(),
+ renderer.getData(), renderer.getLength());
}
TEST_F(Rdata_MX_Test, toWireBuffer) {
@@ -111,8 +113,8 @@ TEST_F(Rdata_MX_Test, toWireBuffer) {
vector<unsigned char> data;
UnitTestUtil::readWireData("rdata_mx_toWire2", data);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, obuffer.getData(),
- obuffer.getLength(), &data[0], data.size());
+ matchWireData(&data[0], data.size(),
+ obuffer.getData(), obuffer.getLength());
}
TEST_F(Rdata_MX_Test, toText) {
diff --git a/src/lib/dns/tests/rdata_naptr_unittest.cc b/src/lib/dns/tests/rdata_naptr_unittest.cc
index d828e73ea2..982bf76505 100644
--- a/src/lib/dns/tests/rdata_naptr_unittest.cc
+++ b/src/lib/dns/tests/rdata_naptr_unittest.cc
@@ -24,13 +24,15 @@
#include <dns/tests/unittest_util.h>
#include <dns/tests/rdata_unittest.h>
+#include <util/unittests/wiredata.h>
-using isc::UnitTestUtil;
using namespace std;
using namespace isc::dns;
using namespace isc::util;
using namespace isc::dns::rdata;
using namespace isc::dns::rdata::generic;
+using isc::UnitTestUtil;
+using isc::util::unittests::matchWireData;
namespace {
class Rdata_NAPTR_Test : public RdataTest {
@@ -165,19 +167,18 @@ TEST_F(Rdata_NAPTR_Test, createFromLexer) {
TEST_F(Rdata_NAPTR_Test, toWire) {
NAPTR naptr(naptr_str);
- naptr.toWire(obuffer);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, obuffer.getData(),
- obuffer.getLength(), naptr_rdata, sizeof(naptr_rdata));
+ naptr.toWire(obuffer);
+ matchWireData(naptr_rdata, sizeof(naptr_rdata),
+ obuffer.getData(), obuffer.getLength());
}
TEST_F(Rdata_NAPTR_Test, toWireRenderer) {
NAPTR naptr(naptr_str);
naptr.toWire(renderer);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, renderer.getData(),
- renderer.getLength(), naptr_rdata,
- sizeof(naptr_rdata));
+ matchWireData(naptr_rdata, sizeof(naptr_rdata),
+ renderer.getData(), renderer.getLength());
}
TEST_F(Rdata_NAPTR_Test, toText) {
diff --git a/src/lib/dns/tests/rdata_ns_unittest.cc b/src/lib/dns/tests/rdata_ns_unittest.cc
index 53eb6700c3..305149c481 100644
--- a/src/lib/dns/tests/rdata_ns_unittest.cc
+++ b/src/lib/dns/tests/rdata_ns_unittest.cc
@@ -24,12 +24,14 @@
#include <dns/tests/unittest_util.h>
#include <dns/tests/rdata_unittest.h>
+#include <util/unittests/wiredata.h>
-using isc::UnitTestUtil;
using namespace std;
using namespace isc::dns;
using namespace isc::util;
using namespace isc::dns::rdata;
+using isc::UnitTestUtil;
+using isc::util::unittests::matchWireData;
namespace {
class Rdata_NS_Test : public RdataTest {
@@ -118,20 +120,18 @@ TEST_F(Rdata_NS_Test, createFromLexer) {
TEST_F(Rdata_NS_Test, toWireBuffer) {
rdata_ns.toWire(obuffer);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- obuffer.getData(), obuffer.getLength(),
- wiredata_ns, sizeof(wiredata_ns));
+ matchWireData(wiredata_ns, sizeof(wiredata_ns),
+ obuffer.getData(), obuffer.getLength());
}
TEST_F(Rdata_NS_Test, toWireRenderer) {
rdata_ns.toWire(renderer);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- renderer.getData(), renderer.getLength(),
- wiredata_ns, sizeof(wiredata_ns));
+ matchWireData(wiredata_ns, sizeof(wiredata_ns),
+ renderer.getData(), renderer.getLength());
+
rdata_ns2.toWire(renderer);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- renderer.getData(), renderer.getLength(),
- wiredata_ns2, sizeof(wiredata_ns2));
+ matchWireData(wiredata_ns2, sizeof(wiredata_ns2),
+ renderer.getData(), renderer.getLength());
}
TEST_F(Rdata_NS_Test, toText) {
diff --git a/src/lib/dns/tests/rdata_nsec3param_like_unittest.cc b/src/lib/dns/tests/rdata_nsec3param_like_unittest.cc
index 23d6d0ed68..ea38e7c475 100644
--- a/src/lib/dns/tests/rdata_nsec3param_like_unittest.cc
+++ b/src/lib/dns/tests/rdata_nsec3param_like_unittest.cc
@@ -22,14 +22,17 @@
#include <dns/tests/unittest_util.h>
#include <dns/tests/rdata_unittest.h>
+#include <util/unittests/wiredata.h>
#include <string>
#include <vector>
using namespace std;
-using isc::UnitTestUtil;
using namespace isc::dns;
using namespace isc::dns::rdata;
+using namespace isc::util;
+using isc::UnitTestUtil;
+using isc::util::unittests::matchWireData;
namespace {
@@ -230,8 +233,8 @@ toWireCheck(RRType rrtype, OUTPUT_TYPE& output, const string& data_file) {
output.clear();
output.writeUint16(rdlen);
createRdata(rrtype, RRClass::IN(), buffer, rdlen)->toWire(output);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, output.getData(),
- output.getLength(), &data[0], data.size());
+ matchWireData(&data[0], data.size(),
+ output.getData(), output.getLength());
}
TYPED_TEST(NSEC3PARAMLikeTest, toWire) {
diff --git a/src/lib/dns/tests/rdata_nsec3param_unittest.cc b/src/lib/dns/tests/rdata_nsec3param_unittest.cc
index 4fccbf311b..9f121cc928 100644
--- a/src/lib/dns/tests/rdata_nsec3param_unittest.cc
+++ b/src/lib/dns/tests/rdata_nsec3param_unittest.cc
@@ -27,13 +27,15 @@
#include <dns/tests/unittest_util.h>
#include <dns/tests/rdata_unittest.h>
+#include <util/unittests/wiredata.h>
-using isc::UnitTestUtil;
using namespace std;
using namespace isc;
using namespace isc::dns;
using namespace isc::util;
using namespace isc::dns::rdata;
+using isc::UnitTestUtil;
+using isc::util::unittests::matchWireData;
namespace {
class Rdata_NSEC3PARAM_Test : public RdataTest {
@@ -170,9 +172,9 @@ TEST_F(Rdata_NSEC3PARAM_Test, toWireRenderer) {
vector<unsigned char> data;
UnitTestUtil::readWireData("rdata_nsec3param_fromWire1", data);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- static_cast<const uint8_t *>(renderer.getData()) + 2,
- renderer.getLength() - 2, &data[2], data.size() - 2);
+ matchWireData(&data[2], data.size() - 2,
+ static_cast<const uint8_t *>(renderer.getData()) + 2,
+ renderer.getLength() - 2);
}
TEST_F(Rdata_NSEC3PARAM_Test, toWireBuffer) {
@@ -180,9 +182,8 @@ TEST_F(Rdata_NSEC3PARAM_Test, toWireBuffer) {
vector<unsigned char> data;
UnitTestUtil::readWireData("rdata_nsec3param_fromWire1", data);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- obuffer.getData(), obuffer.getLength(),
- &data[2], data.size() - 2);
+ matchWireData(&data[2], data.size() - 2,
+ obuffer.getData(), obuffer.getLength());
}
TEST_F(Rdata_NSEC3PARAM_Test, getHashAlg) {
diff --git a/src/lib/dns/tests/rdata_nsec_unittest.cc b/src/lib/dns/tests/rdata_nsec_unittest.cc
index 810e2cc3d0..dcbc1f312f 100644
--- a/src/lib/dns/tests/rdata_nsec_unittest.cc
+++ b/src/lib/dns/tests/rdata_nsec_unittest.cc
@@ -26,12 +26,14 @@
#include <dns/tests/unittest_util.h>
#include <dns/tests/rdata_unittest.h>
+#include <util/unittests/wiredata.h>
-using isc::UnitTestUtil;
using namespace std;
using namespace isc::dns;
using namespace isc::util;
using namespace isc::dns::rdata;
+using isc::UnitTestUtil;
+using isc::util::unittests::matchWireData;
namespace {
class Rdata_NSEC_Test : public RdataTest {
@@ -90,9 +92,9 @@ TEST_F(Rdata_NSEC_Test, toWireRenderer_NSEC) {
vector<unsigned char> data;
UnitTestUtil::readWireData("rdata_nsec_fromWire1", data);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- static_cast<const uint8_t *>(renderer.getData()) + 2,
- renderer.getLength() - 2, &data[2], data.size() - 2);
+ matchWireData(&data[2], data.size() - 2,
+ static_cast<const uint8_t *>(renderer.getData()) + 2,
+ renderer.getLength() - 2);
}
TEST_F(Rdata_NSEC_Test, toWireBuffer_NSEC) {
diff --git a/src/lib/dns/tests/rdata_nsecbitmap_unittest.cc b/src/lib/dns/tests/rdata_nsecbitmap_unittest.cc
index fbb256a151..9c2420075a 100644
--- a/src/lib/dns/tests/rdata_nsecbitmap_unittest.cc
+++ b/src/lib/dns/tests/rdata_nsecbitmap_unittest.cc
@@ -23,6 +23,7 @@
#include <gtest/gtest.h>
#include <dns/tests/rdata_unittest.h>
+#include <util/unittests/wiredata.h>
#include <boost/lexical_cast.hpp>
@@ -30,10 +31,12 @@
#include <vector>
using namespace std;
-using boost::lexical_cast;
-using isc::UnitTestUtil;
using namespace isc::dns;
using namespace isc::dns::rdata;
+using namespace isc::util;
+using isc::UnitTestUtil;
+using isc::util::unittests::matchWireData;
+using boost::lexical_cast;
namespace {
@@ -253,16 +256,16 @@ TEST_F(NSEC3BitmapTest, emptyMap) {
OutputBuffer obuffer(0);
obuffer.writeUint16(rdlen);
empty_nsec3.toWire(obuffer);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, obuffer.getData(),
- obuffer.getLength(), &data[0], data.size());
+ matchWireData(&data[0], data.size(),
+ obuffer.getData(), obuffer.getLength());
// Same for MessageRenderer.
obuffer.clear();
MessageRenderer renderer;
renderer.writeUint16(rdlen);
empty_nsec3.toWire(renderer);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, renderer.getData(),
- renderer.getLength(), &data[0], data.size());
+ matchWireData(&data[0], data.size(),
+ renderer.getData(), renderer.getLength());
}
}
diff --git a/src/lib/dns/tests/rdata_opt_unittest.cc b/src/lib/dns/tests/rdata_opt_unittest.cc
index 20ccfe4994..9d09a60656 100644
--- a/src/lib/dns/tests/rdata_opt_unittest.cc
+++ b/src/lib/dns/tests/rdata_opt_unittest.cc
@@ -23,19 +23,28 @@
#include <dns/tests/unittest_util.h>
#include <dns/tests/rdata_unittest.h>
+#include <util/unittests/wiredata.h>
-using isc::UnitTestUtil;
using namespace std;
using namespace isc::dns;
using namespace isc::util;
using namespace isc::dns::rdata;
+using isc::UnitTestUtil;
+using isc::util::unittests::matchWireData;
namespace {
class Rdata_OPT_Test : public RdataTest {
// there's nothing to specialize
};
-const generic::OPT rdata_opt;
+const uint8_t rdata_opt_wiredata[] = {
+ // Option code
+ 0x00, 0x2a,
+ // Option length
+ 0x00, 0x03,
+ // Option data
+ 0x00, 0x01, 0x02
+};
TEST_F(Rdata_OPT_Test, createFromText) {
// OPT RR cannot be created from text.
@@ -46,14 +55,28 @@ TEST_F(Rdata_OPT_Test, createFromWire) {
// Valid cases: in the simple implementation with no supported options,
// we can only check these don't throw.
EXPECT_NO_THROW(rdataFactoryFromFile(RRType::OPT(), RRClass("CLASS4096"),
- "rdata_opt_fromWire"));
+ "rdata_opt_fromWire1"));
EXPECT_NO_THROW(rdataFactoryFromFile(RRType::OPT(), RRClass::CH(),
- "rdata_opt_fromWire", 2));
+ "rdata_opt_fromWire1", 2));
- // short buffer case.
+ // Short RDLEN. This throws InvalidRdataLength even if subsequent
+ // pseudo RRs cause RDLEN size to be exhausted.
EXPECT_THROW(rdataFactoryFromFile(RRType::OPT(), RRClass::IN(),
- "rdata_opt_fromWire", 11),
+ "rdata_opt_fromWire2"),
InvalidRdataLength);
+ EXPECT_THROW(rdataFactoryFromFile(RRType::OPT(), RRClass::IN(),
+ "rdata_opt_fromWire3"),
+ InvalidRdataLength);
+ // Option lengths can add up and overflow RDLEN. Unlikely when
+ // parsed from wire data, but we'll check for it anyway.
+ EXPECT_THROW(rdataFactoryFromFile(RRType::OPT(), RRClass::IN(),
+ "rdata_opt_fromWire4"),
+ InvalidRdataText);
+
+ // short buffer case.
+ EXPECT_THROW(rdataFactoryFromFile(RRType::OPT(), RRClass::IN(),
+ "rdata_opt_fromWire1", 11),
+ InvalidBufferPosition);
}
TEST_F(Rdata_OPT_Test, createFromLexer) {
@@ -64,26 +87,118 @@ TEST_F(Rdata_OPT_Test, createFromLexer) {
}
TEST_F(Rdata_OPT_Test, toWireBuffer) {
+ const generic::OPT rdata_opt =
+ dynamic_cast<const generic::OPT&>
+ (*rdataFactoryFromFile(RRType("OPT"), RRClass("IN"),
+ "rdata_opt_fromWire1", 2));
+
+ obuffer.clear();
rdata_opt.toWire(obuffer);
- EXPECT_EQ(0, obuffer.getLength());
+
+ matchWireData(rdata_opt_wiredata, sizeof(rdata_opt_wiredata),
+ obuffer.getData(), obuffer.getLength());
}
TEST_F(Rdata_OPT_Test, toWireRenderer) {
+ const generic::OPT rdata_opt =
+ dynamic_cast<const generic::OPT&>
+ (*rdataFactoryFromFile(RRType("OPT"), RRClass("IN"),
+ "rdata_opt_fromWire1", 2));
+
+ renderer.clear();
rdata_opt.toWire(renderer);
- EXPECT_EQ(0, obuffer.getLength());
+
+ matchWireData(rdata_opt_wiredata, sizeof(rdata_opt_wiredata),
+ renderer.getData(), renderer.getLength());
}
TEST_F(Rdata_OPT_Test, toText) {
- EXPECT_EQ("", rdata_opt.toText());
+ // empty OPT
+ const generic::OPT rdata_opt;
+
+ EXPECT_THROW(rdata_opt.toText(),
+ isc::InvalidOperation);
}
TEST_F(Rdata_OPT_Test, compare) {
- // This simple implementation always returns "true"
- EXPECT_EQ(0, rdata_opt.compare(
+ // empty OPT
+ const generic::OPT rdata_opt;
+
+ EXPECT_THROW(rdata_opt.compare(
*rdataFactoryFromFile(RRType::OPT(), RRClass::CH(),
- "rdata_opt_fromWire", 2)));
+ "rdata_opt_fromWire1", 2)),
+ isc::InvalidOperation);
+
+ // comparison attempt between incompatible RR types also results in
+ // isc::InvalidOperation.
+ EXPECT_THROW(rdata_opt.compare(*RdataTest::rdata_nomatch),
+ isc::InvalidOperation);
+}
+
+TEST_F(Rdata_OPT_Test, appendPseudoRR) {
+ generic::OPT rdata_opt;
+
+ // Append empty option data
+ rdata_opt.appendPseudoRR(0x0042, NULL, 0);
+
+ // Append simple option data
+ const uint8_t option_data[] = {'H', 'e', 'l', 'l', 'o'};
+ rdata_opt.appendPseudoRR(0x0043, option_data, sizeof(option_data));
+
+ // Duplicate option codes are okay.
+ rdata_opt.appendPseudoRR(0x0042, option_data, sizeof(option_data));
+
+ // When option length may overflow RDLEN, append should throw.
+ const std::vector<uint8_t> buffer((1 << 16) - 1);
+ EXPECT_THROW(rdata_opt.appendPseudoRR(0x0044, &buffer[0], buffer.size()),
+ isc::InvalidParameter);
+
+ const uint8_t rdata_opt_wiredata2[] = {
+ // OPTION #1
+ // ` Option code
+ 0x00, 0x42,
+ // ` Option length
+ 0x00, 0x00,
+
+ // OPTION #2
+ // ` Option code
+ 0x00, 0x43,
+ // ` Option length
+ 0x00, 0x05,
+ // ` Option data
+ 'H', 'e', 'l', 'l', 'o',
+
+ // OPTION #3
+ // ` Option code
+ 0x00, 0x42,
+ // ` Option length
+ 0x00, 0x05,
+ // ` Option data
+ 'H', 'e', 'l', 'l', 'o'
+ };
+
+ obuffer.clear();
+ rdata_opt.toWire(obuffer);
+
+ matchWireData(rdata_opt_wiredata2, sizeof(rdata_opt_wiredata2),
+ obuffer.getData(), obuffer.getLength());
+}
+
+TEST_F(Rdata_OPT_Test, getPseudoRRs) {
+ const generic::OPT rdf =
+ dynamic_cast<const generic::OPT&>
+ (*rdataFactoryFromFile(RRType("OPT"), RRClass("IN"),
+ "rdata_opt_fromWire1", 2));
+
+ const std::vector<generic::OPT::PseudoRR>& rrs = rdf.getPseudoRRs();
+ ASSERT_FALSE(rrs.empty());
+ EXPECT_EQ(1, rrs.size());
+ EXPECT_EQ(0x2a, rrs.at(0).getCode());
+ EXPECT_EQ(3, rrs.at(0).getLength());
- // comparison attempt between incompatible RR types should be rejected
- EXPECT_THROW(rdata_opt.compare(*RdataTest::rdata_nomatch), bad_cast);
+ const uint8_t expected_data[] = {0x00, 0x01, 0x02};
+ const uint8_t* actual_data = rrs.at(0).getData();
+ EXPECT_EQ(0, std::memcmp(expected_data, actual_data,
+ sizeof(expected_data)));
}
}
diff --git a/src/lib/dns/tests/rdata_pimpl_holder_unittest.cc b/src/lib/dns/tests/rdata_pimpl_holder_unittest.cc
new file mode 100644
index 0000000000..96a03ba5ea
--- /dev/null
+++ b/src/lib/dns/tests/rdata_pimpl_holder_unittest.cc
@@ -0,0 +1,62 @@
+// Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or 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 ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS. IN NO EVENT SHALL ISC 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.
+
+#include <dns/rdata_pimpl_holder.h>
+
+#include <gtest/gtest.h>
+
+using namespace isc::dns::rdata;
+
+namespace {
+
+TEST(RdataPimplHolderTest, all) {
+ // Let's check with an integer
+ int* i1 = new int(42);
+ RdataPimplHolder<int> holder1(i1);
+ // The same pointer must be returned.
+ EXPECT_EQ(i1, holder1.get());
+ // Obviously the value should match too.
+ EXPECT_EQ(42, *holder1.get());
+ // We don't explictly delete i or holder1, so it should not leak
+ // anything when the test is done (checked by Valgrind).
+
+ // The following cases are similar:
+
+ // Test no-argument reset()
+ int* i2 = new int(43);
+ RdataPimplHolder<int> holder2(i2);
+ holder2.reset();
+ EXPECT_EQ(NULL, holder2.get());
+
+ // Test reset() with argument
+ int* i3 = new int(44);
+ int* i4 = new int(45);
+ RdataPimplHolder<int> holder3(i3);
+ EXPECT_EQ(i3, holder3.get());
+ holder3.reset(i4);
+ EXPECT_EQ(i4, holder3.get());
+ EXPECT_EQ(45, *holder3.get());
+
+ // Test release()
+ RdataPimplHolder<int> holder4(new int(46));
+ EXPECT_NE(static_cast<void*>(NULL), holder4.get());
+ EXPECT_EQ(46, *holder4.get());
+ int* i5 = holder4.release();
+ EXPECT_EQ(NULL, holder4.get());
+ EXPECT_NE(static_cast<void*>(NULL), i5);
+ EXPECT_EQ(46, *i5);
+ delete i5;
+}
+
+}
diff --git a/src/lib/dns/tests/rdata_ptr_unittest.cc b/src/lib/dns/tests/rdata_ptr_unittest.cc
index 5d6d37db91..d6a99f77f9 100644
--- a/src/lib/dns/tests/rdata_ptr_unittest.cc
+++ b/src/lib/dns/tests/rdata_ptr_unittest.cc
@@ -24,12 +24,14 @@
#include <dns/tests/unittest_util.h>
#include <dns/tests/rdata_unittest.h>
+#include <util/unittests/wiredata.h>
-using isc::UnitTestUtil;
using namespace std;
using namespace isc::dns;
using namespace isc::util;
using namespace isc::dns::rdata;
+using isc::UnitTestUtil;
+using isc::util::unittests::matchWireData;
//
// This test currently simply copies the NS RDATA tests.
@@ -118,20 +120,18 @@ TEST_F(Rdata_PTR_Test, createFromLexer) {
TEST_F(Rdata_PTR_Test, toWireBuffer) {
rdata_ptr.toWire(obuffer);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- obuffer.getData(), obuffer.getLength(),
- wiredata_ptr, sizeof(wiredata_ptr));
+ matchWireData(wiredata_ptr, sizeof(wiredata_ptr),
+ obuffer.getData(), obuffer.getLength());
}
TEST_F(Rdata_PTR_Test, toWireRenderer) {
rdata_ptr.toWire(renderer);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- renderer.getData(), renderer.getLength(),
- wiredata_ptr, sizeof(wiredata_ptr));
+ matchWireData(wiredata_ptr, sizeof(wiredata_ptr),
+ renderer.getData(), renderer.getLength());
+
rdata_ptr2.toWire(renderer);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- renderer.getData(), renderer.getLength(),
- wiredata_ptr2, sizeof(wiredata_ptr2));
+ matchWireData(wiredata_ptr2, sizeof(wiredata_ptr2),
+ renderer.getData(), renderer.getLength());
}
TEST_F(Rdata_PTR_Test, toText) {
diff --git a/src/lib/dns/tests/rdata_rp_unittest.cc b/src/lib/dns/tests/rdata_rp_unittest.cc
index 38bec04211..d8de028926 100644
--- a/src/lib/dns/tests/rdata_rp_unittest.cc
+++ b/src/lib/dns/tests/rdata_rp_unittest.cc
@@ -22,12 +22,14 @@
#include <dns/tests/unittest_util.h>
#include <dns/tests/rdata_unittest.h>
+#include <util/unittests/wiredata.h>
-using isc::UnitTestUtil;
using namespace std;
using namespace isc::util;
using namespace isc::dns;
using namespace isc::dns::rdata;
+using isc::UnitTestUtil;
+using isc::util::unittests::matchWireData;
namespace {
class Rdata_RP_Test : public RdataTest {
@@ -157,9 +159,8 @@ TEST_F(Rdata_RP_Test, toWireBuffer) {
rdata_rp.toWire(obuffer);
// then compare them
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- obuffer.getData(), obuffer.getLength(),
- &expected_wire[0], expected_wire.size());
+ matchWireData(&expected_wire[0], expected_wire.size(),
+ obuffer.getData(), obuffer.getLength());
}
TEST_F(Rdata_RP_Test, toWireRenderer) {
@@ -172,9 +173,8 @@ TEST_F(Rdata_RP_Test, toWireRenderer) {
renderer.writeName(Name("a.example.com"));
renderer.writeName(Name("b.example.net"));
generic::RP(mailbox_name, Name("rp-text.example.net")).toWire(renderer);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- renderer.getData(), renderer.getLength(),
- &expected_wire[0], expected_wire.size());
+ matchWireData(&expected_wire[0], expected_wire.size(),
+ renderer.getData(), renderer.getLength());
}
TEST_F(Rdata_RP_Test, toText) {
diff --git a/src/lib/dns/tests/rdata_rrsig_unittest.cc b/src/lib/dns/tests/rdata_rrsig_unittest.cc
index 2d075ece97..67ead3c713 100644
--- a/src/lib/dns/tests/rdata_rrsig_unittest.cc
+++ b/src/lib/dns/tests/rdata_rrsig_unittest.cc
@@ -25,16 +25,57 @@
#include <gtest/gtest.h>
#include <dns/tests/unittest_util.h>
+#include <util/unittests/wiredata.h>
#include <dns/tests/rdata_unittest.h>
-using isc::UnitTestUtil;
using namespace std;
using namespace isc;
using namespace isc::dns;
using namespace isc::util;
using namespace isc::dns::rdata;
+using isc::UnitTestUtil;
+using isc::util::unittests::matchWireData;
namespace {
+
+const uint8_t wiredata_rrsig[] = {
+ // type covered = A
+ 0x00, 0x01,
+ // algorithm = 5
+ 0x05,
+ // labels = 4
+ 0x04,
+ // original TTL = 43200 (0x0000a8c0)
+ 0x00, 0x00, 0xa8, 0xc0,
+ // signature expiration = 1266961577 (0x4b844ca9)
+ 0x4b, 0x84, 0x4c, 0xa9,
+ // signature inception = 1266875177 (0x4b82fb29)
+ 0x4b, 0x82, 0xfb, 0x29,
+ // key tag = 8496 (0x2130)
+ 0x21, 0x30,
+ // signer's name (isc.org.)
+ // 3 i s c 3 o r g 0
+ 0x03, 0x69, 0x73, 0x63, 0x03, 0x6f, 0x72, 0x67, 0x00,
+ // signature data follows
+ 0x7a, 0xfc, 0x61, 0x94, 0x6c,
+ 0x75, 0xde, 0x6a, 0x4a, 0x2d, 0x59, 0x0a, 0xb2,
+ 0x3a, 0x46, 0xcf, 0x27, 0x12, 0xe6, 0xdc, 0x2d,
+ 0x22, 0x8c, 0x4e, 0x9a, 0x53, 0x75, 0xe3, 0x0f,
+ 0x6d, 0xe4, 0x08, 0x33, 0x18, 0x19, 0xb3, 0x76,
+ 0x21, 0x9d, 0x2c, 0x8a, 0xc5, 0x69, 0xba, 0xab,
+ 0xef, 0x66, 0x9f, 0xda, 0xb5, 0x2a, 0xf9, 0x40,
+ 0xc1, 0x28, 0xc5, 0x97, 0xba, 0x3c, 0x19, 0x4d,
+ 0x95, 0x13, 0xc2, 0xcd, 0xf6, 0xb1, 0x59, 0x5d,
+ 0x0c, 0xf9, 0x3f, 0x35, 0xbb, 0x9a, 0x70, 0x93,
+ 0x36, 0xe5, 0xf4, 0x17, 0x7e, 0xfe, 0x66, 0x3b,
+ 0x70, 0x1f, 0xed, 0x33, 0xa8, 0xa3, 0x0d, 0xc0,
+ 0x8c, 0xc6, 0x95, 0x1b, 0xd8, 0x9c, 0x8c, 0x25,
+ 0xb4, 0x57, 0x9e, 0x56, 0x71, 0x64, 0x14, 0x7f,
+ 0x8f, 0x6d, 0xfa, 0xc5, 0xca, 0x3f, 0x36, 0xe2,
+ 0xa4, 0xdf, 0x60, 0xfa, 0xcd, 0x59, 0x3e, 0x22,
+ 0x32, 0xa1, 0xf7
+};
+
class Rdata_RRSIG_Test : public RdataTest {
protected:
Rdata_RRSIG_Test() :
@@ -299,13 +340,17 @@ TEST_F(Rdata_RRSIG_Test, createFromLexer) {
}
TEST_F(Rdata_RRSIG_Test, toWireRenderer) {
- // FIXME: This doesn't check the result.
rdata_rrsig.toWire(renderer);
+
+ matchWireData(wiredata_rrsig, sizeof(wiredata_rrsig),
+ renderer.getData(), renderer.getLength());
}
TEST_F(Rdata_RRSIG_Test, toWireBuffer) {
- // FIXME: This doesn't check the result.
rdata_rrsig.toWire(obuffer);
+
+ matchWireData(wiredata_rrsig, sizeof(wiredata_rrsig),
+ obuffer.getData(), obuffer.getLength());
}
TEST_F(Rdata_RRSIG_Test, createFromWire) {
diff --git a/src/lib/dns/tests/rdata_soa_unittest.cc b/src/lib/dns/tests/rdata_soa_unittest.cc
index 11412e14d1..f74c66d956 100644
--- a/src/lib/dns/tests/rdata_soa_unittest.cc
+++ b/src/lib/dns/tests/rdata_soa_unittest.cc
@@ -23,12 +23,14 @@
#include <dns/tests/unittest_util.h>
#include <dns/tests/rdata_unittest.h>
+#include <util/unittests/wiredata.h>
-using isc::UnitTestUtil;
using namespace std;
using namespace isc::dns;
using namespace isc::util;
using namespace isc::dns::rdata;
+using isc::UnitTestUtil;
+using isc::util::unittests::matchWireData;
namespace {
class Rdata_SOA_Test : public RdataTest {
@@ -179,9 +181,9 @@ TEST_F(Rdata_SOA_Test, toWireRenderer) {
vector<unsigned char> data;
UnitTestUtil::readWireData("rdata_soa_fromWire", data);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- static_cast<const uint8_t *>(renderer.getData()) + 2,
- renderer.getLength() - 2, &data[2], data.size() - 2);
+ matchWireData(&data[2], data.size() - 2,
+ static_cast<const uint8_t *>(renderer.getData()) + 2,
+ renderer.getLength() - 2);
}
TEST_F(Rdata_SOA_Test, toWireBuffer) {
@@ -189,9 +191,9 @@ TEST_F(Rdata_SOA_Test, toWireBuffer) {
rdata_soa.toWire(obuffer);
vector<unsigned char> data;
UnitTestUtil::readWireData("rdata_soa_toWireUncompressed.wire", data);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- static_cast<const uint8_t *>(obuffer.getData()) + 2,
- obuffer.getLength() - 2, &data[2], data.size() - 2);
+ matchWireData(&data[2], data.size() - 2,
+ static_cast<const uint8_t *>(obuffer.getData()) + 2,
+ obuffer.getLength() - 2);
}
TEST_F(Rdata_SOA_Test, toText) {
diff --git a/src/lib/dns/tests/rdata_srv_unittest.cc b/src/lib/dns/tests/rdata_srv_unittest.cc
index 6ca0c7fe7a..8608c48710 100644
--- a/src/lib/dns/tests/rdata_srv_unittest.cc
+++ b/src/lib/dns/tests/rdata_srv_unittest.cc
@@ -24,12 +24,14 @@
#include <dns/tests/unittest_util.h>
#include <dns/tests/rdata_unittest.h>
+#include <util/unittests/wiredata.h>
-using isc::UnitTestUtil;
using namespace std;
using namespace isc::dns;
using namespace isc::util;
using namespace isc::dns::rdata;
+using isc::UnitTestUtil;
+using isc::util::unittests::matchWireData;
namespace {
class Rdata_SRV_Test : public RdataTest {
@@ -159,26 +161,24 @@ TEST_F(Rdata_SRV_Test, createFromLexer) {
TEST_F(Rdata_SRV_Test, toWireBuffer) {
rdata_srv.toWire(obuffer);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- obuffer.getData(), obuffer.getLength(),
- wiredata_srv, sizeof(wiredata_srv));
+ matchWireData(wiredata_srv, sizeof(wiredata_srv),
+ obuffer.getData(), obuffer.getLength());
+
obuffer.clear();
rdata_srv2.toWire(obuffer);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- obuffer.getData(), obuffer.getLength(),
- wiredata_srv2, sizeof(wiredata_srv2));
+ matchWireData(wiredata_srv2, sizeof(wiredata_srv2),
+ obuffer.getData(), obuffer.getLength());
}
TEST_F(Rdata_SRV_Test, toWireRenderer) {
rdata_srv.toWire(renderer);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- renderer.getData(), renderer.getLength(),
- wiredata_srv, sizeof(wiredata_srv));
+ matchWireData(wiredata_srv, sizeof(wiredata_srv),
+ renderer.getData(), renderer.getLength());
+
renderer.clear();
rdata_srv2.toWire(renderer);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- renderer.getData(), renderer.getLength(),
- wiredata_srv2, sizeof(wiredata_srv2));
+ matchWireData(wiredata_srv2, sizeof(wiredata_srv2),
+ renderer.getData(), renderer.getLength());
}
TEST_F(Rdata_SRV_Test, toText) {
diff --git a/src/lib/dns/tests/rdata_sshfp_unittest.cc b/src/lib/dns/tests/rdata_sshfp_unittest.cc
index b85dfa5ebe..cb8640af1a 100644
--- a/src/lib/dns/tests/rdata_sshfp_unittest.cc
+++ b/src/lib/dns/tests/rdata_sshfp_unittest.cc
@@ -26,14 +26,17 @@
#include <dns/tests/unittest_util.h>
#include <dns/tests/rdata_unittest.h>
+#include <util/unittests/wiredata.h>
+
#include <boost/algorithm/string.hpp>
-using isc::UnitTestUtil;
using namespace std;
using namespace isc;
using namespace isc::dns;
using namespace isc::util;
using namespace isc::dns::rdata;
+using isc::UnitTestUtil;
+using isc::util::unittests::matchWireData;
namespace {
class Rdata_SSHFP_Test : public RdataTest {
@@ -59,11 +62,6 @@ protected:
rdata_str, rdata_sshfp, true, true);
}
- void checkFromText_BadValue(const string& rdata_str) {
- checkFromText<generic::SSHFP, InvalidRdataText, BadValue>(
- rdata_str, rdata_sshfp, true, true);
- }
-
void checkFromText_BadString(const string& rdata_str) {
checkFromText
<generic::SSHFP, InvalidRdataText, isc::Exception>(
@@ -138,8 +136,8 @@ TEST_F(Rdata_SSHFP_Test, badText) {
checkFromText_LexerError("1");
checkFromText_LexerError("ONE 2 123456789abcdef67890123456789abcdef67890");
checkFromText_LexerError("1 TWO 123456789abcdef67890123456789abcdef67890");
- checkFromText_BadValue("1 2 BUCKLEMYSHOE");
- checkFromText_BadValue(sshfp_txt + " extra text");
+ checkFromText_InvalidText("1 2 BUCKLEMYSHOE");
+ checkFromText_InvalidText(sshfp_txt + " extra text");
// yes, these are redundant to the last test cases in algorithmTypes
checkFromText_InvalidText(
@@ -232,12 +230,11 @@ TEST_F(Rdata_SSHFP_Test, toWire) {
this->obuffer.clear();
rdata_sshfp.toWire(this->obuffer);
- EXPECT_EQ(22, this->obuffer.getLength());
+ EXPECT_EQ(sizeof (rdata_sshfp_wiredata),
+ this->obuffer.getLength());
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- this->obuffer.getData(),
- this->obuffer.getLength(),
- rdata_sshfp_wiredata, sizeof(rdata_sshfp_wiredata));
+ matchWireData(rdata_sshfp_wiredata, sizeof(rdata_sshfp_wiredata),
+ obuffer.getData(), obuffer.getLength());
}
TEST_F(Rdata_SSHFP_Test, compare) {
@@ -254,8 +251,20 @@ TEST_F(Rdata_SSHFP_Test, getFingerprintType) {
EXPECT_EQ(1, rdata_sshfp.getFingerprintType());
}
-TEST_F(Rdata_SSHFP_Test, getFingerprintLen) {
- EXPECT_EQ(20, rdata_sshfp.getFingerprintLen());
+TEST_F(Rdata_SSHFP_Test, getFingerprint) {
+ const std::vector<uint8_t>& fingerprint =
+ rdata_sshfp.getFingerprint();
+
+ EXPECT_EQ(rdata_sshfp.getFingerprintLength(),
+ fingerprint.size());
+ for (int i = 0; i < fingerprint.size(); ++i) {
+ EXPECT_EQ(rdata_sshfp_wiredata[i + 2],
+ fingerprint.at(i));
+ }
+}
+
+TEST_F(Rdata_SSHFP_Test, getFingerprintLength) {
+ EXPECT_EQ(20, rdata_sshfp.getFingerprintLength());
}
TEST_F(Rdata_SSHFP_Test, emptyFingerprintFromWire) {
@@ -273,17 +282,15 @@ TEST_F(Rdata_SSHFP_Test, emptyFingerprintFromWire) {
EXPECT_EQ(4, rdf.getAlgorithmNumber());
EXPECT_EQ(9, rdf.getFingerprintType());
- EXPECT_EQ(0, rdf.getFingerprintLen());
+ EXPECT_EQ(0, rdf.getFingerprintLength());
this->obuffer.clear();
rdf.toWire(this->obuffer);
EXPECT_EQ(2, this->obuffer.getLength());
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- this->obuffer.getData(),
- this->obuffer.getLength(),
- rdf_wiredata, sizeof(rdf_wiredata));
+ matchWireData(rdf_wiredata, sizeof(rdf_wiredata),
+ obuffer.getData(), obuffer.getLength());
}
TEST_F(Rdata_SSHFP_Test, emptyFingerprintFromString) {
@@ -297,16 +304,14 @@ TEST_F(Rdata_SSHFP_Test, emptyFingerprintFromString) {
EXPECT_EQ(5, rdata_sshfp2.getAlgorithmNumber());
EXPECT_EQ(6, rdata_sshfp2.getFingerprintType());
- EXPECT_EQ(0, rdata_sshfp2.getFingerprintLen());
+ EXPECT_EQ(0, rdata_sshfp2.getFingerprintLength());
this->obuffer.clear();
rdata_sshfp2.toWire(this->obuffer);
EXPECT_EQ(2, this->obuffer.getLength());
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- this->obuffer.getData(),
- this->obuffer.getLength(),
- rdata_sshfp2_wiredata, sizeof(rdata_sshfp2_wiredata));
+ matchWireData(rdata_sshfp2_wiredata, sizeof(rdata_sshfp2_wiredata),
+ obuffer.getData(), obuffer.getLength());
}
}
diff --git a/src/lib/dns/tests/rdata_tlsa_unittest.cc b/src/lib/dns/tests/rdata_tlsa_unittest.cc
new file mode 100644
index 0000000000..30b608b244
--- /dev/null
+++ b/src/lib/dns/tests/rdata_tlsa_unittest.cc
@@ -0,0 +1,282 @@
+// Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or 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 ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS. IN NO EVENT SHALL ISC 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.
+
+#include <algorithm>
+#include <string>
+
+#include <util/buffer.h>
+#include <dns/messagerenderer.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rrclass.h>
+#include <dns/rrtype.h>
+
+#include <gtest/gtest.h>
+
+#include <dns/tests/unittest_util.h>
+#include <dns/tests/rdata_unittest.h>
+#include <util/unittests/wiredata.h>
+
+#include <boost/algorithm/string.hpp>
+
+using namespace std;
+using namespace isc;
+using namespace isc::dns;
+using namespace isc::util;
+using namespace isc::dns::rdata;
+using isc::UnitTestUtil;
+using isc::util::unittests::matchWireData;
+
+namespace {
+class Rdata_TLSA_Test : public RdataTest {
+protected:
+ Rdata_TLSA_Test() :
+ tlsa_txt("0 0 1 d2abde240d7cd3ee6b4b28c54df034b9"
+ "7983a1d16e8a410e4561cb106618e971"),
+ rdata_tlsa(tlsa_txt)
+ {}
+
+ void checkFromText_None(const string& rdata_str) {
+ checkFromText<generic::TLSA, isc::Exception, isc::Exception>(
+ rdata_str, rdata_tlsa, false, false);
+ }
+
+ void checkFromText_InvalidText(const string& rdata_str) {
+ checkFromText<generic::TLSA, InvalidRdataText, InvalidRdataText>(
+ rdata_str, rdata_tlsa, true, true);
+ }
+
+ void checkFromText_LexerError(const string& rdata_str) {
+ checkFromText
+ <generic::TLSA, InvalidRdataText, MasterLexer::LexerError>(
+ rdata_str, rdata_tlsa, true, true);
+ }
+
+ void checkFromText_BadString(const string& rdata_str) {
+ checkFromText
+ <generic::TLSA, InvalidRdataText, isc::Exception>(
+ rdata_str, rdata_tlsa, true, false);
+ }
+
+ const string tlsa_txt;
+ const generic::TLSA rdata_tlsa;
+};
+
+const uint8_t rdata_tlsa_wiredata[] = {
+ // certificate usage
+ 0x00,
+ // selector
+ 0x00,
+ // matching type
+ 0x01,
+ // certificate association data
+ 0xd2, 0xab, 0xde, 0x24, 0x0d, 0x7c, 0xd3, 0xee,
+ 0x6b, 0x4b, 0x28, 0xc5, 0x4d, 0xf0, 0x34, 0xb9,
+ 0x79, 0x83, 0xa1, 0xd1, 0x6e, 0x8a, 0x41, 0x0e,
+ 0x45, 0x61, 0xcb, 0x10, 0x66, 0x18, 0xe9, 0x71
+};
+
+TEST_F(Rdata_TLSA_Test, createFromText) {
+ // Basic test
+ checkFromText_None(tlsa_txt);
+
+ // With different spacing
+ checkFromText_None("0 0 1 d2abde240d7cd3ee6b4b28c54df034b9"
+ "7983a1d16e8a410e4561cb106618e971");
+
+ // Combination of lowercase and uppercase
+ checkFromText_None("0 0 1 D2ABDE240D7CD3EE6B4B28C54DF034B9"
+ "7983a1d16e8a410e4561cb106618e971");
+
+ // spacing in the certificate association data field
+ checkFromText_None("0 0 1 d2abde240d7cd3ee6b4b28c54df034b9"
+ " 7983a1d16e8a410e4561cb106618e971");
+
+ // multi-line certificate association data field
+ checkFromText_None("0 0 1 ( d2abde240d7cd3ee6b4b28c54df034b9\n"
+ " 7983a1d16e8a410e4561cb106618e971 )");
+
+ // string constructor throws if there's extra text,
+ // but lexer constructor doesn't
+ checkFromText_BadString(tlsa_txt + "\n" + tlsa_txt);
+}
+
+TEST_F(Rdata_TLSA_Test, fields) {
+ // Some of these may not be RFC conformant, but we relax the check
+ // in our code to work with other field values that may show up in
+ // the future.
+ EXPECT_NO_THROW(const generic::TLSA rdata_tlsa("1 0 1 12ab"));
+ EXPECT_NO_THROW(const generic::TLSA rdata_tlsa("2 0 1 12ab"));
+ EXPECT_NO_THROW(const generic::TLSA rdata_tlsa("3 0 1 12ab"));
+ EXPECT_NO_THROW(const generic::TLSA rdata_tlsa("128 0 1 12ab"));
+ EXPECT_NO_THROW(const generic::TLSA rdata_tlsa("255 0 1 12ab"));
+
+ EXPECT_NO_THROW(const generic::TLSA rdata_tlsa("0 1 1 12ab"));
+ EXPECT_NO_THROW(const generic::TLSA rdata_tlsa("0 2 1 12ab"));
+ EXPECT_NO_THROW(const generic::TLSA rdata_tlsa("0 3 1 12ab"));
+ EXPECT_NO_THROW(const generic::TLSA rdata_tlsa("0 128 1 12ab"));
+ EXPECT_NO_THROW(const generic::TLSA rdata_tlsa("0 255 1 12ab"));
+
+ EXPECT_NO_THROW(const generic::TLSA rdata_tlsa("0 0 1 12ab"));
+ EXPECT_NO_THROW(const generic::TLSA rdata_tlsa("0 0 2 12ab"));
+ EXPECT_NO_THROW(const generic::TLSA rdata_tlsa("0 0 3 12ab"));
+ EXPECT_NO_THROW(const generic::TLSA rdata_tlsa("0 0 128 12ab"));
+ EXPECT_NO_THROW(const generic::TLSA rdata_tlsa("0 0 255 12ab"));
+
+ // > 255 would be broken
+ EXPECT_THROW(const generic::TLSA rdata_tlsa("256 0 1 12ab"),
+ InvalidRdataText);
+ EXPECT_THROW(const generic::TLSA rdata_tlsa("0 256 1 12ab"),
+ InvalidRdataText);
+ EXPECT_THROW(const generic::TLSA rdata_tlsa("0 0 256 12ab"),
+ InvalidRdataText);
+}
+
+TEST_F(Rdata_TLSA_Test, badText) {
+ checkFromText_LexerError("1");
+ checkFromText_LexerError("ONE 2 3 123456789abcdef67890123456789abcdef67890");
+ checkFromText_LexerError("1 TWO 3 123456789abcdef67890123456789abcdef67890");
+ checkFromText_LexerError("1 2 THREE 123456789abcdef67890123456789abcdef67890");
+ checkFromText_InvalidText("1 2 3 BAABAABLACKSHEEP");
+ checkFromText_InvalidText(tlsa_txt + " extra text");
+
+ // yes, these are redundant to the last test cases in the .fields
+ // test
+ checkFromText_InvalidText(
+ "2345 1 2 123456789abcdef67890123456789abcdef67890");
+ checkFromText_InvalidText(
+ "3 1234 4 123456789abcdef67890123456789abcdef67890");
+ checkFromText_InvalidText(
+ "5 6 1234 123456789abcdef67890123456789abcdef67890");
+
+ // negative values are trapped in the lexer rather than the
+ // constructor
+ checkFromText_LexerError("-2 0 1 123456789abcdef67890123456789abcdef67890");
+ checkFromText_LexerError("0 -2 1 123456789abcdef67890123456789abcdef67890");
+ checkFromText_LexerError("0 0 -2 123456789abcdef67890123456789abcdef67890");
+}
+
+TEST_F(Rdata_TLSA_Test, copyAndAssign) {
+ // Copy construct
+ generic::TLSA rdata_tlsa2(rdata_tlsa);
+ EXPECT_EQ(0, rdata_tlsa.compare(rdata_tlsa2));
+
+ // Assignment, mainly to confirm it doesn't cause disruption.
+ rdata_tlsa2 = rdata_tlsa;
+ EXPECT_EQ(0, rdata_tlsa.compare(rdata_tlsa2));
+}
+
+TEST_F(Rdata_TLSA_Test, createFromWire) {
+ // Basic test
+ EXPECT_EQ(0, rdata_tlsa.compare(
+ *rdataFactoryFromFile(RRType("TLSA"), RRClass("IN"),
+ "rdata_tlsa_fromWire")));
+ // Combination of lowercase and uppercase
+ EXPECT_EQ(0, rdata_tlsa.compare(
+ *rdataFactoryFromFile(RRType("TLSA"), RRClass("IN"),
+ "rdata_tlsa_fromWire2")));
+ // certificate_usage=0, selector=0, matching_type=1
+ EXPECT_NO_THROW(rdataFactoryFromFile(RRType("TLSA"), RRClass("IN"),
+ "rdata_tlsa_fromWire3.wire"));
+
+ // certificate_usage=255, selector=0, matching_type=1
+ EXPECT_NO_THROW(rdataFactoryFromFile(RRType("TLSA"), RRClass("IN"),
+ "rdata_tlsa_fromWire4.wire"));
+
+ // certificate_usage=0, selector=255, matching_type=1
+ EXPECT_NO_THROW(rdataFactoryFromFile(RRType("TLSA"), RRClass("IN"),
+ "rdata_tlsa_fromWire5.wire"));
+
+ // certificate_usage=0, selector=0, matching_type=255
+ EXPECT_NO_THROW(rdataFactoryFromFile(RRType("TLSA"), RRClass("IN"),
+ "rdata_tlsa_fromWire6.wire"));
+
+ // certificate_usage=3, selector=1, matching_type=2
+ EXPECT_NO_THROW(rdataFactoryFromFile(RRType("TLSA"), RRClass("IN"),
+ "rdata_tlsa_fromWire7.wire"));
+
+ // short certificate association data
+ EXPECT_NO_THROW(rdataFactoryFromFile(RRType("TLSA"), RRClass("IN"),
+ "rdata_tlsa_fromWire8.wire"));
+
+ // certificate association data is shorter than rdata len
+ EXPECT_THROW(rdataFactoryFromFile(RRType("TLSA"), RRClass("IN"),
+ "rdata_tlsa_fromWire9"),
+ InvalidBufferPosition);
+
+ // certificate association data is missing
+ EXPECT_THROW(rdataFactoryFromFile(RRType("TLSA"), RRClass("IN"),
+ "rdata_tlsa_fromWire10"),
+ InvalidBufferPosition);
+
+ // certificate association data is empty
+ EXPECT_THROW(rdataFactoryFromFile(RRType("TLSA"), RRClass("IN"),
+ "rdata_tlsa_fromWire12"),
+ InvalidRdataLength);
+
+ // all RDATA is missing
+ EXPECT_THROW(rdataFactoryFromFile(RRType("TLSA"), RRClass("IN"),
+ "rdata_tlsa_fromWire11"),
+ InvalidBufferPosition);
+}
+
+TEST_F(Rdata_TLSA_Test, createFromParams) {
+ const generic::TLSA rdata_tlsa2(
+ 0, 0, 1, "d2abde240d7cd3ee6b4b28c54df034b9"
+ "7983a1d16e8a410e4561cb106618e971");
+ EXPECT_EQ(0, rdata_tlsa2.compare(rdata_tlsa));
+
+ // empty certificate association data should throw
+ EXPECT_THROW(const generic::TLSA rdata_tlsa2(0, 0, 1, ""),
+ InvalidRdataText);
+}
+
+TEST_F(Rdata_TLSA_Test, toText) {
+ EXPECT_TRUE(boost::iequals(tlsa_txt, rdata_tlsa.toText()));
+}
+
+TEST_F(Rdata_TLSA_Test, toWire) {
+ this->obuffer.clear();
+ rdata_tlsa.toWire(this->obuffer);
+
+ EXPECT_EQ(sizeof (rdata_tlsa_wiredata),
+ this->obuffer.getLength());
+
+ matchWireData(rdata_tlsa_wiredata, sizeof(rdata_tlsa_wiredata),
+ obuffer.getData(), obuffer.getLength());
+}
+
+TEST_F(Rdata_TLSA_Test, compare) {
+ const generic::TLSA rdata_tlsa2("0 0 0 d2abde240d7cd3ee6b4b28c54df034b9"
+ "7983a1d16e8a410e4561cb106618e971");
+ EXPECT_EQ(-1, rdata_tlsa2.compare(rdata_tlsa));
+ EXPECT_EQ(1, rdata_tlsa.compare(rdata_tlsa2));
+}
+
+TEST_F(Rdata_TLSA_Test, getCertificateUsage) {
+ EXPECT_EQ(0, rdata_tlsa.getCertificateUsage());
+}
+
+TEST_F(Rdata_TLSA_Test, getSelector) {
+ EXPECT_EQ(0, rdata_tlsa.getSelector());
+}
+
+TEST_F(Rdata_TLSA_Test, getMatchingType) {
+ EXPECT_EQ(1, rdata_tlsa.getMatchingType());
+}
+
+TEST_F(Rdata_TLSA_Test, getDataLength) {
+ EXPECT_EQ(32, rdata_tlsa.getDataLength());
+}
+}
diff --git a/src/lib/dns/tests/rdata_tsig_unittest.cc b/src/lib/dns/tests/rdata_tsig_unittest.cc
index 270a1b284a..ab8fa273bf 100644
--- a/src/lib/dns/tests/rdata_tsig_unittest.cc
+++ b/src/lib/dns/tests/rdata_tsig_unittest.cc
@@ -29,32 +29,34 @@
#include <dns/tests/unittest_util.h>
#include <dns/tests/rdata_unittest.h>
+#include <util/unittests/wiredata.h>
-using isc::UnitTestUtil;
using namespace std;
using namespace isc;
using namespace isc::dns;
using namespace isc::util;
using namespace isc::dns::rdata;
+using isc::UnitTestUtil;
+using isc::util::unittests::matchWireData;
namespace {
class Rdata_TSIG_Test : public RdataTest {
protected:
Rdata_TSIG_Test() :
- // no MAC or Other Data
+ // no MAC or Other Data
valid_text1("hmac-md5.sig-alg.reg.int. 1286779327 300 "
"0 16020 BADKEY 0"),
- // MAC but no Other Data
+ // MAC but no Other Data
valid_text2("hmac-sha256. 1286779327 300 12 "
"FAKEFAKEFAKEFAKE 16020 BADSIG 0"),
- // MAC and Other Data
+ // MAC and Other Data
valid_text3("hmac-sha1. 1286779327 300 12 "
"FAKEFAKEFAKEFAKE 16020 BADTIME 6 FAKEFAKE"),
- // MAC and Other Data (with Error that doesn't expect Other Data)
+ // MAC and Other Data (with Error that doesn't expect Other Data)
valid_text4("hmac-sha1. 1286779327 300 12 "
"FAKEFAKEFAKEFAKE 16020 BADSIG 6 FAKEFAKE"),
- // numeric error code
+ // numeric error code
valid_text5("hmac-sha256. 1286779327 300 12 "
"FAKEFAKEFAKEFAKE 16020 2845 0"),
rdata_tsig(valid_text1)
@@ -204,9 +206,8 @@ fromWireCommonChecks(const any::TSIG& tsig) {
EXPECT_EQ(300, tsig.getFudge());
vector<uint8_t> expect_mac(32, 'x');
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- &expect_mac[0], expect_mac.size(),
- tsig.getMAC(), tsig.getMACSize());
+ matchWireData(&expect_mac[0], expect_mac.size(),
+ tsig.getMAC(), tsig.getMACSize());
EXPECT_EQ(2845, tsig.getOriginalID());
@@ -234,9 +235,8 @@ TEST_F(Rdata_TSIG_Test, createFromWireWithOtherData) {
expect_data[3] = ((otherdata >> 16) & 0xff);
expect_data[4] = ((otherdata >> 8) & 0xff);
expect_data[5] = (otherdata & 0xff);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- &expect_data[0], expect_data.size(),
- tsig.getOtherData(), tsig.getOtherLen());
+ matchWireData(&expect_data[0], expect_data.size(),
+ tsig.getOtherData(), tsig.getOtherLen());
}
TEST_F(Rdata_TSIG_Test, createFromWireWithoutMAC) {
@@ -351,27 +351,24 @@ Rdata_TSIG_Test::toWireCommonChecks(Output& output) const {
// read the expected wire format data and trim the RDLEN part.
UnitTestUtil::readWireData("rdata_tsig_toWire1.wire", expect_data);
expect_data.erase(expect_data.begin(), expect_data.begin() + 2);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- &expect_data[0], expect_data.size(),
- output.getData(), output.getLength());
+ matchWireData(&expect_data[0], expect_data.size(),
+ output.getData(), output.getLength());
expect_data.clear();
output.clear();
any::TSIG(valid_text2).toWire(output);
UnitTestUtil::readWireData("rdata_tsig_toWire2.wire", expect_data);
expect_data.erase(expect_data.begin(), expect_data.begin() + 2);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- &expect_data[0], expect_data.size(),
- output.getData(), output.getLength());
+ matchWireData(&expect_data[0], expect_data.size(),
+ output.getData(), output.getLength());
expect_data.clear();
output.clear();
any::TSIG(valid_text3).toWire(output);
UnitTestUtil::readWireData("rdata_tsig_toWire3.wire", expect_data);
expect_data.erase(expect_data.begin(), expect_data.begin() + 2);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- &expect_data[0], expect_data.size(),
- output.getData(), output.getLength());
+ matchWireData(&expect_data[0], expect_data.size(),
+ output.getData(), output.getLength());
}
TEST_F(Rdata_TSIG_Test, toWireBuffer) {
@@ -388,9 +385,8 @@ TEST_F(Rdata_TSIG_Test, toWireRenderer) {
renderer.writeUint16(42); // RDLEN
rdata_tsig.toWire(renderer);
UnitTestUtil::readWireData("rdata_tsig_toWire4.wire", expect_data);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- &expect_data[0], expect_data.size(),
- renderer.getData(), renderer.getLength());
+ matchWireData(&expect_data[0], expect_data.size(),
+ renderer.getData(), renderer.getLength());
// check algorithm can be used as a compression target.
expect_data.clear();
@@ -399,9 +395,8 @@ TEST_F(Rdata_TSIG_Test, toWireRenderer) {
rdata_tsig.toWire(renderer);
renderer.writeName(Name("hmac-md5.sig-alg.reg.int"));
UnitTestUtil::readWireData("rdata_tsig_toWire5.wire", expect_data);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- &expect_data[0], expect_data.size(),
- renderer.getData(), renderer.getLength());
+ matchWireData(&expect_data[0], expect_data.size(),
+ renderer.getData(), renderer.getLength());
}
TEST_F(Rdata_TSIG_Test, toText) {
diff --git a/src/lib/dns/tests/rdata_txt_like_unittest.cc b/src/lib/dns/tests/rdata_txt_like_unittest.cc
index 2a83ea9892..e5283273ae 100644
--- a/src/lib/dns/tests/rdata_txt_like_unittest.cc
+++ b/src/lib/dns/tests/rdata_txt_like_unittest.cc
@@ -21,6 +21,8 @@
#include <dns/tests/unittest_util.h>
#include <dns/tests/rdata_unittest.h>
+#include <util/unittests/wiredata.h>
+
#include <gtest/gtest.h>
#include <boost/bind.hpp>
@@ -29,11 +31,12 @@
#include <sstream>
#include <vector>
-using isc::UnitTestUtil;
using namespace std;
using namespace isc::dns;
using namespace isc::util;
using namespace isc::dns::rdata;
+using isc::UnitTestUtil;
+using isc::util::unittests::matchWireData;
namespace {
@@ -133,31 +136,31 @@ TYPED_TEST(Rdata_TXT_LIKE_Test, createFromText) {
// Null character-string.
this->obuffer.clear();
TypeParam(string("\"\"")).toWire(this->obuffer);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- this->obuffer.getData(), this->obuffer.getLength(),
- wiredata_nulltxt, sizeof(wiredata_nulltxt));
+ matchWireData(wiredata_nulltxt, sizeof(wiredata_nulltxt),
+ this->obuffer.getData(), this->obuffer.getLength());
+
this->obuffer.clear();
TypeParam(this->lexer, NULL, MasterLoader::MANY_ERRORS, this->loader_cb).
toWire(this->obuffer);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- this->obuffer.getData(), this->obuffer.getLength(),
- wiredata_nulltxt, sizeof(wiredata_nulltxt));
+ matchWireData(wiredata_nulltxt, sizeof(wiredata_nulltxt),
+ this->obuffer.getData(), this->obuffer.getLength());
+
EXPECT_EQ(MasterToken::END_OF_LINE, this->lexer.getNextToken().getType());
// Longest possible character-string.
this->obuffer.clear();
TypeParam(string(255, 'a')).toWire(this->obuffer);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- this->obuffer.getData(), this->obuffer.getLength(),
- &this->wiredata_longesttxt[0],
- this->wiredata_longesttxt.size());
+ matchWireData(&this->wiredata_longesttxt[0],
+ this->wiredata_longesttxt.size(),
+ this->obuffer.getData(), this->obuffer.getLength());
+
this->obuffer.clear();
TypeParam(this->lexer, NULL, MasterLoader::MANY_ERRORS, this->loader_cb).
toWire(this->obuffer);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- this->obuffer.getData(), this->obuffer.getLength(),
- &this->wiredata_longesttxt[0],
- this->wiredata_longesttxt.size());
+ matchWireData(&this->wiredata_longesttxt[0],
+ this->wiredata_longesttxt.size(),
+ this->obuffer.getData(), this->obuffer.getLength());
+
EXPECT_EQ(MasterToken::END_OF_LINE, this->lexer.getNextToken().getType());
// Too long text for a valid character-string.
@@ -268,10 +271,8 @@ TYPED_TEST(Rdata_TXT_LIKE_Test, createFromWire) {
sizeof(wiredata_txt_like));
expected_data.insert(expected_data.end(), wiredata_txt_like,
wiredata_txt_like + sizeof(wiredata_txt_like));
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- this->obuffer.getData(),
- this->obuffer.getLength(),
- &expected_data[0], expected_data.size());
+ matchWireData(&expected_data[0], expected_data.size(),
+ this->obuffer.getData(), this->obuffer.getLength());
// Largest length of data. There's nothing special, but should be
// constructed safely, and the content should be identical to the original
@@ -283,11 +284,8 @@ TYPED_TEST(Rdata_TXT_LIKE_Test, createFromWire) {
TypeParam largest_txt_like(ibuffer, largest_txt_like_data.size());
this->obuffer.clear();
largest_txt_like.toWire(this->obuffer);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- this->obuffer.getData(),
- this->obuffer.getLength(),
- &largest_txt_like_data[0],
- largest_txt_like_data.size());
+ matchWireData(&largest_txt_like_data[0], largest_txt_like_data.size(),
+ this->obuffer.getData(), this->obuffer.getLength());
// rdlen parameter is out of range. This is a rare event because we'd
// normally call the constructor via a polymorphic wrapper, where the
@@ -315,18 +313,14 @@ TYPED_TEST(Rdata_TXT_LIKE_Test, createFromLexer) {
TYPED_TEST(Rdata_TXT_LIKE_Test, toWireBuffer) {
this->rdata_txt_like.toWire(this->obuffer);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- this->obuffer.getData(),
- this->obuffer.getLength(),
- wiredata_txt_like, sizeof(wiredata_txt_like));
+ matchWireData(wiredata_txt_like, sizeof(wiredata_txt_like),
+ this->obuffer.getData(), this->obuffer.getLength());
}
TYPED_TEST(Rdata_TXT_LIKE_Test, toWireRenderer) {
this->rdata_txt_like.toWire(this->renderer);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- this->renderer.getData(),
- this->renderer.getLength(),
- wiredata_txt_like, sizeof(wiredata_txt_like));
+ matchWireData(wiredata_txt_like, sizeof(wiredata_txt_like),
+ this->renderer.getData(), this->renderer.getLength());
}
TYPED_TEST(Rdata_TXT_LIKE_Test, toText) {
diff --git a/src/lib/dns/tests/rdata_unittest.cc b/src/lib/dns/tests/rdata_unittest.cc
index 3839fbd24f..f29b61cf56 100644
--- a/src/lib/dns/tests/rdata_unittest.cc
+++ b/src/lib/dns/tests/rdata_unittest.cc
@@ -28,14 +28,17 @@
#include <dns/tests/unittest_util.h>
#include <dns/tests/rdata_unittest.h>
+#include <util/unittests/wiredata.h>
+
#include <boost/bind.hpp>
#include <boost/lexical_cast.hpp>
-using isc::UnitTestUtil;
using namespace std;
using namespace isc::dns;
using namespace isc::util;
using namespace isc::dns::rdata;
+using isc::UnitTestUtil;
+using isc::util::unittests::matchWireData;
namespace isc {
namespace dns {
@@ -211,6 +214,14 @@ TEST_F(RdataTest, createRdataWithLexer) {
"file does not end with newline");
}
+TEST_F(RdataTest, getLength) {
+ const in::AAAA aaaa_rdata("2001:db8::1");
+ EXPECT_EQ(16, aaaa_rdata.getLength());
+
+ const generic::TXT txt_rdata("Hello World");
+ EXPECT_EQ(12, txt_rdata.getLength());
+}
+
}
}
}
@@ -290,14 +301,14 @@ TEST_F(Rdata_Unknown_Test, createFromText) {
// the length should be 16-bit unsigned integer
EXPECT_THROW(generic::Generic("\\# 65536 a1b2c30d"), InvalidRdataLength);
EXPECT_THROW(generic::Generic("\\# -1 a1b2c30d"), InvalidRdataLength);
- EXPECT_THROW(generic::Generic("\\# 1.1 a1"), InvalidRdataText);
+ EXPECT_THROW(generic::Generic("\\# 1.1 a1"), InvalidRdataLength);
EXPECT_THROW(generic::Generic("\\# 0a 00010203040506070809"),
- InvalidRdataText);
+ InvalidRdataLength);
// should reject if the special token is missing.
EXPECT_THROW(generic::Generic("4 a1b2c30d"), InvalidRdataText);
// the special token, the RDLENGTH and the data must be space separated.
EXPECT_THROW(generic::Generic("\\#0"), InvalidRdataText);
- EXPECT_THROW(generic::Generic("\\# 1ff"), InvalidRdataText);
+ EXPECT_THROW(generic::Generic("\\# 1ff"), InvalidRdataLength);
}
TEST_F(Rdata_Unknown_Test, createFromWire) {
@@ -393,16 +404,14 @@ TEST_F(Rdata_Unknown_Test, toText) {
TEST_F(Rdata_Unknown_Test, toWireBuffer) {
rdata_unknown.toWire(obuffer);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- obuffer.getData(), obuffer.getLength(),
- wiredata_unknown, sizeof(wiredata_unknown));
+ matchWireData(wiredata_unknown, sizeof(wiredata_unknown),
+ obuffer.getData(), obuffer.getLength());
}
TEST_F(Rdata_Unknown_Test, toWireRenderer) {
rdata_unknown.toWire(renderer);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- renderer.getData(), renderer.getLength(),
- wiredata_unknown, sizeof(wiredata_unknown));
+ matchWireData(wiredata_unknown, sizeof(wiredata_unknown),
+ renderer.getData(), renderer.getLength());
}
TEST_F(Rdata_Unknown_Test, compare) {
diff --git a/src/lib/dns/tests/rdata_unittest.h b/src/lib/dns/tests/rdata_unittest.h
index 04af07c2fe..8c7f954eeb 100644
--- a/src/lib/dns/tests/rdata_unittest.h
+++ b/src/lib/dns/tests/rdata_unittest.h
@@ -27,8 +27,6 @@
#include <string>
#include <sstream>
-using namespace isc::util;
-
namespace isc {
namespace dns {
namespace rdata {
@@ -77,7 +75,7 @@ protected:
}
}
- OutputBuffer obuffer;
+ isc::util::OutputBuffer obuffer;
MessageRenderer renderer;
/// This is an RDATA object of some "unknown" RR type so that it can be
/// used to test the compare() method against a well-known RR type.
diff --git a/src/lib/dns/tests/rdatafields_unittest.cc b/src/lib/dns/tests/rdatafields_unittest.cc
index ef83ed4b26..a6bead79bb 100644
--- a/src/lib/dns/tests/rdatafields_unittest.cc
+++ b/src/lib/dns/tests/rdatafields_unittest.cc
@@ -24,14 +24,17 @@
#include <dns/rdatafields.h>
#include <dns/tests/unittest_util.h>
+#include <util/unittests/wiredata.h>
+
#include <gtest/gtest.h>
-using isc::UnitTestUtil;
using namespace std;
using namespace isc::dns;
using namespace isc::dns::rdata;
+using isc::UnitTestUtil;
using isc::util::OutputBuffer;
using isc::util::InputBuffer;
+using isc::util::unittests::matchWireData;
namespace {
class RdataFieldsTest : public ::testing::Test {
@@ -67,23 +70,21 @@ RdataFieldsTest::constructCommonTests(const RdataFields& fields,
const uint8_t* const expected_data,
const size_t expected_data_len)
{
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, expected_data,
- expected_data_len, fields.getData(),
- fields.getDataLength());
+ matchWireData(expected_data, expected_data_len,
+ fields.getData(), fields.getDataLength());
+
EXPECT_EQ(sizeof(RdataFields::FieldSpec), fields.getFieldSpecDataSize());
EXPECT_EQ(1, fields.getFieldCount());
EXPECT_EQ(RdataFields::DATA, fields.getFieldSpec(0).type);
EXPECT_EQ(4, fields.getFieldSpec(0).len);
fields.toWire(obuffer);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, expected_data,
- expected_data_len, obuffer.getData(),
- obuffer.getLength());
+ matchWireData(expected_data, expected_data_len,
+ obuffer.getData(), obuffer.getLength());
fields.toWire(renderer);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, expected_data,
- expected_data_len, renderer.getData(),
- renderer.getLength());
+ matchWireData(expected_data, expected_data_len,
+ renderer.getData(), renderer.getLength());
}
TEST_F(RdataFieldsTest, constructFromRdata) {
@@ -112,17 +113,15 @@ RdataFieldsTest::constructCommonTestsNS(const RdataFields& fields) {
UnitTestUtil::readWireData("rdatafields1.wire", expected_wire);
other_name.toWire(obuffer);
fields.toWire(obuffer);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, &expected_wire[0],
- expected_wire.size(), obuffer.getData(),
- obuffer.getLength());
+ matchWireData(&expected_wire[0], expected_wire.size(),
+ obuffer.getData(), obuffer.getLength());
expected_wire.clear();
UnitTestUtil::readWireData("rdatafields2.wire", expected_wire);
other_name.toWire(renderer);
fields.toWire(renderer);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, &expected_wire[0],
- expected_wire.size(), renderer.getData(),
- renderer.getLength());
+ matchWireData(&expected_wire[0], expected_wire.size(),
+ renderer.getData(), renderer.getLength());
}
TEST_F(RdataFieldsTest, constructFromRdataNS) {
@@ -150,14 +149,12 @@ RdataFieldsTest::constructCommonTestsTXT(const RdataFields& fields) {
EXPECT_EQ(expected_wire.size(), fields.getFieldSpec(0).len);
fields.toWire(obuffer);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, &expected_wire[0],
- expected_wire.size(), obuffer.getData(),
- obuffer.getLength());
+ matchWireData(&expected_wire[0], expected_wire.size(),
+ obuffer.getData(), obuffer.getLength());
fields.toWire(renderer);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, &expected_wire[0],
- expected_wire.size(), renderer.getData(),
- renderer.getLength());
+ matchWireData(&expected_wire[0], expected_wire.size(),
+ renderer.getData(), renderer.getLength());
}
TEST_F(RdataFieldsTest, constructFromRdataTXT) {
@@ -208,9 +205,8 @@ RdataFieldsTest::constructCommonTestsRRSIG(const RdataFields& fields) {
obuffer.writeUint16(fields.getDataLength());
fields.toWire(obuffer);
other_name.toWire(obuffer);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, &expected_wire[0],
- expected_wire.size(), obuffer.getData(),
- obuffer.getLength());
+ matchWireData(&expected_wire[0], expected_wire.size(),
+ obuffer.getData(), obuffer.getLength());
expected_wire.clear();
UnitTestUtil::readWireData("rdatafields6.wire", expected_wire);
@@ -218,9 +214,8 @@ RdataFieldsTest::constructCommonTestsRRSIG(const RdataFields& fields) {
renderer.writeUint16(fields.getDataLength());
fields.toWire(renderer); // the signer field won't be compressed
other_name.toWire(renderer); // but will be used as a compression target
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, &expected_wire[0],
- expected_wire.size(), renderer.getData(),
- renderer.getLength());
+ matchWireData(&expected_wire[0], expected_wire.size(),
+ renderer.getData(), renderer.getLength());
}
TEST_F(RdataFieldsTest, constructFromRdataRRSIG) {
diff --git a/src/lib/dns/tests/rrclass_unittest.cc b/src/lib/dns/tests/rrclass_unittest.cc
index b79aedff5f..c20125e0b5 100644
--- a/src/lib/dns/tests/rrclass_unittest.cc
+++ b/src/lib/dns/tests/rrclass_unittest.cc
@@ -19,6 +19,7 @@
#include <dns/rrclass.h>
#include <dns/tests/unittest_util.h>
+#include <util/unittests/wiredata.h>
#include <boost/scoped_ptr.hpp>
@@ -27,6 +28,7 @@ using namespace isc;
using namespace isc::dns;
using namespace isc::util;
using boost::scoped_ptr;
+using isc::util::unittests::matchWireData;
namespace {
class RRClassTest : public ::testing::Test {
@@ -115,9 +117,8 @@ TEST_F(RRClassTest, toWireBuffer) {
rrclass_0x8000.toWire(obuffer);
rrclass_max.toWire(obuffer);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- obuffer.getData(), obuffer.getLength(),
- wiredata, sizeof(wiredata));
+ matchWireData(wiredata, sizeof (wiredata),
+ obuffer.getData(), obuffer.getLength());
}
TEST_F(RRClassTest, toWireRenderer) {
@@ -127,9 +128,8 @@ TEST_F(RRClassTest, toWireRenderer) {
rrclass_0x8000.toWire(renderer);
rrclass_max.toWire(renderer);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- renderer.getData(), renderer.getLength(),
- wiredata, sizeof(wiredata));
+ matchWireData(wiredata, sizeof (wiredata),
+ renderer.getData(), renderer.getLength());
}
TEST_F(RRClassTest, wellKnownClasss) {
diff --git a/src/lib/dns/tests/rrset_unittest.cc b/src/lib/dns/tests/rrset_unittest.cc
index da3eb52267..fc75b7731c 100644
--- a/src/lib/dns/tests/rrset_unittest.cc
+++ b/src/lib/dns/tests/rrset_unittest.cc
@@ -23,18 +23,19 @@
#include <dns/rrset.h>
#include <dns/tests/unittest_util.h>
+#include <util/unittests/wiredata.h>
#include <gtest/gtest.h>
#include <stdexcept>
#include <sstream>
-using isc::UnitTestUtil;
-
using namespace std;
using namespace isc::dns;
using namespace isc::util;
using namespace isc::dns::rdata;
+using isc::UnitTestUtil;
+using isc::util::unittests::matchWireData;
namespace {
class RRsetTest : public ::testing::Test {
@@ -130,7 +131,7 @@ TEST_F(RRsetTest, isSameKind) {
void
addRdataTestCommon(const RRset& rrset) {
- EXPECT_EQ(2, rrset.getRdataCount());
+ ASSERT_EQ(2, rrset.getRdataCount());
RdataIteratorPtr it = rrset.getRdataIterator(); // cursor is set to the 1st
EXPECT_FALSE(it->isLast());
@@ -157,14 +158,34 @@ TEST_F(RRsetTest, addRdataPtr) {
rrset_a_empty.addRdata(createRdata(rrset_a_empty.getType(),
rrset_a_empty.getClass(),
"192.0.2.2"));
+ addRdataTestCommon(rrset_a_empty);
+}
- addRdataTestCommon(rrset_a);
-
+TEST_F(RRsetTest, addRdataPtrMismatched) {
// Pointer version of addRdata() doesn't type check and does allow to
//add a different type of Rdata as a result.
+
+ // Type mismatch
rrset_a_empty.addRdata(createRdata(RRType::NS(), RRClass::IN(),
"ns.example.com."));
- EXPECT_EQ(3, rrset_a_empty.getRdataCount());
+ EXPECT_EQ(1, rrset_a_empty.getRdataCount());
+
+ // Class mismatch
+ rrset_ch_txt.addRdata(createRdata(RRType::TXT(), RRClass::IN(),
+ "Test String"));
+ EXPECT_EQ(1, rrset_ch_txt.getRdataCount());
+}
+
+TEST_F(RRsetTest, addRdataString) {
+ rrset_a_empty.addRdata("192.0.2.1");
+ rrset_a_empty.addRdata("192.0.2.2");
+
+ addRdataTestCommon(rrset_a_empty);
+
+ // String version of addRdata() will throw for bad RDATA for
+ // RRType::A().
+ EXPECT_THROW(rrset_a_empty.addRdata("ns.example.com."), InvalidRdataText);
+ addRdataTestCommon(rrset_a_empty);
}
TEST_F(RRsetTest, iterator) {
@@ -204,12 +225,36 @@ TEST_F(RRsetTest, toText) {
rrset_none_a_empty.toText());
}
+TEST_F(RRsetTest, getLength) {
+ // Empty RRset should throw
+ EXPECT_THROW(rrset_a_empty.getLength(), EmptyRRset);
+
+ // Unless it is type ANY or NONE:
+ // test.example.com = 1 + 4 + 1 + 7 + 1 + 3 + 1 = 18 octets
+ // TYPE field = 2 octets
+ // CLASS field = 2 octets
+ // TTL field = 4 octets
+ // RDLENGTH field = 2 octets
+ // Total = 18 + 2 + 2 + 4 + 2 = 28 octets
+ EXPECT_EQ(28, rrset_any_a_empty.getLength());
+ EXPECT_EQ(28, rrset_none_a_empty.getLength());
+
+ // RRset with single RDATA
+ // 28 (above) + 4 octets (A RDATA) = 32 octets
+ rrset_a_empty.addRdata(in::A("192.0.2.1"));
+ EXPECT_EQ(32, rrset_a_empty.getLength());
+
+ // 2 A RRs
+ rrset_a_empty.addRdata(in::A("192.0.2.2"));
+ EXPECT_EQ(32 + 32, rrset_a_empty.getLength());
+}
+
TEST_F(RRsetTest, toWireBuffer) {
rrset_a.toWire(buffer);
UnitTestUtil::readWireData("rrset_toWire1", wiredata);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, buffer.getData(),
- buffer.getLength(), &wiredata[0], wiredata.size());
+ matchWireData(&wiredata[0], wiredata.size(),
+ buffer.getData(), buffer.getLength());
// toWire() cannot be performed for an empty RRset except when
// class=ANY or class=NONE.
@@ -222,14 +267,15 @@ TEST_F(RRsetTest, toWireBuffer) {
rrset_any_a_empty.toWire(buffer);
wiredata.clear();
UnitTestUtil::readWireData("rrset_toWire3", wiredata);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, buffer.getData(),
- buffer.getLength(), &wiredata[0], wiredata.size());
+ matchWireData(&wiredata[0], wiredata.size(),
+ buffer.getData(), buffer.getLength());
+
buffer.clear();
rrset_none_a_empty.toWire(buffer);
wiredata.clear();
UnitTestUtil::readWireData("rrset_toWire4", wiredata);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, buffer.getData(),
- buffer.getLength(), &wiredata[0], wiredata.size());
+ matchWireData(&wiredata[0], wiredata.size(),
+ buffer.getData(), buffer.getLength());
}
TEST_F(RRsetTest, toWireRenderer) {
@@ -239,8 +285,8 @@ TEST_F(RRsetTest, toWireRenderer) {
rrset_ns.toWire(renderer);
UnitTestUtil::readWireData("rrset_toWire2", wiredata);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, renderer.getData(),
- renderer.getLength(), &wiredata[0], wiredata.size());
+ matchWireData(&wiredata[0], wiredata.size(),
+ renderer.getData(), renderer.getLength());
// toWire() cannot be performed for an empty RRset except when
// class=ANY or class=NONE.
@@ -253,15 +299,15 @@ TEST_F(RRsetTest, toWireRenderer) {
rrset_any_a_empty.toWire(renderer);
wiredata.clear();
UnitTestUtil::readWireData("rrset_toWire3", wiredata);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, renderer.getData(),
- renderer.getLength(), &wiredata[0], wiredata.size());
+ matchWireData(&wiredata[0], wiredata.size(),
+ renderer.getData(), renderer.getLength());
renderer.clear();
rrset_none_a_empty.toWire(renderer);
wiredata.clear();
UnitTestUtil::readWireData("rrset_toWire4", wiredata);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, renderer.getData(),
- renderer.getLength(), &wiredata[0], wiredata.size());
+ matchWireData(&wiredata[0], wiredata.size(),
+ renderer.getData(), renderer.getLength());
}
// test operator<<. We simply confirm it appends the result of toText().
@@ -365,4 +411,38 @@ TEST_F(RRsetRRSIGTest, toText) {
"20100322084538 20100220084538 1 example.com. FAKEFAKEFAKEFAKE\n",
rrset_aaaa->toText());
}
+
+TEST_F(RRsetRRSIGTest, getLength) {
+ // A RR
+ // test.example.com = 1 + 4 + 1 + 7 + 1 + 3 + 1 = 18 octets
+ // TYPE field = 2 octets
+ // CLASS field = 2 octets
+ // TTL field = 4 octets
+ // RDLENGTH field = 2 octets
+ // A RDATA = 4 octets
+ // Total = 18 + 2 + 2 + 4 + 2 + 4 = 32 octets
+
+ // 2 A RRs
+ EXPECT_EQ(32 + 32, rrset_a->getLength());
+
+ // RRSIG
+ // test.example.com = 1 + 4 + 1 + 7 + 1 + 3 + 1 = 18 octets
+ // TYPE field = 2 octets
+ // CLASS field = 2 octets
+ // TTL field = 4 octets
+ // RDLENGTH field = 2 octets
+ // RRSIG RDATA = 40 octets
+ // Total = 18 + 2 + 2 + 4 + 2 + 40 = 68 octets
+ RRsetPtr my_rrsig(new RRset(test_name, RRClass::IN(),
+ RRType::RRSIG(), RRTTL(3600)));
+ my_rrsig->addRdata(generic::RRSIG("A 4 3 3600 "
+ "20000101000000 20000201000000 "
+ "12345 example.com. FAKEFAKEFAKE"));
+ EXPECT_EQ(68, my_rrsig->getLength());
+
+ // RRset with attached RRSIG
+ rrset_a->addRRsig(my_rrsig);
+
+ EXPECT_EQ(32 + 32 + 68, rrset_a->getLength());
+}
}
diff --git a/src/lib/dns/tests/rrttl_unittest.cc b/src/lib/dns/tests/rrttl_unittest.cc
index c849c444ca..23b7c2d9ce 100644
--- a/src/lib/dns/tests/rrttl_unittest.cc
+++ b/src/lib/dns/tests/rrttl_unittest.cc
@@ -19,6 +19,7 @@
#include <dns/rrttl.h>
#include <dns/tests/unittest_util.h>
+#include <util/unittests/wiredata.h>
#include <boost/scoped_ptr.hpp>
@@ -27,6 +28,7 @@ using namespace isc;
using namespace isc::dns;
using namespace isc::util;
using boost::scoped_ptr;
+using isc::util::unittests::matchWireData;
namespace {
class RRTTLTest : public ::testing::Test {
@@ -193,9 +195,8 @@ TEST_F(RRTTLTest, toWireBuffer) {
ttl_32bit.toWire(obuffer);
ttl_max.toWire(obuffer);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- obuffer.getData(), obuffer.getLength(),
- wiredata, sizeof(wiredata));
+ matchWireData(wiredata, sizeof(wiredata),
+ obuffer.getData(), obuffer.getLength());
}
TEST_F(RRTTLTest, toWireRenderer) {
@@ -205,9 +206,8 @@ TEST_F(RRTTLTest, toWireRenderer) {
ttl_32bit.toWire(renderer);
ttl_max.toWire(renderer);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- renderer.getData(), renderer.getLength(),
- wiredata, sizeof(wiredata));
+ matchWireData(wiredata, sizeof(wiredata),
+ renderer.getData(), renderer.getLength());
}
TEST_F(RRTTLTest, equal) {
diff --git a/src/lib/dns/tests/rrtype_unittest.cc b/src/lib/dns/tests/rrtype_unittest.cc
index ee302a1c41..84d52a9131 100644
--- a/src/lib/dns/tests/rrtype_unittest.cc
+++ b/src/lib/dns/tests/rrtype_unittest.cc
@@ -19,11 +19,13 @@
#include <dns/rrtype.h>
#include <dns/tests/unittest_util.h>
+#include <util/unittests/wiredata.h>
using namespace std;
using namespace isc;
using namespace isc::dns;
using namespace isc::util;
+using isc::util::unittests::matchWireData;
namespace {
class RRTypeTest : public ::testing::Test {
@@ -107,9 +109,8 @@ TEST_F(RRTypeTest, toWireBuffer) {
rrtype_0x8000.toWire(obuffer);
rrtype_max.toWire(obuffer);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- obuffer.getData(), obuffer.getLength(),
- wiredata, sizeof(wiredata));
+ matchWireData(wiredata, sizeof(wiredata),
+ obuffer.getData(), obuffer.getLength());
}
TEST_F(RRTypeTest, toWireRenderer) {
@@ -119,9 +120,8 @@ TEST_F(RRTypeTest, toWireRenderer) {
rrtype_0x8000.toWire(renderer);
rrtype_max.toWire(renderer);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- renderer.getData(), renderer.getLength(),
- wiredata, sizeof(wiredata));
+ matchWireData(wiredata, sizeof(wiredata),
+ renderer.getData(), renderer.getLength());
}
TEST_F(RRTypeTest, wellKnownTypes) {
diff --git a/src/lib/dns/tests/testdata/.gitignore b/src/lib/dns/tests/testdata/.gitignore
index a0a14f4a19..f18ac2fb8c 100644
--- a/src/lib/dns/tests/testdata/.gitignore
+++ b/src/lib/dns/tests/testdata/.gitignore
@@ -87,6 +87,12 @@
/rdata_sshfp_fromWire6.wire
/rdata_sshfp_fromWire7.wire
/rdata_sshfp_fromWire8.wire
+/rdata_tlsa_fromWire3.wire
+/rdata_tlsa_fromWire4.wire
+/rdata_tlsa_fromWire5.wire
+/rdata_tlsa_fromWire6.wire
+/rdata_tlsa_fromWire7.wire
+/rdata_tlsa_fromWire8.wire
/rdata_tsig_fromWire1.wire
/rdata_tsig_fromWire2.wire
/rdata_tsig_fromWire3.wire
@@ -105,6 +111,10 @@
/rdata_txt_fromWire3.wire
/rdata_txt_fromWire4.wire
/rdata_txt_fromWire5.wire
+/rdata_caa_fromWire1.wire
+/rdata_caa_fromWire2.wire
+/rdata_caa_fromWire3.wire
+/rdata_caa_fromWire4.wire
/rdatafields1.wire
/rdatafields2.wire
/rdatafields3.wire
diff --git a/src/lib/dns/tests/testdata/Makefile.am b/src/lib/dns/tests/testdata/Makefile.am
index b6d7e35ada..fadf30eb60 100644
--- a/src/lib/dns/tests/testdata/Makefile.am
+++ b/src/lib/dns/tests/testdata/Makefile.am
@@ -56,6 +56,9 @@ BUILT_SOURCES += rdata_afsdb_toWire1.wire rdata_afsdb_toWire2.wire
BUILT_SOURCES += rdata_soa_toWireUncompressed.wire
BUILT_SOURCES += rdata_txt_fromWire2.wire rdata_txt_fromWire3.wire
BUILT_SOURCES += rdata_txt_fromWire4.wire rdata_txt_fromWire5.wire
+BUILT_SOURCES += rdata_tlsa_fromWire3.wire rdata_tlsa_fromWire4.wire
+BUILT_SOURCES += rdata_tlsa_fromWire5.wire rdata_tlsa_fromWire6.wire
+BUILT_SOURCES += rdata_tlsa_fromWire7.wire rdata_tlsa_fromWire8.wire
BUILT_SOURCES += rdata_tsig_fromWire1.wire rdata_tsig_fromWire2.wire
BUILT_SOURCES += rdata_tsig_fromWire3.wire rdata_tsig_fromWire4.wire
BUILT_SOURCES += rdata_tsig_fromWire5.wire rdata_tsig_fromWire6.wire
@@ -64,6 +67,8 @@ BUILT_SOURCES += rdata_tsig_fromWire9.wire
BUILT_SOURCES += rdata_tsig_toWire1.wire rdata_tsig_toWire2.wire
BUILT_SOURCES += rdata_tsig_toWire3.wire rdata_tsig_toWire4.wire
BUILT_SOURCES += rdata_tsig_toWire5.wire
+BUILT_SOURCES += rdata_caa_fromWire1.wire rdata_caa_fromWire2.wire
+BUILT_SOURCES += rdata_caa_fromWire3.wire rdata_caa_fromWire4.wire
BUILT_SOURCES += tsigrecord_toWire1.wire tsigrecord_toWire2.wire
BUILT_SOURCES += tsig_verify1.wire tsig_verify2.wire tsig_verify3.wire
BUILT_SOURCES += tsig_verify4.wire tsig_verify5.wire tsig_verify6.wire
@@ -127,7 +132,9 @@ EXTRA_DIST += rdata_nsec3_fromWire10.spec rdata_nsec3_fromWire11.spec
EXTRA_DIST += rdata_nsec3_fromWire12.spec rdata_nsec3_fromWire13.spec
EXTRA_DIST += rdata_nsec3_fromWire14.spec rdata_nsec3_fromWire15.spec
EXTRA_DIST += rdata_nsec3_fromWire16.spec rdata_nsec3_fromWire17.spec
-EXTRA_DIST += rdata_opt_fromWire rdata_rrsig_fromWire1
+EXTRA_DIST += rdata_opt_fromWire1 rdata_opt_fromWire2
+EXTRA_DIST += rdata_opt_fromWire3 rdata_opt_fromWire4
+EXTRA_DIST += rdata_rrsig_fromWire1
EXTRA_DIST += rdata_rrsig_fromWire2.spec
EXTRA_DIST += rdata_rp_fromWire1.spec rdata_rp_fromWire2.spec
EXTRA_DIST += rdata_rp_fromWire3.spec rdata_rp_fromWire4.spec
@@ -159,6 +166,12 @@ EXTRA_DIST += rrcode16_fromWire1 rrcode16_fromWire2
EXTRA_DIST += rrcode32_fromWire1 rrcode32_fromWire2
EXTRA_DIST += rrset_toWire1 rrset_toWire2
EXTRA_DIST += rrset_toWire3 rrset_toWire4
+EXTRA_DIST += rdata_tlsa_fromWire rdata_tlsa_fromWire2
+EXTRA_DIST += rdata_tlsa_fromWire3.spec rdata_tlsa_fromWire4.spec
+EXTRA_DIST += rdata_tlsa_fromWire5.spec rdata_tlsa_fromWire6.spec
+EXTRA_DIST += rdata_tlsa_fromWire7.spec rdata_tlsa_fromWire8.spec
+EXTRA_DIST += rdata_tlsa_fromWire9 rdata_tlsa_fromWire10
+EXTRA_DIST += rdata_tlsa_fromWire11 rdata_tlsa_fromWire12
EXTRA_DIST += rdata_tsig_fromWire1.spec rdata_tsig_fromWire2.spec
EXTRA_DIST += rdata_tsig_fromWire3.spec rdata_tsig_fromWire4.spec
EXTRA_DIST += rdata_tsig_fromWire5.spec rdata_tsig_fromWire6.spec
@@ -167,6 +180,9 @@ EXTRA_DIST += rdata_tsig_fromWire9.spec
EXTRA_DIST += rdata_tsig_toWire1.spec rdata_tsig_toWire2.spec
EXTRA_DIST += rdata_tsig_toWire3.spec rdata_tsig_toWire4.spec
EXTRA_DIST += rdata_tsig_toWire5.spec
+EXTRA_DIST += rdata_caa_fromWire1.spec rdata_caa_fromWire2.spec
+EXTRA_DIST += rdata_caa_fromWire3.spec rdata_caa_fromWire4.spec
+EXTRA_DIST += rdata_caa_fromWire5 rdata_caa_fromWire6
EXTRA_DIST += tsigrecord_toWire1.spec tsigrecord_toWire2.spec
EXTRA_DIST += tsig_verify1.spec tsig_verify2.spec tsig_verify3.spec
EXTRA_DIST += tsig_verify4.spec tsig_verify5.spec tsig_verify6.spec
diff --git a/src/lib/dns/tests/testdata/rdata_caa_fromWire1.spec b/src/lib/dns/tests/testdata/rdata_caa_fromWire1.spec
new file mode 100644
index 0000000000..d21987c7eb
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_caa_fromWire1.spec
@@ -0,0 +1,6 @@
+#
+# The simplest form of CAA: all default parameters
+#
+[custom]
+sections: caa
+[caa]
diff --git a/src/lib/dns/tests/testdata/rdata_caa_fromWire2.spec b/src/lib/dns/tests/testdata/rdata_caa_fromWire2.spec
new file mode 100644
index 0000000000..867e43d048
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_caa_fromWire2.spec
@@ -0,0 +1,7 @@
+#
+# Mixed case CAA tag field.
+#
+[custom]
+sections: caa
+[caa]
+tag: 'ISSue'
diff --git a/src/lib/dns/tests/testdata/rdata_caa_fromWire3.spec b/src/lib/dns/tests/testdata/rdata_caa_fromWire3.spec
new file mode 100644
index 0000000000..9297151df0
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_caa_fromWire3.spec
@@ -0,0 +1,7 @@
+#
+# Missing CAA value field.
+#
+[custom]
+sections: caa
+[caa]
+value: ''
diff --git a/src/lib/dns/tests/testdata/rdata_caa_fromWire4.spec b/src/lib/dns/tests/testdata/rdata_caa_fromWire4.spec
new file mode 100644
index 0000000000..53e16b12a3
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_caa_fromWire4.spec
@@ -0,0 +1,7 @@
+#
+# Missing CAA value field.
+#
+[custom]
+sections: caa
+[caa]
+tag: ''
diff --git a/src/lib/dns/tests/testdata/rdata_caa_fromWire5 b/src/lib/dns/tests/testdata/rdata_caa_fromWire5
new file mode 100644
index 0000000000..123011fdb3
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_caa_fromWire5
@@ -0,0 +1,6 @@
+# Test where CAA value field is shorter than the RDATA length
+
+# CAA RDATA, RDLEN=32
+0020
+# FLAGS=0 TAG=c VALUE=ca.example.net
+00 01 63 63612e6578616d706c652e6e6574
diff --git a/src/lib/dns/tests/testdata/rdata_caa_fromWire6 b/src/lib/dns/tests/testdata/rdata_caa_fromWire6
new file mode 100644
index 0000000000..1a35a1aef7
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_caa_fromWire6
@@ -0,0 +1,4 @@
+# Test where RDATA is completely missing
+
+# CAA RDATA, RDLEN=32
+0020
diff --git a/src/lib/dns/tests/testdata/rdata_opt_fromWire b/src/lib/dns/tests/testdata/rdata_opt_fromWire
deleted file mode 100644
index 0ca5f6aa0e..0000000000
--- a/src/lib/dns/tests/testdata/rdata_opt_fromWire
+++ /dev/null
@@ -1,16 +0,0 @@
-#
-# various kinds of OPT RDATA stored in an input buffer
-#
-# empty RDATA (which is okay)
-#
-# 0 1 (bytes)
- 00 00
-#
-# an OPT RR containing an NSID Option
-# code=3 len=3 ID value (opaque)
-# 2 3 4 5 6 7 8 9 10
- 00 07 00 03 00 03 00 01 02
-#
-# short buffer (this can be tested only at the end of the buffer)
-# 1 2 3 4 5
- 00 04 c0 00 02
diff --git a/src/lib/dns/tests/testdata/rdata_opt_fromWire1 b/src/lib/dns/tests/testdata/rdata_opt_fromWire1
new file mode 100644
index 0000000000..f2eb680d0f
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_opt_fromWire1
@@ -0,0 +1,15 @@
+# Various kinds of OPT RDATA stored in an input buffer
+#
+# Empty RDATA (which is okay)
+#
+# 0 1 (bytes)
+ 00 00
+#
+# An OPT RR containing an NSID Option
+# code=3 len=3 ID value (opaque)
+# 2 3 4 5 6 7 8 9 10
+ 00 07 00 2a 00 03 00 01 02
+#
+# Short buffer (this can be tested only at the end of the buffer)
+# 1 2 3 4 5
+ 00 04 c0 00 02
diff --git a/src/lib/dns/tests/testdata/rdata_opt_fromWire2 b/src/lib/dns/tests/testdata/rdata_opt_fromWire2
new file mode 100644
index 0000000000..2c5a11fe54
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_opt_fromWire2
@@ -0,0 +1,4 @@
+# Short RDATA length
+#
+# OPT RDATA, RDLEN=1
+0001
diff --git a/src/lib/dns/tests/testdata/rdata_opt_fromWire3 b/src/lib/dns/tests/testdata/rdata_opt_fromWire3
new file mode 100644
index 0000000000..52db1d8c33
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_opt_fromWire3
@@ -0,0 +1,8 @@
+# Short RDATA length (in second pseudo RR)
+#
+# OPT RDATA, RDLEN=8
+0008
+# Pseudo RR 1 of size 7 (code=3, len=3)
+00 03 00 03 00 01 02
+# Pseudo RR 2 of size 7 exhausts RDLEN (code=4, len=3)
+00 04 00 03 00 01 02
diff --git a/src/lib/dns/tests/testdata/rdata_opt_fromWire4 b/src/lib/dns/tests/testdata/rdata_opt_fromWire4
new file mode 100644
index 0000000000..a302127b1a
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_opt_fromWire4
@@ -0,0 +1,9 @@
+# Sum of option lengths would overflow RDLEN
+#
+# OPT RDATA, RDLEN=14 (0x000e)
+000e
+# Pseudo RR 1 (code=3, len=3)
+00 03 00 03 00 01 02
+# Pseudo RR 2 (code=4, len=65535 overflows RDLEN)
+00 04 ff ff 00 01 02
+# Rest of option data is omitted...
diff --git a/src/lib/dns/tests/testdata/rdata_tlsa_fromWire b/src/lib/dns/tests/testdata/rdata_tlsa_fromWire
new file mode 100644
index 0000000000..38e279ceca
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tlsa_fromWire
@@ -0,0 +1,4 @@
+# TLSA RDATA, RDLEN=35
+0023
+# CERTIFICATE_USAGE=0 SELECTOR=0 MATCHING_TYPE=1 CERTIFICATE_ASSOCIATION_DATA=...
+00 00 01 d2abde240d7cd3ee6b4b28c54df034b97983a1d16e8a410e4561cb106618e971
diff --git a/src/lib/dns/tests/testdata/rdata_tlsa_fromWire10 b/src/lib/dns/tests/testdata/rdata_tlsa_fromWire10
new file mode 100644
index 0000000000..67cecb15de
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tlsa_fromWire10
@@ -0,0 +1,6 @@
+# Test where certificate association data is missing.
+
+# TLSA RDATA, RDLEN=35
+0023
+# CERTIFICATE_USAGE=0 SELECTOR=0 MATCHING_TYPE=1 CERTIFICATE_ASSOCIATION_DATA=(missing)
+00 00 01
diff --git a/src/lib/dns/tests/testdata/rdata_tlsa_fromWire11 b/src/lib/dns/tests/testdata/rdata_tlsa_fromWire11
new file mode 100644
index 0000000000..4b8ec930e2
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tlsa_fromWire11
@@ -0,0 +1,4 @@
+# Test where RDATA is completely missing
+
+# TLSA RDATA, RDLEN=35
+0023
diff --git a/src/lib/dns/tests/testdata/rdata_tlsa_fromWire12 b/src/lib/dns/tests/testdata/rdata_tlsa_fromWire12
new file mode 100644
index 0000000000..71c7b9ceb5
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tlsa_fromWire12
@@ -0,0 +1,4 @@
+# TLSA RDATA, RDLEN=3
+0003
+# CERTIFICATE_USAGE=0 SELECTOR=0 MATCHING_TYPE=1 CERTIFICATE_ASSOCIATION_DATA=(none)
+03 01 02
diff --git a/src/lib/dns/tests/testdata/rdata_tlsa_fromWire2 b/src/lib/dns/tests/testdata/rdata_tlsa_fromWire2
new file mode 100644
index 0000000000..36ce27806f
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tlsa_fromWire2
@@ -0,0 +1,4 @@
+# TLSA RDATA, RDLEN=35
+0023
+# CERTIFICATE_USAGE=0 SELECTOR=0 MATCHING_TYPE=1 CERTIFICATE_ASSOCIATION_DATA=...
+00 00 01 d2abde240d7cd3ee6b4b28c54df034b97983A1D16E8A410E4561CB106618E971
diff --git a/src/lib/dns/tests/testdata/rdata_tlsa_fromWire3.spec b/src/lib/dns/tests/testdata/rdata_tlsa_fromWire3.spec
new file mode 100644
index 0000000000..39c8057d6a
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tlsa_fromWire3.spec
@@ -0,0 +1,7 @@
+#
+# TLSA RDATA
+#
+[custom]
+sections: tlsa
+[tlsa]
+certificate_usage: 0
diff --git a/src/lib/dns/tests/testdata/rdata_tlsa_fromWire4.spec b/src/lib/dns/tests/testdata/rdata_tlsa_fromWire4.spec
new file mode 100644
index 0000000000..d97ae6a9e8
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tlsa_fromWire4.spec
@@ -0,0 +1,7 @@
+#
+# TLSA RDATA
+#
+[custom]
+sections: tlsa
+[tlsa]
+certificate_usage: 255
diff --git a/src/lib/dns/tests/testdata/rdata_tlsa_fromWire5.spec b/src/lib/dns/tests/testdata/rdata_tlsa_fromWire5.spec
new file mode 100644
index 0000000000..cc3e296b84
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tlsa_fromWire5.spec
@@ -0,0 +1,7 @@
+#
+# TLSA RDATA
+#
+[custom]
+sections: tlsa
+[tlsa]
+selector: 255
diff --git a/src/lib/dns/tests/testdata/rdata_tlsa_fromWire6.spec b/src/lib/dns/tests/testdata/rdata_tlsa_fromWire6.spec
new file mode 100644
index 0000000000..eed0ab90a6
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tlsa_fromWire6.spec
@@ -0,0 +1,7 @@
+#
+# TLSA RDATA
+#
+[custom]
+sections: tlsa
+[tlsa]
+matching_type: 255
diff --git a/src/lib/dns/tests/testdata/rdata_tlsa_fromWire7.spec b/src/lib/dns/tests/testdata/rdata_tlsa_fromWire7.spec
new file mode 100644
index 0000000000..576df1ef36
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tlsa_fromWire7.spec
@@ -0,0 +1,9 @@
+#
+# TLSA RDATA
+#
+[custom]
+sections: tlsa
+[tlsa]
+certificate_usage: 3
+selector: 1
+matching_type: 2
diff --git a/src/lib/dns/tests/testdata/rdata_tlsa_fromWire8.spec b/src/lib/dns/tests/testdata/rdata_tlsa_fromWire8.spec
new file mode 100644
index 0000000000..ef5c108dff
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tlsa_fromWire8.spec
@@ -0,0 +1,7 @@
+#
+# TLSA RDATA
+#
+[custom]
+sections: tlsa
+[tlsa]
+certificate_association_data: '0123'
diff --git a/src/lib/dns/tests/testdata/rdata_tlsa_fromWire9 b/src/lib/dns/tests/testdata/rdata_tlsa_fromWire9
new file mode 100644
index 0000000000..fc4560af51
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_tlsa_fromWire9
@@ -0,0 +1,7 @@
+# Test where certificate association data length is smaller than what
+# RDATA length indicates.
+
+# TLSA RDATA, RDLEN=64
+0040
+# CERTIFICATE_USAGE=0 SELECTOR=0 MATCHING_TYPE=1 CERTIFICATE_ASSOCIATION_DATA=(32 bytes)
+00 00 01 d2abde240d7cd3ee6b4b28c54df034b97983a1d16e8a410e4561cb106618e971
diff --git a/src/lib/dns/tests/tsig_unittest.cc b/src/lib/dns/tests/tsig_unittest.cc
index 458a6e0cf3..6348e9cbb5 100644
--- a/src/lib/dns/tests/tsig_unittest.cc
+++ b/src/lib/dns/tests/tsig_unittest.cc
@@ -40,6 +40,7 @@
#include <dns/tsigrecord.h>
#include <dns/tests/unittest_util.h>
+#include <util/unittests/wiredata.h>
using namespace std;
using namespace isc;
@@ -48,6 +49,7 @@ using namespace isc::util;
using namespace isc::util::encode;
using namespace isc::dns::rdata;
using isc::UnitTestUtil;
+using isc::util::unittests::matchWireData;
// See dnssectime.cc
namespace isc {
@@ -188,7 +190,7 @@ TSIGTest::createMessageAndSign(uint16_t id, const Name& qname,
(ctx->getState() == TSIGContext::INIT) ?
TSIGContext::SENT_REQUEST : TSIGContext::SENT_RESPONSE;
- message.toWire(renderer, *ctx);
+ message.toWire(renderer, ctx);
message.clear(Message::PARSE);
InputBuffer buffer(renderer.getData(), renderer.getLength());
@@ -224,15 +226,14 @@ commonSignChecks(ConstTSIGRecordPtr tsig, uint16_t expected_qid,
EXPECT_EQ(expected_timesigned, tsig_rdata.getTimeSigned());
EXPECT_EQ(300, tsig_rdata.getFudge());
EXPECT_EQ(expected_maclen, tsig_rdata.getMACSize());
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- tsig_rdata.getMAC(), tsig_rdata.getMACSize(),
- expected_mac, expected_maclen);
+ matchWireData(expected_mac, expected_maclen,
+ tsig_rdata.getMAC(), tsig_rdata.getMACSize());
+
EXPECT_EQ(expected_qid, tsig_rdata.getOriginalID());
EXPECT_EQ(expected_error, tsig_rdata.getError());
EXPECT_EQ(expected_otherlen, tsig_rdata.getOtherLen());
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- tsig_rdata.getOtherData(), tsig_rdata.getOtherLen(),
- expected_otherdata, expected_otherlen);
+ matchWireData(expected_otherdata, expected_otherlen,
+ tsig_rdata.getOtherData(), tsig_rdata.getOtherLen());
}
void
diff --git a/src/lib/dns/tests/tsigkey_unittest.cc b/src/lib/dns/tests/tsigkey_unittest.cc
index eaf4040d44..8a9d86f73a 100644
--- a/src/lib/dns/tests/tsigkey_unittest.cc
+++ b/src/lib/dns/tests/tsigkey_unittest.cc
@@ -23,10 +23,12 @@
#include <dns/tsigkey.h>
#include <dns/tests/unittest_util.h>
+#include <util/unittests/wiredata.h>
using namespace std;
using namespace isc::dns;
using isc::UnitTestUtil;
+using isc::util::unittests::matchWireData;
namespace {
class TSIGKeyTest : public ::testing::Test {
@@ -72,15 +74,16 @@ TEST_F(TSIGKeyTest, construct) {
secret.c_str(), secret.size());
EXPECT_EQ(key_name, key.getKeyName());
EXPECT_EQ(Name("hmac-md5.sig-alg.reg.int"), key.getAlgorithmName());
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, secret.c_str(),
- secret.size(), key.getSecret(), key.getSecretLength());
+ matchWireData(secret.c_str(), secret.size(),
+ key.getSecret(), key.getSecretLength());
TSIGKey key_short_md5(key_name, TSIGKey::HMACMD5_SHORT_NAME(),
secret.c_str(), secret.size());
- EXPECT_EQ(key_name, key.getKeyName());
- EXPECT_EQ(Name("hmac-md5.sig-alg.reg.int"), key.getAlgorithmName());
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, secret.c_str(),
- secret.size(), key.getSecret(), key.getSecretLength());
+ EXPECT_EQ(key_name, key_short_md5.getKeyName());
+ EXPECT_EQ(Name("hmac-md5.sig-alg.reg.int"),
+ key_short_md5.getAlgorithmName());
+ matchWireData(secret.c_str(), secret.size(),
+ key_short_md5.getSecret(), key_short_md5.getSecretLength());
// "unknown" algorithm is only accepted with empty secret.
EXPECT_THROW(TSIGKey(key_name, Name("unknown-alg"),
@@ -113,9 +116,8 @@ void
compareTSIGKeys(const TSIGKey& expect, const TSIGKey& actual) {
EXPECT_EQ(expect.getKeyName(), actual.getKeyName());
EXPECT_EQ(expect.getAlgorithmName(), actual.getAlgorithmName());
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- expect.getSecret(), expect.getSecretLength(),
- actual.getSecret(), actual.getSecretLength());
+ matchWireData(expect.getSecret(), expect.getSecretLength(),
+ actual.getSecret(), actual.getSecretLength());
}
TEST_F(TSIGKeyTest, copyConstruct) {
@@ -249,9 +251,8 @@ TEST_F(TSIGKeyRingTest, find) {
EXPECT_EQ(TSIGKeyRing::SUCCESS, result1.code);
EXPECT_EQ(key_name, result1.key->getKeyName());
EXPECT_EQ(TSIGKey::HMACSHA256_NAME(), result1.key->getAlgorithmName());
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, secret, secret_len,
- result1.key->getSecret(),
- result1.key->getSecretLength());
+ matchWireData(secret, secret_len,
+ result1.key->getSecret(), result1.key->getSecretLength());
// If either key name or algorithm doesn't match, search should fail.
const TSIGKeyRing::FindResult result2 =
@@ -268,9 +269,8 @@ TEST_F(TSIGKeyRingTest, find) {
EXPECT_EQ(TSIGKeyRing::SUCCESS, result4.code);
EXPECT_EQ(key_name, result4.key->getKeyName());
EXPECT_EQ(TSIGKey::HMACSHA256_NAME(), result4.key->getAlgorithmName());
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, secret, secret_len,
- result4.key->getSecret(),
- result4.key->getSecretLength());
+ matchWireData(secret, secret_len,
+ result4.key->getSecret(), result4.key->getSecretLength());
}
TEST_F(TSIGKeyRingTest, findFromSome) {
diff --git a/src/lib/dns/tests/tsigrecord_unittest.cc b/src/lib/dns/tests/tsigrecord_unittest.cc
index 532681ac2d..9c08fe0dfe 100644
--- a/src/lib/dns/tests/tsigrecord_unittest.cc
+++ b/src/lib/dns/tests/tsigrecord_unittest.cc
@@ -29,12 +29,14 @@
#include <dns/tsigrecord.h>
#include <dns/tests/unittest_util.h>
+#include <util/unittests/wiredata.h>
using namespace std;
using namespace isc::util;
using namespace isc::dns;
using namespace isc::dns::rdata;
using isc::UnitTestUtil;
+using isc::util::unittests::matchWireData;
namespace {
class TSIGRecordTest : public ::testing::Test {
@@ -108,16 +110,14 @@ TEST_F(TSIGRecordTest, fromParams) {
TEST_F(TSIGRecordTest, recordToWire) {
UnitTestUtil::readWireData("tsigrecord_toWire1.wire", data);
EXPECT_EQ(1, test_record.toWire(renderer));
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- renderer.getData(), renderer.getLength(),
- &data[0], data.size());
+ matchWireData(&data[0], data.size(),
+ renderer.getData(), renderer.getLength());
// Same test for a dumb buffer
buffer.clear();
EXPECT_EQ(1, test_record.toWire(buffer));
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- buffer.getData(), buffer.getLength(),
- &data[0], data.size());
+ matchWireData(&data[0], data.size(),
+ buffer.getData(), buffer.getLength());
}
TEST_F(TSIGRecordTest, recordToOLongToWire) {
@@ -139,9 +139,8 @@ TEST_F(TSIGRecordTest, recordToWireAfterNames) {
renderer.writeName(TSIGKey::HMACMD5_NAME());
renderer.writeName(Name("foo.example.com"));
EXPECT_EQ(1, test_record.toWire(renderer));
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- renderer.getData(), renderer.getLength(),
- &data[0], data.size());
+ matchWireData(&data[0], data.size(),
+ renderer.getData(), renderer.getLength());
}
TEST_F(TSIGRecordTest, toText) {
diff --git a/src/lib/dns/tests/unittest_util.cc b/src/lib/dns/tests/unittest_util.cc
index 66d49a8af4..bf4c8cbf33 100644
--- a/src/lib/dns/tests/unittest_util.cc
+++ b/src/lib/dns/tests/unittest_util.cc
@@ -132,33 +132,6 @@ UnitTestUtil::readWireData(const string& datastr,
}
::testing::AssertionResult
-UnitTestUtil::matchWireData(const char*, const char*, const char*, const char*,
- const void* data1, size_t len1,
- const void* data2, size_t len2)
-{
- ::testing::Message msg;
- size_t cmplen = min(len1, len2);
-
- for (size_t i = 0; i < cmplen; i++) {
- int ch1 = static_cast<const uint8_t*>(data1)[i];
- int ch2 = static_cast<const uint8_t*>(data2)[i];
- if (ch1 != ch2) {
- msg << "Wire data mismatch at " << i << "th byte\n"
- << " Actual: " << ch1 << "\n"
- << "Expected: " << ch2 << "\n";
- return (::testing::AssertionFailure(msg));
- }
- }
- if (len1 != len2) {
- msg << "Wire data mismatch in length:\n"
- << " Actual: " << len1 << "\n"
- << "Expected: " << len2 << "\n";
- return (::testing::AssertionFailure(msg));
- }
- return (::testing::AssertionSuccess());
-}
-
-::testing::AssertionResult
UnitTestUtil::matchName(const char*, const char*,
const isc::dns::Name& name1,
const isc::dns::Name& name2)
diff --git a/src/lib/dns/tests/unittest_util.h b/src/lib/dns/tests/unittest_util.h
index f50df14ab2..1d65f8d8bc 100644
--- a/src/lib/dns/tests/unittest_util.h
+++ b/src/lib/dns/tests/unittest_util.h
@@ -46,28 +46,6 @@ public:
std::vector<unsigned char>& data);
///
- /// Compare len1 bytes of data1 with len2 bytes of data2 as binary data.
- ///
- /// If they don't match report the point of mismatch in the google test
- /// format. This method is expected to be used from the EXPECT_PRED_FORMAT4
- /// macro of google test as follows:
- /// \code EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
- /// actual_data, actual_data_len,
- /// expected_data, expected_data_len); \endcode
- /// Parameters from dataexp1 to lenexp2 are passed via the macro but will
- /// be ignored by this method.
- /// Note: newer versions of google test supports the direct use of
- /// AssertionResult with the EXPECT_TRUE macro, which would be more
- /// intuitive, but to be as compatible as possible we use the more primitive
- /// macro, i.e., EXPECT_PRED_FORMAT4.
- ///
- static ::testing::AssertionResult
- matchWireData(const char* dataexp1, const char* lenexp1,
- const char* dataexp2, const char* lenexp2,
- const void* data1, size_t len1,
- const void* data2, size_t len2);
-
- ///
/// Compare two names.
///
/// This check method uses \c Name::compare() for comparison, which performs
diff --git a/src/lib/dns/tsig.cc b/src/lib/dns/tsig.cc
index d7ffcf8fa7..b6e1716d67 100644
--- a/src/lib/dns/tsig.cc
+++ b/src/lib/dns/tsig.cc
@@ -79,7 +79,7 @@ struct TSIGContext::TSIGContextImpl {
key_.getSecret(), key_.getSecretLength(),
key_.getAlgorithm()),
deleteHMAC);
- } catch (const Exception&) {
+ } catch (const isc::Exception&) {
return;
}
digest_len_ = hmac_->getOutputLength();
@@ -289,20 +289,20 @@ TSIGContext::getTSIGLength() const {
//
// The space required for an TSIG record is:
//
- // n1 bytes for the (key) name
- // 2 bytes for the type
- // 2 bytes for the class
- // 4 bytes for the ttl
- // 2 bytes for the rdlength
- // n2 bytes for the algorithm name
- // 6 bytes for the time signed
- // 2 bytes for the fudge
- // 2 bytes for the MAC size
- // x bytes for the MAC
- // 2 bytes for the original id
- // 2 bytes for the error
- // 2 bytes for the other data length
- // y bytes for the other data (at most)
+ // n1 bytes for the (key) name
+ // 2 bytes for the type
+ // 2 bytes for the class
+ // 4 bytes for the ttl
+ // 2 bytes for the rdlength
+ // n2 bytes for the algorithm name
+ // 6 bytes for the time signed
+ // 2 bytes for the fudge
+ // 2 bytes for the MAC size
+ // x bytes for the MAC
+ // 2 bytes for the original id
+ // 2 bytes for the error
+ // 2 bytes for the other data length
+ // y bytes for the other data (at most)
// ---------------------------------
// 26 + n1 + n2 + x + y bytes
//
diff --git a/src/lib/dns/tsigkey.cc b/src/lib/dns/tsigkey.cc
index 24a6f579bd..862d3005eb 100644
--- a/src/lib/dns/tsigkey.cc
+++ b/src/lib/dns/tsigkey.cc
@@ -141,7 +141,7 @@ TSIGKey::TSIGKey(const std::string& str) : impl_(NULL) {
impl_ = new TSIGKeyImpl(Name(keyname_str), algo_name, algorithm,
secret.empty() ? NULL : &secret[0],
secret.size());
- } catch (const Exception& e) {
+ } catch (const isc::Exception& e) {
// 'reduce' the several types of exceptions name parsing and
// Base64 decoding can throw to just the InvalidParameter
isc_throw(InvalidParameter, e.what());