From 93445f2e2a578c547adb2b9e5443468165636383 Mon Sep 17 00:00:00 2001 From: "Jeremy C. Reed" Date: Wed, 8 May 2013 18:29:23 -0500 Subject: [trac2945] miscellaneous doxygen warnings worked on Still have lots to do. Some of these marked with TODO indicating needing further work (but better than it was before). --- src/lib/dns/masterload.h | 2 +- src/lib/dns/nsec3hash.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src/lib/dns') diff --git a/src/lib/dns/masterload.h b/src/lib/dns/masterload.h index 44b3d62c29..5303785b8b 100644 --- a/src/lib/dns/masterload.h +++ b/src/lib/dns/masterload.h @@ -234,7 +234,7 @@ void masterLoad(const char* const filename, const Name& origin, /// each RRset. /// \param source A string to use in error messages if zone content is bad /// (e.g. the file name when reading from a file). If this value is NULL, -/// or left out, the error will use the string '' +/// or left out, the error will use the string '\'. void masterLoad(std::istream& input, const Name& origin, const RRClass& zone_class, MasterLoadCallback callback, const char* source = NULL); diff --git a/src/lib/dns/nsec3hash.h b/src/lib/dns/nsec3hash.h index f1ca1a3c2c..42b5117cb4 100644 --- a/src/lib/dns/nsec3hash.h +++ b/src/lib/dns/nsec3hash.h @@ -122,7 +122,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 static NSEC3Hash* create(uint8_t algorithm, uint16_t iterations, const uint8_t* salt_data, size_t salt_length); @@ -233,7 +233,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; -- cgit v1.2.3 From 96bb3a81d983daaf45ba92807d9a6597511192e1 Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Wed, 8 Jan 2014 06:57:27 +0530 Subject: [2517] Add tests for RRSIG toWire() methods --- src/lib/dns/tests/rdata_rrsig_unittest.cc | 49 +++++++++++++++++++++++++++++-- 1 file changed, 47 insertions(+), 2 deletions(-) (limited to 'src/lib/dns') diff --git a/src/lib/dns/tests/rdata_rrsig_unittest.cc b/src/lib/dns/tests/rdata_rrsig_unittest.cc index 2d075ece97..7c54fad025 100644 --- a/src/lib/dns/tests/rdata_rrsig_unittest.cc +++ b/src/lib/dns/tests/rdata_rrsig_unittest.cc @@ -35,6 +35,45 @@ using namespace isc::util; using namespace isc::dns::rdata; 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 +338,19 @@ TEST_F(Rdata_RRSIG_Test, createFromLexer) { } TEST_F(Rdata_RRSIG_Test, toWireRenderer) { - // FIXME: This doesn't check the result. rdata_rrsig.toWire(renderer); + + EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, + renderer.getData(), renderer.getLength(), + wiredata_rrsig, sizeof(wiredata_rrsig)); } TEST_F(Rdata_RRSIG_Test, toWireBuffer) { - // FIXME: This doesn't check the result. rdata_rrsig.toWire(obuffer); + + EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, + obuffer.getData(), obuffer.getLength(), + wiredata_rrsig, sizeof(wiredata_rrsig)); } TEST_F(Rdata_RRSIG_Test, createFromWire) { -- cgit v1.2.3 From 18c3e8911a8e7c007fc95a33d449ca4e25d9d176 Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Fri, 10 Jan 2014 08:46:02 +0530 Subject: [2518] Move NameParserException to exceptions.h header --- src/lib/dns/exceptions.h | 10 ++++++++++ src/lib/dns/name.h | 11 +---------- 2 files changed, 11 insertions(+), 10 deletions(-) (limited to 'src/lib/dns') diff --git a/src/lib/dns/exceptions.h b/src/lib/dns/exceptions.h index 070b152c2b..d7adeddd7f 100644 --- a/src/lib/dns/exceptions.h +++ b/src/lib/dns/exceptions.h @@ -50,6 +50,16 @@ public: DNSProtocolError(file, line, what) {} virtual const Rcode& getRcode() const; }; + +/// +/// \brief Base class for name parser exceptions. +/// +class NameParserException : public isc::Exception { +public: + NameParserException(const char* file, size_t line, const char* what) : + isc::Exception(file, line, what) {} +}; + } } #endif // DNS_EXCEPTIONS_H 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 #include -#include +#include namespace isc { namespace util { @@ -31,15 +31,6 @@ class OutputBuffer; 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. -- cgit v1.2.3 From 4976235a26688d12d2c2a51f13ef66dc38ff9ee9 Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Fri, 10 Jan 2014 15:57:16 +0530 Subject: [2426] Support generic version of rdata::createRdata(text) in generic RDATA Also adjust tests correcting the expected behaviour. --- src/lib/dns/rdata.cc | 115 +++++++++++++++++------------------- src/lib/dns/rdata.h | 2 +- src/lib/dns/tests/rdata_unittest.cc | 6 +- 3 files changed, 59 insertions(+), 64 deletions(-) (limited to 'src/lib/dns') diff --git a/src/lib/dns/rdata.cc b/src/lib/dns/rdata.cc index f42c349f2d..cdd03c155c 100644 --- a/src/lib/dns/rdata.cc +++ b/src/lib/dns/rdata.cc @@ -15,6 +15,7 @@ #include #include +#include #include #include @@ -212,93 +213,87 @@ Generic::Generic(isc::util::InputBuffer& buffer, size_t rdata_len) { } void -Generic::constructHelper(const std::string& rdata_string) { - istringstream iss(rdata_string); - string unknown_mark; - iss >> unknown_mark; - if (unknown_mark != "\\#") { +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"); + uint32_t rdlen; + + 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 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)) { + 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) { + lexer.ungetToken(); + + 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"); + "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); + try { + std::istringstream ss(rdata_string); + MasterLexer lexer; + lexer.pushSource(ss); + + constructFromLexer(lexer); + + 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()); + } } Generic::Generic(MasterLexer& lexer, const Name*, MasterLoader::Options, MasterLoaderCallbacks&) { - std::string s; - - 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; - } - - if (!s.empty()) { - s += " "; - } - - s += token.getString(); - } - - constructHelper(s); + constructFromLexer(lexer); } Generic::~Generic() { diff --git a/src/lib/dns/rdata.h b/src/lib/dns/rdata.h index 3fe0c74dd2..01ce7b3026 100644 --- a/src/lib/dns/rdata.h +++ b/src/lib/dns/rdata.h @@ -378,7 +378,7 @@ public: //@} private: - void constructHelper(const std::string& rdata_string); + void constructFromLexer(MasterLexer& lexer); GenericImpl* impl_; }; diff --git a/src/lib/dns/tests/rdata_unittest.cc b/src/lib/dns/tests/rdata_unittest.cc index 3839fbd24f..dcac2667e9 100644 --- a/src/lib/dns/tests/rdata_unittest.cc +++ b/src/lib/dns/tests/rdata_unittest.cc @@ -290,14 +290,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) { -- cgit v1.2.3 From ba1265b9abd3b2e7cf8c819e4c411675fd2d131d Mon Sep 17 00:00:00 2001 From: Kean Johnston Date: Mon, 13 Jan 2014 19:28:38 +0200 Subject: [3285] Fix missing dependencies In #3170 where parallel builds were fixed, some of the dependencies for running gen-rcodedata.py were not correctly set. Thus a file could be changed but nothing rebuilt. Fix that. --- src/lib/dns/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/lib/dns') diff --git a/src/lib/dns/Makefile.am b/src/lib/dns/Makefile.am index bda4e85333..48256a7757 100644 --- a/src/lib/dns/Makefile.am +++ b/src/lib/dns/Makefile.am @@ -158,7 +158,7 @@ rrclass.h: rrclass-placeholder.h rrtype.h: rrtype-placeholder.h rrparamregistry.cc: rrparamregistry-placeholder.cc -s-rdatacode: Makefile +s-rdatacode: Makefile rrclass-placeholder.h rrtype-placeholder.h rrparamregistry-placeholder.cc $(PYTHON) ./gen-rdatacode.py touch $@ -- cgit v1.2.3 From d88bd0463689b5d44ff6617ce080bb75f256bf96 Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Tue, 14 Jan 2014 09:36:57 +0530 Subject: [2185] Add support for the TLSA RR type --- src/lib/dns/Makefile.am | 2 + src/lib/dns/gen-rdatacode.py.in | 2 +- src/lib/dns/rdata/generic/tlsa_52.cc | 338 +++++++++++++++++++++ src/lib/dns/rdata/generic/tlsa_52.h | 65 ++++ src/lib/dns/tests/Makefile.am | 1 + src/lib/dns/tests/rdata_tlsa_unittest.cc | 336 ++++++++++++++++++++ src/lib/dns/tests/testdata/.gitignore | 6 + src/lib/dns/tests/testdata/Makefile.am | 9 + src/lib/dns/tests/testdata/rdata_tlsa_fromWire | 4 + src/lib/dns/tests/testdata/rdata_tlsa_fromWire10 | 6 + src/lib/dns/tests/testdata/rdata_tlsa_fromWire11 | 4 + src/lib/dns/tests/testdata/rdata_tlsa_fromWire12 | 4 + src/lib/dns/tests/testdata/rdata_tlsa_fromWire2 | 4 + .../dns/tests/testdata/rdata_tlsa_fromWire3.spec | 7 + .../dns/tests/testdata/rdata_tlsa_fromWire4.spec | 7 + .../dns/tests/testdata/rdata_tlsa_fromWire5.spec | 7 + .../dns/tests/testdata/rdata_tlsa_fromWire6.spec | 7 + .../dns/tests/testdata/rdata_tlsa_fromWire7.spec | 9 + .../dns/tests/testdata/rdata_tlsa_fromWire8.spec | 7 + src/lib/dns/tests/testdata/rdata_tlsa_fromWire9 | 7 + src/lib/util/python/gen_wiredata.py.in | 28 +- 21 files changed, 858 insertions(+), 2 deletions(-) create mode 100644 src/lib/dns/rdata/generic/tlsa_52.cc create mode 100644 src/lib/dns/rdata/generic/tlsa_52.h create mode 100644 src/lib/dns/tests/rdata_tlsa_unittest.cc create mode 100644 src/lib/dns/tests/testdata/rdata_tlsa_fromWire create mode 100644 src/lib/dns/tests/testdata/rdata_tlsa_fromWire10 create mode 100644 src/lib/dns/tests/testdata/rdata_tlsa_fromWire11 create mode 100644 src/lib/dns/tests/testdata/rdata_tlsa_fromWire12 create mode 100644 src/lib/dns/tests/testdata/rdata_tlsa_fromWire2 create mode 100644 src/lib/dns/tests/testdata/rdata_tlsa_fromWire3.spec create mode 100644 src/lib/dns/tests/testdata/rdata_tlsa_fromWire4.spec create mode 100644 src/lib/dns/tests/testdata/rdata_tlsa_fromWire5.spec create mode 100644 src/lib/dns/tests/testdata/rdata_tlsa_fromWire6.spec create mode 100644 src/lib/dns/tests/testdata/rdata_tlsa_fromWire7.spec create mode 100644 src/lib/dns/tests/testdata/rdata_tlsa_fromWire8.spec create mode 100644 src/lib/dns/tests/testdata/rdata_tlsa_fromWire9 (limited to 'src/lib/dns') diff --git a/src/lib/dns/Makefile.am b/src/lib/dns/Makefile.am index bda4e85333..b16c40c47f 100644 --- a/src/lib/dns/Makefile.am +++ b/src/lib/dns/Makefile.am @@ -70,6 +70,8 @@ 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 diff --git a/src/lib/dns/gen-rdatacode.py.in b/src/lib/dns/gen-rdatacode.py.in index 3fd3b33112..0c5bdf48d9 100755 --- a/src/lib/dns/gen-rdatacode.py.in +++ b/src/lib/dns/gen-rdatacode.py.in @@ -41,7 +41,7 @@ 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' } 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..fdf3bc32d3 --- /dev/null +++ b/src/lib/dns/rdata/generic/tlsa_52.cc @@ -0,0 +1,338 @@ +// 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 + +#include + +#include + +#include +#include +#include +#include +#include +#include + +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& 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 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(); + + vector data; + // If certificate association data is missing, it's OK. See the API + // documentation of the constructor. + if (certificate_assoc_data.size() > 0) { + 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 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 TLSAImpl that constructFromLexer() returns. + std::auto_ptr impl_ptr(NULL); + + 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 data; + rdata_len -= 3; + if (rdata_len > 0) { + 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) +{ + vector 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_); + + if (!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_); + + if (!impl_->data_.empty()) { + renderer.writeData(&impl_->data_[0], + impl_->data_.size()); + } +} + +string +TLSA::toText() const { + return (lexical_cast(static_cast(impl_->certificate_usage_)) + " " + + lexical_cast(static_cast(impl_->selector_)) + " " + + lexical_cast(static_cast(impl_->matching_type_)) + + (impl_->data_.empty() ? "" : + " " + encodeHex(impl_->data_))); +} + +int +TLSA::compare(const Rdata& other) const { + const TLSA& other_tlsa = dynamic_cast(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& +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 + +#include +#include + +#include +#include + +// 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& 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/tests/Makefile.am b/src/lib/dns/tests/Makefile.am index 5029681a32..2557228b65 100644 --- a/src/lib/dns/tests/Makefile.am +++ b/src/lib/dns/tests/Makefile.am @@ -59,6 +59,7 @@ 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 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..3e494c2623 --- /dev/null +++ b/src/lib/dns/tests/rdata_tlsa_unittest.cc @@ -0,0 +1,336 @@ +// 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 +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +using isc::UnitTestUtil; +using namespace std; +using namespace isc; +using namespace isc::dns; +using namespace isc::util; +using namespace isc::dns::rdata; + +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( + rdata_str, rdata_tlsa, false, false); + } + + void checkFromText_InvalidText(const string& rdata_str) { + checkFromText( + rdata_str, rdata_tlsa, true, true); + } + + void checkFromText_LexerError(const string& rdata_str) { + checkFromText + ( + rdata_str, rdata_tlsa, true, true); + } + + void checkFromText_BadString(const string& rdata_str) { + checkFromText + ( + 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); + + // 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)); +} + +TEST_F(Rdata_TLSA_Test, toText) { + EXPECT_TRUE(boost::iequals(tlsa_txt, rdata_tlsa.toText())); + + const string tlsa_txt2("3 2 1"); + const generic::TLSA rdata_tlsa2(tlsa_txt2); + EXPECT_TRUE(boost::iequals(tlsa_txt2, rdata_tlsa2.toText())); + + const generic::TLSA rdata_tlsa3("3 2 1 "); + EXPECT_TRUE(boost::iequals(tlsa_txt2, rdata_tlsa3.toText())); +} + +TEST_F(Rdata_TLSA_Test, toWire) { + this->obuffer.clear(); + rdata_tlsa.toWire(this->obuffer); + + EXPECT_EQ(sizeof (rdata_tlsa_wiredata), + this->obuffer.getLength()); + + EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, + this->obuffer.getData(), + this->obuffer.getLength(), + rdata_tlsa_wiredata, sizeof(rdata_tlsa_wiredata)); +} + +TEST_F(Rdata_TLSA_Test, compare) { + const generic::TLSA rdata_tlsa2("0 0 0"); + 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()); +} + +TEST_F(Rdata_TLSA_Test, emptyCertificateAssociationDataFromWire) { + const uint8_t rdf_wiredata[] = { + // certificate usage + 0x03, + // selector + 0x01, + // matching type + 0x02, + }; + + const generic::TLSA rdf = + dynamic_cast + (*rdataFactoryFromFile(RRType("TLSA"), RRClass("IN"), + "rdata_tlsa_fromWire12")); + + EXPECT_EQ(3, rdf.getCertificateUsage()); + EXPECT_EQ(1, rdf.getSelector()); + EXPECT_EQ(2, rdf.getMatchingType()); + EXPECT_EQ(0, rdf.getDataLength()); + + this->obuffer.clear(); + rdf.toWire(this->obuffer); + + EXPECT_EQ(3, this->obuffer.getLength()); + + EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, + this->obuffer.getData(), + this->obuffer.getLength(), + rdf_wiredata, sizeof(rdf_wiredata)); +} + +TEST_F(Rdata_TLSA_Test, emptyCertificateAssociationDataFromString) { + const generic::TLSA rdata_tlsa2("3 2 1"); + const uint8_t rdata_tlsa2_wiredata[] = { + // certificate usage + 0x03, + // selector + 0x02, + // matching type + 0x01 + }; + + EXPECT_EQ(3, rdata_tlsa2.getCertificateUsage()); + EXPECT_EQ(2, rdata_tlsa2.getSelector()); + EXPECT_EQ(1, rdata_tlsa2.getMatchingType()); + EXPECT_EQ(0, rdata_tlsa2.getDataLength()); + + this->obuffer.clear(); + rdata_tlsa2.toWire(this->obuffer); + + EXPECT_EQ(3, this->obuffer.getLength()); + + EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, + this->obuffer.getData(), + this->obuffer.getLength(), + rdata_tlsa2_wiredata, sizeof(rdata_tlsa2_wiredata)); +} +} diff --git a/src/lib/dns/tests/testdata/.gitignore b/src/lib/dns/tests/testdata/.gitignore index a0a14f4a19..8079354c05 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 diff --git a/src/lib/dns/tests/testdata/Makefile.am b/src/lib/dns/tests/testdata/Makefile.am index b6d7e35ada..15c3b3e7bb 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 @@ -159,6 +162,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 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/util/python/gen_wiredata.py.in b/src/lib/util/python/gen_wiredata.py.in index b3858b6b26..1251f9252e 100755 --- a/src/lib/util/python/gen_wiredata.py.in +++ b/src/lib/util/python/gen_wiredata.py.in @@ -352,7 +352,7 @@ dict_rrtype = { 'none' : 0, 'a' : 1, 'ns' : 2, 'md' : 3, 'mf' : 4, 'cname' : 5, 'srv' : 33, 'naptr' : 35, 'kx' : 36, 'cert' : 37, 'a6' : 38, 'dname' : 39, 'opt' : 41, 'apl' : 42, 'ds' : 43, 'sshfp' : 44, 'ipseckey' : 45, 'rrsig' : 46, 'nsec' : 47, 'dnskey' : 48, - 'dhcid' : 49, 'nsec3' : 50, 'nsec3param' : 51, 'hip' : 55, + 'dhcid' : 49, 'nsec3' : 50, 'nsec3param' : 51, 'tlsa' : 52, 'hip' : 55, 'spf' : 99, 'unspec' : 103, 'tkey' : 249, 'tsig' : 250, 'dlv' : 32769, 'ixfr' : 251, 'axfr' : 252, 'mailb' : 253, 'maila' : 254, 'any' : 255 } @@ -1156,6 +1156,32 @@ class RRSIG(RR): f.write('# Tag=%d Signer=%s and Signature\n' % (self.tag, self.signer)) f.write('%04x %s %s\n' % (self.tag, name_wire, sig_wire)) +class TLSA(RR): + '''Implements rendering TLSA RDATA in the test data format. + + Configurable parameters are as follows (see the description of the + same name of attribute for the default value): + - certificate_usage (int): The certificate usage field value. + - selector (int): The selector field value. + - matching_type (int): The matching type field value. + - certificate_association_data (string): The certificate association data. + ''' + certificate_usage = 0 + selector = 0 + matching_type = 1 + certificate_association_data = 'd2abde240d7cd3ee6b4b28c54df034b97983a1d16e8a410e4561cb106618e971' + def dump(self, f): + if self.rdlen is None: + self.rdlen = 2 + (len(self.certificate_association_data) / 2) + else: + self.rdlen = int(self.rdlen) + self.dump_header(f, self.rdlen) + f.write('# CERTIFICATE_USAGE=%d SELECTOR=%d MATCHING_TYPE=%d CERTIFICATE_ASSOCIATION_DATA=%s\n' %\ + (self.certificate_usage, self.selector, self.matching_type,\ + self.certificate_association_data)) + f.write('%02x %02x %02x %s\n' % (self.certificate_usage, self.selector, self.matching_type,\ + self.certificate_association_data)) + class TSIG(RR): '''Implements rendering TSIG RDATA in the test data format. -- cgit v1.2.3 From 56148b90078653c55088d7a275a11b480dc32b22 Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Tue, 14 Jan 2014 17:08:57 +0530 Subject: [3287] Constify argument --- src/lib/dns/rdata/generic/sshfp_44.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/lib/dns') diff --git a/src/lib/dns/rdata/generic/sshfp_44.cc b/src/lib/dns/rdata/generic/sshfp_44.cc index 2865ed18c8..03499f1d6e 100644 --- a/src/lib/dns/rdata/generic/sshfp_44.cc +++ b/src/lib/dns/rdata/generic/sshfp_44.cc @@ -38,7 +38,7 @@ using namespace isc::util::encode; struct SSHFPImpl { // straightforward representation of SSHFP RDATA fields SSHFPImpl(uint8_t algorithm, uint8_t fingerprint_type, - vector& fingerprint) : + const vector& fingerprint) : algorithm_(algorithm), fingerprint_type_(fingerprint_type), fingerprint_(fingerprint) -- cgit v1.2.3 From b3f844906409066e56efb339e0ff22e18d70386f Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Tue, 14 Jan 2014 17:16:04 +0530 Subject: [3287] Rename method --- src/lib/dns/rdata/generic/sshfp_44.cc | 2 +- src/lib/dns/rdata/generic/sshfp_44.h | 2 +- src/lib/dns/tests/rdata_sshfp_unittest.cc | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src/lib/dns') diff --git a/src/lib/dns/rdata/generic/sshfp_44.cc b/src/lib/dns/rdata/generic/sshfp_44.cc index 03499f1d6e..a02fd1cda1 100644 --- a/src/lib/dns/rdata/generic/sshfp_44.cc +++ b/src/lib/dns/rdata/generic/sshfp_44.cc @@ -294,7 +294,7 @@ SSHFP::getFingerprintType() const { } 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..ff1cd51a1c 100644 --- a/src/lib/dns/rdata/generic/sshfp_44.h +++ b/src/lib/dns/rdata/generic/sshfp_44.h @@ -45,7 +45,7 @@ public: /// uint8_t getAlgorithmNumber() const; uint8_t getFingerprintType() const; - size_t getFingerprintLen() const; + size_t getFingerprintLength() const; private: SSHFPImpl* constructFromLexer(MasterLexer& lexer); diff --git a/src/lib/dns/tests/rdata_sshfp_unittest.cc b/src/lib/dns/tests/rdata_sshfp_unittest.cc index b85dfa5ebe..5896ee5766 100644 --- a/src/lib/dns/tests/rdata_sshfp_unittest.cc +++ b/src/lib/dns/tests/rdata_sshfp_unittest.cc @@ -254,8 +254,8 @@ 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, getFingerprintLength) { + EXPECT_EQ(20, rdata_sshfp.getFingerprintLength()); } TEST_F(Rdata_SSHFP_Test, emptyFingerprintFromWire) { @@ -273,7 +273,7 @@ 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); @@ -297,7 +297,7 @@ 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); -- cgit v1.2.3 From a99f8f2985db8650de25810cbb74cf5752c9e703 Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Tue, 14 Jan 2014 17:16:26 +0530 Subject: [3287] Add getter for the fingerprint --- src/lib/dns/rdata/generic/sshfp_44.cc | 7 +++++-- src/lib/dns/rdata/generic/sshfp_44.h | 2 ++ src/lib/dns/tests/rdata_sshfp_unittest.cc | 12 ++++++++++++ 3 files changed, 19 insertions(+), 2 deletions(-) (limited to 'src/lib/dns') diff --git a/src/lib/dns/rdata/generic/sshfp_44.cc b/src/lib/dns/rdata/generic/sshfp_44.cc index a02fd1cda1..c243da7fef 100644 --- a/src/lib/dns/rdata/generic/sshfp_44.cc +++ b/src/lib/dns/rdata/generic/sshfp_44.cc @@ -14,8 +14,6 @@ #include -#include - #include #include @@ -293,6 +291,11 @@ SSHFP::getFingerprintType() const { return (impl_->fingerprint_type_); } +const std::vector& +SSHFP::getFingerprint() const { + return (impl_->fingerprint_); +} + size_t 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 ff1cd51a1c..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 #include +#include #include #include @@ -45,6 +46,7 @@ public: /// uint8_t getAlgorithmNumber() const; uint8_t getFingerprintType() const; + const std::vector& getFingerprint() const; size_t getFingerprintLength() const; private: diff --git a/src/lib/dns/tests/rdata_sshfp_unittest.cc b/src/lib/dns/tests/rdata_sshfp_unittest.cc index 5896ee5766..b2638ef6c7 100644 --- a/src/lib/dns/tests/rdata_sshfp_unittest.cc +++ b/src/lib/dns/tests/rdata_sshfp_unittest.cc @@ -254,6 +254,18 @@ TEST_F(Rdata_SSHFP_Test, getFingerprintType) { EXPECT_EQ(1, rdata_sshfp.getFingerprintType()); } +TEST_F(Rdata_SSHFP_Test, getFingerprint) { + const std::vector& 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()); } -- cgit v1.2.3 From e71ef05f8698763d2e604a55aa7e39ac824241d8 Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Tue, 14 Jan 2014 17:23:18 +0530 Subject: [3287] Don't passthrough BadValue exceptions in decoding hex from SSHFP --- src/lib/dns/rdata/generic/sshfp_44.cc | 12 ++++++------ src/lib/dns/tests/rdata_sshfp_unittest.cc | 9 ++------- 2 files changed, 8 insertions(+), 13 deletions(-) (limited to 'src/lib/dns') diff --git a/src/lib/dns/rdata/generic/sshfp_44.cc b/src/lib/dns/rdata/generic/sshfp_44.cc index c243da7fef..346ad73f22 100644 --- a/src/lib/dns/rdata/generic/sshfp_44.cc +++ b/src/lib/dns/rdata/generic/sshfp_44.cc @@ -80,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)); @@ -126,9 +130,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(); @@ -141,8 +142,7 @@ SSHFP::SSHFP(const string& sshfp_str) : /// /// \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. +/// 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 diff --git a/src/lib/dns/tests/rdata_sshfp_unittest.cc b/src/lib/dns/tests/rdata_sshfp_unittest.cc index b2638ef6c7..9ae23967ec 100644 --- a/src/lib/dns/tests/rdata_sshfp_unittest.cc +++ b/src/lib/dns/tests/rdata_sshfp_unittest.cc @@ -59,11 +59,6 @@ protected: rdata_str, rdata_sshfp, true, true); } - void checkFromText_BadValue(const string& rdata_str) { - checkFromText( - rdata_str, rdata_sshfp, true, true); - } - void checkFromText_BadString(const string& rdata_str) { checkFromText ( @@ -138,8 +133,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( -- cgit v1.2.3 From c1187e4ae7d409c94a73e6b10fa00751d302e05d Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Tue, 14 Jan 2014 17:25:19 +0530 Subject: [3287] Update test to use sizeof instead of hardcoded length --- src/lib/dns/tests/rdata_sshfp_unittest.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/lib/dns') diff --git a/src/lib/dns/tests/rdata_sshfp_unittest.cc b/src/lib/dns/tests/rdata_sshfp_unittest.cc index 9ae23967ec..a3275572d4 100644 --- a/src/lib/dns/tests/rdata_sshfp_unittest.cc +++ b/src/lib/dns/tests/rdata_sshfp_unittest.cc @@ -227,7 +227,8 @@ 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(), -- cgit v1.2.3 From d631937eaeaa137fc1e832993b17d8e331b9b73c Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Tue, 14 Jan 2014 17:32:08 +0530 Subject: [3287] Update API doc comments of SSHFP constructors --- src/lib/dns/rdata/generic/sshfp_44.cc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'src/lib/dns') diff --git a/src/lib/dns/rdata/generic/sshfp_44.cc b/src/lib/dns/rdata/generic/sshfp_44.cc index 346ad73f22..4c1e83274a 100644 --- a/src/lib/dns/rdata/generic/sshfp_44.cc +++ b/src/lib/dns/rdata/generic/sshfp_44.cc @@ -104,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) : @@ -141,7 +142,7 @@ 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 +/// \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 -- cgit v1.2.3 From 659fb323f0b7fdd279cc1c36b0f5fe6526a0994e Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Tue, 14 Jan 2014 17:40:46 +0530 Subject: [2426] Fix leak of GenericImpl object when an exception is thrown --- src/lib/dns/rdata.cc | 21 +++++++++++++++------ src/lib/dns/rdata.h | 2 +- 2 files changed, 16 insertions(+), 7 deletions(-) (limited to 'src/lib/dns') diff --git a/src/lib/dns/rdata.cc b/src/lib/dns/rdata.cc index cdd03c155c..4f7962c162 100644 --- a/src/lib/dns/rdata.cc +++ b/src/lib/dns/rdata.cc @@ -212,7 +212,7 @@ Generic::Generic(isc::util::InputBuffer& buffer, size_t rdata_len) { impl_ = new GenericImpl(data); } -void +GenericImpl* Generic::constructFromLexer(MasterLexer& lexer) { const MasterToken& token = lexer.getNextToken(MasterToken::STRING); if (token.getString() != "\\#") { @@ -268,16 +268,23 @@ Generic::constructFromLexer(MasterLexer& lexer) { << data.size() << " vs. " << rdlen); } - impl_ = new GenericImpl(data); + return (new GenericImpl(data)); } -Generic::Generic(const std::string& rdata_string) { +Generic::Generic(const std::string& rdata_string) : + 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 GenericImpl that constructFromLexer() returns. + std::auto_ptr impl_ptr(NULL); + try { std::istringstream ss(rdata_string); MasterLexer lexer; lexer.pushSource(ss); - constructFromLexer(lexer); + impl_ptr.reset(constructFromLexer(lexer)); if (lexer.getNextToken().getType() != MasterToken::END_OF_FILE) { isc_throw(InvalidRdataText, "extra input text for unknown RDATA: " @@ -287,13 +294,15 @@ Generic::Generic(const std::string& rdata_string) { isc_throw(InvalidRdataText, "Failed to construct unknown RDATA " "from '" << rdata_string << "': " << ex.what()); } + + impl_ = impl_ptr.release(); } Generic::Generic(MasterLexer& lexer, const Name*, MasterLoader::Options, - MasterLoaderCallbacks&) + MasterLoaderCallbacks&) : + impl_(constructFromLexer(lexer)) { - constructFromLexer(lexer); } Generic::~Generic() { diff --git a/src/lib/dns/rdata.h b/src/lib/dns/rdata.h index 01ce7b3026..5468e2698c 100644 --- a/src/lib/dns/rdata.h +++ b/src/lib/dns/rdata.h @@ -378,7 +378,7 @@ public: //@} private: - void constructFromLexer(MasterLexer& lexer); + GenericImpl* constructFromLexer(MasterLexer& lexer); GenericImpl* impl_; }; -- cgit v1.2.3 From 1d34831c4d70162e769625278dd8c901ad21f42d Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Wed, 15 Jan 2014 07:08:31 +0530 Subject: [2168] Remove use of UnitTestUtil::matchWireData() in dns/tests/ This also fixes a bug in TSIGKeyTest.construct where key_short_md5 was not tested correctly. --- src/lib/dns/tests/edns_unittest.cc | 28 ++++++----- src/lib/dns/tests/message_unittest.cc | 28 +++++------ src/lib/dns/tests/messagerenderer_unittest.cc | 55 ++++++++++---------- src/lib/dns/tests/name_unittest.cc | 20 ++++---- src/lib/dns/tests/question_unittest.cc | 12 +++-- src/lib/dns/tests/rdata_afsdb_unittest.cc | 24 ++++----- src/lib/dns/tests/rdata_cname_unittest.cc | 20 ++++---- src/lib/dns/tests/rdata_dhcid_unittest.cc | 12 +++-- src/lib/dns/tests/rdata_dname_unittest.cc | 20 ++++---- src/lib/dns/tests/rdata_dnskey_unittest.cc | 15 +++--- src/lib/dns/tests/rdata_ds_like_unittest.cc | 12 ++--- src/lib/dns/tests/rdata_hinfo_unittest.cc | 15 +++--- src/lib/dns/tests/rdata_in_a_unittest.cc | 14 +++--- src/lib/dns/tests/rdata_in_aaaa_unittest.cc | 14 +++--- src/lib/dns/tests/rdata_minfo_unittest.cc | 25 +++++----- src/lib/dns/tests/rdata_mx_unittest.cc | 12 +++-- src/lib/dns/tests/rdata_naptr_unittest.cc | 15 +++--- src/lib/dns/tests/rdata_ns_unittest.cc | 20 ++++---- .../dns/tests/rdata_nsec3param_like_unittest.cc | 8 +-- src/lib/dns/tests/rdata_nsec3param_unittest.cc | 15 +++--- src/lib/dns/tests/rdata_nsec_unittest.cc | 10 ++-- src/lib/dns/tests/rdata_nsecbitmap_unittest.cc | 14 +++--- src/lib/dns/tests/rdata_ptr_unittest.cc | 20 ++++---- src/lib/dns/tests/rdata_rp_unittest.cc | 14 +++--- src/lib/dns/tests/rdata_soa_unittest.cc | 16 +++--- src/lib/dns/tests/rdata_srv_unittest.cc | 26 +++++----- src/lib/dns/tests/rdata_sshfp_unittest.cc | 23 ++++----- src/lib/dns/tests/rdata_tsig_unittest.cc | 49 ++++++++---------- src/lib/dns/tests/rdata_txt_like_unittest.cc | 58 ++++++++++------------ src/lib/dns/tests/rdata_unittest.cc | 15 +++--- src/lib/dns/tests/rdatafields_unittest.cc | 51 +++++++++---------- src/lib/dns/tests/rrclass_unittest.cc | 12 ++--- src/lib/dns/tests/rrset_unittest.cc | 30 +++++------ src/lib/dns/tests/rrttl_unittest.cc | 12 ++--- src/lib/dns/tests/rrtype_unittest.cc | 12 ++--- src/lib/dns/tests/tsig_unittest.cc | 13 ++--- src/lib/dns/tests/tsigkey_unittest.cc | 30 +++++------ src/lib/dns/tests/tsigrecord_unittest.cc | 17 +++---- 38 files changed, 403 insertions(+), 403 deletions(-) (limited to 'src/lib/dns') 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 #include +#include -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/message_unittest.cc b/src/lib/dns/tests/message_unittest.cc index 8aaebaa183..637357eae4 100644 --- a/src/lib/dns/tests/message_unittest.cc +++ b/src/lib/dns/tests/message_unittest.cc @@ -41,13 +41,15 @@ #include #include +#include -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(NULL), tsig_rr->getRdata().getOtherData()); @@ -729,8 +730,8 @@ TEST_F(MessageTest, toWire) { message_render.toWire(renderer); vector 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 +767,8 @@ TEST_F(MessageTest, toWireSigned) { message_render.toWire(renderer); vector 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 +811,8 @@ TEST_F(MessageTest, toWireSignedAndTruncated) { message_render.toWire(renderer); vector 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) { @@ -867,9 +868,8 @@ commonTSIGToWireCheck(Message& message, MessageRenderer& renderer, message.toWire(renderer, tsig_ctx); vector 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) { 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 #include +#include #include @@ -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(renderer.getData()) + - offset, - renderer.getLength() - offset, - &data[0], data.size()); + matchWireData(&data[0], data.size(), + static_cast(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(renderer.getData()), - renderer.getLength(), - static_cast(expected.getData()), - expected.getLength()); + matchWireData(static_cast(expected.getData()), + expected.getLength(), + static_cast(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..e52b8d0caa 100644 --- a/src/lib/dns/tests/name_unittest.cc +++ b/src/lib/dns/tests/name_unittest.cc @@ -25,6 +25,7 @@ #include #include +#include #include @@ -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) { @@ -454,8 +455,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 +469,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 +629,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/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 #include +#include -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 #include +#include -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_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 #include +#include -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 #include +#include -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 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 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 #include +#include -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 #include +#include -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 data; UnitTestUtil::readWireData("rdata_dnskey_fromWire.wire", data); - EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, - static_cast(renderer.getData()) + 2, - renderer.getLength() - 2, &data[2], data.size() - 2); + matchWireData(&data[2], data.size() - 2, + static_cast(renderer.getData()) + 2, + renderer.getLength() - 2); } TEST_F(Rdata_DNSKEY_Test, toWireBuffer) { @@ -165,9 +167,8 @@ TEST_F(Rdata_DNSKEY_Test, toWireBuffer) { vector 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 #include +#include -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 data; UnitTestUtil::readWireData("rdata_ds_fromWire", data); - EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, - static_cast - (this->renderer.getData()) + 2, - this->renderer.getLength() - 2, - &data[2], data.size() - 2); + matchWireData(&data[2], data.size() - 2, + static_cast(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 #include +#include -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 #include +#include #include #include #include -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 #include +#include -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 #include +#include -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 data; UnitTestUtil::readWireData("rdata_minfo_toWireUncompressed1.wire", data); - EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, - static_cast(obuffer.getData()), - obuffer.getLength(), &data[0], data.size()); + matchWireData(&data[0], data.size(), + obuffer.getData(), obuffer.getLength()); obuffer.clear(); rdata_minfo2.toWire(obuffer); vector data2; UnitTestUtil::readWireData("rdata_minfo_toWireUncompressed2.wire", data2); - EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, - static_cast(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 data; UnitTestUtil::readWireData("rdata_minfo_toWire1.wire", data); - EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, - static_cast(renderer.getData()), - renderer.getLength(), &data[0], data.size()); + matchWireData(&data[0], data.size(), + renderer.getData(), renderer.getLength()); + renderer.clear(); rdata_minfo2.toWire(renderer); vector data2; UnitTestUtil::readWireData("rdata_minfo_toWire2.wire", data2); - EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, - static_cast(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 #include +#include -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 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 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 #include +#include -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 #include +#include -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..e7962dd080 100644 --- a/src/lib/dns/tests/rdata_nsec3param_like_unittest.cc +++ b/src/lib/dns/tests/rdata_nsec3param_like_unittest.cc @@ -22,14 +22,16 @@ #include #include +#include #include #include using namespace std; -using isc::UnitTestUtil; using namespace isc::dns; using namespace isc::dns::rdata; +using isc::UnitTestUtil; +using isc::util::unittests::matchWireData; namespace { @@ -230,8 +232,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 #include +#include -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 data; UnitTestUtil::readWireData("rdata_nsec3param_fromWire1", data); - EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, - static_cast(renderer.getData()) + 2, - renderer.getLength() - 2, &data[2], data.size() - 2); + matchWireData(&data[2], data.size() - 2, + static_cast(renderer.getData()) + 2, + renderer.getLength() - 2); } TEST_F(Rdata_NSEC3PARAM_Test, toWireBuffer) { @@ -180,9 +182,8 @@ TEST_F(Rdata_NSEC3PARAM_Test, toWireBuffer) { vector 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 #include +#include -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 data; UnitTestUtil::readWireData("rdata_nsec_fromWire1", data); - EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, - static_cast(renderer.getData()) + 2, - renderer.getLength() - 2, &data[2], data.size() - 2); + matchWireData(&data[2], data.size() - 2, + static_cast(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..c057b58004 100644 --- a/src/lib/dns/tests/rdata_nsecbitmap_unittest.cc +++ b/src/lib/dns/tests/rdata_nsecbitmap_unittest.cc @@ -23,6 +23,7 @@ #include #include +#include #include @@ -30,10 +31,11 @@ #include using namespace std; -using boost::lexical_cast; -using isc::UnitTestUtil; using namespace isc::dns; using namespace isc::dns::rdata; +using isc::UnitTestUtil; +using isc::util::unittests::matchWireData; +using boost::lexical_cast; namespace { @@ -253,16 +255,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_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 #include +#include -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 #include +#include -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_soa_unittest.cc b/src/lib/dns/tests/rdata_soa_unittest.cc index d919329c32..808ff8fba1 100644 --- a/src/lib/dns/tests/rdata_soa_unittest.cc +++ b/src/lib/dns/tests/rdata_soa_unittest.cc @@ -23,12 +23,14 @@ #include #include +#include -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 { @@ -180,9 +182,9 @@ TEST_F(Rdata_SOA_Test, toWireRenderer) { vector data; UnitTestUtil::readWireData("rdata_soa_fromWire", data); - EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, - static_cast(renderer.getData()) + 2, - renderer.getLength() - 2, &data[2], data.size() - 2); + matchWireData(&data[2], data.size() - 2, + static_cast(renderer.getData()) + 2, + renderer.getLength() - 2); } TEST_F(Rdata_SOA_Test, toWireBuffer) { @@ -190,9 +192,9 @@ TEST_F(Rdata_SOA_Test, toWireBuffer) { rdata_soa.toWire(obuffer); vector data; UnitTestUtil::readWireData("rdata_soa_toWireUncompressed.wire", data); - EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, - static_cast(obuffer.getData()) + 2, - obuffer.getLength() - 2, &data[2], data.size() - 2); + matchWireData(&data[2], data.size() - 2, + static_cast(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 #include +#include -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..99ce810ab5 100644 --- a/src/lib/dns/tests/rdata_sshfp_unittest.cc +++ b/src/lib/dns/tests/rdata_sshfp_unittest.cc @@ -26,14 +26,17 @@ #include #include +#include + #include -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 { @@ -234,10 +237,8 @@ TEST_F(Rdata_SSHFP_Test, toWire) { EXPECT_EQ(22, 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) { @@ -280,10 +281,8 @@ TEST_F(Rdata_SSHFP_Test, emptyFingerprintFromWire) { 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) { @@ -304,9 +303,7 @@ TEST_F(Rdata_SSHFP_Test, emptyFingerprintFromString) { 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_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 #include +#include -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 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 cb3c44d889..573a4a1924 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 #include +#include + #include #include @@ -29,11 +31,12 @@ #include #include -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. @@ -269,10 +272,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 @@ -284,11 +285,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 @@ -316,18 +314,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..9739325014 100644 --- a/src/lib/dns/tests/rdata_unittest.cc +++ b/src/lib/dns/tests/rdata_unittest.cc @@ -28,14 +28,17 @@ #include #include +#include + #include #include -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 { @@ -393,16 +396,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/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 #include +#include + #include -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 #include +#include #include @@ -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 0967fce46d..66621b9a15 100644 --- a/src/lib/dns/tests/rrset_unittest.cc +++ b/src/lib/dns/tests/rrset_unittest.cc @@ -23,18 +23,19 @@ #include #include +#include #include #include #include -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 { @@ -208,8 +209,8 @@ 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. buffer.clear(); @@ -220,14 +221,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) { @@ -237,8 +239,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. buffer.clear(); @@ -250,15 +252,15 @@ TEST_F(RRsetTest, toWireRenderer) { 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 operator<<. We simply confirm it appends the result of toText(). 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 #include +#include #include @@ -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 #include +#include 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/tsig_unittest.cc b/src/lib/dns/tests/tsig_unittest.cc index 458a6e0cf3..40a58c0e2c 100644 --- a/src/lib/dns/tests/tsig_unittest.cc +++ b/src/lib/dns/tests/tsig_unittest.cc @@ -40,6 +40,7 @@ #include #include +#include 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 { @@ -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 #include +#include 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 #include +#include 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) { -- cgit v1.2.3 From 8f422c21d3ea53c7f30bfd1548036331558bbf7d Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Wed, 15 Jan 2014 10:49:16 +0530 Subject: [2168] Remove UnitTestUtil::matchWireData() --- src/lib/dns/tests/unittest_util.cc | 27 --------------------------- src/lib/dns/tests/unittest_util.h | 22 ---------------------- 2 files changed, 49 deletions(-) (limited to 'src/lib/dns') 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 @@ -131,33 +131,6 @@ UnitTestUtil::readWireData(const string& datastr, } while (!iss.eof()); } -::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(data1)[i]; - int ch2 = static_cast(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, 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 @@ -45,28 +45,6 @@ public: static void readWireData(const std::string& datastr, std::vector& 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. /// -- cgit v1.2.3 From e29050c245ee56989b0249c55a1e5a0c05f9c2a1 Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Thu, 16 Jan 2014 12:47:16 +0530 Subject: [1894] Avoid expensive Name copy --- src/lib/dns/nsec3hash.cc | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) (limited to 'src/lib/dns') diff --git a/src/lib/dns/nsec3hash.cc b/src/lib/dns/nsec3hash.cc index 0e03798268..c7bcad25e9 100644 --- a/src/lib/dns/nsec3hash.cc +++ b/src/lib/dns/nsec3hash.cc @@ -31,6 +31,7 @@ #include #include #include +#include using namespace std; using namespace isc::util; @@ -120,15 +121,29 @@ NSEC3HashRFC5155::calculate(const Name& name) 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_); + name.toWire(obuf_); + + uint8_t name_buf[256]; + assert(obuf_.getLength() < sizeof (name_buf)); + + const uint8_t *p1 = static_cast(obuf_.getData()); + 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(obuf_.getData()), - obuf_.getLength(), salt_data_, salt_length_, digest); + iterateSHA1(&sha1_ctx_, name_buf, obuf_.getLength(), + salt_data_, salt_length_, digest); for (unsigned int n = 0; n < iterations_; ++n) { iterateSHA1(&sha1_ctx_, digest, SHA1_HASHSIZE, salt_data_, salt_length_, digest); -- cgit v1.2.3 From 4aef41d3641bb940f6e57aeeef9735255b11495f Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Thu, 16 Jan 2014 14:26:12 +0530 Subject: [1894] Add LabelSequence version of NSEC3Hash::calculate() --- src/lib/datasrc/tests/faked_nsec3.cc | 8 ++++++++ src/lib/dns/nsec3hash.cc | 35 +++++++++++++++++++++++++++------ src/lib/dns/nsec3hash.h | 19 ++++++++++++++++-- src/lib/dns/tests/nsec3hash_unittest.cc | 33 ++++++++++++++++++++++++++++++- 4 files changed, 86 insertions(+), 9 deletions(-) (limited to 'src/lib/dns') diff --git a/src/lib/datasrc/tests/faked_nsec3.cc b/src/lib/datasrc/tests/faked_nsec3.cc index f53fbd7616..24d4f3c619 100644 --- a/src/lib/datasrc/tests/faked_nsec3.cc +++ b/src/lib/datasrc/tests/faked_nsec3.cc @@ -15,6 +15,7 @@ #include "faked_nsec3.h" #include +#include #include #include @@ -87,6 +88,13 @@ public: isc_throw(isc::Unexpected, "unexpected name for NSEC3 test: " << name); } + virtual string calculate(const LabelSequence& ls) const { + assert(ls.isAbsolute()); + // This is not very optimal, but it's only going to be used in + // tests. + const Name name(ls.toText()); + return (calculate(name)); + } virtual bool match(const rdata::generic::NSEC3PARAM&) const { return (true); } diff --git a/src/lib/dns/nsec3hash.cc b/src/lib/dns/nsec3hash.cc index c7bcad25e9..4e6fea1ee7 100644 --- a/src/lib/dns/nsec3hash.cc +++ b/src/lib/dns/nsec3hash.cc @@ -29,6 +29,7 @@ #include #include +#include #include #include #include @@ -85,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; @@ -92,6 +94,8 @@ public: const vector& 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_; @@ -117,16 +121,16 @@ 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.toWire(obuf_); uint8_t name_buf[256]; - assert(obuf_.getLength() < sizeof (name_buf)); + assert(length < sizeof (name_buf)); - const uint8_t *p1 = static_cast(obuf_.getData()); + const uint8_t *p1 = data; uint8_t *p2 = name_buf; while (*p1 != 0) { char len = *p1; @@ -142,7 +146,7 @@ NSEC3HashRFC5155::calculate(const Name& name) const { uint8_t* const digest = &digest_[0]; assert(digest_.size() == SHA1_HASHSIZE); - iterateSHA1(&sha1_ctx_, name_buf, obuf_.getLength(), + 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, @@ -152,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(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& salt) const diff --git a/src/lib/dns/nsec3hash.h b/src/lib/dns/nsec3hash.h index f1ca1a3c2c..ef90a96f13 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 { @@ -129,19 +130,33 @@ public: /// \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 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 #include +#include #include #include @@ -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 -- cgit v1.2.3 From 7417af2406fa1e11241b31dfe68a36b55f99146a Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Thu, 16 Jan 2014 18:07:19 +0530 Subject: [1397] Change EXPECT_EQ to ASSERT_EQ --- src/lib/dns/tests/rrset_unittest.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/lib/dns') diff --git a/src/lib/dns/tests/rrset_unittest.cc b/src/lib/dns/tests/rrset_unittest.cc index 0967fce46d..3120e1cbb4 100644 --- a/src/lib/dns/tests/rrset_unittest.cc +++ b/src/lib/dns/tests/rrset_unittest.cc @@ -130,7 +130,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()); -- cgit v1.2.3 From 0022aaf1bd3bb9bb91bbf5542fdd962848776b59 Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Thu, 16 Jan 2014 18:07:42 +0530 Subject: [1397] Fix variable that's tested --- src/lib/dns/tests/rrset_unittest.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src/lib/dns') diff --git a/src/lib/dns/tests/rrset_unittest.cc b/src/lib/dns/tests/rrset_unittest.cc index 3120e1cbb4..78276cbbae 100644 --- a/src/lib/dns/tests/rrset_unittest.cc +++ b/src/lib/dns/tests/rrset_unittest.cc @@ -157,8 +157,7 @@ TEST_F(RRsetTest, addRdataPtr) { rrset_a_empty.addRdata(createRdata(rrset_a_empty.getType(), rrset_a_empty.getClass(), "192.0.2.2")); - - addRdataTestCommon(rrset_a); + addRdataTestCommon(rrset_a_empty); // Pointer version of addRdata() doesn't type check and does allow to //add a different type of Rdata as a result. -- cgit v1.2.3 From 6db6928823e9f7626c3d49f4583f665d92e8ee95 Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Thu, 16 Jan 2014 18:08:41 +0530 Subject: [1397] Add std::string version of Rset::addRdata() --- src/lib/dns/rrset.cc | 5 +++++ src/lib/dns/rrset.h | 17 +++++++++++++++++ src/lib/dns/tests/rrset_unittest.cc | 12 ++++++++++++ 3 files changed, 34 insertions(+) (limited to 'src/lib/dns') diff --git a/src/lib/dns/rrset.cc b/src/lib/dns/rrset.cc index 0d34d1921b..e128c76079 100644 --- a/src/lib/dns/rrset.cc +++ b/src/lib/dns/rrset.cc @@ -194,6 +194,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()); diff --git a/src/lib/dns/rrset.h b/src/lib/dns/rrset.h index eb8fa6ed0c..f1bd4fc3c1 100644 --- a/src/lib/dns/rrset.h +++ b/src/lib/dns/rrset.h @@ -380,6 +380,16 @@ public: /// 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. /// @@ -727,6 +737,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. /// diff --git a/src/lib/dns/tests/rrset_unittest.cc b/src/lib/dns/tests/rrset_unittest.cc index 78276cbbae..6e85380a6f 100644 --- a/src/lib/dns/tests/rrset_unittest.cc +++ b/src/lib/dns/tests/rrset_unittest.cc @@ -166,6 +166,18 @@ TEST_F(RRsetTest, addRdataPtr) { EXPECT_EQ(3, rrset_a_empty.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) { // Iterator for an empty RRset. RdataIteratorPtr it = rrset_a_empty.getRdataIterator(); -- cgit v1.2.3 From 4b77db4d8be806ebfb82ef5403fae266c56b1c89 Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Fri, 17 Jan 2014 10:33:29 +0530 Subject: Add Rdata::getWireLength() method --- src/lib/dns/rdata.cc | 9 +++++++++ src/lib/dns/rdata.h | 15 +++++++++++++++ src/lib/dns/tests/rdata_unittest.cc | 8 ++++++++ 3 files changed, 32 insertions(+) (limited to 'src/lib/dns') diff --git a/src/lib/dns/rdata.cc b/src/lib/dns/rdata.cc index f42c349f2d..09f289b7dd 100644 --- a/src/lib/dns/rdata.cc +++ b/src/lib/dns/rdata.cc @@ -46,6 +46,15 @@ namespace isc { namespace dns { namespace rdata { +uint16_t +Rdata::getWireLength() 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 diff --git a/src/lib/dns/rdata.h b/src/lib/dns/rdata.h index 3fe0c74dd2..352554e1af 100644 --- a/src/lib/dns/rdata.h +++ b/src/lib/dns/rdata.h @@ -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 getWireLength() method to every RDATA + /// type. This is why this method is virtual. Once all Rdata types + /// have \c getWireLength() 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 getWireLength() const; }; namespace generic { diff --git a/src/lib/dns/tests/rdata_unittest.cc b/src/lib/dns/tests/rdata_unittest.cc index 3839fbd24f..3772e9b4b0 100644 --- a/src/lib/dns/tests/rdata_unittest.cc +++ b/src/lib/dns/tests/rdata_unittest.cc @@ -211,6 +211,14 @@ TEST_F(RdataTest, createRdataWithLexer) { "file does not end with newline"); } +TEST_F(RdataTest, getWireLength) { + const in::AAAA aaaa_rdata("2001:db8::1"); + EXPECT_EQ(16, aaaa_rdata.getWireLength()); + + const generic::TXT txt_rdata("Hello World"); + EXPECT_EQ(12, txt_rdata.getWireLength()); +} + } } } -- cgit v1.2.3 From 362a47928d1c939a51d694ab81e68bf47ec564f9 Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Fri, 17 Jan 2014 13:27:28 +0530 Subject: [2518] Introduce isc::dns::Exception and organize all DNS exceptions under it --- src/lib/dns/exceptions.h | 28 +++++++++++++++++----------- src/lib/dns/master_lexer.h | 6 +++--- src/lib/dns/message.h | 18 +++++++++--------- src/lib/dns/rdata.h | 14 +++++++------- src/lib/dns/rrclass-placeholder.h | 10 +++++----- src/lib/dns/rrparamregistry.h | 10 +++++----- src/lib/dns/rrset.h | 6 +++--- src/lib/dns/rrttl.h | 10 +++++----- src/lib/dns/rrtype-placeholder.h | 10 +++++----- src/lib/dns/tsig.cc | 2 +- src/lib/dns/tsigkey.cc | 2 +- 11 files changed, 61 insertions(+), 55 deletions(-) (limited to 'src/lib/dns') diff --git a/src/lib/dns/exceptions.h b/src/lib/dns/exceptions.h index d7adeddd7f..34413aa4a1 100644 --- a/src/lib/dns/exceptions.h +++ b/src/lib/dns/exceptions.h @@ -30,10 +30,25 @@ 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 name parser exceptions. +/// +class NameParserException : public isc::dns::Exception { +public: + NameParserException(const char* file, size_t line, const char* what) : + isc::dns::Exception(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; }; @@ -51,15 +66,6 @@ public: virtual const Rcode& getRcode() const; }; -/// -/// \brief Base class for name parser exceptions. -/// -class NameParserException : public isc::Exception { -public: - NameParserException(const char* file, size_t line, const char* what) : - isc::Exception(file, line, what) {} -}; - } } #endif // DNS_EXCEPTIONS_H diff --git a/src/lib/dns/master_lexer.h b/src/lib/dns/master_lexer.h index e33f9649b8..1184f046ca 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 +#include #include #include @@ -324,10 +324,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/message.h b/src/lib/dns/message.h index 1c83e1eec3..2d4e15d8a8 100644 --- a/src/lib/dns/message.h +++ b/src/lib/dns/message.h @@ -21,7 +21,7 @@ #include #include -#include +#include #include #include @@ -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; diff --git a/src/lib/dns/rdata.h b/src/lib/dns/rdata.h index 3fe0c74dd2..a1115fd2a3 100644 --- a/src/lib/dns/rdata.h +++ b/src/lib/dns/rdata.h @@ -19,7 +19,7 @@ #include #include -#include +#include #include @@ -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 isc::dns::Exception { public: InvalidRdataLength(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 RDATA parser /// fails to recognize a given textual representation. /// -class InvalidRdataText : public Exception { +class InvalidRdataText : public isc::dns::Exception { public: InvalidRdataText(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: /// encounters a character-string (as defined in RFC1035) exceeding /// the maximum allowable length (\c MAX_CHARSTRING_LEN). /// -class CharStringTooLong : public Exception { +class CharStringTooLong : public isc::dns::Exception { public: CharStringTooLong(const char* file, size_t line, const char* what) : - isc::Exception(file, line, what) {} + isc::dns::Exception(file, line, what) {} }; // Forward declaration to define RdataPtr. diff --git a/src/lib/dns/rrclass-placeholder.h b/src/lib/dns/rrclass-placeholder.h index b4f1851aa4..56d94741b5 100644 --- a/src/lib/dns/rrclass-placeholder.h +++ b/src/lib/dns/rrclass-placeholder.h @@ -20,7 +20,7 @@ #include #include -#include +#include #include @@ -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 isc::dns::Exception { public: InvalidRRClass(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 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 -#include +#include #include @@ -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.h b/src/lib/dns/rrset.h index 395cbdd3ba..01e59f802d 100644 --- a/src/lib/dns/rrset.h +++ b/src/lib/dns/rrset.h @@ -20,7 +20,7 @@ #include -#include +#include #include #include @@ -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 diff --git a/src/lib/dns/rrttl.h b/src/lib/dns/rrttl.h index 35403b6294..7804234115 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 +#include #include @@ -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 isc::dns::Exception { public: InvalidRRTTL(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 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..08ab287f33 100644 --- a/src/lib/dns/rrtype-placeholder.h +++ b/src/lib/dns/rrtype-placeholder.h @@ -20,7 +20,7 @@ #include #include -#include +#include // Solaris x86 defines DS in , 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 isc::dns::Exception { public: InvalidRRType(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 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/tsig.cc b/src/lib/dns/tsig.cc index d7ffcf8fa7..0739ab6409 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(); 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()); -- cgit v1.2.3 From fc5c7370d09294a8920da0780c615dcb77d7efd7 Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Fri, 17 Jan 2014 13:27:38 +0530 Subject: [2518] Untabify code --- src/lib/dns/tsig.cc | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'src/lib/dns') diff --git a/src/lib/dns/tsig.cc b/src/lib/dns/tsig.cc index 0739ab6409..b6e1716d67 100644 --- a/src/lib/dns/tsig.cc +++ b/src/lib/dns/tsig.cc @@ -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 // -- cgit v1.2.3 From 7d109f38cbdff76b09ee2e587fe751c4b32737c6 Mon Sep 17 00:00:00 2001 From: Kean Johnston Date: Fri, 17 Jan 2014 10:42:20 +0200 Subject: [3285] Use EXTRA_DIST for dependencies to be even more accurate --- src/lib/dns/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/lib/dns') diff --git a/src/lib/dns/Makefile.am b/src/lib/dns/Makefile.am index 48256a7757..ede699a2b7 100644 --- a/src/lib/dns/Makefile.am +++ b/src/lib/dns/Makefile.am @@ -158,7 +158,7 @@ rrclass.h: rrclass-placeholder.h rrtype.h: rrtype-placeholder.h rrparamregistry.cc: rrparamregistry-placeholder.cc -s-rdatacode: Makefile rrclass-placeholder.h rrtype-placeholder.h rrparamregistry-placeholder.cc +s-rdatacode: Makefile $(EXTRA_DIST) $(PYTHON) ./gen-rdatacode.py touch $@ -- cgit v1.2.3 From 2e80ea0623fc05edc4f6088b024f9ea3cd168dff Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Mon, 20 Jan 2014 21:10:44 +0530 Subject: [2512] Add support for the CAA RR type --- src/lib/dns/Makefile.am | 2 + src/lib/dns/gen-rdatacode.py.in | 2 +- src/lib/dns/rdata/generic/caa_257.cc | 313 +++++++++++++++++++++ src/lib/dns/rdata/generic/caa_257.h | 61 ++++ src/lib/dns/tests/Makefile.am | 1 + src/lib/dns/tests/rdata_caa_unittest.cc | 300 ++++++++++++++++++++ src/lib/dns/tests/testdata/.gitignore | 4 + src/lib/dns/tests/testdata/Makefile.am | 5 + .../dns/tests/testdata/rdata_caa_fromWire1.spec | 6 + .../dns/tests/testdata/rdata_caa_fromWire2.spec | 7 + .../dns/tests/testdata/rdata_caa_fromWire3.spec | 7 + .../dns/tests/testdata/rdata_caa_fromWire4.spec | 7 + src/lib/dns/tests/testdata/rdata_caa_fromWire5 | 6 + src/lib/dns/tests/testdata/rdata_caa_fromWire6 | 4 + src/lib/util/python/gen_wiredata.py.in | 28 +- 15 files changed, 751 insertions(+), 2 deletions(-) create mode 100644 src/lib/dns/rdata/generic/caa_257.cc create mode 100644 src/lib/dns/rdata/generic/caa_257.h create mode 100644 src/lib/dns/tests/rdata_caa_unittest.cc create mode 100644 src/lib/dns/tests/testdata/rdata_caa_fromWire1.spec create mode 100644 src/lib/dns/tests/testdata/rdata_caa_fromWire2.spec create mode 100644 src/lib/dns/tests/testdata/rdata_caa_fromWire3.spec create mode 100644 src/lib/dns/tests/testdata/rdata_caa_fromWire4.spec create mode 100644 src/lib/dns/tests/testdata/rdata_caa_fromWire5 create mode 100644 src/lib/dns/tests/testdata/rdata_caa_fromWire6 (limited to 'src/lib/dns') diff --git a/src/lib/dns/Makefile.am b/src/lib/dns/Makefile.am index bda4e85333..bbc214d131 100644 --- a/src/lib/dns/Makefile.am +++ b/src/lib/dns/Makefile.am @@ -76,6 +76,8 @@ 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 diff --git a/src/lib/dns/gen-rdatacode.py.in b/src/lib/dns/gen-rdatacode.py.in index 3fd3b33112..84b55f8146 100755 --- a/src/lib/dns/gen-rdatacode.py.in +++ b/src/lib/dns/gen-rdatacode.py.in @@ -43,7 +43,7 @@ meta_types = { '27': 'gpos', '29': 'loc', '36': 'kx', '37': 'cert', '42': 'apl', '45': 'ipseckey', '52': 'tlsa', '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/rdata/generic/caa_257.cc b/src/lib/dns/rdata/generic/caa_257.cc new file mode 100644 index 0000000000..47366d651a --- /dev/null +++ b/src/lib/dns/rdata/generic/caa_257.cc @@ -0,0 +1,313 @@ +// 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 + +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include + +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 std::vector& value) : + flags_(flags), + tag_(tag), + value_(value) + {} + + uint8_t flags_; + const std::string tag_; + + // The first byte of this vector contains the length of the rest of + // the vector. This byte is actually unused and is skipped when + // reading the vector. + const detail::CharString 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. + std::vector value; + MasterToken token = lexer.getNextToken(MasterToken::QSTRING, true); + if ((token.getType() != MasterToken::END_OF_FILE) && + (token.getType() != MasterToken::END_OF_LINE)) + { + detail::stringToCharString(token.getStringRegion(), value); + } else { + // Convert it into a CharString. + value.push_back(0); + } + + 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 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"); + } + + vector tag_vec; + tag_vec.resize(tag_length + 1); + tag_vec[0] = tag_length; + buffer.readData(&tag_vec[1], tag_length); + rdata_len -= tag_length; + + const std::string tag = detail::charStringToString(tag_vec); + + if (rdata_len > 255) { + isc_throw(InvalidRdataLength, + "CAA value field is too long: " << rdata_len); + } + + vector value; + value.resize(rdata_len + 1); + value[0] = rdata_len; + if (rdata_len > 0) { + buffer.readData(&value[1], 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()); + } + + if (value.size() > 255) { + isc_throw(isc::InvalidParameter, + "CAA value field is too long: " << value.size()); + } + + std::vector value_vec; + value_vec.reserve(value.size() + 1); + value_vec.push_back(value.size()); + value_vec.insert(value_vec.end(), value.begin(), value.end()); + + 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_); + buffer.writeUint8(impl_->tag_.size()); + if (!impl_->tag_.empty()) { + buffer.writeData(&impl_->tag_[0], + impl_->tag_.size()); + } + if (impl_->value_.size() > 1) { + buffer.writeData(&impl_->value_[1], + impl_->value_.size() - 1); + } +} + +void +CAA::toWire(AbstractMessageRenderer& renderer) const { + renderer.writeUint8(impl_->flags_); + renderer.writeUint8(impl_->tag_.size()); + if (!impl_->tag_.empty()) { + renderer.writeData(&impl_->tag_[0], + impl_->tag_.size()); + } + if (impl_->value_.size() > 1) { + renderer.writeData(&impl_->value_[1], + impl_->value_.size() - 1); + } +} + +std::string +CAA::toText() const { + std::string result; + + result = lexical_cast(static_cast(impl_->flags_)); + result += " " + impl_->tag_; + result += " \"" + detail::charStringToString(impl_->value_) + "\""; + + return (result); +} + +int +CAA::compare(const Rdata& other) const { + const CAA& other_caa = dynamic_cast(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 + (impl_->tag_, other_caa.impl_->tag_); + if (result != 0) { + return (result); + } + + return (detail::compareCharStrings(impl_->value_, + other_caa.impl_->value_)); +} + +uint8_t +CAA::getFlags() const { + return (impl_->flags_); +} + +const std::string& +CAA::getTag() const { + return (impl_->tag_); +} + +// 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..69e3936d82 --- /dev/null +++ b/src/lib/dns/rdata/generic/caa_257.h @@ -0,0 +1,61 @@ +// 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 + +#include +#include + +#include +#include + +// 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 + /// + uint8_t getFlags() const; + const std::string& getTag() 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/tests/Makefile.am b/src/lib/dns/tests/Makefile.am index 5029681a32..46fcfb100d 100644 --- a/src/lib/dns/tests/Makefile.am +++ b/src/lib/dns/tests/Makefile.am @@ -63,6 +63,7 @@ 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/rdata_caa_unittest.cc b/src/lib/dns/tests/rdata_caa_unittest.cc new file mode 100644 index 0000000000..afa1c3c760 --- /dev/null +++ b/src/lib/dns/tests/rdata_caa_unittest.cc @@ -0,0 +1,300 @@ +// 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 +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +using isc::UnitTestUtil; +using namespace std; +using namespace isc; +using namespace isc::dns; +using namespace isc::util; +using namespace isc::dns::rdata; + +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( + rdata_str, rdata_caa, false, false); + } + + void checkFromText_InvalidText(const string& rdata_str) { + checkFromText( + rdata_str, rdata_caa, true, true); + } + + void checkFromText_LexerError(const string& rdata_str) { + checkFromText + ( + rdata_str, rdata_caa, true, true); + } + + void checkFromText_BadString(const string& rdata_str) { + checkFromText + ( + 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 + 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, 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)); + + // 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(256, 'a'); + EXPECT_THROW(const generic::CAA rdata_caa3(0, "issue", value), + isc::InvalidParameter); +} + +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) { + this->obuffer.clear(); + rdata_caa.toWire(this->obuffer); + + EXPECT_EQ(sizeof (rdata_caa_wiredata), + this->obuffer.getLength()); + + EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, + this->obuffer.getData(), + this->obuffer.getLength(), + rdata_caa_wiredata, sizeof(rdata_caa_wiredata)); +} + +TEST_F(Rdata_CAA_Test, compare) { + 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, emptyValueFromWire) { + const uint8_t rdf_wiredata[] = { + // flags + 0x00, + // tag length + 0x5, + // tag + 'i', 's', 's', 'u', 'e' + }; + + const generic::CAA rdf = + dynamic_cast + (*rdataFactoryFromFile(RRType("CAA"), RRClass("IN"), + "rdata_caa_fromWire3.wire")); + + EXPECT_EQ(0, rdf.getFlags()); + EXPECT_EQ("issue", rdf.getTag()); + + this->obuffer.clear(); + rdf.toWire(this->obuffer); + + EXPECT_EQ(sizeof(rdf_wiredata), this->obuffer.getLength()); + + EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, + this->obuffer.getData(), + this->obuffer.getLength(), + rdf_wiredata, sizeof(rdf_wiredata)); +} + +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()); + + this->obuffer.clear(); + rdata_caa2.toWire(this->obuffer); + + EXPECT_EQ(sizeof(rdata_caa2_wiredata), + this->obuffer.getLength()); + + EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, + this->obuffer.getData(), + this->obuffer.getLength(), + rdata_caa2_wiredata, sizeof(rdata_caa2_wiredata)); +} +} diff --git a/src/lib/dns/tests/testdata/.gitignore b/src/lib/dns/tests/testdata/.gitignore index a0a14f4a19..12be2c4d7a 100644 --- a/src/lib/dns/tests/testdata/.gitignore +++ b/src/lib/dns/tests/testdata/.gitignore @@ -105,6 +105,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..8ade682a76 100644 --- a/src/lib/dns/tests/testdata/Makefile.am +++ b/src/lib/dns/tests/testdata/Makefile.am @@ -64,6 +64,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 @@ -167,6 +169,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/util/python/gen_wiredata.py.in b/src/lib/util/python/gen_wiredata.py.in index b3858b6b26..b2b6d206cc 100755 --- a/src/lib/util/python/gen_wiredata.py.in +++ b/src/lib/util/python/gen_wiredata.py.in @@ -355,7 +355,7 @@ dict_rrtype = { 'none' : 0, 'a' : 1, 'ns' : 2, 'md' : 3, 'mf' : 4, 'cname' : 5, 'dhcid' : 49, 'nsec3' : 50, 'nsec3param' : 51, 'hip' : 55, 'spf' : 99, 'unspec' : 103, 'tkey' : 249, 'tsig' : 250, 'dlv' : 32769, 'ixfr' : 251, 'axfr' : 252, 'mailb' : 253, - 'maila' : 254, 'any' : 255 } + 'maila' : 254, 'any' : 255, 'caa' : 257 } rdict_rrtype = dict([(dict_rrtype[k], k.upper()) for k in dict_rrtype.keys()]) dict_rrclass = { 'in' : 1, 'ch' : 3, 'hs' : 4, 'any' : 255 } rdict_rrclass = dict([(dict_rrclass[k], k.upper()) for k in \ @@ -893,6 +893,32 @@ class AFSDB(RR): f.write('# SUBTYPE=%d SERVER=%s\n' % (self.subtype, self.server)) f.write('%04x %s\n' % (self.subtype, server_wire)) +class CAA(RR): + '''Implements rendering CAA RDATA in the test data format. + + Configurable parameters are as follows (see the description of the + same name of attribute for the default value): + - flags (int): The flags field. + - tag (string): The tag field. + - value (string): The value field. + ''' + flags = 0 + tag = 'issue' + value = 'ca.example.net' + def dump(self, f): + if self.rdlen is None: + self.rdlen = 1 + 1 + len(self.tag) + len(self.value) + else: + self.rdlen = int(self.rdlen) + self.dump_header(f, self.rdlen) + f.write('# FLAGS=%d TAG=%s VALUE=%s\n' % \ + (self.flags, self.tag, self.value)) + f.write('%02x %02x ' % \ + (self.flags, len(self.tag))) + f.write(encode_string(self.tag)) + f.write(encode_string(self.value)) + f.write('\n') + class DNSKEY(RR): '''Implements rendering DNSKEY RDATA in the test data format. -- cgit v1.2.3 From 60a4f25645165d590b0130f810472418cdf3f5b4 Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Wed, 22 Jan 2014 09:54:01 +0530 Subject: [2443] Skip checks in LabelSequence when building in non-debug mode --- src/lib/dns/labelsequence.cc | 15 ++++++++++++++- src/lib/dns/tests/labelsequence_unittest.cc | 6 ++++++ 2 files changed, 20 insertions(+), 1 deletion(-) (limited to 'src/lib/dns') diff --git a/src/lib/dns/labelsequence.cc b/src/lib/dns/labelsequence.cc index f5f6a95a1b..eb865b059c 100644 --- a/src/lib/dns/labelsequence.cc +++ b/src/lib/dns/labelsequence.cc @@ -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 #include #include @@ -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(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(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/tests/labelsequence_unittest.cc b/src/lib/dns/tests/labelsequence_unittest.cc index a3ac767b4f..191958194c 100644 --- a/src/lib/dns/tests/labelsequence_unittest.cc +++ b/src/lib/dns/tests/labelsequence_unittest.cc @@ -853,6 +853,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 +883,8 @@ TEST_F(LabelSequenceTest, badDeserialize) { EXPECT_THROW(LabelSequence ls(offsets_noincrease), isc::BadValue); } +#endif + namespace { // Helper function; repeatedly calls -- cgit v1.2.3 From b6875c7848cf648d45d0448ba8aa3f30a281d3c4 Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Wed, 22 Jan 2014 18:50:32 +0530 Subject: [2000] Update OPT RDATA parser to handle EDNS options --- src/lib/dns/rdata/generic/opt_41.cc | 156 ++++++++++++++++++++++++++++---- src/lib/dns/rdata/generic/opt_41.h | 30 +++++- src/lib/dns/tests/rdata_opt_unittest.cc | 41 +++++++-- 3 files changed, 197 insertions(+), 30 deletions(-) (limited to 'src/lib/dns') diff --git a/src/lib/dns/rdata/generic/opt_41.cc b/src/lib/dns/rdata/generic/opt_41.cc index 136bdf931a..167c309659 100644 --- a/src/lib/dns/rdata/generic/opt_41.cc +++ b/src/lib/dns/rdata/generic/opt_41.cc @@ -14,25 +14,68 @@ #include -#include - #include #include #include #include +#include + +#include +#include + using namespace std; using namespace isc::util; // BEGIN_ISC_NAMESPACE // BEGIN_RDATA_NAMESPACE +/// \brief Constructor. +OPT::PseudoRR::PseudoRR(uint16_t code, + boost::shared_ptr >& 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 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,30 +85,80 @@ 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 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 ((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 > + option_data(new std::vector(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 @@ -79,13 +172,36 @@ OPT::toWire(AbstractMessageRenderer&) const { } int -OPT::compare(const Rdata& other) const { - //const OPT& other_opt = dynamic_cast(other); - // right now we don't need other_opt: - static_cast(dynamic_cast(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 ((impl_->rdlength_ + length) < impl_->rdlength_) { + isc_throw(isc::InvalidParameter, + "Option length " << length + << " would overflow OPT RR RDLEN (currently " + << impl_->rdlength_ << ")."); + } + + boost::shared_ptr > + option_data(new std::vector(length)); + std::memcpy(&(*option_data)[0], data, length); + impl_->pseudo_rrs_.push_back(PseudoRR(code, option_data)); + impl_->rdlength_ += length; +} + +const std::vector& +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..88f2b4c2f6 100644 --- a/src/lib/dns/rdata/generic/opt_41.h +++ b/src/lib/dns/rdata/generic/opt_41.h @@ -18,6 +18,10 @@ #include +#include + +#include + // BEGIN_ISC_NAMESPACE // BEGIN_COMMON_DECLARATIONS @@ -25,15 +29,37 @@ // 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(); + + class PseudoRR { + public: + PseudoRR(uint16_t code, + boost::shared_ptr >& data); + + uint16_t getCode() const; + const uint8_t* getData() const; + uint16_t getLength() const; + + private: + uint16_t code_; + boost::shared_ptr > data_; + }; + + void appendPseudoRR(uint16_t code, const uint8_t* data, uint16_t length); + const std::vector& getPseudoRRs() const; + private: - // RR-type specific members are here. + OPTImpl* impl_; }; // END_RDATA_NAMESPACE diff --git a/src/lib/dns/tests/rdata_opt_unittest.cc b/src/lib/dns/tests/rdata_opt_unittest.cc index 20ccfe4994..900c672cf0 100644 --- a/src/lib/dns/tests/rdata_opt_unittest.cc +++ b/src/lib/dns/tests/rdata_opt_unittest.cc @@ -49,11 +49,10 @@ TEST_F(Rdata_OPT_Test, createFromWire) { "rdata_opt_fromWire")); EXPECT_NO_THROW(rdataFactoryFromFile(RRType::OPT(), RRClass::CH(), "rdata_opt_fromWire", 2)); - // short buffer case. EXPECT_THROW(rdataFactoryFromFile(RRType::OPT(), RRClass::IN(), "rdata_opt_fromWire", 11), - InvalidRdataLength); + InvalidBufferPosition); } TEST_F(Rdata_OPT_Test, createFromLexer) { @@ -74,16 +73,42 @@ TEST_F(Rdata_OPT_Test, toWireRenderer) { } TEST_F(Rdata_OPT_Test, toText) { - EXPECT_EQ("", rdata_opt.toText()); + 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( + EXPECT_THROW(rdata_opt.compare( *rdataFactoryFromFile(RRType::OPT(), RRClass::CH(), - "rdata_opt_fromWire", 2))); + "rdata_opt_fromWire", 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, append) { + EXPECT_THROW(rdata_opt.toText(), + isc::InvalidOperation); +} + +TEST_F(Rdata_OPT_Test, getPseudoRRs) { + const generic::OPT rdf = + dynamic_cast + (*rdataFactoryFromFile(RRType("OPT"), RRClass("IN"), + "rdata_opt_fromWire", 2)); + + const std::vector& rrs = rdf.getPseudoRRs(); + ASSERT_FALSE(rrs.empty()); + EXPECT_EQ(1, rrs.size()); + EXPECT_EQ(3, 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))); } } -- cgit v1.2.3 From 32bd410bb036fb31420c2424af685c621cf834be Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Wed, 8 Jan 2014 09:44:08 +0530 Subject: [3263] Add API doc note that RRset::addRdata() can throw --- src/lib/dns/rrset.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src/lib/dns') diff --git a/src/lib/dns/rrset.h b/src/lib/dns/rrset.h index 395cbdd3ba..55fdfd1a7f 100644 --- a/src/lib/dns/rrset.h +++ b/src/lib/dns/rrset.h @@ -382,6 +382,13 @@ 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; -- cgit v1.2.3 From 5519de5b8255213341664ff91d1dc0695de32f6d Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Wed, 8 Jan 2014 10:04:12 +0530 Subject: [3263] Update tests that allow adding RdataPtr to an RRset when class or type don't match --- src/lib/dns/tests/rrset_unittest.cc | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'src/lib/dns') diff --git a/src/lib/dns/tests/rrset_unittest.cc b/src/lib/dns/tests/rrset_unittest.cc index a605caf62b..76270cd1ab 100644 --- a/src/lib/dns/tests/rrset_unittest.cc +++ b/src/lib/dns/tests/rrset_unittest.cc @@ -162,14 +162,22 @@ TEST_F(RRsetTest, addRdataPtr) { rrset_a_empty.addRdata(createRdata(rrset_a_empty.getType(), rrset_a_empty.getClass(), "192.0.2.2")); - 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, iterator) { -- cgit v1.2.3 From e2c4caa23971f3ebd70483ccc9c0b9ba8b7efa2e Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Mon, 27 Jan 2014 12:31:53 +0530 Subject: [2000] Add more fromWire() tests --- src/lib/dns/rdata/generic/opt_41.cc | 10 +++++++--- src/lib/dns/tests/rdata_opt_unittest.cc | 25 ++++++++++++++++++++----- src/lib/dns/tests/testdata/Makefile.am | 4 +++- src/lib/dns/tests/testdata/rdata_opt_fromWire | 16 ---------------- src/lib/dns/tests/testdata/rdata_opt_fromWire1 | 16 ++++++++++++++++ src/lib/dns/tests/testdata/rdata_opt_fromWire2 | 4 ++++ src/lib/dns/tests/testdata/rdata_opt_fromWire3 | 8 ++++++++ src/lib/dns/tests/testdata/rdata_opt_fromWire4 | 9 +++++++++ 8 files changed, 67 insertions(+), 25 deletions(-) delete mode 100644 src/lib/dns/tests/testdata/rdata_opt_fromWire create mode 100644 src/lib/dns/tests/testdata/rdata_opt_fromWire1 create mode 100644 src/lib/dns/tests/testdata/rdata_opt_fromWire2 create mode 100644 src/lib/dns/tests/testdata/rdata_opt_fromWire3 create mode 100644 src/lib/dns/tests/testdata/rdata_opt_fromWire4 (limited to 'src/lib/dns') diff --git a/src/lib/dns/rdata/generic/opt_41.cc b/src/lib/dns/rdata/generic/opt_41.cc index 167c309659..176fa3929b 100644 --- a/src/lib/dns/rdata/generic/opt_41.cc +++ b/src/lib/dns/rdata/generic/opt_41.cc @@ -111,7 +111,9 @@ OPT::OPT(InputBuffer& buffer, size_t rdata_len) : const uint16_t option_length = buffer.readUint16(); rdata_len -= 4; - if ((impl_ptr->rdlength_ + option_length) < impl_ptr->rdlength_) { + if (static_cast(impl_ptr->rdlength_ + option_length) < + impl_ptr->rdlength_) + { isc_throw(InvalidRdataText, "Option length " << option_length << " would overflow OPT RR RDLEN (currently " @@ -119,7 +121,7 @@ OPT::OPT(InputBuffer& buffer, size_t rdata_len) : } if (rdata_len < option_length) { - isc_throw(InvalidRdataLength, "Corrupt Pseudo OPT RR record"); + isc_throw(InvalidRdataLength, "Corrupt pseudo OPT RR record"); } boost::shared_ptr > @@ -184,7 +186,9 @@ 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 ((impl_->rdlength_ + length) < impl_->rdlength_) { + if (static_cast(impl_->rdlength_ + length) < + impl_->rdlength_) + { isc_throw(isc::InvalidParameter, "Option length " << length << " would overflow OPT RR RDLEN (currently " diff --git a/src/lib/dns/tests/rdata_opt_unittest.cc b/src/lib/dns/tests/rdata_opt_unittest.cc index 900c672cf0..6f703bf268 100644 --- a/src/lib/dns/tests/rdata_opt_unittest.cc +++ b/src/lib/dns/tests/rdata_opt_unittest.cc @@ -46,12 +46,27 @@ 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 RDLEN. This throws InvalidRdataLength even if subsequent + // pseudo RRs cause RDLEN size to be exhausted. + EXPECT_THROW(rdataFactoryFromFile(RRType::OPT(), RRClass::IN(), + "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_fromWire", 11), + "rdata_opt_fromWire1", 11), InvalidBufferPosition); } @@ -80,7 +95,7 @@ TEST_F(Rdata_OPT_Test, toText) { TEST_F(Rdata_OPT_Test, compare) { 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 @@ -98,7 +113,7 @@ TEST_F(Rdata_OPT_Test, getPseudoRRs) { const generic::OPT rdf = dynamic_cast (*rdataFactoryFromFile(RRType("OPT"), RRClass("IN"), - "rdata_opt_fromWire", 2)); + "rdata_opt_fromWire1", 2)); const std::vector& rrs = rdf.getPseudoRRs(); ASSERT_FALSE(rrs.empty()); diff --git a/src/lib/dns/tests/testdata/Makefile.am b/src/lib/dns/tests/testdata/Makefile.am index b6d7e35ada..99a124a507 100644 --- a/src/lib/dns/tests/testdata/Makefile.am +++ b/src/lib/dns/tests/testdata/Makefile.am @@ -127,7 +127,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 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..0ca5f6aa0e --- /dev/null +++ b/src/lib/dns/tests/testdata/rdata_opt_fromWire1 @@ -0,0 +1,16 @@ +# +# 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_fromWire2 b/src/lib/dns/tests/testdata/rdata_opt_fromWire2 new file mode 100644 index 0000000000..4f5945c2f9 --- /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..5ec2def0f5 --- /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 +# psuedo RR 1 of size 7 (code=3, len=3) +00 03 00 03 00 01 02 +# psuedo 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..1b388c31d4 --- /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 +# psuedo RR 1 (code=3, len=3) +00 03 00 03 00 01 02 +# psuedo RR 2 (code=4, len=65535 overflows RDLEN) +00 04 ff ff 00 01 02 +# rest of option data is omitted... -- cgit v1.2.3 From a001951886e545f2f0a299fccbeb7fb9388deccf Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Mon, 27 Jan 2014 13:36:53 +0530 Subject: [2000] Add appendPseudoRR() unittests --- src/lib/dns/tests/rdata_opt_unittest.cc | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) (limited to 'src/lib/dns') diff --git a/src/lib/dns/tests/rdata_opt_unittest.cc b/src/lib/dns/tests/rdata_opt_unittest.cc index 6f703bf268..e5695ac328 100644 --- a/src/lib/dns/tests/rdata_opt_unittest.cc +++ b/src/lib/dns/tests/rdata_opt_unittest.cc @@ -104,9 +104,23 @@ TEST_F(Rdata_OPT_Test, compare) { isc::InvalidOperation); } -TEST_F(Rdata_OPT_Test, append) { - EXPECT_THROW(rdata_opt.toText(), - 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 buffer((1 << 16) - 1); + EXPECT_THROW(rdata_opt.appendPseudoRR(0x0044, &buffer[0], buffer.size()), + isc::InvalidParameter); } TEST_F(Rdata_OPT_Test, getPseudoRRs) { -- cgit v1.2.3 From 0408d1e6472105cb9c762ac3ef7082d47dc6a720 Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Mon, 27 Jan 2014 13:46:19 +0530 Subject: [2000] Add OPT::toWire() implementations --- src/lib/dns/rdata/generic/opt_41.cc | 22 +++++++++++++++---- src/lib/dns/tests/rdata_opt_unittest.cc | 39 ++++++++++++++++++++++++++++++--- 2 files changed, 54 insertions(+), 7 deletions(-) (limited to 'src/lib/dns') diff --git a/src/lib/dns/rdata/generic/opt_41.cc b/src/lib/dns/rdata/generic/opt_41.cc index 176fa3929b..6b292e9fa1 100644 --- a/src/lib/dns/rdata/generic/opt_41.cc +++ b/src/lib/dns/rdata/generic/opt_41.cc @@ -164,13 +164,27 @@ OPT::toText() const { } 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 diff --git a/src/lib/dns/tests/rdata_opt_unittest.cc b/src/lib/dns/tests/rdata_opt_unittest.cc index e5695ac328..756f8d3f0f 100644 --- a/src/lib/dns/tests/rdata_opt_unittest.cc +++ b/src/lib/dns/tests/rdata_opt_unittest.cc @@ -35,7 +35,14 @@ 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, 0x03, + // Option length + 0x00, 0x03, + // Option data + 0x00, 0x01, 0x02 +}; TEST_F(Rdata_OPT_Test, createFromText) { // OPT RR cannot be created from text. @@ -78,21 +85,47 @@ TEST_F(Rdata_OPT_Test, createFromLexer) { } TEST_F(Rdata_OPT_Test, toWireBuffer) { + const generic::OPT rdata_opt = + dynamic_cast + (*rdataFactoryFromFile(RRType("OPT"), RRClass("IN"), + "rdata_opt_fromWire1", 2)); + + obuffer.clear(); rdata_opt.toWire(obuffer); - EXPECT_EQ(0, obuffer.getLength()); + + EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, + obuffer.getData(), + obuffer.getLength(), + rdata_opt_wiredata, sizeof(rdata_opt_wiredata)); } TEST_F(Rdata_OPT_Test, toWireRenderer) { + const generic::OPT rdata_opt = + dynamic_cast + (*rdataFactoryFromFile(RRType("OPT"), RRClass("IN"), + "rdata_opt_fromWire1", 2)); + + renderer.clear(); rdata_opt.toWire(renderer); - EXPECT_EQ(0, obuffer.getLength()); + + EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, + renderer.getData(), + renderer.getLength(), + rdata_opt_wiredata, sizeof(rdata_opt_wiredata)); } TEST_F(Rdata_OPT_Test, toText) { + // empty OPT + const generic::OPT rdata_opt; + EXPECT_THROW(rdata_opt.toText(), isc::InvalidOperation); } TEST_F(Rdata_OPT_Test, compare) { + // empty OPT + const generic::OPT rdata_opt; + EXPECT_THROW(rdata_opt.compare( *rdataFactoryFromFile(RRType::OPT(), RRClass::CH(), "rdata_opt_fromWire1", 2)), -- cgit v1.2.3 From 916893ac37eeeb169c90c7cf374630a7cfba127b Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Mon, 27 Jan 2014 14:06:30 +0530 Subject: [2000] Add another toWire() test --- src/lib/dns/tests/rdata_opt_unittest.cc | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) (limited to 'src/lib/dns') diff --git a/src/lib/dns/tests/rdata_opt_unittest.cc b/src/lib/dns/tests/rdata_opt_unittest.cc index 756f8d3f0f..49d3068347 100644 --- a/src/lib/dns/tests/rdata_opt_unittest.cc +++ b/src/lib/dns/tests/rdata_opt_unittest.cc @@ -154,6 +154,38 @@ TEST_F(Rdata_OPT_Test, appendPseudoRR) { const std::vector 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); + + EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, + obuffer.getData(), + obuffer.getLength(), + rdata_opt_wiredata2, sizeof(rdata_opt_wiredata2)); } TEST_F(Rdata_OPT_Test, getPseudoRRs) { -- cgit v1.2.3 From 7f9bc84501ca5a850e4975db715eae07234e7c25 Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Tue, 28 Jan 2014 08:21:48 +0530 Subject: [1396] Rename method to getLength() At first I thought getLength() may already be in use by RR type-specific classes, but it's not in use. getLength() is more consistent with naming of other classes' wire data length methods. --- src/lib/dns/rdata.cc | 2 +- src/lib/dns/rdata.h | 6 +++--- src/lib/dns/tests/rdata_unittest.cc | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) (limited to 'src/lib/dns') diff --git a/src/lib/dns/rdata.cc b/src/lib/dns/rdata.cc index 09f289b7dd..ff95fee6b0 100644 --- a/src/lib/dns/rdata.cc +++ b/src/lib/dns/rdata.cc @@ -47,7 +47,7 @@ namespace dns { namespace rdata { uint16_t -Rdata::getWireLength() const { +Rdata::getLength() const { OutputBuffer obuffer(0); toWire(obuffer); diff --git a/src/lib/dns/rdata.h b/src/lib/dns/rdata.h index 352554e1af..79ca641c80 100644 --- a/src/lib/dns/rdata.h +++ b/src/lib/dns/rdata.h @@ -227,15 +227,15 @@ public: /// 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 getWireLength() method to every RDATA + /// implementations of \c getLength() method to every RDATA /// type. This is why this method is virtual. Once all Rdata types - /// have \c getWireLength() implementations, this base class + /// 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 getWireLength() const; + virtual uint16_t getLength() const; }; namespace generic { diff --git a/src/lib/dns/tests/rdata_unittest.cc b/src/lib/dns/tests/rdata_unittest.cc index 3772e9b4b0..1678f0b1eb 100644 --- a/src/lib/dns/tests/rdata_unittest.cc +++ b/src/lib/dns/tests/rdata_unittest.cc @@ -211,12 +211,12 @@ TEST_F(RdataTest, createRdataWithLexer) { "file does not end with newline"); } -TEST_F(RdataTest, getWireLength) { +TEST_F(RdataTest, getLength) { const in::AAAA aaaa_rdata("2001:db8::1"); - EXPECT_EQ(16, aaaa_rdata.getWireLength()); + EXPECT_EQ(16, aaaa_rdata.getLength()); const generic::TXT txt_rdata("Hello World"); - EXPECT_EQ(12, txt_rdata.getWireLength()); + EXPECT_EQ(12, txt_rdata.getLength()); } } -- cgit v1.2.3 From 000f7efd1c2d316c3ee02902713cedc355efefba Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Tue, 28 Jan 2014 08:53:13 +0530 Subject: [1396] Add RRset::getLength() --- src/lib/dns/rrset.cc | 59 +++++++++++++++++++++++++++++++++++++ src/lib/dns/rrset.h | 28 ++++++++++++++++++ src/lib/dns/tests/rrset_unittest.cc | 58 ++++++++++++++++++++++++++++++++++++ 3 files changed, 145 insertions(+) (limited to 'src/lib/dns') diff --git a/src/lib/dns/rrset.cc b/src/lib/dns/rrset.cc index 8dfe884dac..7fbd0d1503 100644 --- a/src/lib/dns/rrset.cc +++ b/src/lib/dns/rrset.cc @@ -289,6 +289,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 += 2; // 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 += 2; // 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 +366,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..537c999d1f 100644 --- a/src/lib/dns/rrset.h +++ b/src/lib/dns/rrset.h @@ -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 @@ -642,6 +656,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. @@ -813,6 +834,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/tests/rrset_unittest.cc b/src/lib/dns/tests/rrset_unittest.cc index da3eb52267..72049b23ee 100644 --- a/src/lib/dns/tests/rrset_unittest.cc +++ b/src/lib/dns/tests/rrset_unittest.cc @@ -204,6 +204,30 @@ 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 = 2 octets + // RDLENGTH field = 2 octets + // Total = 18 + 2 + 2 + 2 + 2 = 26 octets + EXPECT_EQ(26, rrset_any_a_empty.getLength()); + EXPECT_EQ(26, rrset_none_a_empty.getLength()); + + // RRset with single RDATA + // 26 (above) + 4 octets (A RDATA) = 30 octets + rrset_a_empty.addRdata(in::A("192.0.2.1")); + EXPECT_EQ(30, rrset_a_empty.getLength()); + + // 2 A RRs + rrset_a_empty.addRdata(in::A("192.0.2.2")); + EXPECT_EQ(60, rrset_a_empty.getLength()); +} + TEST_F(RRsetTest, toWireBuffer) { rrset_a.toWire(buffer); @@ -365,4 +389,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 = 2 octets + // RDLENGTH field = 2 octets + // A RDATA = 4 octets + // Total = 18 + 2 + 2 + 2 + 2 + 4 = 30 octets + + // 2 A RRs + EXPECT_EQ(60, 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 = 2 octets + // RDLENGTH field = 2 octets + // RRSIG RDATA = 40 octets + // Total = 18 + 2 + 2 + 2 + 2 + 40 = 66 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(66, my_rrsig->getLength()); + + // RRset with attached RRSIG + rrset_a->addRRsig(my_rrsig); + + EXPECT_EQ(60 + 66, rrset_a->getLength()); +} } -- cgit v1.2.3 From 5410f9ce9d90585e00828253cedce1e024ad4524 Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Tue, 28 Jan 2014 09:29:26 +0530 Subject: [1396] Add Python binding for RRset::getLength() --- src/lib/dns/python/rrset_python.cc | 15 +++++++++++++++ src/lib/dns/python/tests/rrset_python_test.py | 18 ++++++++++++++++++ 2 files changed, 33 insertions(+) (limited to 'src/lib/dns') diff --git a/src/lib/dns/python/rrset_python.cc b/src/lib/dns/python/rrset_python.cc index de5925a431..07af4ea505 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, @@ -135,6 +138,18 @@ RRset_getRdataCount(PyObject* self, PyObject*) { getRdataCount())); } +PyObject* +RRset_getLength(PyObject* self, PyObject*) { + try { + return (Py_BuildValue("H", static_cast(self)->cppobj-> + getLength())); + } catch (const EmptyRRset& ers) { + PyErr_Clear(); + PyErr_SetString(po_EmptyRRset, ers.what()); + return (NULL); + } +} + PyObject* RRset_getName(PyObject* self, PyObject*) { try { diff --git a/src/lib/dns/python/tests/rrset_python_test.py b/src/lib/dns/python/tests/rrset_python_test.py index 9592b42021..429818110d 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 = 2 octets + # RDLENGTH field = 2 octets + # Total = 18 + 2 + 2 + 2 + 2 = 26 octets + self.assertEqual(26, self.rrset_any_a_empty.get_length()) + + # Single A RR: + # 26 octets (above) + 4 octets (A RDATA) = 30 octets + # With 2 A RRs: + self.assertEqual(30 + 30, 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()) -- cgit v1.2.3 From 63eca991aef43dac723b6aec44345c7747b5939a Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Tue, 28 Jan 2014 11:24:31 +0530 Subject: [1396] Fix width of TTL field --- src/lib/datasrc/memory/treenode_rrset.cc | 2 +- .../tests/memory/treenode_rrset_unittest.cc | 12 +++++----- src/lib/dns/python/tests/rrset_python_test.py | 10 ++++---- src/lib/dns/rrset.cc | 4 ++-- src/lib/dns/tests/rrset_unittest.cc | 28 +++++++++++----------- 5 files changed, 28 insertions(+), 28 deletions(-) (limited to 'src/lib/dns') diff --git a/src/lib/datasrc/memory/treenode_rrset.cc b/src/lib/datasrc/memory/treenode_rrset.cc index c95407d820..1d468ef3ea 100644 --- a/src/lib/datasrc/memory/treenode_rrset.cc +++ b/src/lib/datasrc/memory/treenode_rrset.cc @@ -141,7 +141,7 @@ getLengthHelper(size_t* rlength, size_t rr_count, uint16_t name_labels_size, rrlen += name_labels_size; rrlen += 2; // TYPE field rrlen += 2; // CLASS field - rrlen += 2; // TTL field + rrlen += 4; // TTL field rrlen += 2; // RDLENGTH field *rlength = 0; diff --git a/src/lib/datasrc/tests/memory/treenode_rrset_unittest.cc b/src/lib/datasrc/tests/memory/treenode_rrset_unittest.cc index 2a2c3334eb..451a91aacc 100644 --- a/src/lib/datasrc/tests/memory/treenode_rrset_unittest.cc +++ b/src/lib/datasrc/tests/memory/treenode_rrset_unittest.cc @@ -338,30 +338,30 @@ TEST_F(TreeNodeRRsetTest, getLength) { // www.example.com = 1 + 3 + 1 + 7 + 1 + 3 + 1 = 17 octets // TYPE field = 2 octets // CLASS field = 2 octets - // TTL field = 2 octets + // TTL field = 4 octets // RDLENGTH field = 2 octets // A RDATA = 4 octets - // Total = 17 + 2 + 2 + 2 + 2 + 4 = 29 octets + // Total = 17 + 2 + 2 + 4 + 2 + 4 = 31 octets // RRSIG RR // www.example.com = 1 + 4 + 1 + 7 + 1 + 3 + 1 = 17 octets // TYPE field = 2 octets // CLASS field = 2 octets - // TTL field = 2 octets + // TTL field = 4 octets // RDLENGTH field = 2 octets // RRSIG RDATA = 18 + [1 + 7 + 1 + 3 + 1 (example.com)] + 3 (base64 // decode of FAKE) octets - // Total = 17 + 2 + 2 + 2 + 2 + 34 = 59 octets + // Total = 17 + 2 + 2 + 4 + 2 + 34 = 61 octets // 1. with RRSIG, DNSSEC not OK // ` 2 A RRs + 0 RRSIG RRs const TreeNodeRRset rrset1(rrclass_, www_node_, a_rdataset_, false); - EXPECT_EQ(29 + 29, rrset1.getLength()); + EXPECT_EQ(31 + 31, rrset1.getLength()); // 2. with RRSIG, DNSSEC OK // ` 2 A RRs + 1 RRSIG RR const TreeNodeRRset rrset2(rrclass_, www_node_, a_rdataset_, true); - EXPECT_EQ(29 + 29 + 59, rrset2.getLength()); + EXPECT_EQ(31 + 31 + 61, rrset2.getLength()); } TEST_F(TreeNodeRRsetTest, toWire) { diff --git a/src/lib/dns/python/tests/rrset_python_test.py b/src/lib/dns/python/tests/rrset_python_test.py index 429818110d..d848d278b6 100644 --- a/src/lib/dns/python/tests/rrset_python_test.py +++ b/src/lib/dns/python/tests/rrset_python_test.py @@ -53,15 +53,15 @@ class TestModuleSpec(unittest.TestCase): # test.example.com = 1 + 4 + 1 + 7 + 1 + 3 + 1 = 18 octets # TYPE field = 2 octets # CLASS field = 2 octets - # TTL field = 2 octets + # TTL field = 4 octets # RDLENGTH field = 2 octets - # Total = 18 + 2 + 2 + 2 + 2 = 26 octets - self.assertEqual(26, self.rrset_any_a_empty.get_length()) + # Total = 18 + 2 + 2 + 4 + 2 = 28 octets + self.assertEqual(28, self.rrset_any_a_empty.get_length()) # Single A RR: - # 26 octets (above) + 4 octets (A RDATA) = 30 octets + # 28 octets (above) + 4 octets (A RDATA) = 32 octets # With 2 A RRs: - self.assertEqual(30 + 30, self.rrset_a.get_length()) + self.assertEqual(32 + 32, self.rrset_a.get_length()) def test_get_name(self): self.assertEqual(self.test_name, self.rrset_a.get_name()) diff --git a/src/lib/dns/rrset.cc b/src/lib/dns/rrset.cc index 7fbd0d1503..8b9f4c4ee3 100644 --- a/src/lib/dns/rrset.cc +++ b/src/lib/dns/rrset.cc @@ -306,7 +306,7 @@ BasicRRset::getLength() const { length += getName().getLength(); length += 2; // TYPE field length += 2; // CLASS field - length += 2; // TTL field + length += 4; // TTL field length += 2; // RDLENGTH field (=0 in wire format) return (length); @@ -320,7 +320,7 @@ BasicRRset::getLength() const { rrlen += getName().getLength(); rrlen += 2; // TYPE field rrlen += 2; // CLASS field - rrlen += 2; // TTL field + rrlen += 4; // TTL field rrlen += 2; // RDLENGTH field rrlen += it->getCurrent().getLength(); diff --git a/src/lib/dns/tests/rrset_unittest.cc b/src/lib/dns/tests/rrset_unittest.cc index 72049b23ee..558b663c92 100644 --- a/src/lib/dns/tests/rrset_unittest.cc +++ b/src/lib/dns/tests/rrset_unittest.cc @@ -212,20 +212,20 @@ TEST_F(RRsetTest, getLength) { // test.example.com = 1 + 4 + 1 + 7 + 1 + 3 + 1 = 18 octets // TYPE field = 2 octets // CLASS field = 2 octets - // TTL field = 2 octets + // TTL field = 4 octets // RDLENGTH field = 2 octets - // Total = 18 + 2 + 2 + 2 + 2 = 26 octets - EXPECT_EQ(26, rrset_any_a_empty.getLength()); - EXPECT_EQ(26, rrset_none_a_empty.getLength()); + // 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 - // 26 (above) + 4 octets (A RDATA) = 30 octets + // 28 (above) + 4 octets (A RDATA) = 32 octets rrset_a_empty.addRdata(in::A("192.0.2.1")); - EXPECT_EQ(30, rrset_a_empty.getLength()); + EXPECT_EQ(32, rrset_a_empty.getLength()); // 2 A RRs rrset_a_empty.addRdata(in::A("192.0.2.2")); - EXPECT_EQ(60, rrset_a_empty.getLength()); + EXPECT_EQ(32 + 32, rrset_a_empty.getLength()); } TEST_F(RRsetTest, toWireBuffer) { @@ -395,32 +395,32 @@ TEST_F(RRsetRRSIGTest, getLength) { // test.example.com = 1 + 4 + 1 + 7 + 1 + 3 + 1 = 18 octets // TYPE field = 2 octets // CLASS field = 2 octets - // TTL field = 2 octets + // TTL field = 4 octets // RDLENGTH field = 2 octets // A RDATA = 4 octets - // Total = 18 + 2 + 2 + 2 + 2 + 4 = 30 octets + // Total = 18 + 2 + 2 + 4 + 2 + 4 = 32 octets // 2 A RRs - EXPECT_EQ(60, rrset_a->getLength()); + 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 = 2 octets + // TTL field = 4 octets // RDLENGTH field = 2 octets // RRSIG RDATA = 40 octets - // Total = 18 + 2 + 2 + 2 + 2 + 40 = 66 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(66, my_rrsig->getLength()); + EXPECT_EQ(68, my_rrsig->getLength()); // RRset with attached RRSIG rrset_a->addRRsig(my_rrsig); - EXPECT_EQ(60 + 66, rrset_a->getLength()); + EXPECT_EQ(32 + 32 + 68, rrset_a->getLength()); } } -- cgit v1.2.3 From 84de42ee09a14ef8d2a066815f99700e133dcc33 Mon Sep 17 00:00:00 2001 From: Stephen Morris Date: Tue, 28 Jan 2014 11:34:44 +0000 Subject: [2443] Minor changes during the course of the review --- src/lib/dns/labelsequence.cc | 4 ++-- src/lib/dns/tests/labelsequence_unittest.cc | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'src/lib/dns') diff --git a/src/lib/dns/labelsequence.cc b/src/lib/dns/labelsequence.cc index eb865b059c..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,7 +12,7 @@ // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR // PERFORMANCE OF THIS SOFTWARE. -#include "config.h" +#include #include #include diff --git a/src/lib/dns/tests/labelsequence_unittest.cc b/src/lib/dns/tests/labelsequence_unittest.cc index 191958194c..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 + #include #include -- cgit v1.2.3 From c415976948d86aac316937f70a46192c4d079da6 Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Wed, 29 Jan 2014 22:04:29 +0530 Subject: [3312] Reduce scope of variables (cppcheck report) --- src/bin/d2/tests/nc_trans_unittests.cc | 2 +- src/lib/dns/python/rdata_python.cc | 4 ++-- src/lib/dns/python/rrset_python.cc | 2 +- src/lib/log/message_dictionary.cc | 10 +++++----- 4 files changed, 9 insertions(+), 9 deletions(-) (limited to 'src/lib/dns') diff --git a/src/bin/d2/tests/nc_trans_unittests.cc b/src/bin/d2/tests/nc_trans_unittests.cc index 010d1970a0..a62d0ae474 100644 --- a/src/bin/d2/tests/nc_trans_unittests.cc +++ b/src/bin/d2/tests/nc_trans_unittests.cc @@ -326,8 +326,8 @@ public: ASSERT_EQ(NameChangeTransaction::NOP_EVT, name_change->getNextEvent()); - int cnt = 0; while (name_change->getNextEvent() == NameChangeTransaction::NOP_EVT) { + int cnt = 0; ASSERT_NO_THROW(cnt = runTimedIO(run_time)); if (cnt == 0) { FAIL() << "IO Service stopped unexpectedly"; diff --git a/src/lib/dns/python/rdata_python.cc b/src/lib/dns/python/rdata_python.cc index 20f67c8d7e..682a16801b 100644 --- a/src/lib/dns/python/rdata_python.cc +++ b/src/lib/dns/python/rdata_python.cc @@ -104,9 +104,9 @@ Rdata_init(PyObject* self_p, PyObject* args, PyObject*) { const char* s; const char* data; Py_ssize_t len; - s_Rdata* self(static_cast(self_p)); - try { + s_Rdata* self = static_cast(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 07af4ea505..4d864d1d8a 100644 --- a/src/lib/dns/python/rrset_python.cc +++ b/src/lib/dns/python/rrset_python.cc @@ -251,9 +251,9 @@ PyObject* RRset_toWire(PyObject* self_p, PyObject* args) { PyObject* bytes; PyObject* mr; - const s_RRset* self(static_cast(self_p)); try { + const s_RRset* self = static_cast(self_p); if (PyArg_ParseTuple(args, "O", &bytes) && PySequence_Check(bytes)) { PyObject* bytes_o = bytes; diff --git a/src/lib/log/message_dictionary.cc b/src/lib/log/message_dictionary.cc index 3bfc56cd82..577042bc6b 100644 --- a/src/lib/log/message_dictionary.cc +++ b/src/lib/log/message_dictionary.cc @@ -63,13 +63,13 @@ MessageDictionary::load(const char* messages[]) { vector duplicates; int i = 0; while (messages[i]) { - - // ID present, so note it and point to text. - const MessageID ident(messages[i++]); + // ID present, so point to text. + ++i; if (messages[i]) { - + const MessageID ident(messages[i - 1]); // Text not null, note it and point to next ident. - string text(messages[i++]); + const std::string text(messages[i]); + ++i; // Add ID and text to message dictionary, noting if the ID was // already present. -- cgit v1.2.3 From 2d742ae954b869826da72d9c28cb088362839130 Mon Sep 17 00:00:00 2001 From: Shane Kerr Date: Wed, 29 Jan 2014 23:07:44 +0100 Subject: [3010] Avoid signed integer overflow --- src/lib/dns/rrttl.cc | 44 ++++++++++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 16 deletions(-) (limited to 'src/lib/dns') 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(ttlstr); + val = boost::lexical_cast(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(string(pos, - unit)); + const uint64_t value = + boost::lexical_cast(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; } -- cgit v1.2.3 From e19305ef4e339db5ac85f1a3c1ba98abee62dd32 Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Thu, 30 Jan 2014 12:16:06 +0530 Subject: [3286] Clear Message before parsing fromWire() --- src/lib/dns/message.cc | 3 +++ src/lib/dns/tests/message_unittest.cc | 29 +++++++++++++++++++++++------ 2 files changed, 26 insertions(+), 6 deletions(-) (limited to 'src/lib/dns') diff --git a/src/lib/dns/message.cc b/src/lib/dns/message.cc index 2bc337ad6f..0c5cf37385 100644 --- a/src/lib/dns/message.cc +++ b/src/lib/dns/message.cc @@ -645,6 +645,9 @@ Message::fromWire(InputBuffer& buffer, ParseOptions options) { "Message parse attempted in non parse mode"); } + // Clear any old parsed data + clear(Message::PARSE); + if (!impl_->header_parsed_) { parseHeader(buffer); } diff --git a/src/lib/dns/tests/message_unittest.cc b/src/lib/dns/tests/message_unittest.cc index 8aaebaa183..eeeeba73da 100644 --- a/src/lib/dns/tests/message_unittest.cc +++ b/src/lib/dns/tests/message_unittest.cc @@ -572,12 +572,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 +606,25 @@ 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); +} + 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. -- cgit v1.2.3 From 040a4aec3997990a3da8061f20d714060716b8d6 Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Thu, 30 Jan 2014 18:38:08 +0530 Subject: [3286] Make fromWire() always start reading from position 0 in the passed buffer This fixes a bug which occurs if parseHeader() is called separately from fromWire(). --- src/lib/dns/message.cc | 9 ++++++--- src/lib/dns/message.h | 7 ++++++- src/lib/dns/tests/message_unittest.cc | 12 ++++++++++++ 3 files changed, 24 insertions(+), 4 deletions(-) (limited to 'src/lib/dns') diff --git a/src/lib/dns/message.cc b/src/lib/dns/message.cc index 0c5cf37385..8487cf5f54 100644 --- a/src/lib/dns/message.cc +++ b/src/lib/dns/message.cc @@ -620,6 +620,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()); @@ -648,9 +652,8 @@ Message::fromWire(InputBuffer& buffer, ParseOptions options) { // Clear any old parsed data clear(Message::PARSE); - if (!impl_->header_parsed_) { - parseHeader(buffer); - } + 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..17cf88b6ce 100644 --- a/src/lib/dns/message.h +++ b/src/lib/dns/message.h @@ -607,6 +607,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 +646,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/tests/message_unittest.cc b/src/lib/dns/tests/message_unittest.cc index eeeeba73da..61f2e118d2 100644 --- a/src/lib/dns/tests/message_unittest.cc +++ b/src/lib/dns/tests/message_unittest.cc @@ -623,6 +623,18 @@ TEST_F(MessageTest, fromWireMultiple) { 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) { -- cgit v1.2.3 From ab8ff1eda4c0daaeaf06614651ecea31a38339ab Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Thu, 30 Jan 2014 11:17:43 +0530 Subject: [2518] Introduce DNSTextError and remove generic catch for isc::Exception from the MasterLoader --- src/lib/dns/exceptions.h | 13 +++++++++++-- src/lib/dns/master_loader.cc | 22 +++++++++++++--------- src/lib/dns/rdata.h | 12 ++++++------ src/lib/dns/rrclass-placeholder.h | 4 ++-- src/lib/dns/rrttl.h | 4 ++-- src/lib/dns/rrtype-placeholder.h | 4 ++-- 6 files changed, 36 insertions(+), 23 deletions(-) (limited to 'src/lib/dns') diff --git a/src/lib/dns/exceptions.h b/src/lib/dns/exceptions.h index 34413aa4a1..21030b49c2 100644 --- a/src/lib/dns/exceptions.h +++ b/src/lib/dns/exceptions.h @@ -36,13 +36,22 @@ public: 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 isc::dns::Exception { +class NameParserException : public DNSTextError { public: NameParserException(const char* file, size_t line, const char* what) : - isc::dns::Exception(file, line, what) {} + DNSTextError(file, line, what) {} }; class DNSProtocolError : public isc::dns::Exception { diff --git a/src/lib/dns/master_loader.cc b/src/lib/dns/master_loader.cc index 6b6e091489..095a2724d3 100644 --- a/src/lib/dns/master_loader.cc +++ b/src/lib/dns/master_loader.cc @@ -576,15 +576,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/rdata.h b/src/lib/dns/rdata.h index a1115fd2a3..58603bede3 100644 --- a/src/lib/dns/rdata.h +++ b/src/lib/dns/rdata.h @@ -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 isc::dns::Exception { +class InvalidRdataLength : public DNSTextError { public: InvalidRdataLength(const char* file, size_t line, const char* what) : - isc::dns::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 isc::dns::Exception { +class InvalidRdataText : public DNSTextError { public: InvalidRdataText(const char* file, size_t line, const char* what) : - isc::dns::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 isc::dns::Exception { +class CharStringTooLong : public DNSTextError { public: CharStringTooLong(const char* file, size_t line, const char* what) : - isc::dns::Exception(file, line, what) {} + DNSTextError(file, line, what) {} }; // Forward declaration to define RdataPtr. diff --git a/src/lib/dns/rrclass-placeholder.h b/src/lib/dns/rrclass-placeholder.h index 56d94741b5..709057e818 100644 --- a/src/lib/dns/rrclass-placeholder.h +++ b/src/lib/dns/rrclass-placeholder.h @@ -39,10 +39,10 @@ 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 isc::dns::Exception { +class InvalidRRClass : public DNSTextError { public: InvalidRRClass(const char* file, size_t line, const char* what) : - isc::dns::Exception(file, line, what) {} + DNSTextError(file, line, what) {} }; /// diff --git a/src/lib/dns/rrttl.h b/src/lib/dns/rrttl.h index 7804234115..ffa3467970 100644 --- a/src/lib/dns/rrttl.h +++ b/src/lib/dns/rrttl.h @@ -36,10 +36,10 @@ 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 isc::dns::Exception { +class InvalidRRTTL : public DNSTextError { public: InvalidRRTTL(const char* file, size_t line, const char* what) : - isc::dns::Exception(file, line, what) {} + DNSTextError(file, line, what) {} }; /// diff --git a/src/lib/dns/rrtype-placeholder.h b/src/lib/dns/rrtype-placeholder.h index 08ab287f33..46167e45dc 100644 --- a/src/lib/dns/rrtype-placeholder.h +++ b/src/lib/dns/rrtype-placeholder.h @@ -42,10 +42,10 @@ 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 isc::dns::Exception { +class InvalidRRType : public DNSTextError { public: InvalidRRType(const char* file, size_t line, const char* what) : - isc::dns::Exception(file, line, what) {} + DNSTextError(file, line, what) {} }; /// -- cgit v1.2.3 From 4760ac62312e9b5bf24ba73d67b859e6cb3fd61d Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Mon, 3 Feb 2014 03:47:52 +0530 Subject: [2430] Support basic $GENERATE in dns::MasterLoader It doesn't support format specifiers given in {} yet. This will be added in follow-up work on this branch. Relative names are not permitted in the RHS of $GENERATE statements. This is because the string version of createRdata() is used to construct RDATA, which does not take an origin. --- src/lib/dns/master_loader.cc | 137 +++++++++++- src/lib/dns/tests/master_loader_unittest.cc | 332 ++++++++++++++++++++++++++++ 2 files changed, 466 insertions(+), 3 deletions(-) (limited to 'src/lib/dns') diff --git a/src/lib/dns/master_loader.cc b/src/lib/dns/master_loader.cc index 6b6e091489..f8035df334 100644 --- a/src/lib/dns/master_loader.cc +++ b/src/lib/dns/master_loader.cc @@ -21,14 +21,16 @@ #include #include -#include +#include #include // for iequals +#include +#include #include #include #include -#include // for iequals -#include + +#include // for sscanf() using std::string; using std::auto_ptr; @@ -148,6 +150,8 @@ private: } MasterToken handleInitialToken(); + std::string generateForIter(const std::string& str, const int it); + void doGenerate(); void doOrigin(bool is_optional) { // Parse and create the new origin. It is relative to the previous @@ -348,6 +352,9 @@ private: } 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); @@ -437,6 +444,130 @@ public: size_t rr_count_; // number of RRs successfully loaded }; +std::string +MasterLoader::MasterLoaderImpl::generateForIter(const std::string& str, + const int i) +{ + std::string rstr; + + for (std::string::const_iterator it = str.begin(); it != str.end();) { + switch (*it) { + case '$': + ++it; + if ((it != str.end()) && (*it == '$')) { + rstr.push_back('$'); + ++it; + continue; + } + + // TODO: This doesn't handle format specifiers in {} yet. + rstr += boost::str(boost::format("%d") % i); + break; + + case '\\': + rstr.push_back(*it); + ++it; + if (it == str.end()) { + continue; + } + rstr.push_back(*it); + ++it; + break; + + default: + rstr.push_back(*it); + ++it; + break; + } + } + + return (rstr); +} + +void +MasterLoader::MasterLoaderImpl::doGenerate() { + 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(); + + 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(); + + 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); + + 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(); + + unsigned int start; + unsigned int stop; + unsigned int step; + + 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; + } + + for (int i = start; i <= stop; i += step) { + const std::string generated_name = generateForIter(lhs, i); + const std::string generated_rdata = generateForIter(rhs, i); + const size_t name_length = generated_name.size(); + last_name_.reset(new Name(generated_name.c_str(), name_length, + &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"); + } + } + } +} + // 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. diff --git a/src/lib/dns/tests/master_loader_unittest.cc b/src/lib/dns/tests/master_loader_unittest.cc index ce9b8f7844..eedb130080 100644 --- a/src/lib/dns/tests/master_loader_unittest.cc +++ b/src/lib/dns/tests/master_loader_unittest.cc @@ -307,6 +307,338 @@ 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()); + + 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, 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, 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 -- cgit v1.2.3 From 734c918dd9a93c4d69e060bd6d81fa53967b0067 Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Mon, 3 Feb 2014 13:08:51 +0530 Subject: [2430] Support $GENERATE format modifiers Supports everything except nibble mode. Nibble mode will come soon. --- src/lib/dns/master_loader.cc | 61 +++++++++++++++++++- src/lib/dns/tests/master_loader_unittest.cc | 87 +++++++++++++++++++++++++++++ 2 files changed, 145 insertions(+), 3 deletions(-) (limited to 'src/lib/dns') diff --git a/src/lib/dns/master_loader.cc b/src/lib/dns/master_loader.cc index f8035df334..bfb5ec042b 100644 --- a/src/lib/dns/master_loader.cc +++ b/src/lib/dns/master_loader.cc @@ -452,7 +452,7 @@ MasterLoader::MasterLoaderImpl::generateForIter(const std::string& str, for (std::string::const_iterator it = str.begin(); it != str.end();) { switch (*it) { - case '$': + case '$': { ++it; if ((it != str.end()) && (*it == '$')) { rstr.push_back('$'); @@ -460,9 +460,56 @@ MasterLoader::MasterLoaderImpl::generateForIter(const std::string& str, continue; } - // TODO: This doesn't handle format specifiers in {} yet. - rstr += boost::str(boost::format("%d") % i); + bool nibble_mode = false; + bool nibble_uppercase = false; + std::string fmt("%d"); + int delta = 0; + + if (*it == '{') { + const char* scan_str = + str.c_str() + std::distance(str.begin(), it); + unsigned int width; + char mode[2] = {'d', 0}; // char plus null byte + const int n = sscanf(scan_str, "{%d,%u,%1[doxXnN]}", + &delta, &width, mode); + switch (n) { + case 1: + break; + + case 2: + fmt = boost::str(boost::format("%%0%ud") % width); + break; + + case 3: + if ((mode[0] == 'n') || (mode[0] == 'N')) { + nibble_mode = true; + nibble_uppercase = (mode[0] == 'N'); + } + fmt = boost::str(boost::format("%%0%u%c") % width % mode[0]); + break; + + default: + reportError(lexer_.getSourceName(), lexer_.getSourceLine(), + "Invalid $GENERATE format modifiers"); + return (""); + } + + /* Skip past closing brace. */ + while ((it != str.end()) && (*it != '}')) { + ++it; + } + if (it != str.end()) { + ++it; + } + } + + // TODO: Handle nibble mode + assert(!nibble_mode); + nibble_uppercase = nibble_uppercase; + + rstr += boost::str(boost::format(fmt) % (i + delta)); break; + } case '\\': rstr.push_back(*it); @@ -539,6 +586,14 @@ MasterLoader::MasterLoaderImpl::doGenerate() { for (int i = start; i <= stop; i += step) { 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; + } + const size_t name_length = generated_name.size(); last_name_.reset(new Name(generated_name.c_str(), name_length, &active_origin_)); diff --git a/src/lib/dns/tests/master_loader_unittest.cc b/src/lib/dns/tests/master_loader_unittest.cc index eedb130080..1bbfde7437 100644 --- a/src/lib/dns/tests/master_loader_unittest.cc +++ b/src/lib/dns/tests/master_loader_unittest.cc @@ -502,6 +502,93 @@ TEST_F(MasterLoaderTest, generateWithStep) { checkRR("host31.example.org", RRType::A(), "192.0.2.31"); } +TEST_F(MasterLoaderTest, generateWithModifiers) { + const string input = + "$ORIGIN example.org.\n" + "$TTL 3600\n" + "$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" + "$GENERATE 30-31 host${0,4,x} A 192.0.2.$\n" + // Names are case-insensitive, so we use TXT's RDATA to check + // case. + "$GENERATE 42-43 host$ TXT \"Value ${0,4,X}\"\n" + "$GENERATE 45-46 host${0,4,o} A 192.0.2.$\n" + // Junk type will not parse and 'd' is assumed. + "$GENERATE 100-101 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("host001e.example.org", RRType::A(), "192.0.2.30"); + checkRR("host001f.example.org", RRType::A(), "192.0.2.31"); + + 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("host0100.example.org", RRType::A(), "192.0.2.100"); + checkRR("host0101.example.org", RRType::A(), "192.0.2.101"); +} + +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" -- cgit v1.2.3 From c3c9615f0ed155fc8c710897c985d17779c1c8e3 Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Mon, 3 Feb 2014 13:34:46 +0530 Subject: [2430] Rearrange code to be easier to follow --- src/lib/dns/master_loader.cc | 36 +++++++++++++++++------------------- 1 file changed, 17 insertions(+), 19 deletions(-) (limited to 'src/lib/dns') diff --git a/src/lib/dns/master_loader.cc b/src/lib/dns/master_loader.cc index bfb5ec042b..91fa41b03d 100644 --- a/src/lib/dns/master_loader.cc +++ b/src/lib/dns/master_loader.cc @@ -452,7 +452,7 @@ MasterLoader::MasterLoaderImpl::generateForIter(const std::string& str, for (std::string::const_iterator it = str.begin(); it != str.end();) { switch (*it) { - case '$': { + case '$': ++it; if ((it != str.end()) && (*it == '$')) { rstr.push_back('$'); @@ -460,32 +460,37 @@ MasterLoader::MasterLoaderImpl::generateForIter(const std::string& str, continue; } - bool nibble_mode = false; - bool nibble_uppercase = false; - std::string fmt("%d"); - int delta = 0; - - if (*it == '{') { + if (*it != '{') { + rstr += boost::str(boost::format("%d") % i); + } else { const char* scan_str = str.c_str() + std::distance(str.begin(), it); + int delta = 0; unsigned int width; char mode[2] = {'d', 0}; // char plus null byte const int n = sscanf(scan_str, "{%d,%u,%1[doxXnN]}", &delta, &width, mode); switch (n) { case 1: + rstr += boost::str(boost::format("%d") % (i + delta)); break; - case 2: - fmt = boost::str(boost::format("%%0%ud") % width); + case 2: { + const std::string fmt = + boost::str(boost::format("%%0%ud") % width); + rstr += boost::str(boost::format(fmt) % (i + delta)); break; + } case 3: if ((mode[0] == 'n') || (mode[0] == 'N')) { - nibble_mode = true; - nibble_uppercase = (mode[0] == 'N'); + // TODO: Handle nibble mode + assert(true); + } else { + const std::string fmt = + boost::str(boost::format("%%0%u%c") % width % mode[0]); + rstr += boost::str(boost::format(fmt) % (i + delta)); } - fmt = boost::str(boost::format("%%0%u%c") % width % mode[0]); break; default: @@ -502,14 +507,7 @@ MasterLoader::MasterLoaderImpl::generateForIter(const std::string& str, ++it; } } - - // TODO: Handle nibble mode - assert(!nibble_mode); - nibble_uppercase = nibble_uppercase; - - rstr += boost::str(boost::format(fmt) % (i + delta)); break; - } case '\\': rstr.push_back(*it); -- cgit v1.2.3 From 79c9b75382ddd24872d3eb4b23a354c24cb04087 Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Mon, 3 Feb 2014 13:40:13 +0530 Subject: [2430] Support nibble mode with $GENERATE --- src/lib/dns/master_loader.cc | 44 +++++++++++++++++++++++++---- src/lib/dns/tests/master_loader_unittest.cc | 19 +++++++++++++ 2 files changed, 58 insertions(+), 5 deletions(-) (limited to 'src/lib/dns') diff --git a/src/lib/dns/master_loader.cc b/src/lib/dns/master_loader.cc index 91fa41b03d..9a8d68858d 100644 --- a/src/lib/dns/master_loader.cc +++ b/src/lib/dns/master_loader.cc @@ -444,6 +444,39 @@ public: size_t rr_count_; // number of RRs successfully loaded }; +namespace { // begin unnamed namespace + +std::string +genNibbles(int i, unsigned int width, bool uppercase) { + static const char *hex = "0123456789abcdef0123456789ABCDEF"; + std::string rstr; + + do { + char ch = hex[(i & 0x0f) + (uppercase ? 16 : 0)]; + i >>= 4; + rstr.push_back(ch); + + if (width > 0) { + --width; + } + + // If width is non zero then we need to add a label seperator. + // If value is non zero then we need to add another label and + // that requires a label seperator. + if (width > 0 || i != 0) { + rstr.push_back('.'); + + if (width > 0) { + --width; + } + } + } while ((i != 0) || (width > 0)); + + return (rstr); +} + +} // end unnamed namespace + std::string MasterLoader::MasterLoaderImpl::generateForIter(const std::string& str, const int i) @@ -484,8 +517,7 @@ MasterLoader::MasterLoaderImpl::generateForIter(const std::string& str, case 3: if ((mode[0] == 'n') || (mode[0] == 'N')) { - // TODO: Handle nibble mode - assert(true); + rstr += genNibbles(i + delta, width, (mode[0] == 'N')); } else { const std::string fmt = boost::str(boost::format("%%0%u%c") % width % mode[0]); @@ -592,9 +624,11 @@ MasterLoader::MasterLoaderImpl::doGenerate() { return; } - const size_t name_length = generated_name.size(); - last_name_.reset(new Name(generated_name.c_str(), name_length, - &active_origin_)); + // generateForIter() can return a string with a trailing '.' in + // case of a nibble representation. So we cannot use the + // relative Name constructor. + last_name_.reset + (new Name(Name(generated_name).concatenate(active_origin_))); previous_name_ = true; const rdata::RdataPtr rdata = diff --git a/src/lib/dns/tests/master_loader_unittest.cc b/src/lib/dns/tests/master_loader_unittest.cc index 1bbfde7437..037564b64e 100644 --- a/src/lib/dns/tests/master_loader_unittest.cc +++ b/src/lib/dns/tests/master_loader_unittest.cc @@ -514,6 +514,15 @@ TEST_F(MasterLoaderTest, generateWithModifiers) { // case. "$GENERATE 42-43 host$ TXT \"Value ${0,4,X}\"\n" "$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" + // Uppercase nibble + "$GENERATE 98-98 ${0,10,n} A 192.0.2.$\n" // Junk type will not parse and 'd' is assumed. "$GENERATE 100-101 host${0,4,j} A 192.0.2.$\n"; stringstream ss(input); @@ -545,6 +554,16 @@ TEST_F(MasterLoaderTest, generateWithModifiers) { 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("2.6.0.0.0.example.org", RRType::A(), "192.0.2.98"); + checkRR("host0100.example.org", RRType::A(), "192.0.2.100"); checkRR("host0101.example.org", RRType::A(), "192.0.2.101"); } -- cgit v1.2.3 From ada4354704ee0e4c0b088d57b4a04c219d7e8031 Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Mon, 3 Feb 2014 20:46:28 +0530 Subject: [2430] Fix uppercase nibble test (Was broken due to a bad copy and paste.) --- src/lib/dns/tests/master_loader_unittest.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/lib/dns') diff --git a/src/lib/dns/tests/master_loader_unittest.cc b/src/lib/dns/tests/master_loader_unittest.cc index 037564b64e..50fb94a697 100644 --- a/src/lib/dns/tests/master_loader_unittest.cc +++ b/src/lib/dns/tests/master_loader_unittest.cc @@ -522,7 +522,7 @@ TEST_F(MasterLoaderTest, generateWithModifiers) { // number of labels as width=8 above. "$GENERATE 94-96 ${0,7,n} A 192.0.2.$\n" // Uppercase nibble - "$GENERATE 98-98 ${0,10,n} A 192.0.2.$\n" + "$GENERATE 98-98 ${0,10,N} A 192.0.2.$\n" // Junk type will not parse and 'd' is assumed. "$GENERATE 100-101 host${0,4,j} A 192.0.2.$\n"; stringstream ss(input); @@ -558,8 +558,8 @@ TEST_F(MasterLoaderTest, generateWithModifiers) { 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("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("2.6.0.0.0.example.org", RRType::A(), "192.0.2.98"); -- cgit v1.2.3 From de4c5e0913d80405f1795293ba28d63a5154eb60 Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Tue, 4 Feb 2014 10:14:31 +0530 Subject: [2518] Add Python bindings for NameParserException hierarchy --- src/lib/dns/python/name_python.cc | 1 + src/lib/dns/python/name_python.h | 1 + src/lib/dns/python/pydnspp.cc | 24 +++++++++++++++++------- src/lib/dns/python/tests/name_python_test.py | 8 ++++++++ 4 files changed, 27 insertions(+), 7 deletions(-) (limited to 'src/lib/dns') diff --git a/src/lib/dns/python/name_python.cc b/src/lib/dns/python/name_python.cc index 2799db9fde..e1ff5fe926 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; diff --git a/src/lib/dns/python/name_python.h b/src/lib/dns/python/name_python.h index d18c0d9385..27961387c3 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; diff --git a/src/lib/dns/python/pydnspp.cc b/src/lib/dns/python/pydnspp.cc index 30dc09089c..f061783cb2 100644 --- a/src/lib/dns/python/pydnspp.cc +++ b/src/lib/dns/python/pydnspp.cc @@ -243,23 +243,33 @@ 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", NULL, 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 = diff --git a/src/lib/dns/python/tests/name_python_test.py b/src/lib/dns/python/tests/name_python_test.py index 8ea2e3520a..051abb9b6b 100644 --- a/src/lib/dns/python/tests/name_python_test.py +++ b/src/lib/dns/python/tests/name_python_test.py @@ -97,6 +97,14 @@ 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)) + def test_at(self): self.assertEqual(7, self.name1.at(0)) self.assertEqual(101, self.name1.at(1)) -- cgit v1.2.3 From 4ca62ac7345e52e17466789bf65f8c27811e0fd6 Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Tue, 4 Feb 2014 10:26:52 +0530 Subject: [2518] Organize isc::Exception-s in a hierarchy --- src/lib/dns/python/pydnspp.cc | 15 +++++++------ src/lib/dns/python/tests/Makefile.am | 1 + src/lib/dns/python/tests/pydnspp_python_test.py | 30 +++++++++++++++++++++++++ 3 files changed, 39 insertions(+), 7 deletions(-) create mode 100644 src/lib/dns/python/tests/pydnspp_python_test.py (limited to 'src/lib/dns') diff --git a/src/lib/dns/python/pydnspp.cc b/src/lib/dns/python/pydnspp.cc index f061783cb2..29d770d024 100644 --- a/src/lib/dns/python/pydnspp.cc +++ b/src/lib/dns/python/pydnspp.cc @@ -244,7 +244,8 @@ initModulePart_Name(PyObject* mod) { // Add the exceptions to the module try { po_NameParserException = - PyErr_NewException("pydnspp.NameParserException", NULL, NULL); + PyErr_NewException("pydnspp.NameParserException", + po_IscException, NULL); PyObjectContainer(po_NameParserException) .installToModule(mod, "NameParserException"); @@ -875,14 +876,14 @@ 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"); } catch (const std::exception& ex) { const std::string ex_what = "Unexpected failure in pydnspp initialization: " + 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/pydnspp_python_test.py b/src/lib/dns/python/tests/pydnspp_python_test.py new file mode 100644 index 0000000000..af9db52efc --- /dev/null +++ b/src/lib/dns/python/tests/pydnspp_python_test.py @@ -0,0 +1,30 @@ +# 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)) + +if __name__ == '__main__': + unittest.main() -- cgit v1.2.3 From 293665afec0c7ee83316eec966574da9f1559d1b Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Tue, 4 Feb 2014 10:27:07 +0530 Subject: [2518] Fix description --- src/lib/dns/python/tests/name_python_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/lib/dns') diff --git a/src/lib/dns/python/tests/name_python_test.py b/src/lib/dns/python/tests/name_python_test.py index 051abb9b6b..86b1edc074 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 -- cgit v1.2.3 From ad3f1d33b943410cc4b782be9f07a4083883ea71 Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Tue, 4 Feb 2014 10:40:12 +0530 Subject: [2518] Update common DNS exceptions into a hierarchy --- src/lib/dns/python/name_python.cc | 1 - src/lib/dns/python/name_python.h | 1 - src/lib/dns/python/pydnspp.cc | 39 ++++++++++++++++++------- src/lib/dns/python/pydnspp_common.cc | 6 +++- src/lib/dns/python/pydnspp_common.h | 4 +++ src/lib/dns/python/rdata_python.cc | 1 + src/lib/dns/python/tests/name_python_test.py | 2 ++ src/lib/dns/python/tests/pydnspp_python_test.py | 4 +++ 8 files changed, 44 insertions(+), 14 deletions(-) (limited to 'src/lib/dns') diff --git a/src/lib/dns/python/name_python.cc b/src/lib/dns/python/name_python.cc index e1ff5fe926..ecdae841c3 100644 --- a/src/lib/dns/python/name_python.cc +++ b/src/lib/dns/python/name_python.cc @@ -545,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 27961387c3..2cce9994cc 100644 --- a/src/lib/dns/python/name_python.h +++ b/src/lib/dns/python/name_python.h @@ -31,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 29d770d024..b0bda22c4b 100644 --- a/src/lib/dns/python/pydnspp.cc +++ b/src/lib/dns/python/pydnspp.cc @@ -28,6 +28,7 @@ #include #include +#include #include #include #include @@ -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 = @@ -245,7 +252,7 @@ initModulePart_Name(PyObject* mod) { try { po_NameParserException = PyErr_NewException("pydnspp.NameParserException", - po_IscException, NULL); + po_DNSTextError, NULL); PyObjectContainer(po_NameParserException) .installToModule(mod, "NameParserException"); @@ -277,13 +284,6 @@ initModulePart_Name(PyObject* mod) { 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: " + @@ -878,12 +878,29 @@ PyInit_pydnspp(void) { po_InvalidOperation = PyErr_NewException("pydnspp.InvalidOperation", po_IscException, NULL); PyObjectContainer(po_InvalidOperation) - .installToModule(mod, "InvalidOperation"); + .installToModule(mod, "InvalidOperation"); po_InvalidParameter = PyErr_NewException("pydnspp.InvalidParameter", po_IscException, NULL); PyObjectContainer(po_InvalidParameter) - .installToModule(mod, "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 8e498b3f93..b33125e09c 100644 --- a/src/lib/dns/python/pydnspp_common.h +++ b/src/lib/dns/python/pydnspp_common.h @@ -32,6 +32,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..df45e9ef9d 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; diff --git a/src/lib/dns/python/tests/name_python_test.py b/src/lib/dns/python/tests/name_python_test.py index 86b1edc074..8160716896 100644 --- a/src/lib/dns/python/tests/name_python_test.py +++ b/src/lib/dns/python/tests/name_python_test.py @@ -105,6 +105,8 @@ class NameTest(unittest.TestCase): 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 index af9db52efc..574fc00e00 100644 --- a/src/lib/dns/python/tests/pydnspp_python_test.py +++ b/src/lib/dns/python/tests/pydnspp_python_test.py @@ -26,5 +26,9 @@ class CommonTest(unittest.TestCase): 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() -- cgit v1.2.3 From 5e1c35d6a779706ba16f3076a0f6fa21dbeea81d Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Tue, 4 Feb 2014 11:03:59 +0530 Subject: [2518] Add C++ unittests for DNS exception hierarchy --- src/lib/dns/tests/Makefile.am | 1 + src/lib/dns/tests/dns_exceptions_unittest.cc | 69 ++++++++++++++++++++++++++++ src/lib/dns/tests/name_unittest.cc | 58 +++++++++++++++++++++++ 3 files changed, 128 insertions(+) create mode 100644 src/lib/dns/tests/dns_exceptions_unittest.cc (limited to 'src/lib/dns') diff --git a/src/lib/dns/tests/Makefile.am b/src/lib/dns/tests/Makefile.am index 5029681a32..f982f886f6 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 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 + +#include + +namespace { // begin unnamed namespace + +TEST(DNSExceptionsTest, checkExceptionsHierarchy) { + EXPECT_NO_THROW({ + const isc::dns::Exception exception("", 0, ""); + const isc::Exception& exception_cast = + dynamic_cast(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(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(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(exception); + const isc::dns::Exception& exception_cast2 = + dynamic_cast(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(exception); + const isc::dns::Exception& exception_cast2 = + dynamic_cast(exception); + // to avoid compiler warning + exception_cast.what(); + exception_cast2.what(); + }); +} + +} // end unnamed namespace diff --git a/src/lib/dns/tests/name_unittest.cc b/src/lib/dns/tests/name_unittest.cc index 10d1e550cc..435ae978f7 100644 --- a/src/lib/dns/tests/name_unittest.cc +++ b/src/lib/dns/tests/name_unittest.cc @@ -164,6 +164,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(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(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(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(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(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(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(exception); + // to avoid compiler warning + exception_cast.what(); + }); +} + TEST_F(NameTest, fromText) { vector strnames; strnames.push_back("www.example.com"); -- cgit v1.2.3 From 06cd899614951d962cf1454d2deeff5b31ad38c7 Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Tue, 4 Feb 2014 18:52:59 +0530 Subject: [2430] Rollback case change These were not the correct tests to be modified. The correct tests to be modified do not use any hex alphabets currently, and the alphabets are also generated in the LHS names which are case-insensitive during comparison. This will be properly fixed in the next commits on the branch. --- src/lib/dns/tests/master_loader_unittest.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/lib/dns') diff --git a/src/lib/dns/tests/master_loader_unittest.cc b/src/lib/dns/tests/master_loader_unittest.cc index 50fb94a697..5ded29352d 100644 --- a/src/lib/dns/tests/master_loader_unittest.cc +++ b/src/lib/dns/tests/master_loader_unittest.cc @@ -558,8 +558,8 @@ TEST_F(MasterLoaderTest, generateWithModifiers) { 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("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("2.6.0.0.0.example.org", RRType::A(), "192.0.2.98"); -- cgit v1.2.3 From 2fb705ea4e81f57170a9335a1d524946f6eef829 Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Tue, 4 Feb 2014 19:07:43 +0530 Subject: [2430] Do case-specific tests using TXT RR type (The implementation being tested did not need any changes.) --- src/lib/dns/tests/master_loader_unittest.cc | 36 +++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 10 deletions(-) (limited to 'src/lib/dns') diff --git a/src/lib/dns/tests/master_loader_unittest.cc b/src/lib/dns/tests/master_loader_unittest.cc index 5ded29352d..09ee3d0b41 100644 --- a/src/lib/dns/tests/master_loader_unittest.cc +++ b/src/lib/dns/tests/master_loader_unittest.cc @@ -506,25 +506,38 @@ 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" - "$GENERATE 30-31 host${0,4,x} A 192.0.2.$\n" + // Names are case-insensitive, so we use TXT's RDATA to check - // case. + // 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" - // Uppercase nibble - "$GENERATE 98-98 ${0,10,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. - "$GENERATE 100-101 host${0,4,j} A 192.0.2.$\n"; + "$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); @@ -545,8 +558,8 @@ TEST_F(MasterLoaderTest, generateWithModifiers) { checkRR("host0014.example.org", RRType::A(), "192.0.2.14"); checkRR("host0015.example.org", RRType::A(), "192.0.2.15"); - checkRR("host001e.example.org", RRType::A(), "192.0.2.30"); - checkRR("host001f.example.org", RRType::A(), "192.0.2.31"); + 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"); @@ -562,10 +575,13 @@ TEST_F(MasterLoaderTest, generateWithModifiers) { 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("2.6.0.0.0.example.org", RRType::A(), "192.0.2.98"); + 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("host0100.example.org", RRType::A(), "192.0.2.100"); - checkRR("host0101.example.org", RRType::A(), "192.0.2.101"); + checkRR("host0200.example.org", RRType::A(), "192.0.2.200"); + checkRR("host0201.example.org", RRType::A(), "192.0.2.201"); } TEST_F(MasterLoaderTest, generateWithNoModifiers) { -- cgit v1.2.3 From f6d053c16792e0a511af21ca758b14fcf26ae032 Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Tue, 4 Feb 2014 19:25:05 +0530 Subject: [2430] Print debugging aid when check fails --- src/lib/dns/tests/master_loader_unittest.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/lib/dns') diff --git a/src/lib/dns/tests/master_loader_unittest.cc b/src/lib/dns/tests/master_loader_unittest.cc index 09ee3d0b41..b12034f15b 100644 --- a/src/lib/dns/tests/master_loader_unittest.cc +++ b/src/lib/dns/tests/master_loader_unittest.cc @@ -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() { -- cgit v1.2.3 From 9fcbaef68193a99a142f63b576fdfdd5519192c0 Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Wed, 5 Feb 2014 01:37:12 +0530 Subject: [2536] Remove "using namespace" from headers (DNS code) --- src/lib/cache/message_cache.h | 5 +- src/lib/cache/message_entry.cc | 1 + src/lib/cache/message_entry.h | 8 +- src/lib/cache/rrset_cache.h | 2 - src/lib/cache/rrset_entry.cc | 1 + src/lib/cache/rrset_entry.h | 8 +- src/lib/cache/tests/cache_test_messagefromfile.h | 8 +- src/lib/cache/tests/cache_test_sectioncount.h | 8 +- src/lib/cache/tests/message_cache_unittest.cc | 1 + .../dns/tests/rdata_nsec3param_like_unittest.cc | 1 + src/lib/dns/tests/rdata_nsecbitmap_unittest.cc | 1 + src/lib/dns/tests/rdata_unittest.h | 4 +- src/lib/nsas/tests/hash_unittest.cc | 1 + .../tests/nameserver_address_store_unittest.cc | 2 + src/lib/nsas/tests/nameserver_address_unittest.cc | 7 +- src/lib/nsas/tests/nameserver_entry_unittest.cc | 2 +- src/lib/nsas/tests/nsas_entry_compare_unittest.cc | 1 + src/lib/nsas/tests/nsas_test.h | 124 +++++++++++++-------- src/lib/nsas/tests/zone_entry_unittest.cc | 4 +- src/lib/resolve/recursive_query.cc | 1 + 20 files changed, 106 insertions(+), 84 deletions(-) (limited to 'src/lib/dns') diff --git a/src/lib/cache/message_cache.h b/src/lib/cache/message_cache.h index 0c19139088..0df23ede37 100644 --- a/src/lib/cache/message_cache.h +++ b/src/lib/cache/message_cache.h @@ -73,8 +73,8 @@ protected: /// \param name query name of the message. /// \param type query type of the message. /// \return return the hash key. - HashKey getEntryHashKey(const isc::dns::Name& name, - const isc::dns::RRType& type) const; + isc::nsas::HashKey getEntryHashKey(const isc::dns::Name& name, + const isc::dns::RRType& type) const; // Make these variants be protected for easy unittest. protected: @@ -91,4 +91,3 @@ typedef boost::shared_ptr MessageCachePtr; } // namespace isc #endif // MESSAGE_CACHE_H - diff --git a/src/lib/cache/message_entry.cc b/src/lib/cache/message_entry.cc index b6af869d28..36e76915db 100644 --- a/src/lib/cache/message_entry.cc +++ b/src/lib/cache/message_entry.cc @@ -23,6 +23,7 @@ #include "logger.h" using namespace isc::dns; +using namespace isc::nsas; using namespace std; // Put file scope functions in unnamed namespace. diff --git a/src/lib/cache/message_entry.h b/src/lib/cache/message_entry.h index 206e601c1b..5b55fbbf3c 100644 --- a/src/lib/cache/message_entry.h +++ b/src/lib/cache/message_entry.h @@ -22,8 +22,6 @@ #include "rrset_cache.h" #include "rrset_entry.h" -using namespace isc::nsas; - namespace isc { namespace cache { @@ -33,7 +31,7 @@ class RRsetEntry; /// /// The object of MessageEntry represents one response message /// answered to the resolver client. -class MessageEntry : public NsasEntry { +class MessageEntry : public isc::nsas::NsasEntry { // Noncopyable private: MessageEntry(const MessageEntry& source); @@ -92,7 +90,7 @@ public: /// \brief Get the hash key of the message entry. /// /// \return return hash key - virtual HashKey hashKey() const { + virtual isc::nsas::HashKey hashKey() const { return (*hash_key_ptr_); } @@ -173,7 +171,7 @@ protected: private: std::string entry_name_; // The name for this entry(name + type) - HashKey* hash_key_ptr_; // the key for messag entry in hash table. + isc::nsas::HashKey* hash_key_ptr_; // the key for messag entry in hash table. std::vector rrsets_; RRsetCachePtr rrset_cache_; //Normal rrset cache diff --git a/src/lib/cache/rrset_cache.h b/src/lib/cache/rrset_cache.h index 304c6e8907..8587ec7ab5 100644 --- a/src/lib/cache/rrset_cache.h +++ b/src/lib/cache/rrset_cache.h @@ -20,8 +20,6 @@ #include -using namespace isc::nsas; - namespace isc { namespace cache { diff --git a/src/lib/cache/rrset_entry.cc b/src/lib/cache/rrset_entry.cc index 359fd686ec..2e5bf93049 100644 --- a/src/lib/cache/rrset_entry.cc +++ b/src/lib/cache/rrset_entry.cc @@ -21,6 +21,7 @@ #include "rrset_copy.h" using namespace isc::dns; +using namespace isc::nsas; namespace isc { namespace cache { diff --git a/src/lib/cache/rrset_entry.h b/src/lib/cache/rrset_entry.h index 0efda3660f..71b5e4b1fe 100644 --- a/src/lib/cache/rrset_entry.h +++ b/src/lib/cache/rrset_entry.h @@ -22,8 +22,6 @@ #include #include "cache_entry_key.h" -using namespace isc::nsas; - namespace isc { namespace cache { @@ -60,7 +58,7 @@ enum RRsetTrustLevel { /// The object of RRsetEntry represents one cached RRset. /// Each RRset entry may be refered using shared_ptr by several message /// entries. -class RRsetEntry : public NsasEntry +class RRsetEntry : public isc::nsas::NsasEntry { /// /// \name Constructors and Destructor @@ -105,7 +103,7 @@ public: /// \brief Get the hash key /// /// \return return hash key - HashKey hashKey() const { + isc::nsas::HashKey hashKey() const { return (hash_key_); } @@ -124,7 +122,7 @@ private: time_t expire_time_; // Expiration time of rrset. RRsetTrustLevel trust_level_; // RRset trustworthiness. boost::shared_ptr rrset_; - HashKey hash_key_; // RRsetEntry hash key + isc::nsas::HashKey hash_key_; // RRsetEntry hash key }; typedef boost::shared_ptr RRsetEntryPtr; diff --git a/src/lib/cache/tests/cache_test_messagefromfile.h b/src/lib/cache/tests/cache_test_messagefromfile.h index 7d55f08c71..85bc0d9c8d 100644 --- a/src/lib/cache/tests/cache_test_messagefromfile.h +++ b/src/lib/cache/tests/cache_test_messagefromfile.h @@ -17,9 +17,6 @@ #include #include -using namespace isc; -using namespace isc::dns; - namespace { /// \brief Reads a Message from a data file @@ -27,13 +24,12 @@ namespace { /// \param message Message to put the read data in /// \param datafile The file to read from void -messageFromFile(Message& message, const char* datafile) { +messageFromFile(isc::dns::Message& message, const char* datafile) { std::vector data; - UnitTestUtil::readWireData(datafile, data); + isc::UnitTestUtil::readWireData(datafile, data); isc::util::InputBuffer buffer(&data[0], data.size()); message.fromWire(buffer); } } // namespace - diff --git a/src/lib/cache/tests/cache_test_sectioncount.h b/src/lib/cache/tests/cache_test_sectioncount.h index df7cb5258d..0dcdaee804 100644 --- a/src/lib/cache/tests/cache_test_sectioncount.h +++ b/src/lib/cache/tests/cache_test_sectioncount.h @@ -17,9 +17,6 @@ #include #include -using namespace isc; -using namespace isc::dns; - namespace { /// \brief Counts the number of rrsets in the given section @@ -29,9 +26,9 @@ namespace { /// /// \return The number of RRsets in the given section int -sectionRRsetCount(Message& msg, Message::Section section) { +sectionRRsetCount(isc::dns::Message& msg, isc::dns::Message::Section section) { int count = 0; - for (RRsetIterator rrset_iter = msg.beginSection(section); + for (isc::dns::RRsetIterator rrset_iter = msg.beginSection(section); rrset_iter != msg.endSection(section); ++rrset_iter) { ++count; @@ -41,4 +38,3 @@ sectionRRsetCount(Message& msg, Message::Section section) { } } // namespace - diff --git a/src/lib/cache/tests/message_cache_unittest.cc b/src/lib/cache/tests/message_cache_unittest.cc index 60ae0371a2..c26b3cb6a6 100644 --- a/src/lib/cache/tests/message_cache_unittest.cc +++ b/src/lib/cache/tests/message_cache_unittest.cc @@ -23,6 +23,7 @@ #include "cache_test_messagefromfile.h" using namespace isc::cache; +using namespace isc::nsas; using namespace isc; using namespace isc::dns; using namespace isc::util; diff --git a/src/lib/dns/tests/rdata_nsec3param_like_unittest.cc b/src/lib/dns/tests/rdata_nsec3param_like_unittest.cc index 23d6d0ed68..23461805af 100644 --- a/src/lib/dns/tests/rdata_nsec3param_like_unittest.cc +++ b/src/lib/dns/tests/rdata_nsec3param_like_unittest.cc @@ -30,6 +30,7 @@ using namespace std; using isc::UnitTestUtil; using namespace isc::dns; using namespace isc::dns::rdata; +using namespace isc::util; namespace { diff --git a/src/lib/dns/tests/rdata_nsecbitmap_unittest.cc b/src/lib/dns/tests/rdata_nsecbitmap_unittest.cc index fbb256a151..0af1a12f9a 100644 --- a/src/lib/dns/tests/rdata_nsecbitmap_unittest.cc +++ b/src/lib/dns/tests/rdata_nsecbitmap_unittest.cc @@ -34,6 +34,7 @@ using boost::lexical_cast; using isc::UnitTestUtil; using namespace isc::dns; using namespace isc::dns::rdata; +using namespace isc::util; namespace { 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 #include -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/nsas/tests/hash_unittest.cc b/src/lib/nsas/tests/hash_unittest.cc index f71d4b35e5..fe43bfabcd 100644 --- a/src/lib/nsas/tests/hash_unittest.cc +++ b/src/lib/nsas/tests/hash_unittest.cc @@ -26,6 +26,7 @@ #include "nsas_test.h" using namespace std; +using namespace isc::dns; namespace isc { namespace nsas { diff --git a/src/lib/nsas/tests/nameserver_address_store_unittest.cc b/src/lib/nsas/tests/nameserver_address_store_unittest.cc index a606f2614c..3bde33bffb 100644 --- a/src/lib/nsas/tests/nameserver_address_store_unittest.cc +++ b/src/lib/nsas/tests/nameserver_address_store_unittest.cc @@ -41,8 +41,10 @@ #include "nsas_test.h" using namespace isc::dns; +using namespace isc::dns::rdata; using namespace isc::util; using namespace std; +using isc::util::unittests::TestResolver; namespace isc { namespace nsas { diff --git a/src/lib/nsas/tests/nameserver_address_unittest.cc b/src/lib/nsas/tests/nameserver_address_unittest.cc index 1b211e9e3e..f8512bf3ff 100644 --- a/src/lib/nsas/tests/nameserver_address_unittest.cc +++ b/src/lib/nsas/tests/nameserver_address_unittest.cc @@ -26,12 +26,13 @@ #include "../nameserver_entry.h" #include "nsas_test.h" +using namespace isc::dns; +using namespace isc::dns::rdata; +using isc::util::unittests::TestResolver; + namespace isc { namespace nsas { -using namespace dns; -using namespace rdata; - #define TEST_ADDRESS_INDEX 1 /// \brief NameserverEntry sample class for testing diff --git a/src/lib/nsas/tests/nameserver_entry_unittest.cc b/src/lib/nsas/tests/nameserver_entry_unittest.cc index 10f0c20b80..dd7f3b970d 100644 --- a/src/lib/nsas/tests/nameserver_entry_unittest.cc +++ b/src/lib/nsas/tests/nameserver_entry_unittest.cc @@ -41,7 +41,7 @@ using namespace isc::nsas; using namespace isc::asiolink; using namespace std; using namespace isc::dns; -using namespace rdata; +using isc::util::unittests::TestResolver; namespace { diff --git a/src/lib/nsas/tests/nsas_entry_compare_unittest.cc b/src/lib/nsas/tests/nsas_entry_compare_unittest.cc index 33e41b80cc..9bc5b9c3a7 100644 --- a/src/lib/nsas/tests/nsas_entry_compare_unittest.cc +++ b/src/lib/nsas/tests/nsas_entry_compare_unittest.cc @@ -25,6 +25,7 @@ #include "../nsas_entry_compare.h" #include "nsas_test.h" +using namespace isc::dns; using namespace std; namespace isc { diff --git a/src/lib/nsas/tests/nsas_test.h b/src/lib/nsas/tests/nsas_test.h index 9f92149891..54e5d45d6f 100644 --- a/src/lib/nsas/tests/nsas_test.h +++ b/src/lib/nsas/tests/nsas_test.h @@ -38,11 +38,6 @@ #include #include "../nsas_entry.h" -using namespace isc::dns::rdata; -using namespace isc::dns; -using namespace isc::util; -using isc::util::unittests::TestResolver; - namespace isc { namespace dns { @@ -77,15 +72,15 @@ public: /// For this reason, a single class definition template -class RdataTest: public Rdata { +class RdataTest: public rdata::Rdata { public: /// \brief Constructor /// /// Set the data in the object. /// - /// \param v4address IPV4 address to store. (The format of this address is - /// not checked.) + /// \param v4address IPV4 address to store. (The format of this + /// address is not checked.) RdataTest(const std::string& data) : data_(data) {} @@ -99,8 +94,9 @@ public: /// \brief Return type of Rdata /// - /// Returns the type of the data. May be useful in the tests, although this - /// will not appear in the main code as this interface is not defined. + /// Returns the type of the data. May be useful in the tests, + /// although this will not appear in the main code as this interface + /// is not defined. virtual uint16_t getType() const { return (type_.getType()); } @@ -111,13 +107,13 @@ public: /// //@{ /// \brief Render the \c Rdata in the wire format to a buffer - virtual void toWire(OutputBuffer& buffer) const; + virtual void toWire(isc::util::OutputBuffer& buffer) const; /// \brief render the \Rdata in the wire format to a \c MessageRenderer virtual void toWire(AbstractMessageRenderer& renderer) const; /// \brief Comparison Method - virtual int compare(const Rdata& other) const; + virtual int compare(const rdata::Rdata& other) const; //@} private: @@ -126,7 +122,7 @@ private: }; template -void RdataTest::toWire(OutputBuffer&) const { +void RdataTest::toWire(isc::util::OutputBuffer&) const { } template @@ -134,7 +130,7 @@ void RdataTest::toWire(AbstractMessageRenderer&) const { } template -int RdataTest::compare(const Rdata&) const { +int RdataTest::compare(const rdata::Rdata&) const { return 0; } @@ -210,7 +206,8 @@ private: /// /// Some constants used in the various tests. -static const uint32_t HASHTABLE_DEFAULT_SIZE = 1009; ///< First prime above 1000 +static const uint32_t HASHTABLE_DEFAULT_SIZE = 1009; ///< First prime + ///above 1000 // String constants. These should end in a dot. static const std::string EXAMPLE_CO_UK("example.co.uk."); @@ -219,63 +216,92 @@ static const std::string MIXED_EXAMPLE_CO_UK("EXAmple.co.uk."); class TestWithRdata : public ::testing::Test { protected: - typedef boost::shared_ptr RRsetPtr; + typedef boost::shared_ptr RRsetPtr; /// \brief Constructor /// - /// Initializes the RRsets used in the tests. The RRsets themselves have to - /// be initialized with the basic data on their construction. The Rdata for - /// them is added in SetUp(). + /// Initializes the RRsets used in the tests. The RRsets themselves + /// have to be initialized with the basic data on their + /// construction. The Rdata for them is added in SetUp(). TestWithRdata() : - rrv4_(new RRset(Name(EXAMPLE_CO_UK), RRClass::IN(), RRType::A(), - RRTTL(1200))), - rrcase_(new RRset(Name(MIXED_EXAMPLE_CO_UK), RRClass::IN(), - RRType::A(), RRTTL(1200))), - rrch_(new RRset(Name(EXAMPLE_CO_UK), RRClass::CH(), RRType::A(), - RRTTL(1200))), - rrns_(new RRset(Name(EXAMPLE_CO_UK), RRClass::IN(), RRType::NS(), - RRTTL(1200))), - rr_single_(new RRset(Name(EXAMPLE_CO_UK), RRClass::IN(), - RRType::NS(), RRTTL(600))), - rr_empty_(new RRset(Name(EXAMPLE_CO_UK), RRClass::IN(), - RRType::NS(), RRTTL(600))), - rrv6_(new RRset(Name(EXAMPLE_CO_UK), RRClass::IN(), - RRType::AAAA(), RRTTL(900))), - rrnet_(new RRset(Name(EXAMPLE_NET), RRClass::IN(), RRType::A(), - RRTTL(600))), + rrv4_(new isc::dns::RRset(isc::dns::Name(EXAMPLE_CO_UK), + isc::dns::RRClass::IN(), + isc::dns::RRType::A(), + isc::dns::RRTTL(1200))), + rrcase_(new isc::dns::RRset(isc::dns::Name(MIXED_EXAMPLE_CO_UK), + isc::dns::RRClass::IN(), + isc::dns::RRType::A(), + isc::dns::RRTTL(1200))), + rrch_(new isc::dns::RRset(isc::dns::Name(EXAMPLE_CO_UK), + isc::dns::RRClass::CH(), + isc::dns::RRType::A(), + isc::dns::RRTTL(1200))), + rrns_(new isc::dns::RRset(isc::dns::Name(EXAMPLE_CO_UK), + isc::dns::RRClass::IN(), + isc::dns::RRType::NS(), + isc::dns::RRTTL(1200))), + rr_single_(new isc::dns::RRset(isc::dns::Name(EXAMPLE_CO_UK), + isc::dns::RRClass::IN(), + isc::dns::RRType::NS(), + isc::dns::RRTTL(600))), + rr_empty_(new isc::dns::RRset(isc::dns::Name(EXAMPLE_CO_UK), + isc::dns::RRClass::IN(), + isc::dns::RRType::NS(), + isc::dns::RRTTL(600))), + rrv6_(new isc::dns::RRset(isc::dns::Name(EXAMPLE_CO_UK), + isc::dns::RRClass::IN(), + isc::dns::RRType::AAAA(), + isc::dns::RRTTL(900))), + rrnet_(new isc::dns::RRset(isc::dns::Name(EXAMPLE_NET), + isc::dns::RRClass::IN(), + isc::dns::RRType::A(), + isc::dns::RRTTL(600))), ns_name_("ns.example.net.") {} /// \brief Add Rdata to RRsets /// - /// The data are added as const pointers to avoid the stricter type checking - /// applied by the Rdata code. There is no need for it in these tests. + /// The data are added as const pointers to avoid the stricter type + /// checking applied by the Rdata code. There is no need for it in + /// these tests. virtual void SetUp() { // A records - rrv4_->addRdata(ConstRdataPtr(new RdataTest("1.2.3.4"))); - rrv4_->addRdata(ConstRdataPtr(new RdataTest("5.6.7.8"))); - rrv4_->addRdata(ConstRdataPtr(new RdataTest("9.10.11.12"))); + rrv4_->addRdata(isc::dns::rdata::ConstRdataPtr + (new isc::dns::RdataTest("1.2.3.4"))); + rrv4_->addRdata(isc::dns::rdata::ConstRdataPtr + (new isc::dns::RdataTest("5.6.7.8"))); + rrv4_->addRdata(isc::dns::rdata::ConstRdataPtr + (new isc::dns::RdataTest("9.10.11.12"))); // A records - rrcase_->addRdata(ConstRdataPtr(new RdataTest("13.14.15.16"))); + rrcase_->addRdata(isc::dns::rdata::ConstRdataPtr + (new isc::dns::RdataTest + ("13.14.15.16"))); // No idea what Chaosnet address look like other than they are 16 bits // The fact that they are type A is probably also incorrect. - rrch_->addRdata(ConstRdataPtr(new RdataTest("1324"))); + rrch_->addRdata(isc::dns::rdata::ConstRdataPtr + (new isc::dns::RdataTest("1324"))); // NS records take a single name - rrns_->addRdata(rdata::generic::NS("example.fr.")); - rrns_->addRdata(rdata::generic::NS("example.de.")); + rrns_->addRdata(isc::dns::rdata::generic::NS("example.fr.")); + rrns_->addRdata(isc::dns::rdata::generic::NS("example.de.")); // Single NS record with 0 TTL - rr_single_->addRdata(rdata::generic::NS(ns_name_)); + rr_single_->addRdata(isc::dns::rdata::generic::NS(ns_name_)); // AAAA records - rrv6_->addRdata(ConstRdataPtr(new RdataTest("2001::1002"))); - rrv6_->addRdata(ConstRdataPtr(new RdataTest("dead:beef:feed::"))); + rrv6_->addRdata(isc::dns::rdata::ConstRdataPtr + (new isc::dns::RdataTest + ("2001::1002"))); + rrv6_->addRdata(isc::dns::rdata::ConstRdataPtr + (new isc::dns::RdataTest + ("dead:beef:feed::"))); // A record for example.net - rrnet_->addRdata(ConstRdataPtr(new RdataTest("17.18.18.20"))); + rrnet_->addRdata(isc::dns::rdata::ConstRdataPtr + (new isc::dns::RdataTest + ("17.18.18.20"))); } /// \brief Data for the tests @@ -287,7 +313,7 @@ protected: RRsetPtr rr_empty_; ///< NS RRset without any nameservers RRsetPtr rrv6_; ///< Standard RRset, IN, AAAA, lowercase name RRsetPtr rrnet_; ///< example.net A RRset - Name ns_name_; ///< Nameserver name of ns.example.net + isc::dns::Name ns_name_; ///< Nameserver name of ns.example.net }; } // namespace nsas diff --git a/src/lib/nsas/tests/zone_entry_unittest.cc b/src/lib/nsas/tests/zone_entry_unittest.cc index d685fbb390..04a6d4da8f 100644 --- a/src/lib/nsas/tests/zone_entry_unittest.cc +++ b/src/lib/nsas/tests/zone_entry_unittest.cc @@ -33,9 +33,11 @@ using namespace isc::nsas; using namespace isc::asiolink; -using namespace std; using namespace isc::dns; +using namespace isc::dns::rdata; using namespace isc::util; +using namespace std; +using isc::util::unittests::TestResolver; namespace { diff --git a/src/lib/resolve/recursive_query.cc b/src/lib/resolve/recursive_query.cc index 3c54a781c1..e0c5a30034 100644 --- a/src/lib/resolve/recursive_query.cc +++ b/src/lib/resolve/recursive_query.cc @@ -43,6 +43,7 @@ #include using namespace isc::dns; +using namespace isc::nsas; using namespace isc::util; using namespace isc::asiolink; using namespace isc::resolve; -- cgit v1.2.3 From 86d5acdb8b857924b207ada60173186e1d03afc9 Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Wed, 5 Feb 2014 12:49:17 +0530 Subject: [956] Make Message::toWire() TSIG agnostic --- src/bin/auth/auth_srv.cc | 26 +++++++-------------- src/bin/ddns/ddns.py.in | 5 +--- src/bin/ddns/tests/ddns_test.py | 5 +--- src/bin/xfrin/tests/xfrin_test.py | 5 +--- src/bin/xfrout/xfrout.py.in | 7 +----- src/lib/dns/message.cc | 9 ++----- src/lib/dns/message.h | 31 +++++++++---------------- src/lib/dns/python/message_python.cc | 8 +++---- src/lib/dns/python/tests/message_python_test.py | 7 ++++++ src/lib/dns/python/tsig_python.cc | 11 +++++++-- src/lib/dns/python/tsig_python.h | 6 ++--- src/lib/dns/tests/message_unittest.cc | 4 ++-- src/lib/dns/tests/tsig_unittest.cc | 2 +- src/lib/testutils/srv_test.cc | 7 +----- 14 files changed, 52 insertions(+), 81 deletions(-) (limited to 'src/lib/dns') diff --git a/src/bin/auth/auth_srv.cc b/src/bin/auth/auth_srv.cc index 37fdf5286e..63ed888361 100644 --- a/src/bin/auth/auth_srv.cc +++ b/src/bin/auth/auth_srv.cc @@ -442,12 +442,9 @@ makeErrorMessage(MessageRenderer& renderer, Message& message, message.setRcode(rcode); RendererHolder holder(renderer, &buffer, stats_attrs); - if (tsig_context.get() != NULL) { - message.toWire(renderer, *tsig_context); - stats_attrs.setResponseTSIG(true); - } else { - message.toWire(renderer); - } + message.toWire(renderer, tsig_context.get()); + stats_attrs.setResponseTSIG(tsig_context.get() != NULL); + LOG_DEBUG(auth_logger, DBG_AUTH_MESSAGES, AUTH_SEND_ERROR_RESPONSE) .arg(renderer.getLength()).arg(message); } @@ -674,12 +671,9 @@ AuthSrvImpl::processNormalQuery(const IOMessage& io_message, const bool udp_buffer = (io_message.getSocket().getProtocol() == IPPROTO_UDP); renderer_.setLengthLimit(udp_buffer ? remote_bufsize : 65535); - if (tsig_context.get() != NULL) { - message.toWire(renderer_, *tsig_context); - stats_attrs.setResponseTSIG(true); - } else { - message.toWire(renderer_); - } + message.toWire(renderer_, tsig_context.get()); + stats_attrs.setResponseTSIG(tsig_context.get() != NULL); + LOG_DEBUG(auth_logger, DBG_AUTH_MESSAGES, AUTH_SEND_NORMAL_RESPONSE) .arg(renderer_.getLength()).arg(message); return (true); @@ -836,12 +830,8 @@ AuthSrvImpl::processNotify(const IOMessage& io_message, Message& message, message.setRcode(Rcode::NOERROR()); RendererHolder holder(renderer_, &buffer, stats_attrs); - if (tsig_context.get() != NULL) { - message.toWire(renderer_, *tsig_context); - stats_attrs.setResponseTSIG(true); - } else { - message.toWire(renderer_); - } + message.toWire(renderer_, tsig_context.get()); + stats_attrs.setResponseTSIG(tsig_context.get() != NULL); return (true); } diff --git a/src/bin/ddns/ddns.py.in b/src/bin/ddns/ddns.py.in index 6bb81c5b6c..f87a21f352 100755 --- a/src/bin/ddns/ddns.py.in +++ b/src/bin/ddns/ddns.py.in @@ -495,10 +495,7 @@ class DDNSServer: return False msg = update_session.get_message() self.__response_renderer.clear() - if tsig_ctx is not None: - msg.to_wire(self.__response_renderer, tsig_ctx) - else: - msg.to_wire(self.__response_renderer) + msg.to_wire(self.__response_renderer, tsig_ctx) ret = self.__send_response(sock, self.__response_renderer.get_data(), remote_addr) diff --git a/src/bin/ddns/tests/ddns_test.py b/src/bin/ddns/tests/ddns_test.py index 66e87a4e4c..c5db61aa71 100755 --- a/src/bin/ddns/tests/ddns_test.py +++ b/src/bin/ddns/tests/ddns_test.py @@ -900,10 +900,7 @@ def create_msg(opcode=Opcode.UPDATE, zones=[TEST_ZONE_RECORD], prereq=[], msg.add_rrset(SECTION_PREREQUISITE, p) renderer = MessageRenderer() - if tsigctx is not None: - msg.to_wire(renderer, tsigctx) - else: - msg.to_wire(renderer) + msg.to_wire(renderer, tsigctx) # re-read the created data in the parse mode msg.clear(Message.PARSE) diff --git a/src/bin/xfrin/tests/xfrin_test.py b/src/bin/xfrin/tests/xfrin_test.py index 4158638456..1405cd83a4 100644 --- a/src/bin/xfrin/tests/xfrin_test.py +++ b/src/bin/xfrin/tests/xfrin_test.py @@ -373,10 +373,7 @@ class MockXfrinConnection(XfrinConnection): [resp.add_rrset(Message.SECTION_AUTHORITY, a) for a in authorities] renderer = MessageRenderer() - if tsig_ctx is not None: - resp.to_wire(renderer, tsig_ctx) - else: - resp.to_wire(renderer) + resp.to_wire(renderer, tsig_ctx) reply_data = struct.pack('H', socket.htons(renderer.get_length())) reply_data += renderer.get_data() diff --git a/src/bin/xfrout/xfrout.py.in b/src/bin/xfrout/xfrout.py.in index a776690dca..0fe8e1511b 100755 --- a/src/bin/xfrout/xfrout.py.in +++ b/src/bin/xfrout/xfrout.py.in @@ -345,12 +345,7 @@ class XfroutSession(): render.set_compress_mode(MessageRenderer.CASE_SENSITIVE) render.set_length_limit(XFROUT_MAX_MESSAGE_SIZE) - # XXX Currently, python wrapper doesn't accept 'None' parameter in this case, - # we should remove the if statement and use a universal interface later. - if tsig_ctx is not None: - msg.to_wire(render, tsig_ctx) - else: - msg.to_wire(render) + msg.to_wire(render, tsig_ctx) header_len = struct.pack('H', socket.htons(render.get_length())) self._send_data(sock_fd, header_len) diff --git a/src/lib/dns/message.cc b/src/lib/dns/message.cc index 8487cf5f54..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 diff --git a/src/lib/dns/message.h b/src/lib/dns/message.h index 17cf88b6ce..828346fef1 100644 --- a/src/lib/dns/message.h +++ b/src/lib/dns/message.h @@ -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. /// 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/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/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(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/tests/message_unittest.cc b/src/lib/dns/tests/message_unittest.cc index 61f2e118d2..46927ddbbf 100644 --- a/src/lib/dns/tests/message_unittest.cc +++ b/src/lib/dns/tests/message_unittest.cc @@ -893,7 +893,7 @@ commonTSIGToWireCheck(Message& message, MessageRenderer& renderer, message.addRRset(Message::SECTION_ANSWER, ans_rrset); } - message.toWire(renderer, tsig_ctx); + message.toWire(renderer, &tsig_ctx); vector expected_data; UnitTestUtil::readWireData(expected_file, expected_data); EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, renderer.getData(), @@ -1026,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/tsig_unittest.cc b/src/lib/dns/tests/tsig_unittest.cc index 458a6e0cf3..b96f61f7dc 100644 --- a/src/lib/dns/tests/tsig_unittest.cc +++ b/src/lib/dns/tests/tsig_unittest.cc @@ -188,7 +188,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()); diff --git a/src/lib/testutils/srv_test.cc b/src/lib/testutils/srv_test.cc index 7b0b1bbeb4..8b1337116b 100644 --- a/src/lib/testutils/srv_test.cc +++ b/src/lib/testutils/srv_test.cc @@ -72,12 +72,7 @@ SrvTestBase::createRequestPacket(Message& message, const char* const remote_address, uint16_t remote_port) { - if (context == NULL) { - message.toWire(request_renderer); - } else { - message.toWire(request_renderer, *context); - } - + message.toWire(request_renderer, context); endpoint.reset(IOEndpoint::create(protocol, IOAddress(remote_address), remote_port)); io_sock = (protocol == IPPROTO_UDP) ? &IOSocket::getDummyUDPSocket() : -- cgit v1.2.3 From 195af9e40f0715d241af51c704faa4fea6a96839 Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Thu, 6 Feb 2014 14:33:24 +0530 Subject: [2168] Remove more cases of UnitTestUtil::matchWireData (merged from master) --- src/lib/dns/tests/rdata_rrsig_unittest.cc | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'src/lib/dns') diff --git a/src/lib/dns/tests/rdata_rrsig_unittest.cc b/src/lib/dns/tests/rdata_rrsig_unittest.cc index 7c54fad025..67ead3c713 100644 --- a/src/lib/dns/tests/rdata_rrsig_unittest.cc +++ b/src/lib/dns/tests/rdata_rrsig_unittest.cc @@ -25,14 +25,16 @@ #include #include +#include #include -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 { @@ -340,17 +342,15 @@ TEST_F(Rdata_RRSIG_Test, createFromLexer) { TEST_F(Rdata_RRSIG_Test, toWireRenderer) { rdata_rrsig.toWire(renderer); - EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, - renderer.getData(), renderer.getLength(), - wiredata_rrsig, sizeof(wiredata_rrsig)); + matchWireData(wiredata_rrsig, sizeof(wiredata_rrsig), + renderer.getData(), renderer.getLength()); } TEST_F(Rdata_RRSIG_Test, toWireBuffer) { rdata_rrsig.toWire(obuffer); - EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, - obuffer.getData(), obuffer.getLength(), - wiredata_rrsig, sizeof(wiredata_rrsig)); + matchWireData(wiredata_rrsig, sizeof(wiredata_rrsig), + obuffer.getData(), obuffer.getLength()); } TEST_F(Rdata_RRSIG_Test, createFromWire) { -- cgit v1.2.3 From 9ffc91f18aa5ec78ef283a8412ed9da1a6874508 Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Thu, 6 Feb 2014 16:45:28 +0530 Subject: [413] Add a unittest for numeric owner names in master files --- src/lib/dns/tests/master_loader_unittest.cc | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'src/lib/dns') diff --git a/src/lib/dns/tests/master_loader_unittest.cc b/src/lib/dns/tests/master_loader_unittest.cc index ce9b8f7844..d5200055d3 100644 --- a/src/lib/dns/tests/master_loader_unittest.cc +++ b/src/lib/dns/tests/master_loader_unittest.cc @@ -952,4 +952,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"); +} + } -- cgit v1.2.3 From e48ae4647c1dfbc827d3e4538e9f35dd1d3c96f9 Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Thu, 6 Feb 2014 17:44:22 +0530 Subject: [2512] Add equality test in .compare unittest --- src/lib/dns/tests/rdata_caa_unittest.cc | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/lib/dns') diff --git a/src/lib/dns/tests/rdata_caa_unittest.cc b/src/lib/dns/tests/rdata_caa_unittest.cc index afa1c3c760..40cb1bfb12 100644 --- a/src/lib/dns/tests/rdata_caa_unittest.cc +++ b/src/lib/dns/tests/rdata_caa_unittest.cc @@ -229,6 +229,11 @@ TEST_F(Rdata_CAA_Test, toWire) { } 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)); -- cgit v1.2.3 From 969a916daeffe16ba2c04f3f1eead285284b3162 Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Thu, 6 Feb 2014 17:46:24 +0530 Subject: [2512] Add a comment about redundant test --- src/lib/dns/tests/rdata_caa_unittest.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/lib/dns') diff --git a/src/lib/dns/tests/rdata_caa_unittest.cc b/src/lib/dns/tests/rdata_caa_unittest.cc index 40cb1bfb12..e842bd69e9 100644 --- a/src/lib/dns/tests/rdata_caa_unittest.cc +++ b/src/lib/dns/tests/rdata_caa_unittest.cc @@ -116,7 +116,8 @@ TEST_F(Rdata_CAA_Test, fields) { 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 + // 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 -- cgit v1.2.3 From 11052a822a6c329a087e5590ac525ab3107926a8 Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Thu, 6 Feb 2014 17:47:18 +0530 Subject: [2512] Fix indent level --- src/lib/dns/tests/rdata_caa_unittest.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/lib/dns') diff --git a/src/lib/dns/tests/rdata_caa_unittest.cc b/src/lib/dns/tests/rdata_caa_unittest.cc index e842bd69e9..579cba98e2 100644 --- a/src/lib/dns/tests/rdata_caa_unittest.cc +++ b/src/lib/dns/tests/rdata_caa_unittest.cc @@ -38,10 +38,10 @@ using namespace isc::dns::rdata; namespace { class Rdata_CAA_Test : public RdataTest { protected: - Rdata_CAA_Test() : - caa_txt("0 issue \"ca.example.net\""), - rdata_caa(caa_txt) - {} + Rdata_CAA_Test() : + caa_txt("0 issue \"ca.example.net\""), + rdata_caa(caa_txt) + {} void checkFromText_None(const string& rdata_str) { checkFromText( -- cgit v1.2.3 From 79defea75c875181597598e880ee20af3016167f Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Thu, 6 Feb 2014 17:51:17 +0530 Subject: [2512] Update check to an assertion All the constructors currently check that the tag field is not empty. --- src/lib/dns/rdata/generic/caa_257.cc | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'src/lib/dns') diff --git a/src/lib/dns/rdata/generic/caa_257.cc b/src/lib/dns/rdata/generic/caa_257.cc index 47366d651a..ecaf559591 100644 --- a/src/lib/dns/rdata/generic/caa_257.cc +++ b/src/lib/dns/rdata/generic/caa_257.cc @@ -242,11 +242,12 @@ CAA::~CAA() { 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()); - if (!impl_->tag_.empty()) { - buffer.writeData(&impl_->tag_[0], - impl_->tag_.size()); - } + buffer.writeData(&impl_->tag_[0], impl_->tag_.size()); + if (impl_->value_.size() > 1) { buffer.writeData(&impl_->value_[1], impl_->value_.size() - 1); @@ -256,11 +257,12 @@ CAA::toWire(OutputBuffer& buffer) const { 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()); - if (!impl_->tag_.empty()) { - renderer.writeData(&impl_->tag_[0], - impl_->tag_.size()); - } + renderer.writeData(&impl_->tag_[0], impl_->tag_.size()); + if (impl_->value_.size() > 1) { renderer.writeData(&impl_->value_[1], impl_->value_.size() - 1); -- cgit v1.2.3 From 9ac39be69c035539d8bca28d3a5e6dd5d0d2ef19 Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Fri, 7 Feb 2014 18:30:50 +0530 Subject: [2185] Add and use a RdataPimplHolder instead of auto_ptr --- src/lib/dns/rdata/generic/tlsa_52.cc | 9 +++--- src/lib/dns/rdata_pimpl_holder.h | 58 ++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 4 deletions(-) create mode 100644 src/lib/dns/rdata_pimpl_holder.h (limited to 'src/lib/dns') diff --git a/src/lib/dns/rdata/generic/tlsa_52.cc b/src/lib/dns/rdata/generic/tlsa_52.cc index fdf3bc32d3..a896e8d47f 100644 --- a/src/lib/dns/rdata/generic/tlsa_52.cc +++ b/src/lib/dns/rdata/generic/tlsa_52.cc @@ -24,6 +24,7 @@ #include #include #include +#include using namespace std; using boost::lexical_cast; @@ -126,10 +127,10 @@ TLSA::constructFromLexer(MasterLexer& lexer) { TLSA::TLSA(const string& tlsa_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 TLSAImpl that constructFromLexer() returns. - std::auto_ptr impl_ptr(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 impl_ptr; try { std::istringstream ss(tlsa_str); diff --git a/src/lib/dns/rdata_pimpl_holder.h b/src/lib/dns/rdata_pimpl_holder.h new file mode 100644 index 0000000000..456440525d --- /dev/null +++ b/src/lib/dns/rdata_pimpl_holder.h @@ -0,0 +1,58 @@ +// 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 + +namespace isc { +namespace dns { +namespace rdata { + +template +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 -- cgit v1.2.3 From 5813a6de50708cb1d0a738afa56d0adbd6ba23da Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Fri, 7 Feb 2014 18:54:48 +0530 Subject: [2185] Add tests for RdataPimplHolder --- src/lib/dns/Makefile.am | 1 + src/lib/dns/tests/Makefile.am | 1 + src/lib/dns/tests/rdata_pimpl_holder_unittest.cc | 62 ++++++++++++++++++++++++ 3 files changed, 64 insertions(+) create mode 100644 src/lib/dns/tests/rdata_pimpl_holder_unittest.cc (limited to 'src/lib/dns') diff --git a/src/lib/dns/Makefile.am b/src/lib/dns/Makefile.am index b16c40c47f..057a7b60e0 100644 --- a/src/lib/dns/Makefile.am +++ b/src/lib/dns/Makefile.am @@ -137,6 +137,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 diff --git a/src/lib/dns/tests/Makefile.am b/src/lib/dns/tests/Makefile.am index 2557228b65..3f1a756470 100644 --- a/src/lib/dns/tests/Makefile.am +++ b/src/lib/dns/tests/Makefile.am @@ -38,6 +38,7 @@ 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_in_a_unittest.cc rdata_in_aaaa_unittest.cc run_unittests_SOURCES += rdata_ns_unittest.cc rdata_soa_unittest.cc 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 + +#include + +using namespace isc::dns::rdata; + +namespace { + +TEST(RdataPimplHolderTest, all) { + // Let's check with an integer + int* i1 = new int(42); + RdataPimplHolder 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 holder2(i2); + holder2.reset(); + EXPECT_EQ(NULL, holder2.get()); + + // Test reset() with argument + int* i3 = new int(44); + int* i4 = new int(45); + RdataPimplHolder holder3(i3); + EXPECT_EQ(i3, holder3.get()); + holder3.reset(i4); + EXPECT_EQ(i4, holder3.get()); + EXPECT_EQ(45, *holder3.get()); + + // Test release() + RdataPimplHolder holder4(new int(46)); + EXPECT_NE(static_cast(NULL), holder4.get()); + EXPECT_EQ(46, *holder4.get()); + int* i5 = holder4.release(); + EXPECT_EQ(NULL, holder4.get()); + EXPECT_NE(static_cast(NULL), i5); + EXPECT_EQ(46, *i5); + delete i5; +} + +} -- cgit v1.2.3 From 506b5310b54aa834f2a1dcdff167f91a07b974fa Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Tue, 11 Feb 2014 11:01:27 +0530 Subject: [2185] Don't allow empty TLSA certificate association data --- src/lib/dns/rdata/generic/tlsa_52.cc | 59 ++++++++++++++---------- src/lib/dns/tests/rdata_tlsa_unittest.cc | 77 +++++--------------------------- 2 files changed, 46 insertions(+), 90 deletions(-) (limited to 'src/lib/dns') diff --git a/src/lib/dns/rdata/generic/tlsa_52.cc b/src/lib/dns/rdata/generic/tlsa_52.cc index a896e8d47f..774bdef6cf 100644 --- a/src/lib/dns/rdata/generic/tlsa_52.cc +++ b/src/lib/dns/rdata/generic/tlsa_52.cc @@ -89,16 +89,16 @@ TLSA::constructFromLexer(MasterLexer& lexer) { } lexer.ungetToken(); + if (certificate_assoc_data.empty()) { + isc_throw(InvalidRdataText, "Empty TLSA certificate association data"); + } + vector data; - // If certificate association data is missing, it's OK. See the API - // documentation of the constructor. - if (certificate_assoc_data.size() > 0) { - try { - decodeHex(certificate_assoc_data, data); - } catch (const isc::BadValue& e) { - isc_throw(InvalidRdataText, - "Bad TLSA certificate association data: " << e.what()); - } + 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)); @@ -187,18 +187,26 @@ TLSA::TLSA(InputBuffer& buffer, size_t rdata_len) { vector data; rdata_len -= 3; - if (rdata_len > 0) { - data.resize(rdata_len); - buffer.readData(&data[0], rdata_len); + + 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) : + 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 data; try { decodeHex(certificate_assoc_data, data); @@ -237,10 +245,10 @@ TLSA::toWire(OutputBuffer& buffer) const { buffer.writeUint8(impl_->selector_); buffer.writeUint8(impl_->matching_type_); - if (!impl_->data_.empty()) { - buffer.writeData(&impl_->data_[0], - impl_->data_.size()); - } + // 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 @@ -249,19 +257,22 @@ TLSA::toWire(AbstractMessageRenderer& renderer) const { renderer.writeUint8(impl_->selector_); renderer.writeUint8(impl_->matching_type_); - if (!impl_->data_.empty()) { - renderer.writeData(&impl_->data_[0], - impl_->data_.size()); - } + // 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(static_cast(impl_->certificate_usage_)) + " " + lexical_cast(static_cast(impl_->selector_)) + " " + - lexical_cast(static_cast(impl_->matching_type_)) + - (impl_->data_.empty() ? "" : - " " + encodeHex(impl_->data_))); + lexical_cast(static_cast(impl_->matching_type_)) + " " + + encodeHex(impl_->data_)); } int diff --git a/src/lib/dns/tests/rdata_tlsa_unittest.cc b/src/lib/dns/tests/rdata_tlsa_unittest.cc index 3e494c2623..b1129afc70 100644 --- a/src/lib/dns/tests/rdata_tlsa_unittest.cc +++ b/src/lib/dns/tests/rdata_tlsa_unittest.cc @@ -217,6 +217,11 @@ TEST_F(Rdata_TLSA_Test, createFromWire) { "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"), @@ -228,17 +233,14 @@ TEST_F(Rdata_TLSA_Test, createFromParams) { 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())); - - const string tlsa_txt2("3 2 1"); - const generic::TLSA rdata_tlsa2(tlsa_txt2); - EXPECT_TRUE(boost::iequals(tlsa_txt2, rdata_tlsa2.toText())); - - const generic::TLSA rdata_tlsa3("3 2 1 "); - EXPECT_TRUE(boost::iequals(tlsa_txt2, rdata_tlsa3.toText())); } TEST_F(Rdata_TLSA_Test, toWire) { @@ -255,7 +257,8 @@ TEST_F(Rdata_TLSA_Test, toWire) { } TEST_F(Rdata_TLSA_Test, compare) { - const generic::TLSA rdata_tlsa2("0 0 0"); + 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)); } @@ -275,62 +278,4 @@ TEST_F(Rdata_TLSA_Test, getMatchingType) { TEST_F(Rdata_TLSA_Test, getDataLength) { EXPECT_EQ(32, rdata_tlsa.getDataLength()); } - -TEST_F(Rdata_TLSA_Test, emptyCertificateAssociationDataFromWire) { - const uint8_t rdf_wiredata[] = { - // certificate usage - 0x03, - // selector - 0x01, - // matching type - 0x02, - }; - - const generic::TLSA rdf = - dynamic_cast - (*rdataFactoryFromFile(RRType("TLSA"), RRClass("IN"), - "rdata_tlsa_fromWire12")); - - EXPECT_EQ(3, rdf.getCertificateUsage()); - EXPECT_EQ(1, rdf.getSelector()); - EXPECT_EQ(2, rdf.getMatchingType()); - EXPECT_EQ(0, rdf.getDataLength()); - - this->obuffer.clear(); - rdf.toWire(this->obuffer); - - EXPECT_EQ(3, this->obuffer.getLength()); - - EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, - this->obuffer.getData(), - this->obuffer.getLength(), - rdf_wiredata, sizeof(rdf_wiredata)); -} - -TEST_F(Rdata_TLSA_Test, emptyCertificateAssociationDataFromString) { - const generic::TLSA rdata_tlsa2("3 2 1"); - const uint8_t rdata_tlsa2_wiredata[] = { - // certificate usage - 0x03, - // selector - 0x02, - // matching type - 0x01 - }; - - EXPECT_EQ(3, rdata_tlsa2.getCertificateUsage()); - EXPECT_EQ(2, rdata_tlsa2.getSelector()); - EXPECT_EQ(1, rdata_tlsa2.getMatchingType()); - EXPECT_EQ(0, rdata_tlsa2.getDataLength()); - - this->obuffer.clear(); - rdata_tlsa2.toWire(this->obuffer); - - EXPECT_EQ(3, this->obuffer.getLength()); - - EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, - this->obuffer.getData(), - this->obuffer.getLength(), - rdata_tlsa2_wiredata, sizeof(rdata_tlsa2_wiredata)); -} } -- cgit v1.2.3 From cb1407f6e846eaa57940be4d13ff03d25c1728c8 Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Tue, 11 Feb 2014 13:13:01 +0530 Subject: [2512] Add a CharStringData type (with no length byte prefix) --- src/lib/dns/rdata/generic/detail/char_string.cc | 78 +++++++++ src/lib/dns/rdata/generic/detail/char_string.h | 37 ++++ src/lib/dns/tests/Makefile.am | 1 + .../dns/tests/rdata_char_string_data_unittest.cc | 187 +++++++++++++++++++++ 4 files changed, 303 insertions(+) create mode 100644 src/lib/dns/tests/rdata_char_string_data_unittest.cc (limited to 'src/lib/dns') diff --git a/src/lib/dns/rdata/generic/detail/char_string.cc b/src/lib/dns/rdata/generic/detail/char_string.cc index 4c8965a10b..16b281dae6 100644 --- a/src/lib/dns/rdata/generic/detail/char_string.cc +++ b/src/lib/dns/rdata/generic/detail/char_string.cc @@ -93,6 +93,33 @@ 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); + assert(n >= 3); + 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 +143,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 +194,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 CharString; +/// \brief Type for DNS character string without the length prefix. +typedef std::vector 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 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/tests/Makefile.am b/src/lib/dns/tests/Makefile.am index 46fcfb100d..01773e0374 100644 --- a/src/lib/dns/tests/Makefile.am +++ b/src/lib/dns/tests/Makefile.am @@ -39,6 +39,7 @@ 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_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 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..6f059369d2 --- /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 + +#include +#include +#include +#include + +#include + +#include +#include + +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 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(sizeof(idata) >= length); + 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 -- cgit v1.2.3 From 7606f0759b4ae96e49edad0e46316d8d1784aaff Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Tue, 11 Feb 2014 13:14:00 +0530 Subject: [2512] Simplify CAA implementation using CharStringData type --- src/lib/dns/rdata/generic/caa_257.cc | 70 +++++++++++++-------------------- src/lib/dns/tests/rdata_caa_unittest.cc | 4 +- 2 files changed, 29 insertions(+), 45 deletions(-) (limited to 'src/lib/dns') diff --git a/src/lib/dns/rdata/generic/caa_257.cc b/src/lib/dns/rdata/generic/caa_257.cc index ecaf559591..97b9ba32bb 100644 --- a/src/lib/dns/rdata/generic/caa_257.cc +++ b/src/lib/dns/rdata/generic/caa_257.cc @@ -37,19 +37,20 @@ using namespace isc::util; struct CAAImpl { // straightforward representation of CAA RDATA fields CAAImpl(uint8_t flags, const std::string& tag, - const std::vector& value) : + 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_; - - // The first byte of this vector contains the length of the rest of - // the vector. This byte is actually unused and is skipped when - // reading the vector. - const detail::CharString value_; + const detail::CharStringData value_; }; // helper function for string and lexer constructors @@ -73,15 +74,12 @@ CAA::constructFromLexer(MasterLexer& lexer) { } // Value field may be empty. - std::vector value; + detail::CharStringData value; MasterToken token = lexer.getNextToken(MasterToken::QSTRING, true); if ((token.getType() != MasterToken::END_OF_FILE) && (token.getType() != MasterToken::END_OF_LINE)) { - detail::stringToCharString(token.getStringRegion(), value); - } else { - // Convert it into a CharString. - value.push_back(0); + detail::stringToCharStringData(token.getStringRegion(), value); } return (new CAAImpl(flags, tag, value)); @@ -172,23 +170,15 @@ CAA::CAA(InputBuffer& buffer, size_t rdata_len) { } vector tag_vec; - tag_vec.resize(tag_length + 1); - tag_vec[0] = tag_length; - buffer.readData(&tag_vec[1], tag_length); + tag_vec.resize(tag_length); + buffer.readData(&tag_vec[0], tag_length); + std::string tag(tag_vec.begin(), tag_vec.end()); rdata_len -= tag_length; - const std::string tag = detail::charStringToString(tag_vec); - - if (rdata_len > 255) { - isc_throw(InvalidRdataLength, - "CAA value field is too long: " << rdata_len); - } - - vector value; - value.resize(rdata_len + 1); - value[0] = rdata_len; + detail::CharStringData value; + value.resize(rdata_len); if (rdata_len > 0) { - buffer.readData(&value[1], rdata_len); + buffer.readData(&value[0], rdata_len); } impl_ = new CAAImpl(flags, tag, value); @@ -205,14 +195,8 @@ CAA::CAA(uint8_t flags, const std::string& tag, const std::string& value) : "CAA tag field is too large: " << tag.size()); } - if (value.size() > 255) { - isc_throw(isc::InvalidParameter, - "CAA value field is too long: " << value.size()); - } - - std::vector value_vec; - value_vec.reserve(value.size() + 1); - value_vec.push_back(value.size()); + detail::CharStringData value_vec; + value_vec.reserve(value.size()); value_vec.insert(value_vec.end(), value.begin(), value.end()); impl_ = new CAAImpl(flags, tag, value_vec); @@ -248,9 +232,9 @@ CAA::toWire(OutputBuffer& buffer) const { buffer.writeUint8(impl_->tag_.size()); buffer.writeData(&impl_->tag_[0], impl_->tag_.size()); - if (impl_->value_.size() > 1) { - buffer.writeData(&impl_->value_[1], - impl_->value_.size() - 1); + if (!impl_->value_.empty()) { + buffer.writeData(&impl_->value_[0], + impl_->value_.size()); } } @@ -263,9 +247,9 @@ CAA::toWire(AbstractMessageRenderer& renderer) const { renderer.writeUint8(impl_->tag_.size()); renderer.writeData(&impl_->tag_[0], impl_->tag_.size()); - if (impl_->value_.size() > 1) { - renderer.writeData(&impl_->value_[1], - impl_->value_.size() - 1); + if (!impl_->value_.empty()) { + renderer.writeData(&impl_->value_[0], + impl_->value_.size()); } } @@ -275,7 +259,7 @@ CAA::toText() const { result = lexical_cast(static_cast(impl_->flags_)); result += " " + impl_->tag_; - result += " \"" + detail::charStringToString(impl_->value_) + "\""; + result += " \"" + detail::charStringDataToString(impl_->value_) + "\""; return (result); } @@ -297,8 +281,8 @@ CAA::compare(const Rdata& other) const { return (result); } - return (detail::compareCharStrings(impl_->value_, - other_caa.impl_->value_)); + return (detail::compareCharStringDatas(impl_->value_, + other_caa.impl_->value_)); } uint8_t diff --git a/src/lib/dns/tests/rdata_caa_unittest.cc b/src/lib/dns/tests/rdata_caa_unittest.cc index 579cba98e2..e740619a03 100644 --- a/src/lib/dns/tests/rdata_caa_unittest.cc +++ b/src/lib/dns/tests/rdata_caa_unittest.cc @@ -203,9 +203,9 @@ TEST_F(Rdata_CAA_Test, createFromParams) { isc::InvalidParameter); // Value is too long - const std::string value(256, 'a'); + const std::string value(65536, 'a'); EXPECT_THROW(const generic::CAA rdata_caa3(0, "issue", value), - isc::InvalidParameter); + InvalidRdataLength); } TEST_F(Rdata_CAA_Test, toText) { -- cgit v1.2.3 From a5d2806bff9656a3ea7900c8dba4101bf3c86ca8 Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Tue, 11 Feb 2014 13:18:50 +0530 Subject: [2512] Add CAA::getValue() --- src/lib/dns/rdata/generic/caa_257.cc | 5 +++++ src/lib/dns/rdata/generic/caa_257.h | 1 + src/lib/dns/tests/rdata_caa_unittest.cc | 13 +++++++++++++ 3 files changed, 19 insertions(+) (limited to 'src/lib/dns') diff --git a/src/lib/dns/rdata/generic/caa_257.cc b/src/lib/dns/rdata/generic/caa_257.cc index 97b9ba32bb..a031ab1ede 100644 --- a/src/lib/dns/rdata/generic/caa_257.cc +++ b/src/lib/dns/rdata/generic/caa_257.cc @@ -295,5 +295,10 @@ CAA::getTag() const { return (impl_->tag_); } +const std::vector& +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 index 69e3936d82..e06b250340 100644 --- a/src/lib/dns/rdata/generic/caa_257.h +++ b/src/lib/dns/rdata/generic/caa_257.h @@ -45,6 +45,7 @@ public: /// uint8_t getFlags() const; const std::string& getTag() const; + const std::vector& getValue() const; private: CAAImpl* constructFromLexer(MasterLexer& lexer); diff --git a/src/lib/dns/tests/rdata_caa_unittest.cc b/src/lib/dns/tests/rdata_caa_unittest.cc index e740619a03..8968f46c7d 100644 --- a/src/lib/dns/tests/rdata_caa_unittest.cc +++ b/src/lib/dns/tests/rdata_caa_unittest.cc @@ -249,6 +249,19 @@ 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& value = rdata_caa.getValue(); + EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, + &value[0], value.size(), + value_data, sizeof(value_data)); +} + TEST_F(Rdata_CAA_Test, emptyValueFromWire) { const uint8_t rdf_wiredata[] = { // flags -- cgit v1.2.3 From 3c09cb5da05b2439201dc01b351f5003f1dd8557 Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Tue, 11 Feb 2014 13:30:14 +0530 Subject: [2512] Add some tests for Value field --- src/lib/dns/tests/rdata_caa_unittest.cc | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'src/lib/dns') diff --git a/src/lib/dns/tests/rdata_caa_unittest.cc b/src/lib/dns/tests/rdata_caa_unittest.cc index 8968f46c7d..05d177e00f 100644 --- a/src/lib/dns/tests/rdata_caa_unittest.cc +++ b/src/lib/dns/tests/rdata_caa_unittest.cc @@ -134,6 +134,20 @@ TEST_F(Rdata_CAA_Test, fields) { 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\""); -- cgit v1.2.3 From a6a6cb2e33f807593e6d457bfc822a9c31ef211e Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Tue, 11 Feb 2014 13:35:59 +0530 Subject: [2512] Use CharStringData when constructing from parameters too This supports handling escapes and such when coming from the presentation format. --- src/lib/dns/rdata/generic/caa_257.cc | 7 +++++-- src/lib/dns/tests/rdata_caa_unittest.cc | 6 ++++++ 2 files changed, 11 insertions(+), 2 deletions(-) (limited to 'src/lib/dns') diff --git a/src/lib/dns/rdata/generic/caa_257.cc b/src/lib/dns/rdata/generic/caa_257.cc index a031ab1ede..9e6fa9bab5 100644 --- a/src/lib/dns/rdata/generic/caa_257.cc +++ b/src/lib/dns/rdata/generic/caa_257.cc @@ -195,9 +195,12 @@ CAA::CAA(uint8_t flags, const std::string& tag, const std::string& value) : "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; - value_vec.reserve(value.size()); - value_vec.insert(value_vec.end(), value.begin(), value.end()); + detail::stringToCharStringData(region, value_vec); impl_ = new CAAImpl(flags, tag, value_vec); } diff --git a/src/lib/dns/tests/rdata_caa_unittest.cc b/src/lib/dns/tests/rdata_caa_unittest.cc index 05d177e00f..a2a9f9ea80 100644 --- a/src/lib/dns/tests/rdata_caa_unittest.cc +++ b/src/lib/dns/tests/rdata_caa_unittest.cc @@ -207,6 +207,12 @@ 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); -- cgit v1.2.3 From 569e7f0737f69d0c2768bdc02f0b0961e992a24c Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Fri, 14 Feb 2014 13:09:47 +0530 Subject: [2185] Add include for NULL definition --- src/lib/dns/rdata_pimpl_holder.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/lib/dns') diff --git a/src/lib/dns/rdata_pimpl_holder.h b/src/lib/dns/rdata_pimpl_holder.h index 456440525d..2705dd854d 100644 --- a/src/lib/dns/rdata_pimpl_holder.h +++ b/src/lib/dns/rdata_pimpl_holder.h @@ -17,6 +17,8 @@ #include +#include // for NULL + namespace isc { namespace dns { namespace rdata { -- cgit v1.2.3 From 1cc088ff06c72fa566dde903f972450f4a78ce1b Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Fri, 14 Feb 2014 18:52:46 +0530 Subject: [2430] Update copyright year --- src/lib/dns/master_loader.cc | 2 +- src/lib/dns/tests/master_loader_unittest.cc | 2 +- tests/lettuce/features/terrain/terrain.py | 3 +-- 3 files changed, 3 insertions(+), 4 deletions(-) (limited to 'src/lib/dns') diff --git a/src/lib/dns/master_loader.cc b/src/lib/dns/master_loader.cc index 9a8d68858d..a0ef890847 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 diff --git a/src/lib/dns/tests/master_loader_unittest.cc b/src/lib/dns/tests/master_loader_unittest.cc index b12034f15b..4a8c1a34b1 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 diff --git a/tests/lettuce/features/terrain/terrain.py b/tests/lettuce/features/terrain/terrain.py index f20dfc899c..e59a28934f 100644 --- a/tests/lettuce/features/terrain/terrain.py +++ b/tests/lettuce/features/terrain/terrain.py @@ -1,5 +1,4 @@ - -# Copyright (C) 2011 Internet Systems Consortium. +# Copyright (C) 2011-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 -- cgit v1.2.3 From 23911dbc9aafb2f8b00755a74284ac82dba19bee Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Fri, 14 Feb 2014 18:53:26 +0530 Subject: [2430] Fix separator spelling --- src/lib/dns/master_loader.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/lib/dns') diff --git a/src/lib/dns/master_loader.cc b/src/lib/dns/master_loader.cc index a0ef890847..d5979feb5b 100644 --- a/src/lib/dns/master_loader.cc +++ b/src/lib/dns/master_loader.cc @@ -460,9 +460,9 @@ genNibbles(int i, unsigned int width, bool uppercase) { --width; } - // If width is non zero then we need to add a label seperator. + // 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 seperator. + // that requires a label separator. if (width > 0 || i != 0) { rstr.push_back('.'); -- cgit v1.2.3 From 98a54e274774cb7b8f1d2d3673fa39f3ef14beb8 Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Fri, 14 Feb 2014 18:55:24 +0530 Subject: [2430] Update test comment --- src/lib/dns/tests/master_loader_unittest.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/lib/dns') diff --git a/src/lib/dns/tests/master_loader_unittest.cc b/src/lib/dns/tests/master_loader_unittest.cc index 4a8c1a34b1..3bfd9f943b 100644 --- a/src/lib/dns/tests/master_loader_unittest.cc +++ b/src/lib/dns/tests/master_loader_unittest.cc @@ -538,7 +538,8 @@ TEST_F(MasterLoaderTest, generateWithModifiers) { "$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. + // 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(), -- cgit v1.2.3 From 4df951747393f5e59babd70ecba190b6dcb2fd74 Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Fri, 14 Feb 2014 19:05:01 +0530 Subject: [2430] Rename variables to match BIND 9 ARM documentation --- src/lib/dns/master_loader.cc | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'src/lib/dns') diff --git a/src/lib/dns/master_loader.cc b/src/lib/dns/master_loader.cc index d5979feb5b..6073125990 100644 --- a/src/lib/dns/master_loader.cc +++ b/src/lib/dns/master_loader.cc @@ -498,30 +498,30 @@ MasterLoader::MasterLoaderImpl::generateForIter(const std::string& str, } else { const char* scan_str = str.c_str() + std::distance(str.begin(), it); - int delta = 0; + int offset = 0; unsigned int width; - char mode[2] = {'d', 0}; // char plus null byte + char base[2] = {'d', 0}; // char plus null byte const int n = sscanf(scan_str, "{%d,%u,%1[doxXnN]}", - &delta, &width, mode); + &offset, &width, base); switch (n) { case 1: - rstr += boost::str(boost::format("%d") % (i + delta)); + rstr += boost::str(boost::format("%d") % (i + offset)); break; case 2: { const std::string fmt = boost::str(boost::format("%%0%ud") % width); - rstr += boost::str(boost::format(fmt) % (i + delta)); + rstr += boost::str(boost::format(fmt) % (i + offset)); break; } case 3: - if ((mode[0] == 'n') || (mode[0] == 'N')) { - rstr += genNibbles(i + delta, width, (mode[0] == 'N')); + if ((base[0] == 'n') || (base[0] == 'N')) { + rstr += genNibbles(i + offset, width, (base[0] == 'N')); } else { const std::string fmt = - boost::str(boost::format("%%0%u%c") % width % mode[0]); - rstr += boost::str(boost::format(fmt) % (i + delta)); + boost::str(boost::format("%%0%u%c") % width % base[0]); + rstr += boost::str(boost::format(fmt) % (i + offset)); } break; -- cgit v1.2.3 From 9aa52ecbbc7366e0246cbc554db9d3fccdf47b3b Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Fri, 14 Feb 2014 19:11:58 +0530 Subject: [2430] Rename argument i to num --- src/lib/dns/master_loader.cc | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'src/lib/dns') diff --git a/src/lib/dns/master_loader.cc b/src/lib/dns/master_loader.cc index 6073125990..6ca4aebefa 100644 --- a/src/lib/dns/master_loader.cc +++ b/src/lib/dns/master_loader.cc @@ -447,13 +447,13 @@ public: namespace { // begin unnamed namespace std::string -genNibbles(int i, unsigned int width, bool uppercase) { +genNibbles(int num, unsigned int width, bool uppercase) { static const char *hex = "0123456789abcdef0123456789ABCDEF"; std::string rstr; do { - char ch = hex[(i & 0x0f) + (uppercase ? 16 : 0)]; - i >>= 4; + char ch = hex[(num & 0x0f) + (uppercase ? 16 : 0)]; + num >>= 4; rstr.push_back(ch); if (width > 0) { @@ -463,14 +463,14 @@ genNibbles(int i, unsigned int width, bool uppercase) { // 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 || i != 0) { + if (width > 0 || num != 0) { rstr.push_back('.'); if (width > 0) { --width; } } - } while ((i != 0) || (width > 0)); + } while ((num != 0) || (width > 0)); return (rstr); } @@ -479,7 +479,7 @@ genNibbles(int i, unsigned int width, bool uppercase) { std::string MasterLoader::MasterLoaderImpl::generateForIter(const std::string& str, - const int i) + const int num) { std::string rstr; @@ -494,7 +494,7 @@ MasterLoader::MasterLoaderImpl::generateForIter(const std::string& str, } if (*it != '{') { - rstr += boost::str(boost::format("%d") % i); + rstr += boost::str(boost::format("%d") % num); } else { const char* scan_str = str.c_str() + std::distance(str.begin(), it); @@ -505,23 +505,23 @@ MasterLoader::MasterLoaderImpl::generateForIter(const std::string& str, &offset, &width, base); switch (n) { case 1: - rstr += boost::str(boost::format("%d") % (i + offset)); + rstr += boost::str(boost::format("%d") % (num + offset)); break; case 2: { const std::string fmt = boost::str(boost::format("%%0%ud") % width); - rstr += boost::str(boost::format(fmt) % (i + offset)); + rstr += boost::str(boost::format(fmt) % (num + offset)); break; } case 3: if ((base[0] == 'n') || (base[0] == 'N')) { - rstr += genNibbles(i + offset, width, (base[0] == 'N')); + rstr += genNibbles(num + offset, width, (base[0] == 'N')); } else { const std::string fmt = boost::str(boost::format("%%0%u%c") % width % base[0]); - rstr += boost::str(boost::format(fmt) % (i + offset)); + rstr += boost::str(boost::format(fmt) % (num + offset)); } break; -- cgit v1.2.3 From a96232b3826660654f5afe4bb6961e6929635e2a Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Fri, 14 Feb 2014 19:14:58 +0530 Subject: [2430] Add comment about before and after scaffolding in test --- src/lib/dns/tests/master_loader_unittest.cc | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/lib/dns') diff --git a/src/lib/dns/tests/master_loader_unittest.cc b/src/lib/dns/tests/master_loader_unittest.cc index 3bfd9f943b..7ffa5672cf 100644 --- a/src/lib/dns/tests/master_loader_unittest.cc +++ b/src/lib/dns/tests/master_loader_unittest.cc @@ -337,6 +337,9 @@ TEST_F(MasterLoaderTest, generate) { 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"); -- cgit v1.2.3 From d8558bef68e5c67785deaceb23046c168afca4c4 Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Fri, 14 Feb 2014 19:19:53 +0530 Subject: [2430] Add generateAtEnd unittest --- src/lib/dns/tests/master_loader_unittest.cc | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'src/lib/dns') diff --git a/src/lib/dns/tests/master_loader_unittest.cc b/src/lib/dns/tests/master_loader_unittest.cc index 7ffa5672cf..ee747c9c74 100644 --- a/src/lib/dns/tests/master_loader_unittest.cc +++ b/src/lib/dns/tests/master_loader_unittest.cc @@ -398,6 +398,23 @@ TEST_F(MasterLoaderTest, generateInMiddle) { 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" -- cgit v1.2.3 From a06fc6d984b97e2d6aef8233acd2161b44adfdc4 Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Fri, 14 Feb 2014 21:20:37 +0530 Subject: [2430] Document the code --- src/lib/dns/master_loader.cc | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) (limited to 'src/lib/dns') diff --git a/src/lib/dns/master_loader.cc b/src/lib/dns/master_loader.cc index 6ca4aebefa..d003469bf3 100644 --- a/src/lib/dns/master_loader.cc +++ b/src/lib/dns/master_loader.cc @@ -486,6 +486,9 @@ MasterLoader::MasterLoaderImpl::generateForIter(const std::string& str, 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('$'); @@ -493,9 +496,15 @@ MasterLoader::MasterLoaderImpl::generateForIter(const std::string& str, 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; @@ -505,10 +514,15 @@ MasterLoader::MasterLoaderImpl::generateForIter(const std::string& str, &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)); @@ -516,9 +530,15 @@ MasterLoader::MasterLoaderImpl::generateForIter(const std::string& str, } 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)); @@ -526,15 +546,18 @@ MasterLoader::MasterLoaderImpl::generateForIter(const std::string& str, break; default: + // Any other case in the modifiers is an error. reportError(lexer_.getSourceName(), lexer_.getSourceLine(), "Invalid $GENERATE format modifiers"); return (""); } - /* Skip past closing brace. */ + // 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; } @@ -542,6 +565,10 @@ MasterLoader::MasterLoaderImpl::generateForIter(const std::string& str, 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()) { @@ -552,6 +579,9 @@ MasterLoader::MasterLoaderImpl::generateForIter(const std::string& str, 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; -- cgit v1.2.3 From 65c3f68979e3f0fd2078c77f114a45a26faeaaba Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Fri, 14 Feb 2014 21:36:00 +0530 Subject: [2430] Document the code further --- src/lib/dns/master_loader.cc | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) (limited to 'src/lib/dns') diff --git a/src/lib/dns/master_loader.cc b/src/lib/dns/master_loader.cc index d003469bf3..ab4b4be24d 100644 --- a/src/lib/dns/master_loader.cc +++ b/src/lib/dns/master_loader.cc @@ -593,6 +593,7 @@ MasterLoader::MasterLoaderImpl::generateForIter(const std::string& str, 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(), @@ -601,6 +602,7 @@ MasterLoader::MasterLoaderImpl::doGenerate() { } 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(), @@ -609,15 +611,25 @@ MasterLoader::MasterLoaderImpl::doGenerate() { } 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 and may be missing. 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)) @@ -628,10 +640,12 @@ MasterLoader::MasterLoaderImpl::doGenerate() { } 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; - const int n = sscanf(range.c_str(), "%u-%u/%u", &start, &stop, &step); if ((n < 2) || (stop < start)) { reportError(lexer_.getSourceName(), lexer_.getSourceLine(), @@ -643,7 +657,10 @@ MasterLoader::MasterLoaderImpl::doGenerate() { 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()) { @@ -656,7 +673,9 @@ MasterLoader::MasterLoaderImpl::doGenerate() { // generateForIter() can return a string with a trailing '.' in // case of a nibble representation. So we cannot use the - // relative Name constructor. + // 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; -- cgit v1.2.3 From b9bfb886c58492b361bbbcc0db90d7a0a641d493 Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Fri, 14 Feb 2014 21:38:40 +0530 Subject: [2430] Update a comment --- src/lib/dns/master_loader.cc | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'src/lib/dns') diff --git a/src/lib/dns/master_loader.cc b/src/lib/dns/master_loader.cc index ab4b4be24d..81db1213b5 100644 --- a/src/lib/dns/master_loader.cc +++ b/src/lib/dns/master_loader.cc @@ -612,13 +612,13 @@ MasterLoader::MasterLoaderImpl::doGenerate() { 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 and may be missing. 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. + // 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(), -- cgit v1.2.3 From afd6081696c2ae59c01f527bdbdb5381bb8052ba Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Sat, 15 Feb 2014 14:48:33 +0530 Subject: [2430] Change to C++ include --- src/lib/dns/master_loader.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/lib/dns') diff --git a/src/lib/dns/master_loader.cc b/src/lib/dns/master_loader.cc index 81db1213b5..f8e4552230 100644 --- a/src/lib/dns/master_loader.cc +++ b/src/lib/dns/master_loader.cc @@ -30,7 +30,7 @@ #include #include -#include // for sscanf() +#include // for sscanf() using std::string; using std::auto_ptr; -- cgit v1.2.3 From 3fc1c63ddb5524345e80c07c5dbea3cfc785e683 Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Mon, 17 Feb 2014 11:25:19 +0530 Subject: [2430] Write API doc for MasterLoaderImpl --- src/lib/dns/master_loader.cc | 228 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 183 insertions(+), 45 deletions(-) (limited to 'src/lib/dns') diff --git a/src/lib/dns/master_loader.cc b/src/lib/dns/master_loader.cc index f8e4552230..da31132c35 100644 --- a/src/lib/dns/master_loader.cc +++ b/src/lib/dns/master_loader.cc @@ -56,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, @@ -83,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)) { @@ -100,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) { @@ -125,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); @@ -143,16 +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. @@ -185,6 +271,7 @@ private: } } + /// \brief Process the $INCLUDE directive. void doInclude() { // First, get the filename to include const string @@ -205,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 @@ -249,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() - @@ -274,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 @@ -300,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 @@ -346,6 +450,10 @@ 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(); @@ -364,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 (;;) { @@ -446,6 +555,44 @@ public: 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" +/// +/// \param num The number for which the dotted nibble sequence should be +/// generated. +/// \param width The width of the generated string. +/// \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"; @@ -704,15 +851,6 @@ MasterLoader::MasterLoaderImpl::doGenerate() { } } -// 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. MasterToken MasterLoader::MasterLoaderImpl::handleInitialToken() { const MasterToken& initial_token = -- cgit v1.2.3 From 89ba2e6d39cb06fab5a594f7cabae57802726133 Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Mon, 17 Feb 2014 13:45:17 +0530 Subject: [2430] Update genNibbles() doc --- src/lib/dns/master_loader.cc | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'src/lib/dns') diff --git a/src/lib/dns/master_loader.cc b/src/lib/dns/master_loader.cc index da31132c35..5e68fedd9e 100644 --- a/src/lib/dns/master_loader.cc +++ b/src/lib/dns/master_loader.cc @@ -587,9 +587,23 @@ namespace { // begin unnamed namespace /// 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. +/// \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. -- cgit v1.2.3 From 8c77a05c8564a26113933d9cba6d5019cf1e75eb Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Tue, 18 Feb 2014 10:46:09 +0530 Subject: [2512] Combine resize() call with the constructor --- src/lib/dns/rdata/generic/caa_257.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src/lib/dns') diff --git a/src/lib/dns/rdata/generic/caa_257.cc b/src/lib/dns/rdata/generic/caa_257.cc index 9e6fa9bab5..7d46a57662 100644 --- a/src/lib/dns/rdata/generic/caa_257.cc +++ b/src/lib/dns/rdata/generic/caa_257.cc @@ -169,8 +169,7 @@ CAA::CAA(InputBuffer& buffer, size_t rdata_len) { "RDATA is too short for CAA tag field"); } - vector tag_vec; - tag_vec.resize(tag_length); + std::vector tag_vec(tag_length); buffer.readData(&tag_vec[0], tag_length); std::string tag(tag_vec.begin(), tag_vec.end()); rdata_len -= tag_length; -- cgit v1.2.3 From 5b61be1e6e567272b7bc372db457e2d1db1ddd49 Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Tue, 18 Feb 2014 17:51:31 +0530 Subject: [2512] Update assert() to a gtest ASSERT --- src/lib/dns/tests/rdata_char_string_data_unittest.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/lib/dns') diff --git a/src/lib/dns/tests/rdata_char_string_data_unittest.cc b/src/lib/dns/tests/rdata_char_string_data_unittest.cc index 6f059369d2..88a00a9b56 100644 --- a/src/lib/dns/tests/rdata_char_string_data_unittest.cc +++ b/src/lib/dns/tests/rdata_char_string_data_unittest.cc @@ -145,7 +145,7 @@ 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(sizeof(idata) >= length); + 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)); -- cgit v1.2.3 From 8d831e948945c913ac59424fa549fd7e2f18b117 Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Tue, 18 Feb 2014 17:51:45 +0530 Subject: [2512] Add some comments --- src/lib/dns/rdata/generic/detail/char_string.cc | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src/lib/dns') diff --git a/src/lib/dns/rdata/generic/detail/char_string.cc b/src/lib/dns/rdata/generic/detail/char_string.cc index 16b281dae6..328fa7b406 100644 --- a/src/lib/dns/rdata/generic/detail/char_string.cc +++ b/src/lib/dns/rdata/generic/detail/char_string.cc @@ -105,7 +105,13 @@ stringToCharStringData(const MasterToken::StringRegion& str_region, 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 == '\\') { -- cgit v1.2.3 From 9b9a1771a28d416d7c5e954ef41799b6d9c02959 Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Tue, 18 Feb 2014 18:02:38 +0530 Subject: [2512] Add API doc comments for generic::CAA specialized methods --- src/lib/dns/rdata/generic/caa_257.h | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'src/lib/dns') diff --git a/src/lib/dns/rdata/generic/caa_257.h b/src/lib/dns/rdata/generic/caa_257.h index e06b250340..47a1369c97 100644 --- a/src/lib/dns/rdata/generic/caa_257.h +++ b/src/lib/dns/rdata/generic/caa_257.h @@ -43,8 +43,18 @@ public: /// /// 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& getValue() const; private: -- cgit v1.2.3 From 8ec8a19d2342170d7deb9ee771c157eb439bc278 Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Tue, 18 Feb 2014 18:20:02 +0530 Subject: [2426] Initialize rdlen (apparently cppcheck doesn't detect the throw and complains) --- src/lib/dns/rdata.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/lib/dns') diff --git a/src/lib/dns/rdata.cc b/src/lib/dns/rdata.cc index 4f7962c162..bc0b403d64 100644 --- a/src/lib/dns/rdata.cc +++ b/src/lib/dns/rdata.cc @@ -221,7 +221,8 @@ Generic::constructFromLexer(MasterLexer& lexer) { "unknown RDATA encoding"); } - uint32_t rdlen; + // Initialize with an absurd value. + uint32_t rdlen = 65536; try { rdlen = lexer.getNextToken(MasterToken::NUMBER).getNumber(); -- cgit v1.2.3 From 1233aa6063c1790b69247fa96790651742d27c12 Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Tue, 18 Feb 2014 18:25:25 +0530 Subject: [2426] Move the ungetToken() call to make it easier to follow --- src/lib/dns/rdata.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src/lib/dns') diff --git a/src/lib/dns/rdata.cc b/src/lib/dns/rdata.cc index bc0b403d64..c5ece2741a 100644 --- a/src/lib/dns/rdata.cc +++ b/src/lib/dns/rdata.cc @@ -247,14 +247,13 @@ Generic::constructFromLexer(MasterLexer& lexer) { lexer.getNextToken(MasterToken::STRING, true); if ((token.getType() == MasterToken::END_OF_FILE) || (token.getType() == MasterToken::END_OF_LINE)) { + lexer.ungetToken(); break; } token.getString(hex_part); hex_txt.append(hex_part); } - lexer.ungetToken(); - try { isc::util::encode::decodeHex(hex_txt, data); } catch (const isc::BadValue& ex) { -- cgit v1.2.3 From 5c94286b3fcf47697829b2edba32cd47ed090bd6 Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Tue, 18 Feb 2014 18:33:27 +0530 Subject: [2426] Add a comment on why the ungetToken() is necessary --- src/lib/dns/rdata.cc | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/lib/dns') diff --git a/src/lib/dns/rdata.cc b/src/lib/dns/rdata.cc index c5ece2741a..533b325297 100644 --- a/src/lib/dns/rdata.cc +++ b/src/lib/dns/rdata.cc @@ -247,6 +247,9 @@ Generic::constructFromLexer(MasterLexer& lexer) { 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; } -- cgit v1.2.3 From acb20abee749563f5de98d582825f29b39046f11 Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Tue, 18 Feb 2014 18:36:57 +0530 Subject: [2426] Update exception message --- src/lib/dns/rdata.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/lib/dns') diff --git a/src/lib/dns/rdata.cc b/src/lib/dns/rdata.cc index 533b325297..4576b17342 100644 --- a/src/lib/dns/rdata.cc +++ b/src/lib/dns/rdata.cc @@ -267,7 +267,7 @@ Generic::constructFromLexer(MasterLexer& lexer) { if (data.size() != rdlen) { isc_throw(InvalidRdataLength, - "Unknown RDATA hex data doesn't match RDLENGTH: " + "Size of unknown RDATA hex data doesn't match RDLENGTH: " << data.size() << " vs. " << rdlen); } -- cgit v1.2.3 From 5ba017624caefa28eb330dbcf4bafe0890fbb899 Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Tue, 18 Feb 2014 19:34:49 +0530 Subject: [master] Add cppcheck suppressions for sscanf() false-positives Reviewed by Thomas Markwalder on Jabber. --- src/lib/dns/master_loader.cc | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/lib/dns') diff --git a/src/lib/dns/master_loader.cc b/src/lib/dns/master_loader.cc index 431c34b0c8..80b1053432 100644 --- a/src/lib/dns/master_loader.cc +++ b/src/lib/dns/master_loader.cc @@ -671,6 +671,7 @@ MasterLoader::MasterLoaderImpl::generateForIter(const std::string& str, 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) { @@ -807,6 +808,7 @@ MasterLoader::MasterLoaderImpl::doGenerate() { 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(), -- cgit v1.2.3 From 080f7d6b93825785ebdca4aaa64df2f636d4e54a Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Wed, 19 Feb 2014 13:27:57 +0530 Subject: [2185] Stop using API that was removed --- src/lib/dns/tests/rdata_tlsa_unittest.cc | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'src/lib/dns') diff --git a/src/lib/dns/tests/rdata_tlsa_unittest.cc b/src/lib/dns/tests/rdata_tlsa_unittest.cc index b1129afc70..30b608b244 100644 --- a/src/lib/dns/tests/rdata_tlsa_unittest.cc +++ b/src/lib/dns/tests/rdata_tlsa_unittest.cc @@ -26,14 +26,17 @@ #include #include +#include + #include -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_TLSA_Test : public RdataTest { @@ -250,10 +253,8 @@ TEST_F(Rdata_TLSA_Test, toWire) { EXPECT_EQ(sizeof (rdata_tlsa_wiredata), this->obuffer.getLength()); - EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, - this->obuffer.getData(), - this->obuffer.getLength(), - rdata_tlsa_wiredata, sizeof(rdata_tlsa_wiredata)); + matchWireData(rdata_tlsa_wiredata, sizeof(rdata_tlsa_wiredata), + obuffer.getData(), obuffer.getLength()); } TEST_F(Rdata_TLSA_Test, compare) { -- cgit v1.2.3 From 0c6ca2779a9152db8f4d43a88faf382380769961 Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Wed, 19 Feb 2014 13:49:06 +0530 Subject: [2512] Stop using API that was removed --- src/lib/dns/tests/rdata_caa_unittest.cc | 48 +++++++++++++-------------------- 1 file changed, 18 insertions(+), 30 deletions(-) (limited to 'src/lib/dns') diff --git a/src/lib/dns/tests/rdata_caa_unittest.cc b/src/lib/dns/tests/rdata_caa_unittest.cc index a2a9f9ea80..b88aba31e7 100644 --- a/src/lib/dns/tests/rdata_caa_unittest.cc +++ b/src/lib/dns/tests/rdata_caa_unittest.cc @@ -26,14 +26,17 @@ #include #include +#include + #include -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_CAA_Test : public RdataTest { @@ -237,16 +240,11 @@ TEST_F(Rdata_CAA_Test, toText) { } TEST_F(Rdata_CAA_Test, toWire) { - this->obuffer.clear(); - rdata_caa.toWire(this->obuffer); + obuffer.clear(); + rdata_caa.toWire(obuffer); - EXPECT_EQ(sizeof (rdata_caa_wiredata), - this->obuffer.getLength()); - - EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, - this->obuffer.getData(), - this->obuffer.getLength(), - rdata_caa_wiredata, sizeof(rdata_caa_wiredata)); + matchWireData(rdata_caa_wiredata, sizeof(rdata_caa_wiredata), + obuffer.getData(), obuffer.getLength()); } TEST_F(Rdata_CAA_Test, compare) { @@ -277,9 +275,8 @@ TEST_F(Rdata_CAA_Test, getValue) { }; const std::vector& value = rdata_caa.getValue(); - EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, - &value[0], value.size(), - value_data, sizeof(value_data)); + matchWireData(value_data, sizeof(value_data), + &value[0], value.size()); } TEST_F(Rdata_CAA_Test, emptyValueFromWire) { @@ -300,15 +297,11 @@ TEST_F(Rdata_CAA_Test, emptyValueFromWire) { EXPECT_EQ(0, rdf.getFlags()); EXPECT_EQ("issue", rdf.getTag()); - this->obuffer.clear(); - rdf.toWire(this->obuffer); - - EXPECT_EQ(sizeof(rdf_wiredata), this->obuffer.getLength()); + obuffer.clear(); + rdf.toWire(obuffer); - 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_CAA_Test, emptyValueFromString) { @@ -325,15 +318,10 @@ TEST_F(Rdata_CAA_Test, emptyValueFromString) { EXPECT_EQ(0, rdata_caa2.getFlags()); EXPECT_EQ("issue", rdata_caa2.getTag()); - this->obuffer.clear(); - rdata_caa2.toWire(this->obuffer); - - EXPECT_EQ(sizeof(rdata_caa2_wiredata), - this->obuffer.getLength()); + obuffer.clear(); + rdata_caa2.toWire(obuffer); - EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, - this->obuffer.getData(), - this->obuffer.getLength(), - rdata_caa2_wiredata, sizeof(rdata_caa2_wiredata)); + matchWireData(rdata_caa2_wiredata, sizeof(rdata_caa2_wiredata), + obuffer.getData(), obuffer.getLength()); } } -- cgit v1.2.3 From 8f858639af900655ea87f54ed7193169ff559088 Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Wed, 19 Feb 2014 14:27:11 +0530 Subject: [2000] Fix spelling mistake --- src/lib/dns/tests/testdata/rdata_opt_fromWire3 | 4 ++-- src/lib/dns/tests/testdata/rdata_opt_fromWire4 | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src/lib/dns') diff --git a/src/lib/dns/tests/testdata/rdata_opt_fromWire3 b/src/lib/dns/tests/testdata/rdata_opt_fromWire3 index 5ec2def0f5..f394c95cca 100644 --- a/src/lib/dns/tests/testdata/rdata_opt_fromWire3 +++ b/src/lib/dns/tests/testdata/rdata_opt_fromWire3 @@ -2,7 +2,7 @@ # # OPT RDATA, RDLEN=8 0008 -# psuedo RR 1 of size 7 (code=3, len=3) +# pseudo RR 1 of size 7 (code=3, len=3) 00 03 00 03 00 01 02 -# psuedo RR 2 of size 7 exhausts RDLEN (code=4, len=3) +# 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 index 1b388c31d4..89be2235c9 100644 --- a/src/lib/dns/tests/testdata/rdata_opt_fromWire4 +++ b/src/lib/dns/tests/testdata/rdata_opt_fromWire4 @@ -2,8 +2,8 @@ # # OPT RDATA, RDLEN=14 (0x000e) 000e -# psuedo RR 1 (code=3, len=3) +# pseudo RR 1 (code=3, len=3) 00 03 00 03 00 01 02 -# psuedo RR 2 (code=4, len=65535 overflows RDLEN) +# pseudo RR 2 (code=4, len=65535 overflows RDLEN) 00 04 ff ff 00 01 02 # rest of option data is omitted... -- cgit v1.2.3 From bb87247db5283a9c406255feb8449ccfefb74c49 Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Wed, 19 Feb 2014 14:28:17 +0530 Subject: [2000] Start comments with a capital letter --- src/lib/dns/tests/testdata/rdata_opt_fromWire1 | 9 ++++----- src/lib/dns/tests/testdata/rdata_opt_fromWire2 | 2 +- src/lib/dns/tests/testdata/rdata_opt_fromWire3 | 6 +++--- src/lib/dns/tests/testdata/rdata_opt_fromWire4 | 6 +++--- 4 files changed, 11 insertions(+), 12 deletions(-) (limited to 'src/lib/dns') diff --git a/src/lib/dns/tests/testdata/rdata_opt_fromWire1 b/src/lib/dns/tests/testdata/rdata_opt_fromWire1 index 0ca5f6aa0e..f1005ef91b 100644 --- a/src/lib/dns/tests/testdata/rdata_opt_fromWire1 +++ b/src/lib/dns/tests/testdata/rdata_opt_fromWire1 @@ -1,16 +1,15 @@ +# Various kinds of OPT RDATA stored in an input buffer # -# various kinds of OPT RDATA stored in an input buffer -# -# empty RDATA (which is okay) +# Empty RDATA (which is okay) # # 0 1 (bytes) 00 00 # -# an OPT RR containing an NSID Option +# 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) +# 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 index 4f5945c2f9..2c5a11fe54 100644 --- a/src/lib/dns/tests/testdata/rdata_opt_fromWire2 +++ b/src/lib/dns/tests/testdata/rdata_opt_fromWire2 @@ -1,4 +1,4 @@ -# short RDATA length +# 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 index f394c95cca..52db1d8c33 100644 --- a/src/lib/dns/tests/testdata/rdata_opt_fromWire3 +++ b/src/lib/dns/tests/testdata/rdata_opt_fromWire3 @@ -1,8 +1,8 @@ -# short RDATA length (in second pseudo RR) +# Short RDATA length (in second pseudo RR) # # OPT RDATA, RDLEN=8 0008 -# pseudo RR 1 of size 7 (code=3, len=3) +# 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) +# 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 index 89be2235c9..a302127b1a 100644 --- a/src/lib/dns/tests/testdata/rdata_opt_fromWire4 +++ b/src/lib/dns/tests/testdata/rdata_opt_fromWire4 @@ -2,8 +2,8 @@ # # OPT RDATA, RDLEN=14 (0x000e) 000e -# pseudo RR 1 (code=3, len=3) +# Pseudo RR 1 (code=3, len=3) 00 03 00 03 00 01 02 -# pseudo RR 2 (code=4, len=65535 overflows RDLEN) +# Pseudo RR 2 (code=4, len=65535 overflows RDLEN) 00 04 ff ff 00 01 02 -# rest of option data is omitted... +# Rest of option data is omitted... -- cgit v1.2.3 From 6e87315672b64f37f850add634946899e452af99 Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Wed, 19 Feb 2014 14:38:59 +0530 Subject: [2000] Update option code to be different from option length --- src/lib/dns/tests/rdata_opt_unittest.cc | 4 ++-- src/lib/dns/tests/testdata/rdata_opt_fromWire1 | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src/lib/dns') diff --git a/src/lib/dns/tests/rdata_opt_unittest.cc b/src/lib/dns/tests/rdata_opt_unittest.cc index 49d3068347..c5a10b9c07 100644 --- a/src/lib/dns/tests/rdata_opt_unittest.cc +++ b/src/lib/dns/tests/rdata_opt_unittest.cc @@ -37,7 +37,7 @@ class Rdata_OPT_Test : public RdataTest { const uint8_t rdata_opt_wiredata[] = { // Option code - 0x00, 0x03, + 0x00, 0x2a, // Option length 0x00, 0x03, // Option data @@ -197,7 +197,7 @@ TEST_F(Rdata_OPT_Test, getPseudoRRs) { const std::vector& rrs = rdf.getPseudoRRs(); ASSERT_FALSE(rrs.empty()); EXPECT_EQ(1, rrs.size()); - EXPECT_EQ(3, rrs.at(0).getCode()); + EXPECT_EQ(0x2a, rrs.at(0).getCode()); EXPECT_EQ(3, rrs.at(0).getLength()); const uint8_t expected_data[] = {0x00, 0x01, 0x02}; diff --git a/src/lib/dns/tests/testdata/rdata_opt_fromWire1 b/src/lib/dns/tests/testdata/rdata_opt_fromWire1 index f1005ef91b..f2eb680d0f 100644 --- a/src/lib/dns/tests/testdata/rdata_opt_fromWire1 +++ b/src/lib/dns/tests/testdata/rdata_opt_fromWire1 @@ -8,7 +8,7 @@ # 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 + 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 -- cgit v1.2.3 From f9daba2bfb0b915cd17d4330d47c991c18652d8d Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Wed, 19 Feb 2014 14:51:10 +0530 Subject: [2000] Add API documentation for specialized methods and PseudoRR class --- src/lib/dns/rdata/generic/opt_41.h | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'src/lib/dns') diff --git a/src/lib/dns/rdata/generic/opt_41.h b/src/lib/dns/rdata/generic/opt_41.h index 88f2b4c2f6..cc51977e3a 100644 --- a/src/lib/dns/rdata/generic/opt_41.h +++ b/src/lib/dns/rdata/generic/opt_41.h @@ -41,13 +41,25 @@ public: 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 >& 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: @@ -55,7 +67,22 @@ public: boost::shared_ptr > 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& getPseudoRRs() const; private: -- cgit v1.2.3 From c1c4ea8d1b7629dac379f192d30cc79535214236 Mon Sep 17 00:00:00 2001 From: Mukund Sivaraman Date: Wed, 19 Feb 2014 19:18:41 +0530 Subject: [2000] Stop using API that was removed --- src/lib/dns/tests/rdata_opt_unittest.cc | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) (limited to 'src/lib/dns') diff --git a/src/lib/dns/tests/rdata_opt_unittest.cc b/src/lib/dns/tests/rdata_opt_unittest.cc index c5a10b9c07..9d09a60656 100644 --- a/src/lib/dns/tests/rdata_opt_unittest.cc +++ b/src/lib/dns/tests/rdata_opt_unittest.cc @@ -23,12 +23,14 @@ #include #include +#include -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 { @@ -93,10 +95,8 @@ TEST_F(Rdata_OPT_Test, toWireBuffer) { obuffer.clear(); rdata_opt.toWire(obuffer); - EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, - obuffer.getData(), - obuffer.getLength(), - rdata_opt_wiredata, sizeof(rdata_opt_wiredata)); + matchWireData(rdata_opt_wiredata, sizeof(rdata_opt_wiredata), + obuffer.getData(), obuffer.getLength()); } TEST_F(Rdata_OPT_Test, toWireRenderer) { @@ -108,10 +108,8 @@ TEST_F(Rdata_OPT_Test, toWireRenderer) { renderer.clear(); rdata_opt.toWire(renderer); - EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, - renderer.getData(), - renderer.getLength(), - rdata_opt_wiredata, sizeof(rdata_opt_wiredata)); + matchWireData(rdata_opt_wiredata, sizeof(rdata_opt_wiredata), + renderer.getData(), renderer.getLength()); } TEST_F(Rdata_OPT_Test, toText) { @@ -182,10 +180,8 @@ TEST_F(Rdata_OPT_Test, appendPseudoRR) { obuffer.clear(); rdata_opt.toWire(obuffer); - EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, - obuffer.getData(), - obuffer.getLength(), - rdata_opt_wiredata2, sizeof(rdata_opt_wiredata2)); + matchWireData(rdata_opt_wiredata2, sizeof(rdata_opt_wiredata2), + obuffer.getData(), obuffer.getLength()); } TEST_F(Rdata_OPT_Test, getPseudoRRs) { -- cgit v1.2.3