diff options
author | Razvan Becheriu <razvan@isc.org> | 2024-03-01 19:37:15 +0100 |
---|---|---|
committer | Razvan Becheriu <razvan@isc.org> | 2024-03-07 12:42:05 +0100 |
commit | 561b90bee8e741369eb5b6b85c51a7a4d9add501 (patch) | |
tree | 37a4c2f82db5a9e19cc0db238c6271d392be22b9 /src/lib | |
parent | [#3270] Make Perfmon addSampleAndClear UT reliable (diff) | |
download | kea-561b90bee8e741369eb5b6b85c51a7a4d9add501.tar.xz kea-561b90bee8e741369eb5b6b85c51a7a4d9add501.zip |
[#3208] remove unused code in libdns
Diffstat (limited to 'src/lib')
208 files changed, 600 insertions, 38252 deletions
diff --git a/src/lib/d2srv/nc_trans.cc b/src/lib/d2srv/nc_trans.cc index bb13726bca..4b2baaf2aa 100644 --- a/src/lib/d2srv/nc_trans.cc +++ b/src/lib/d2srv/nc_trans.cc @@ -10,6 +10,7 @@ #include <d2srv/nc_trans.h> #include <dns/qid_gen.h> #include <dns/rdata.h> +#include <dns/rdataclass.h> #include <hooks/hooks.h> #include <hooks/hooks_manager.h> @@ -287,7 +288,7 @@ NameChangeTransaction::retryTransition(const int fail_to_state) { if (update_attempts_ < MAX_UPDATE_TRIES_PER_SERVER) { // Re-enter the current state with same server selected. transition(getCurrState(), SERVER_SELECTED_EVT); - } else { + } else { // Transition to given fail_to_state state if we are out // of retries. transition(fail_to_state, SERVER_IO_ERROR_EVT); @@ -571,7 +572,7 @@ NameChangeTransaction::getUpdateAttempts() const { const dns::RRType& NameChangeTransaction::getAddressRRType() const { - return (ncr_->isV4() ? dns::RRType::A() : dns::RRType::AAAA()); + return (ncr_->isV4() ? dns::RRType::A() : dns::RRType::AAAA()); } } // namespace isc::d2 diff --git a/src/lib/dns/Makefile.am b/src/lib/dns/Makefile.am index 67fb67e17a..feac9e3c22 100644 --- a/src/lib/dns/Makefile.am +++ b/src/lib/dns/Makefile.am @@ -23,77 +23,23 @@ EXTRA_DIST += rrtype-placeholder.h # NOTE: when an rdata file is added, please also add to this list: EXTRA_DIST += rdata/any_255/tsig_250.cc EXTRA_DIST += rdata/any_255/tsig_250.h -EXTRA_DIST += rdata/ch_3/a_1.cc -EXTRA_DIST += rdata/ch_3/a_1.h -EXTRA_DIST += rdata/generic/cname_5.cc -EXTRA_DIST += rdata/generic/cname_5.h -EXTRA_DIST += rdata/generic/detail/char_string.cc -EXTRA_DIST += rdata/generic/detail/char_string.h EXTRA_DIST += rdata/generic/detail/lexer_util.h -EXTRA_DIST += rdata/generic/detail/nsec_bitmap.cc -EXTRA_DIST += rdata/generic/detail/nsec_bitmap.h -EXTRA_DIST += rdata/generic/detail/nsec3param_common.cc -EXTRA_DIST += rdata/generic/detail/nsec3param_common.h -EXTRA_DIST += rdata/generic/detail/txt_like.h -EXTRA_DIST += rdata/generic/detail/ds_like.h -EXTRA_DIST += rdata/generic/dlv_32769.cc -EXTRA_DIST += rdata/generic/dlv_32769.h -EXTRA_DIST += rdata/generic/dname_39.cc -EXTRA_DIST += rdata/generic/dname_39.h -EXTRA_DIST += rdata/generic/dnskey_48.cc -EXTRA_DIST += rdata/generic/dnskey_48.h -EXTRA_DIST += rdata/generic/ds_43.cc -EXTRA_DIST += rdata/generic/ds_43.h -EXTRA_DIST += rdata/generic/hinfo_13.cc -EXTRA_DIST += rdata/generic/hinfo_13.h -EXTRA_DIST += rdata/generic/mx_15.cc -EXTRA_DIST += rdata/generic/mx_15.h -EXTRA_DIST += rdata/generic/naptr_35.cc -EXTRA_DIST += rdata/generic/naptr_35.h -EXTRA_DIST += rdata/generic/ns_2.cc -EXTRA_DIST += rdata/generic/ns_2.h -EXTRA_DIST += rdata/generic/nsec3_50.cc -EXTRA_DIST += rdata/generic/nsec3_50.h -EXTRA_DIST += rdata/generic/nsec3param_51.cc -EXTRA_DIST += rdata/generic/nsec3param_51.h -EXTRA_DIST += rdata/generic/nsec_47.cc -EXTRA_DIST += rdata/generic/nsec_47.h EXTRA_DIST += rdata/generic/opt_41.cc EXTRA_DIST += rdata/generic/opt_41.h EXTRA_DIST += rdata/generic/ptr_12.cc EXTRA_DIST += rdata/generic/ptr_12.h -EXTRA_DIST += rdata/generic/rp_17.cc -EXTRA_DIST += rdata/generic/rp_17.h EXTRA_DIST += rdata/generic/rrsig_46.cc EXTRA_DIST += rdata/generic/rrsig_46.h EXTRA_DIST += rdata/generic/soa_6.cc EXTRA_DIST += rdata/generic/soa_6.h -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/tkey_249.cc EXTRA_DIST += rdata/generic/tkey_249.h -EXTRA_DIST += rdata/generic/txt_16.cc -EXTRA_DIST += rdata/generic/txt_16.h -EXTRA_DIST += rdata/generic/minfo_14.cc -EXTRA_DIST += rdata/generic/minfo_14.h -EXTRA_DIST += rdata/generic/afsdb_18.cc -EXTRA_DIST += rdata/generic/afsdb_18.h -EXTRA_DIST += rdata/generic/caa_257.cc -EXTRA_DIST += rdata/generic/caa_257.h -EXTRA_DIST += rdata/hs_4/a_1.cc -EXTRA_DIST += rdata/hs_4/a_1.h EXTRA_DIST += rdata/in_1/a_1.cc EXTRA_DIST += rdata/in_1/a_1.h EXTRA_DIST += rdata/in_1/aaaa_28.cc EXTRA_DIST += rdata/in_1/aaaa_28.h EXTRA_DIST += rdata/in_1/dhcid_49.cc EXTRA_DIST += rdata/in_1/dhcid_49.h -EXTRA_DIST += rdata/in_1/srv_33.cc -EXTRA_DIST += rdata/in_1/srv_33.h EXTRA_DIST += rdata/template.cc EXTRA_DIST += rdata/template.h @@ -114,7 +60,6 @@ libkea_dns___la_SOURCES += edns.h edns.cc libkea_dns___la_SOURCES += exceptions.h exceptions.cc libkea_dns___la_SOURCES += master_lexer_inputsource.h master_lexer_inputsource.cc libkea_dns___la_SOURCES += labelsequence.h labelsequence.cc -libkea_dns___la_SOURCES += masterload.h masterload.cc libkea_dns___la_SOURCES += master_lexer.h master_lexer.cc libkea_dns___la_SOURCES += master_lexer_state.h libkea_dns___la_SOURCES += master_loader.h master_loader.cc @@ -122,17 +67,14 @@ libkea_dns___la_SOURCES += message.h message.cc libkea_dns___la_SOURCES += messagerenderer.h messagerenderer.cc libkea_dns___la_SOURCES += name.h name.cc libkea_dns___la_SOURCES += name_internal.h -libkea_dns___la_SOURCES += nsec3hash.h nsec3hash.cc libkea_dns___la_SOURCES += opcode.h opcode.cc libkea_dns___la_SOURCES += rcode.h rcode.cc libkea_dns___la_SOURCES += rdata.h rdata.cc -libkea_dns___la_SOURCES += rdatafields.h rdatafields.cc libkea_dns___la_SOURCES += rrclass.cc libkea_dns___la_SOURCES += rrparamregistry.h libkea_dns___la_SOURCES += rrset.h rrset.cc libkea_dns___la_SOURCES += rrttl.h rrttl.cc libkea_dns___la_SOURCES += rrtype.cc -libkea_dns___la_SOURCES += rrcollator.h rrcollator.cc libkea_dns___la_SOURCES += qid_gen.h qid_gen.cc libkea_dns___la_SOURCES += question.h question.cc libkea_dns___la_SOURCES += serial.h serial.cc @@ -140,20 +82,8 @@ libkea_dns___la_SOURCES += tsig.h tsig.cc libkea_dns___la_SOURCES += tsigerror.h tsigerror.cc libkea_dns___la_SOURCES += tsigkey.h tsigkey.cc libkea_dns___la_SOURCES += tsigrecord.h tsigrecord.cc -libkea_dns___la_SOURCES += master_loader_callbacks.h master_loader_callbacks.cc +libkea_dns___la_SOURCES += master_loader_callbacks.h libkea_dns___la_SOURCES += master_loader.h -libkea_dns___la_SOURCES += rrset_collection_base.h -libkea_dns___la_SOURCES += rrset_collection.h rrset_collection.cc -libkea_dns___la_SOURCES += zone_checker.h zone_checker.cc -libkea_dns___la_SOURCES += rdata_pimpl_holder.h -libkea_dns___la_SOURCES += rdata/generic/detail/char_string.h -libkea_dns___la_SOURCES += rdata/generic/detail/char_string.cc -libkea_dns___la_SOURCES += rdata/generic/detail/nsec_bitmap.h -libkea_dns___la_SOURCES += rdata/generic/detail/nsec_bitmap.cc -libkea_dns___la_SOURCES += rdata/generic/detail/nsec3param_common.cc -libkea_dns___la_SOURCES += rdata/generic/detail/nsec3param_common.h -libkea_dns___la_SOURCES += rdata/generic/detail/txt_like.h -libkea_dns___la_SOURCES += rdata/generic/detail/ds_like.h libkea_dns___la_CPPFLAGS = $(AM_CPPFLAGS) libkea_dns___la_LIBADD = $(top_builddir)/src/lib/cryptolink/libkea-cryptolink.la @@ -192,33 +122,25 @@ libdns___include_HEADERS = \ master_lexer_state.h \ master_loader.h \ master_loader_callbacks.h \ - masterload.h \ message.h \ messagerenderer.h \ name.h \ - nsec3hash.h \ opcode.h \ qid_gen.h \ question.h \ rcode.h \ rdata.h \ - rdata_pimpl_holder.h \ rdataclass.h \ - rdatafields.h \ rrclass.h \ - rrcollator.h \ rrparamregistry.h \ rrset.h \ - rrset_collection.h \ - rrset_collection_base.h \ rrttl.h \ rrtype.h \ serial.h \ tsig.h \ tsigerror.h \ tsigkey.h \ - tsigrecord.h \ - zone_checker.h + tsigrecord.h # Purposely not installing these headers: # name_internal.h: used only internally, and not actually DNS specific # rdata/*/detail/*.h: these are internal use only diff --git a/src/lib/dns/dns_fwd.h b/src/lib/dns/dns_fwd.h index 99dac37ded..5ba2802a7f 100644 --- a/src/lib/dns/dns_fwd.h +++ b/src/lib/dns/dns_fwd.h @@ -5,7 +5,7 @@ // file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef DNS_FWD_H -#define DNS_FWD_H 1 +#define DNS_FWD_H /// \file dns_fwd.h /// \brief Forward declarations for definitions of libdns++ @@ -16,41 +16,6 @@ namespace isc { namespace dns { - -class EDNS; -class Name; -class MasterLoader; -class MasterLoaderCallbacks; -class Message; -class AbstractMessageRenderer; -class MessageRenderer; -class NSEC3Hash; -class NSEC3HashCreator; -class Opcode; -class Question; -class Rcode; -namespace rdata { -class Rdata; -} -class RRCollator; -class RRClass; -class RRType; -class RRTTL; -class AbstractRRset; -class RdataIterator; -class RRsetCollectionBase; -class RRsetCollection; -class Serial; -class TSIGContext; -class TSIGError; -class TSIGKey; -class TSIGKeyRing; -class TSIGRecord; - } // namespace dns } // namespace isc #endif // DNS_FWD_H - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/edns.cc b/src/lib/dns/edns.cc index 49253cf222..3d9c21ac45 100644 --- a/src/lib/dns/edns.cc +++ b/src/lib/dns/edns.cc @@ -55,8 +55,7 @@ const uint32_t EXTFLAG_DO = 0x00008000; EDNS::EDNS(const uint8_t version) : version_(version), udp_size_(Message::DEFAULT_MAX_UDPSIZE), - dnssec_aware_(false) -{ + dnssec_aware_(false) { if (version_ > SUPPORTED_VERSION) { isc_throw(isc::InvalidParameter, "failed to construct EDNS: unsupported version: " << @@ -66,8 +65,7 @@ EDNS::EDNS(const uint8_t version) : EDNS::EDNS(const Name& name, const RRClass& rrclass, const RRType& rrtype, const RRTTL& ttl, const Rdata&) : - version_((ttl.getValue() & VERSION_MASK) >> VERSION_SHIFT) -{ + version_((ttl.getValue() & VERSION_MASK) >> VERSION_SHIFT) { if (rrtype != RRType::OPT()) { isc_throw(isc::InvalidParameter, "EDNS is being created with incompatible RR type: " @@ -109,8 +107,7 @@ template <typename Output> int toWireCommon(Output& output, const uint8_t version, const uint16_t udp_size, const bool dnssec_aware, - const uint8_t extended_rcode) -{ + const uint8_t extended_rcode) { // Render EDNS OPT RR uint32_t extrcode_flags = extended_rcode << EXTRCODE_SHIFT; extrcode_flags |= (version << VERSION_SHIFT) & VERSION_MASK; @@ -132,8 +129,7 @@ toWireCommon(Output& output, const uint8_t version, unsigned int EDNS::toWire(AbstractMessageRenderer& renderer, - const uint8_t extended_rcode) const -{ + const uint8_t extended_rcode) const { // If adding the OPT RR would exceed the size limit, don't do it. // 11 = len(".") + type(2byte) + class(2byte) + TTL(4byte) + RDLEN(2byte) // (RDATA is empty in this simple implementation) @@ -147,8 +143,7 @@ EDNS::toWire(AbstractMessageRenderer& renderer, unsigned int EDNS::toWire(isc::util::OutputBuffer& buffer, - const uint8_t extended_rcode) const -{ + const uint8_t extended_rcode) const { return (toWireCommon(buffer, version_, udp_size_, dnssec_aware_, extended_rcode)); } @@ -157,8 +152,7 @@ EDNS* createEDNSFromRR(const Name& name, const RRClass& rrclass, const RRType& rrtype, const RRTTL& ttl, const Rdata& rdata, - uint8_t& extended_rcode) -{ + uint8_t& extended_rcode) { // Create a new EDNS object first for exception guarantee. EDNS* edns = new EDNS(name, rrclass, rrtype, ttl, rdata); diff --git a/src/lib/dns/edns.h b/src/lib/dns/edns.h index d5e6375481..2415a52724 100644 --- a/src/lib/dns/edns.h +++ b/src/lib/dns/edns.h @@ -5,7 +5,9 @@ // file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EDNS_H -#define EDNS_H 1 +#define EDNS_H + +#include <util/buffer.h> #include <stdint.h> @@ -16,10 +18,6 @@ #include <dns/rdata.h> namespace isc { -namespace util { -class OutputBuffer; -} - namespace dns { class EDNS; @@ -431,7 +429,3 @@ std::ostream& operator<<(std::ostream& os, const EDNS& edns); } } #endif // EDNS_H - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/exceptions.h b/src/lib/dns/exceptions.h index 40f2cc1d87..76c464f9e6 100644 --- a/src/lib/dns/exceptions.h +++ b/src/lib/dns/exceptions.h @@ -10,7 +10,7 @@ // package. #ifndef DNS_EXCEPTIONS_H -#define DNS_EXCEPTIONS_H 1 +#define DNS_EXCEPTIONS_H #include <exceptions/exceptions.h> @@ -70,7 +70,3 @@ public: } } #endif // DNS_EXCEPTIONS_H - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/gen-rdatacode.py.in b/src/lib/dns/gen-rdatacode.py.in index f39fc095cf..e5284a3459 100644 --- a/src/lib/dns/gen-rdatacode.py.in +++ b/src/lib/dns/gen-rdatacode.py.in @@ -104,11 +104,6 @@ def import_classheader(class_txt, type_txt, type_code, file): continue if re.match('// BEGIN_ISC_NAMESPACE', line): content += 'namespace isc {\n' - content += 'namespace util {\n' - content += ''' -class InputBuffer; -class OutputBuffer;\n''' - content += '}\n\n' content += 'namespace dns {\n' continue if re.match('// BEGIN_RDATA_NAMESPACE', line): @@ -230,7 +225,7 @@ def generate_rdatahdr(file, heading, declarations, basemtime): return heading += ''' #ifndef DNS_RDATACLASS_H -#define DNS_RDATACLASS_H 1 +#define DNS_RDATACLASS_H #include <dns/master_loader.h> @@ -244,10 +239,6 @@ class MasterLoaderCallbacks; ''' declarations += ''' #endif // DNS_RDATACLASS_H - -// Local Variables: -// mode: c++ -// End: ''' rdata_header = open(file, 'w') rdata_header.write(heading) diff --git a/src/lib/dns/labelsequence.cc b/src/lib/dns/labelsequence.cc index 8e0be4390a..04f3bc2fe3 100644 --- a/src/lib/dns/labelsequence.cc +++ b/src/lib/dns/labelsequence.cc @@ -61,8 +61,7 @@ LabelSequence::LabelSequence(const void* buf) { } LabelSequence::LabelSequence(const LabelSequence& src, - uint8_t buf[MAX_SERIALIZED_LENGTH]) -{ + uint8_t buf[MAX_SERIALIZED_LENGTH]) { size_t data_len; const uint8_t *data = src.getData(&data_len); std::memcpy(buf, data, data_len); @@ -102,8 +101,7 @@ namespace { // - beginning of buffer is on or after ep bool isOutOfRange(const uint8_t* bp, const uint8_t* ep, - const uint8_t* buf, size_t buf_len) -{ + const uint8_t* buf, size_t buf_len) { return (bp >= buf + buf_len || // end of buffer is before bp ep <= buf); // beginning of buffer is on or after ep } @@ -167,8 +165,7 @@ LabelSequence::equals(const LabelSequence& other, bool case_sensitive) const { NameComparisonResult LabelSequence::compare(const LabelSequence& other, - bool case_sensitive) const -{ + bool case_sensitive) const { // Determine the relative ordering under the DNSSEC order relation of // 'this' and 'other', and also determine the hierarchical relationship // of the labels. @@ -418,8 +415,7 @@ LabelSequence::toText() const { void LabelSequence::extend(const LabelSequence& labels, - uint8_t buf[MAX_SERIALIZED_LENGTH]) -{ + uint8_t buf[MAX_SERIALIZED_LENGTH]) { // collect data to perform steps before anything is changed size_t label_count = last_label_ + 1; // Since we may have been stripped, do not use getDataLength(), but diff --git a/src/lib/dns/labelsequence.h b/src/lib/dns/labelsequence.h index 91dbe591a2..20dfec5114 100644 --- a/src/lib/dns/labelsequence.h +++ b/src/lib/dns/labelsequence.h @@ -5,7 +5,7 @@ // file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef LABELSEQUENCE_H -#define LABELSEQUENCE_H 1 +#define LABELSEQUENCE_H #include <dns/name.h> #include <util/buffer.h> @@ -65,8 +65,8 @@ public: data_(&name.ndata_[0]), offsets_(&name.offsets_[0]), first_label_(0), - last_label_(name.getLabelCount() - 1) - {} + last_label_(name.getLabelCount() - 1) { + } /// \brief Constructor from serialized image. /// @@ -126,8 +126,8 @@ public: data_(ls.data_), offsets_(ls.offsets_), first_label_(ls.first_label_), - last_label_(ls.last_label_) - {} + last_label_(ls.last_label_) { + } /// \brief Assignment operator. /// @@ -450,7 +450,3 @@ LabelSequence::WILDCARD() { } // end namespace isc #endif - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/master_lexer.cc b/src/lib/dns/master_lexer.cc index 8853a168ea..d157aa0d10 100644 --- a/src/lib/dns/master_lexer.cc +++ b/src/lib/dns/master_lexer.cc @@ -12,7 +12,6 @@ #include <dns/master_lexer_inputsource.h> #include <dns/master_lexer_state.h> -#include <boost/shared_ptr.hpp> #include <boost/lexical_cast.hpp> #include <bitset> @@ -38,15 +37,13 @@ typedef boost::shared_ptr<master_lexer_internal::InputSource> InputSourcePtr; } // end unnamed namespace using namespace master_lexer_internal; - struct MasterLexer::MasterLexerImpl { MasterLexerImpl() : source_(NULL), token_(MasterToken::NOT_STARTED), total_size_(0), popped_size_(0), paren_count_(0), last_was_eol_(true), has_previous_(false), previous_paren_count_(0), - previous_was_eol_(false) - { + previous_was_eol_(false) { separators_.set('\r'); separators_.set('\n'); separators_.set(' '); @@ -130,7 +127,6 @@ MasterLexer::MasterLexer() : impl_(new MasterLexerImpl()) { } MasterLexer::~MasterLexer() { - delete impl_; } bool diff --git a/src/lib/dns/master_lexer.h b/src/lib/dns/master_lexer.h index 9ed4e813e6..0965aa1c1f 100644 --- a/src/lib/dns/master_lexer.h +++ b/src/lib/dns/master_lexer.h @@ -5,7 +5,7 @@ // file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef MASTER_LEXER_H -#define MASTER_LEXER_H 1 +#define MASTER_LEXER_H #include <dns/exceptions.h> @@ -15,6 +15,7 @@ #include <stdint.h> #include <boost/noncopyable.hpp> +#include <boost/shared_ptr.hpp> namespace isc { namespace dns { @@ -125,8 +126,7 @@ public: /// \param str_len The size of the string in bytes /// \param quoted true if it's a quoted string; false otherwise. MasterToken(const char* str_beg, size_t str_len, bool quoted = false) : - type_(quoted ? QSTRING : STRING) - { + type_(quoted ? QSTRING : STRING) { val_.str_region_.beg = str_beg; val_.str_region_.len = str_len; } @@ -154,7 +154,9 @@ public: /// \brief Return the token type. /// /// \throw none - Type getType() const { return (type_); } + Type getType() const { + return (type_); + } /// \brief Return the value of a string-variant token. /// @@ -656,7 +658,7 @@ public: private: struct MasterLexerImpl; - MasterLexerImpl* impl_; + boost::shared_ptr<MasterLexerImpl> impl_; }; /// \brief Operator to combine \c MasterLexer options @@ -672,7 +674,3 @@ operator|(MasterLexer::Options o1, MasterLexer::Options o2) { } // namespace dns } // namespace isc #endif // MASTER_LEXER_H - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/master_lexer_inputsource.cc b/src/lib/dns/master_lexer_inputsource.cc index 841fc6c1bb..1a1058fdfe 100644 --- a/src/lib/dns/master_lexer_inputsource.cc +++ b/src/lib/dns/master_lexer_inputsource.cc @@ -90,8 +90,8 @@ InputSource::InputSource(std::istream& input_stream) : total_pos_(0), name_(createStreamName(input_stream)), input_(input_stream), - input_size_(getStreamSize(input_)) -{} + input_size_(getStreamSize(input_)) { +} namespace { // A helper to initialize InputSource::input_ in the member initialization @@ -122,11 +122,10 @@ InputSource::InputSource(const char* filename) : total_pos_(0), name_(filename), input_(openFileStream(file_stream_, filename)), - input_size_(getStreamSize(input_)) -{} + input_size_(getStreamSize(input_)) { +} -InputSource::~InputSource() -{ +InputSource::~InputSource() { if (file_stream_.is_open()) { file_stream_.close(); } diff --git a/src/lib/dns/master_lexer_inputsource.h b/src/lib/dns/master_lexer_inputsource.h index d830239c98..12a75757b7 100644 --- a/src/lib/dns/master_lexer_inputsource.h +++ b/src/lib/dns/master_lexer_inputsource.h @@ -5,7 +5,7 @@ // file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef DNS_INPUTSOURCE_H -#define DNS_INPUTSOURCE_H 1 +#define DNS_INPUTSOURCE_H #include <exceptions/exceptions.h> @@ -87,7 +87,9 @@ public: /// the size of sources and for when the size can be unknown. /// /// \throw None - size_t getSize() const { return (input_size_); } + size_t getSize() const { + return (input_size_); + } /// \brief Returns the current read position in the input source. /// @@ -105,7 +107,9 @@ public: /// values may not always monotonically increase. /// /// \throw None - size_t getPosition() const { return (total_pos_); } + size_t getPosition() const { + return (total_pos_); + } /// \brief Returns if the input source is at end of file. bool atEOF() const { @@ -179,7 +183,3 @@ private: } // namespace isc #endif // DNS_INPUTSOURCE_H - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/master_lexer_state.h b/src/lib/dns/master_lexer_state.h index d328a70918..b62a366cb2 100644 --- a/src/lib/dns/master_lexer_state.h +++ b/src/lib/dns/master_lexer_state.h @@ -5,7 +5,7 @@ // file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef MASTER_LEXER_STATE_H -#define MASTER_LEXER_STATE_H 1 +#define MASTER_LEXER_STATE_H #include <dns/master_lexer.h> @@ -124,7 +124,7 @@ protected: /// \return A pointer to the implementation class object of the given /// lexer. This is never NULL. MasterLexer::MasterLexerImpl* getLexerImpl(MasterLexer& lexer) const { - return (lexer.impl_); + return (lexer.impl_.get()); } }; @@ -132,7 +132,3 @@ protected: } // namespace dns } // namespace isc #endif // MASTER_LEXER_STATE_H - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/master_loader.cc b/src/lib/dns/master_loader.cc index 50c34f90d7..f10cac0eda 100644 --- a/src/lib/dns/master_loader.cc +++ b/src/lib/dns/master_loader.cc @@ -99,8 +99,8 @@ public: complete_(false), seen_error_(false), warn_rfc1035_ttl_(true), - rr_count_(0) - {} + rr_count_(0) { + } /// \brief Wrapper around \c MasterLexer::pushSource() (file version) /// @@ -147,11 +147,15 @@ public: /// \brief Return the total size of the input sources pushed so /// far. See \c MasterLexer::getTotalSourceSize(). - size_t getSize() const { return (lexer_.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()); } + size_t getPosition() const { + return (lexer_.getPosition()); + } private: /// \brief Report an error using the callbacks that were supplied @@ -159,8 +163,7 @@ private: /// 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) - { + const std::string& reason) { seen_error_ = true; callbacks_.error(filename, line, reason); if (!many_errors_) { @@ -634,8 +637,7 @@ genNibbles(int num, unsigned int width, bool uppercase) { std::string MasterLoader::MasterLoaderImpl::generateForIter(const std::string& str, - const int num) -{ + const int num) { std::string rstr; for (auto it = str.begin(); it != str.end();) { @@ -1017,13 +1019,12 @@ MasterLoader::MasterLoader(const char* master_file, const RRClass& zone_class, const MasterLoaderCallbacks& callbacks, const AddRRCallback& add_callback, - Options options) -{ + Options options) { if (!add_callback) { isc_throw(isc::InvalidParameter, "Empty add RR callback"); } - impl_ = new MasterLoaderImpl(master_file, zone_origin, - zone_class, callbacks, add_callback, options); + impl_.reset(new MasterLoaderImpl(master_file, zone_origin, + zone_class, callbacks, add_callback, options)); } MasterLoader::MasterLoader(std::istream& stream, @@ -1031,20 +1032,18 @@ MasterLoader::MasterLoader(std::istream& stream, const RRClass& zone_class, const MasterLoaderCallbacks& callbacks, const AddRRCallback& add_callback, - Options options) -{ + Options options) { if (!add_callback) { isc_throw(isc::InvalidParameter, "Empty add RR callback"); } - unique_ptr<MasterLoaderImpl> + boost::shared_ptr<MasterLoaderImpl> impl(new MasterLoaderImpl("", zone_origin, zone_class, callbacks, add_callback, options)); impl->pushStreamSource(stream); - impl_ = impl.release(); + impl_ = impl; } MasterLoader::~MasterLoader() { - delete impl_; } bool diff --git a/src/lib/dns/master_loader.h b/src/lib/dns/master_loader.h index b385806ad8..48d26664d5 100644 --- a/src/lib/dns/master_loader.h +++ b/src/lib/dns/master_loader.h @@ -7,9 +7,11 @@ #ifndef MASTER_LOADER_H #define MASTER_LOADER_H +#include <dns/exceptions.h> #include <dns/master_loader_callbacks.h> #include <boost/noncopyable.hpp> +#include <boost/shared_ptr.hpp> namespace isc { namespace dns { @@ -174,14 +176,10 @@ public: private: class MasterLoaderImpl; - MasterLoaderImpl* impl_; + boost::shared_ptr<MasterLoaderImpl> impl_; }; } // end namespace dns } // end namespace isc #endif // MASTER_LOADER_H - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/master_loader_callbacks.cc b/src/lib/dns/master_loader_callbacks.cc deleted file mode 100644 index 088a223c31..0000000000 --- a/src/lib/dns/master_loader_callbacks.cc +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (C) 2012-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#include <config.h> - -#include <dns/master_loader_callbacks.h> - -#include <string> - -namespace isc { -namespace dns { - -namespace { -void -nullCallback(const std::string&, size_t, const std::string&) { -} -} - -MasterLoaderCallbacks -MasterLoaderCallbacks::getNullCallbacks() { - return (MasterLoaderCallbacks(nullCallback, nullCallback)); -} - -} // end namespace dns -} // end namespace isc diff --git a/src/lib/dns/master_loader_callbacks.h b/src/lib/dns/master_loader_callbacks.h index a73168569f..cfc2e21966 100644 --- a/src/lib/dns/master_loader_callbacks.h +++ b/src/lib/dns/master_loader_callbacks.h @@ -72,8 +72,7 @@ public: MasterLoaderCallbacks(const IssueCallback& error, const IssueCallback& warning) : error_(error), - warning_(warning) - { + warning_(warning) { if (!error_ || !warning_) { isc_throw(isc::InvalidParameter, "Empty function passed as callback"); @@ -92,8 +91,7 @@ public: /// If the caller of the loader wants to abort, it is possible to throw /// from the callback, which aborts the load. void error(const std::string& source_name, size_t source_line, - const std::string& reason) const - { + const std::string& reason) const { error_(source_name, source_line, reason); } @@ -109,23 +107,12 @@ public: /// may be false positives), it is possible to throw from inside the /// callback. void warning(const std::string& source_name, size_t source_line, - const std::string& reason) const - { + const std::string& reason) const { warning_(source_name, source_line, reason); } - - /// \brief Return a callbacks instance with null callbacks - /// - /// This is a convenience wrapper to generate a - /// \c MasterLoaderCallbacks object with both callbacks being nothing. - /// This will be useful for applications that only need to run - /// \c MasterLoader and get the end result. - /// - /// \throw None - static MasterLoaderCallbacks getNullCallbacks(); - private: - const IssueCallback error_, warning_; + const IssueCallback error_; + const IssueCallback warning_; }; } diff --git a/src/lib/dns/masterload.cc b/src/lib/dns/masterload.cc deleted file mode 100644 index 94638c17ae..0000000000 --- a/src/lib/dns/masterload.cc +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright (C) 2010-2020 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#include <config.h> - -#include <dns/masterload.h> -#include <dns/master_loader.h> -#include <dns/name.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> -#include <dns/rrclass.h> -#include <dns/rrset.h> -#include <dns/rrttl.h> -#include <dns/rrtype.h> -#include <dns/rrcollator.h> -#include <exceptions/exceptions.h> - -#include <boost/scoped_ptr.hpp> - -#include <functional> -#include <istream> -#include <fstream> -#include <sstream> -#include <string> -#include <cctype> -#include <cerrno> - -using namespace isc::dns::rdata; - -using namespace std; -namespace ph = std::placeholders; - -namespace isc { -namespace dns { -namespace { -void -callbackWrapper(const RRsetPtr& rrset, MasterLoadCallback callback, - const Name* origin) -{ - // Origin related validation: - // - reject out-of-zone data - // - reject SOA whose owner is not at the top of zone - const NameComparisonResult cmp_result = - rrset->getName().compare(*origin); - if (cmp_result.getRelation() != NameComparisonResult::EQUAL && - cmp_result.getRelation() != NameComparisonResult::SUBDOMAIN) { - isc_throw(MasterLoadError, "Out-of-zone data for " << *origin - << "/" << rrset->getClass() << ": " << rrset->getName()); - } - if (rrset->getType() == RRType::SOA() && - cmp_result.getRelation() != NameComparisonResult::EQUAL) { - isc_throw(MasterLoadError, "SOA not at top of zone: " - << *rrset); - } - - callback(rrset); -} - -template <typename InputType> -void -loadHelper(InputType input, const Name& origin, - const RRClass& zone_class, MasterLoadCallback callback) -{ - RRCollator rr_collator(std::bind(callbackWrapper, ph::_1, callback, - &origin)); - MasterLoader loader(input, origin, zone_class, - MasterLoaderCallbacks::getNullCallbacks(), - rr_collator.getCallback()); - try { - loader.load(); - } catch (const MasterLoaderError& ex) { - isc_throw(MasterLoadError, ex.what()); - } - rr_collator.flush(); -} -} - -void -masterLoad(const char* const filename, const Name& origin, - const RRClass& zone_class, MasterLoadCallback callback) -{ - if ((filename == NULL) || (*filename == '\0')) { - isc_throw(MasterLoadError, "Name of master file must not be null"); - } - - loadHelper<const char*>(filename, origin, zone_class, callback); -} - -void -masterLoad(istream& input, const Name& origin, const RRClass& zone_class, - MasterLoadCallback callback, const char*) -{ - loadHelper<istream&>(input, origin, zone_class, callback); -} - -} // namespace dns -} // namespace isc diff --git a/src/lib/dns/masterload.h b/src/lib/dns/masterload.h deleted file mode 100644 index 3762d54e47..0000000000 --- a/src/lib/dns/masterload.h +++ /dev/null @@ -1,175 +0,0 @@ -// Copyright (C) 2010-2020 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef MASTERLOAD_H -#define MASTERLOAD_H 1 - -#include <dns/rrset.h> -#include <exceptions/exceptions.h> - -#include <functional> -#include <iosfwd> - -namespace isc { -namespace dns { -class Name; -class RRClass; - -/// \brief An exception that is thrown if an error occurs while loading a -/// master zone data. -class MasterLoadError : public isc::Exception { -public: - MasterLoadError(const char* file, size_t line, const char* what) : - isc::Exception(file, line, what) {} -}; - -/// The type of the \c callback parameter of \c masterLoad(). -/// -/// This represents a functor object or a function that takes one parameter -/// of type \c RRsetPtr and returns nothing. -typedef std::function<void(RRsetPtr)> MasterLoadCallback; - -/// -/// \name Master zone file loader functions. -/// -//@{ -/// Master zone file loader from a file. -/// -/// This function parses a given file as a master DNS zone file for -/// the given origin name and RR class, constructs a sequence of \c RRset -/// from the RRs containing in the file, and calls the given \c callback -/// functor object or function with each \c RRset. -/// -/// The \c callback parameter is a functor object or a function that -/// takes one parameter of type \c RRsetPtr and returns nothing, -/// i.e. \c void (see below for specific examples). -/// More precisely, it can be anything that this form of std::function -/// can represent, but the caller normally doesn't have to care about -/// that level of details. -/// -/// The ownership of constructed RRsets is transferred to the callback -/// and this function never uses it once it is called. -/// The callback can freely modify the passed \c RRset. -/// -/// This function internally uses the MasterLoader class, and basically -/// accepts and rejects input that MasterLoader accepts and rejects, -/// accordingly. In addition, this function performs the following validation: -/// if an SOA RR is included, its owner name must be the origin name. -/// -/// It does not perform other semantical checks, however. For example, -/// it doesn't check if an NS RR of the origin name is included or if -/// there is more than one SOA RR. Such further checks are the caller's -/// (or the callback's) responsibility. -/// -/// <b>Exceptions</b> -/// -/// This function throws an exception of class \c MasterLoadError in the -/// following cases: -/// - Any of the validation checks fails (see above). -/// - The input data has a syntax error. -/// - The specified file cannot be opened for loading. -/// - An I/O error occurs during the loading. -/// -/// In addition, this function requires resource allocation for parsing and -/// constructing RRsets. If it fails, the corresponding standard exception -/// will be thrown. -/// -/// The callback may throw its own function. This function doesn't catch it -/// and will simply propagate it towards the caller. -/// -/// <b>Usage Examples</b> -/// -/// A simplest example usage of this function would be to parse a zone -/// file and (after validation) dump the content to the standard output. -/// This is an example functor object and a call to \c masterLoad -/// that implements this scenario: -/// \code struct ZoneDumper { -/// void operator()(ConstRRsetPtr rrset) const { -/// std::cout << *rrset; -/// } -/// }; -/// ... -/// masterLoad(zone_file, Name("example.com"), RRClass::IN(), ZoneDumper()); -/// \endcode -/// Alternatively, you can use a normal function instead of a functor: -/// \code void zoneDumper(ConstRRsetPtr rrset) { -/// std::cout << *rrset; -/// } -/// ... -/// masterLoad(zone_file, Name("example.com"), RRClass::IN(), zoneDumper); -/// \endcode -/// Or, if you want to use it with a member function of some other class, -/// wrapping things with \c std::bind would be handy: -/// \code class ZoneDumper { -/// public: -/// void dump(ConstRRsetPtr rrset) const { -/// std::cout << *rrset; -/// } -/// }; -/// ... -/// ZoneDumper dumper; -/// masterLoad(rr_stream, Name("example.com"), RRClass::IN(), -/// std::bind(&ZoneDumper::dump, &dumper, _1)); -/// \endcode -/// You can find a bit more complicated examples in the unit tests code for -/// this function. -/// -/// <b>Implementation Notes</b> -/// -/// The current implementation is in a preliminary level and needs further -/// extensions. Some design decisions may also have to be reconsidered as -/// we gain experiences. Those include: -/// - We may want to allow optional conditions. For example, we may want to -/// be generous about some validation failures and be able to continue -/// parsing. -/// - Especially if we allow to be generous, we may also want to support -/// returning an error code instead of throwing an exception when we -/// encounter validation failure. -/// - RRSIGs are handled as separate RRsets, i.e. they are not included in -/// the RRset they cover. -/// -/// \param filename A path to a master zone file to be loaded. -/// \param origin The origin name of the zone. -/// \param zone_class The RR class of the zone. -/// \param callback A callback functor or function that is to be called -/// for each RRset. -void masterLoad(const char* const filename, const Name& origin, - const RRClass& zone_class, MasterLoadCallback callback); - -/// Master zone file loader from input stream. -/// -/// This function is same as the other version -/// (\c masterLoad(const char* const, const Name&, const RRClass&, MasterLoadCallback)) -/// except that it takes a \c std::istream instead of a file. -/// It extracts lines from the stream and handles each line just as a line -/// of a file for the other version of function. -/// All descriptions of the other version apply to this version except those -/// specific to file I/O. -/// -/// Note: The 'source' parameter is now ignored, but it was only used in -/// exception messages on some error. So the compatibility effect should be -/// minimal. -/// -/// \param input An input stream object that is to emit zone's RRs. -/// \param origin The origin name of the zone. -/// \param zone_class The RR class of the zone. -/// \param callback A callback functor or function that is to be called for -/// each RRset. -/// \param source This parameter is now ignored but left for compatibility. -void masterLoad(std::istream& input, const Name& origin, - const RRClass& zone_class, MasterLoadCallback callback, - const char* source = NULL); -} - - -//@} -} - -#endif // MASTERLOAD_H - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/message.h b/src/lib/dns/message.h index df5ba62674..2a4ecf579a 100644 --- a/src/lib/dns/message.h +++ b/src/lib/dns/message.h @@ -5,7 +5,7 @@ // file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef MESSAGE_H -#define MESSAGE_H 1 +#define MESSAGE_H #include <stdint.h> @@ -14,16 +14,13 @@ #include <ostream> #include <dns/exceptions.h> +#include <util/buffer.h> #include <dns/edns.h> #include <dns/question.h> #include <dns/rrset.h> namespace isc { -namespace util { -class InputBuffer; -} - namespace dns { class TSIGContext; class TSIGRecord; @@ -643,8 +640,7 @@ public: /// \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); + void fromWire(isc::util::InputBuffer& buffer, ParseOptions options = PARSE_DEFAULT); /// /// \name Protocol constants diff --git a/src/lib/dns/messagerenderer.cc b/src/lib/dns/messagerenderer.cc index 5c84f78244..fcef95c9aa 100644 --- a/src/lib/dns/messagerenderer.cc +++ b/src/lib/dns/messagerenderer.cc @@ -38,8 +38,8 @@ namespace { // hide internal-only names from the public namespaces /// the buffer. struct OffsetItem { OffsetItem(size_t hash, size_t pos, size_t len) : - hash_(hash), pos_(pos), len_(len) - {} + hash_(hash), pos_(pos), len_(len) { + } /// The hash value for the stored name calculated by LabelSequence.getHash. /// This will help make name comparison in \c NameCompare more efficient. @@ -71,8 +71,8 @@ struct NameCompare { /// \param hash The hash value for the name. NameCompare(const OutputBuffer& buffer, InputBuffer& name_buf, size_t hash) : - buffer_(&buffer), name_buf_(&name_buf), hash_(hash) - {} + buffer_(&buffer), name_buf_(&name_buf), hash_(hash) { + } bool operator()(const OffsetItem& item) const { // Trivial inequality check. If either the hash or the total length @@ -112,8 +112,7 @@ struct NameCompare { private: static uint16_t nextPosition(const OutputBuffer& buffer, - uint16_t pos, uint16_t& llen) - { + uint16_t pos, uint16_t& llen) { if (llen == 0) { size_t i = 0; @@ -164,8 +163,7 @@ struct MessageRenderer::MessageRendererImpl { /// \brief Constructor MessageRendererImpl() : msglength_limit_(512), truncated_(false), - compress_mode_(MessageRenderer::CASE_INSENSITIVE) - { + compress_mode_(MessageRenderer::CASE_INSENSITIVE) { // Reserve some spaces for hash table items. for (size_t i = 0; i < BUCKETS; ++i) { table_[i].reserve(RESERVED_ITEMS); @@ -173,8 +171,7 @@ struct MessageRenderer::MessageRendererImpl { } uint16_t findOffset(const OutputBuffer& buffer, InputBuffer& name_buf, - size_t hash, bool case_sensitive) const - { + size_t hash, bool case_sensitive) const { // Find a matching entry, if any. We use some heuristics here: often // the same name appears consecutively (like repeating the same owner // name for a single RRset), so in case there's a collision in the @@ -224,7 +221,6 @@ MessageRenderer::MessageRenderer() : } MessageRenderer::~MessageRenderer() { - delete impl_; } void @@ -363,8 +359,7 @@ MessageRenderer::writeName(const Name& name, const bool compress) { } AbstractMessageRenderer::AbstractMessageRenderer() : - local_buffer_(0), buffer_(&local_buffer_) -{ + local_buffer_(0), buffer_(&local_buffer_) { } void diff --git a/src/lib/dns/messagerenderer.h b/src/lib/dns/messagerenderer.h index 1b8b9c0f96..d63bbd7ea5 100644 --- a/src/lib/dns/messagerenderer.h +++ b/src/lib/dns/messagerenderer.h @@ -5,10 +5,11 @@ // file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef MESSAGERENDERER_H -#define MESSAGERENDERER_H 1 +#define MESSAGERENDERER_H #include <util/buffer.h> +#include <boost/shared_ptr.hpp> #include <boost/noncopyable.hpp> namespace isc { @@ -384,7 +385,7 @@ public: private: struct MessageRendererImpl; - MessageRendererImpl* impl_; + boost::shared_ptr<MessageRendererImpl> impl_; }; } } diff --git a/src/lib/dns/name.cc b/src/lib/dns/name.cc index 2d85d38e1c..addac4fa8e 100644 --- a/src/lib/dns/name.cc +++ b/src/lib/dns/name.cc @@ -14,8 +14,6 @@ #include <algorithm> #include <exceptions/isc_assert.h> -#include <util/buffer.h> -#include <dns/exceptions.h> #include <dns/name.h> #include <dns/name_internal.h> #include <dns/messagerenderer.h> @@ -23,7 +21,6 @@ using namespace std; using namespace isc::util; -using isc::dns::NameComparisonResult; using namespace isc::dns::name::internal; namespace isc { @@ -311,8 +308,7 @@ Name::Name(const std::string &namestring, bool downcase) { } Name::Name(const char* namedata, size_t data_len, const Name* origin, - bool downcase) -{ + bool downcase) { // Check validity of data if (namedata == NULL || data_len == 0) { isc_throw(isc::InvalidParameter, diff --git a/src/lib/dns/name.h b/src/lib/dns/name.h index 0720684097..226fa79995 100644 --- a/src/lib/dns/name.h +++ b/src/lib/dns/name.h @@ -5,7 +5,10 @@ // file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef NAME_H -#define NAME_H 1 +#define NAME_H + +#include <util/buffer.h> +#include <dns/messagerenderer.h> #include <stdint.h> @@ -15,14 +18,7 @@ #include <dns/exceptions.h> namespace isc { -namespace util { -class InputBuffer; -class OutputBuffer; -} - namespace dns { -class AbstractMessageRenderer; - /// /// \brief A standard DNS module exception that is thrown if the name parser /// encounters an empty label in the middle of a name. @@ -760,7 +756,3 @@ operator<<(std::ostream& os, const Name& name); } } #endif // NAME_H - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/name_internal.h b/src/lib/dns/name_internal.h index 8be55ec1d8..9864622e53 100644 --- a/src/lib/dns/name_internal.h +++ b/src/lib/dns/name_internal.h @@ -5,7 +5,7 @@ // file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef NAME_INTERNAL_H -#define NAME_INTERNAL_H 1 +#define NAME_INTERNAL_H // This is effectively a "private" namespace for the Name class implementation, // but exposed publicly so the definitions in it can be shared with other diff --git a/src/lib/dns/nsec3hash.cc b/src/lib/dns/nsec3hash.cc deleted file mode 100644 index 83e7d70c78..0000000000 --- a/src/lib/dns/nsec3hash.cc +++ /dev/null @@ -1,270 +0,0 @@ -// Copyright (C) 2012-2024 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#include <config.h> - -#include <stdint.h> - -#include <cassert> -#include <cstring> -#include <cstdlib> -#include <string> -#include <vector> - -#include <boost/noncopyable.hpp> -#include <boost/scoped_ptr.hpp> - -#include <exceptions/exceptions.h> - -#include <util/buffer.h> -#include <util/encode/encode.h> - -#include <cryptolink/cryptolink.h> -#include <cryptolink/crypto_hash.h> - -#include <dns/name.h> -#include <dns/labelsequence.h> -#include <dns/nsec3hash.h> -#include <dns/rdataclass.h> -#include <dns/name_internal.h> - -using namespace std; -using namespace isc::util; -using namespace isc::util::encode; -using namespace isc::cryptolink; -using namespace isc::dns; -using namespace isc::dns::rdata; - -namespace { - -/// \brief A derived class of \c NSEC3Hash that implements the standard hash -/// calculation specified in RFC5155. -/// -/// Currently the only pre-defined algorithm in the RFC is SHA1. So we don't -/// over-generalize it at the moment, and rather hardcode it and assume that -/// specific algorithm. -/// -/// The implementation details are only open within this file, but to avoid -/// an accidental error in this implementation we explicitly make it non -/// copyable. -class NSEC3HashRFC5155 : boost::noncopyable, public NSEC3Hash { -private: - // This is the algorithm number for SHA1/NSEC3 as defined in RFC5155. - static const uint8_t NSEC3_HASH_SHA1 = 1; - // For digest_ allocation - static const size_t DEFAULT_DIGEST_LENGTH = 32; - -public: - NSEC3HashRFC5155(uint8_t algorithm, uint16_t iterations, - const uint8_t* salt_data, size_t salt_length) : - algorithm_(algorithm), iterations_(iterations), - salt_data_(NULL), salt_length_(salt_length), - digest_(DEFAULT_DIGEST_LENGTH), obuf_(Name::MAX_WIRE) { - if (algorithm_ != NSEC3_HASH_SHA1) { - isc_throw(UnknownNSEC3HashAlgorithm, "Unknown NSEC3 algorithm: " << - static_cast<unsigned int>(algorithm_)); - } - - if (salt_length > 0) { - if (salt_data == NULL) { - isc_throw(isc::BadValue, "salt data is NULL"); - } - salt_data_ = static_cast<uint8_t*>(std::malloc(salt_length)); - if (salt_data_ == NULL) { - throw std::bad_alloc(); - } - std::memcpy(salt_data_, salt_data, salt_length); - } - } - - virtual ~NSEC3HashRFC5155() { - std::free(salt_data_); - } - - 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; - bool match(uint8_t algorithm, uint16_t iterations, - const vector<uint8_t>& salt) const; - -private: - std::string calculateForWiredata(const uint8_t* data, size_t length) const; - - const uint8_t algorithm_; - const uint16_t iterations_; - uint8_t* salt_data_; - const size_t salt_length_; - - // The following members are placeholder of work place and don't hold - // any state over multiple calls so can be mutable without breaking - // constness. - mutable OutputBuffer digest_; - mutable vector<uint8_t> vdigest_; - mutable OutputBuffer obuf_; -}; - -inline void -iterateSHA1(const uint8_t* input, size_t inlength, - const uint8_t* salt, size_t saltlen, - OutputBuffer& output) -{ - boost::scoped_ptr<Hash> hash(CryptoLink::getCryptoLink().createHash(SHA1)); - hash->update(input, inlength); - hash->update(salt, saltlen); // this works whether saltlen == or > 0 - hash->final(output, hash->getOutputLength()); -} - -string -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. - - uint8_t name_buf[256]; - assert(length < sizeof (name_buf)); - - const uint8_t *p1 = data; - uint8_t *p2 = name_buf; - while (*p1 != 0) { - char len = *p1; - - *p2++ = *p1++; - while (len--) { - *p2++ = isc::dns::name::internal::maptolower[*p1++]; - } - } - - *p2 = *p1; - - digest_.clear(); - iterateSHA1(name_buf, length, - salt_data_, salt_length_, digest_); - const uint8_t* dgst_data = static_cast<const uint8_t*>(digest_.getData()); - size_t dgst_len = digest_.getLength(); - for (unsigned int n = 0; n < iterations_; ++n) { - digest_.clear(); - iterateSHA1(dgst_data, dgst_len, salt_data_, salt_length_, digest_); - } - - vdigest_.resize(dgst_len); - std::memcpy(&vdigest_[0], dgst_data, dgst_len); - return (encodeBase32Hex(vdigest_)); -} - -string -NSEC3HashRFC5155::calculate(const Name& name) const { - obuf_.clear(); - name.toWire(obuf_); - - return (calculateForWiredata(static_cast<const uint8_t*>(obuf_.getData()), - obuf_.getLength())); -} - -string -NSEC3HashRFC5155::calculate(const LabelSequence& ls) const { - assert(ls.isAbsolute()); - - size_t length; - const uint8_t* data = ls.getData(&length); - - return (calculateForWiredata(data, length)); -} - -bool -NSEC3HashRFC5155::match(uint8_t algorithm, uint16_t iterations, - const vector<uint8_t>& salt) const -{ - return (algorithm_ == algorithm && iterations_ == iterations && - salt_length_ == salt.size() && - ((salt_length_ == 0) || - memcmp(salt_data_, &salt[0], salt_length_) == 0)); -} - -bool -NSEC3HashRFC5155::match(const generic::NSEC3& nsec3) const { - return (match(nsec3.getHashalg(), nsec3.getIterations(), - nsec3.getSalt())); -} - -bool -NSEC3HashRFC5155::match(const generic::NSEC3PARAM& nsec3param) const { - return (match(nsec3param.getHashalg(), nsec3param.getIterations(), - nsec3param.getSalt())); -} - -// A static pointer that refers to the currently usable creator. -// Only get/setNSEC3HashCreator are expected to get access to this variable -// directly. -const NSEC3HashCreator* creator; - -// The accessor to the current creator. If it's not explicitly set or has -// been reset from a customized one, the default creator will be used. -const NSEC3HashCreator* -getNSEC3HashCreator() { - static DefaultNSEC3HashCreator default_creator; - if (creator == NULL) { - creator = &default_creator; - } - return (creator); -} - -} // end of unnamed namespace - -namespace isc { -namespace dns { - -NSEC3Hash* -NSEC3Hash::create(const generic::NSEC3PARAM& param) { - return (getNSEC3HashCreator()->create(param)); -} - -NSEC3Hash* -NSEC3Hash::create(const generic::NSEC3& nsec3) { - return (getNSEC3HashCreator()->create(nsec3)); -} - -NSEC3Hash* -NSEC3Hash::create(uint8_t algorithm, uint16_t iterations, - const uint8_t* salt_data, size_t salt_length) { - return (getNSEC3HashCreator()->create(algorithm, iterations, - salt_data, salt_length)); -} - -NSEC3Hash* -DefaultNSEC3HashCreator::create(const generic::NSEC3PARAM& param) const { - const vector<uint8_t>& salt = param.getSalt(); - return (new NSEC3HashRFC5155(param.getHashalg(), param.getIterations(), - salt.empty() ? NULL : &salt[0], - salt.size())); -} - -NSEC3Hash* -DefaultNSEC3HashCreator::create(const generic::NSEC3& nsec3) const { - const vector<uint8_t>& salt = nsec3.getSalt(); - return (new NSEC3HashRFC5155(nsec3.getHashalg(), nsec3.getIterations(), - salt.empty() ? NULL : &salt[0], - salt.size())); -} - -NSEC3Hash* -DefaultNSEC3HashCreator::create(uint8_t algorithm, uint16_t iterations, - const uint8_t* salt_data, - size_t salt_length) const -{ - return (new NSEC3HashRFC5155(algorithm, iterations, - salt_data, salt_length)); -} - -void -setNSEC3HashCreator(const NSEC3HashCreator* new_creator) { - creator = new_creator; -} - -} // namespace dns -} // namespace isc diff --git a/src/lib/dns/nsec3hash.h b/src/lib/dns/nsec3hash.h deleted file mode 100644 index 26bb715db2..0000000000 --- a/src/lib/dns/nsec3hash.h +++ /dev/null @@ -1,290 +0,0 @@ -// Copyright (C) 2012-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef NSEC3HASH_H -#define NSEC3HASH_H 1 - -#include <string> -#include <vector> -#include <stdint.h> -#include <exceptions/exceptions.h> - -namespace isc { -namespace dns { -class Name; -class LabelSequence; - -namespace rdata { -namespace generic { -class NSEC3; -class NSEC3PARAM; -} -} - -/// \brief An exception that is thrown for when an \c NSEC3Hash object is -/// constructed with an unknown hash algorithm. -/// -/// A specific exception class is used so that the caller can selectively -/// catch this exception, e.g., while loading a zone, and handle it -/// accordingly. -class UnknownNSEC3HashAlgorithm : public isc::Exception { -public: - UnknownNSEC3HashAlgorithm(const char* file, size_t line, - const char* what) : - isc::Exception(file, line, what) {} -}; - -/// \brief A calculator of NSEC3 hashes. -/// -/// This is an abstract base class that defines a simple interface to -/// calculating NSEC3 hash values as defined in RFC5155. -/// -/// (Derived classes of) this class is designed to be "stateless" in that it -/// basically doesn't hold mutable state once constructed, and hash -/// calculation solely depends on the parameters given on construction and -/// input to the \c calculate() method. In that sense this could be a -/// single free function rather than a class, but we decided to provide the -/// functionality as a class for two reasons: NSEC3 hash calculations would -/// often take place more than one time in a single query or validation -/// process, so it would be more efficient if we could hold some internal -/// resources used for the calculation and reuse it over multiple calls to -/// \c calculate() (a concrete implementation in this library actually does -/// this); Second, we may want to customize the hash calculation logic for -/// testing purposes or for other future extensions. For example, we may -/// want to use a fake calculator for tests that returns pre-defined hash -/// values (so a slight change to the test input wouldn't affect the test -/// result). Using classes from this base would make it possible more -/// transparently to the application. -/// -/// A specific derived class instance must be created by the factory method, -/// \c create(). -/// -/// There can be several ways to extend this class in future. Those include: -/// - Allow customizing the factory method so the application change the -/// behavior dynamically. -/// - Allow to construct the class from a tuple of parameters, that is, -/// integers for algorithm, iterations and flags, and opaque salt data. -/// For example, we might want to use that version for validators. -/// - Allow producing hash value as binary data -/// - Allow updating NSEC3 parameters of a class object so we can still reuse -/// the internal resources for different sets of parameters. -class NSEC3Hash { -protected: - /// \brief The default constructor. - /// - /// This is defined as protected to prevent this class from being directly - /// instantiated even if the class definition is modified (accidentally - /// or intentionally) to have no pure virtual methods. - NSEC3Hash() {} - -public: - /// \brief Factory method of NSECHash from NSEC3PARAM RDATA. - /// - /// The hash algorithm given via \c param must be known to the - /// implementation. Otherwise \c UnknownNSEC3HashAlgorithm exception - /// will be thrown. - /// - /// This method creates an \c NSEC3Hash object using \c new. The caller - /// is responsible for releasing it with \c delete that is compatible to - /// the one used in this library. In practice, the application would - /// generally need to store the returned pointer in some form of smart - /// pointer; otherwise the resulting code will be quite fragile against - /// exceptions (and in this case the application doesn't have to worry - /// about explicit \c delete). - /// - /// \throw UnknownNSEC3HashAlgorithm The specified algorithm in \c param - /// is unknown. - /// \throw std::bad_alloc Internal resource allocation failure. - /// - /// \param param NSEC3 parameters used for subsequent calculation. - /// \return A pointer to a concrete derived object of \c NSEC3Hash. - static NSEC3Hash* create(const rdata::generic::NSEC3PARAM& param); - - /// \brief Factory method of NSECHash from NSEC3 RDATA. - /// - /// This is similar to the other version, but extracts the parameters - /// for hash calculation from an NSEC3 RDATA object. - static NSEC3Hash* create(const rdata::generic::NSEC3& nsec3); - - /// \brief Factory method of NSECHash from args. - /// - /// \param algorithm the NSEC3 algorithm to use; currently only 1 - /// (SHA-1) is supported - /// \param iterations the number of iterations - /// \param salt_data the salt data as a byte array - /// \param salt_length the length of the salt data - static NSEC3Hash* create(uint8_t algorithm, uint16_t iterations, - const uint8_t* salt_data, size_t salt_length); - - /// \brief The destructor. - virtual ~NSEC3Hash() {} - - /// \brief Calculate the NSEC3 hash (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 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 - /// in the object with those in the given NSEC3 RDATA, and return - /// true iff they completely match. In the current implementation - /// only the algorithm, iterations and salt are compared; the flags - /// are ignored (as they don't affect hash calculation per RFC5155). - /// - /// \throw None - /// - /// \param nsec3 An NSEC3 RDATA object whose hash parameters are to be - /// matched - /// \return true If the given parameters match the local ones; false - /// otherwise. - virtual bool match(const rdata::generic::NSEC3& nsec3) const = 0; - - /// \brief Match given NSEC3PARAM parameters with that of the hash. - /// - /// This is similar to the other version, but extracts the parameters - /// to compare from an NSEC3PARAM RDATA object. - virtual bool match(const rdata::generic::NSEC3PARAM& nsec3param) const = 0; -}; - -/// \brief Factory class of NSEC3Hash. -/// -/// This class is an abstract base class that provides the creation interfaces -/// of \c NSEC3Hash objects. By defining a specific derived class of the -/// creator, normally with a different specific class of \c NSEC3Hash, -/// the application can use a customized implementation of \c NSEC3Hash -/// without changing the library itself. The intended primary application of -/// such customization is tests (it would be convenient for a test to produce -/// a faked hash value regardless of the input so it doesn't have to identify -/// a specific input value to produce a particular hash). Another possibility -/// would be an experimental extension for a newer hash algorithm or -/// implementation. -/// -/// The three main methods named \c create() correspond to the static factory -/// methods of \c NSEC3Hash of the same name. -/// -/// By default, the library uses the \c DefaultNSEC3HashCreator creator. -/// The \c setNSEC3HashCreator() function can be used to replace it with a -/// user defined version. For such customization purposes as implementing -/// experimental new hash algorithms, the application may internally want to -/// use the \c DefaultNSEC3HashCreator in general cases while creating a -/// customized type of \c NSEC3Hash object for that particular hash algorithm. -/// -/// The creator objects are generally expected to be stateless; they will -/// only encapsulate the factory logic. The \c create() methods are declared -/// as const member functions for this reason. But if we see the need for -/// having a customized creator that benefits from its own state in future, -/// this condition can be loosened. -class NSEC3HashCreator { -protected: - /// \brief The default constructor. - /// - /// Make very sure this isn't directly instantiated by making it protected - /// even if this class is modified to lose all pure virtual methods. - NSEC3HashCreator() {} - -public: - /// \brief The destructor. - /// - /// This does nothing; defined only for allowing derived classes to - /// specialize its behavior. - virtual ~NSEC3HashCreator() {} - - /// \brief Factory method of NSECHash from NSEC3PARAM RDATA. - /// - /// See - /// <code>NSEC3Hash::create(const rdata::generic::NSEC3PARAM& param)</code> - virtual NSEC3Hash* create(const rdata::generic::NSEC3PARAM& nsec3param) - const = 0; - - /// \brief Factory method of NSECHash from NSEC3 RDATA. - /// - /// See - /// <code>NSEC3Hash::create(const rdata::generic::NSEC3& param)</code> - virtual NSEC3Hash* create(const rdata::generic::NSEC3& nsec3) - const = 0; - - /// \brief Factory method of NSECHash from args. - /// - /// See - /// <code>NSEC3Hash::create(uint8_t algorithm, uint16_t iterations, - /// const uint8_t* salt_data, - /// size_t salt_length)</code> - /// - /// \param algorithm the NSEC3 algorithm to use; currently only 1 - /// (SHA-1) is supported - /// \param iterations the number of iterations - /// \param salt_data the salt data as a byte array - /// \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; -}; - -/// \brief The default NSEC3Hash creator. -/// -/// This derived class implements the \c NSEC3HashCreator interfaces for -/// the standard NSEC3 hash calculator as defined in RFC5155. The library -/// will use this creator by default, so normal applications don't have to -/// be aware of this class at all. This class is publicly visible for the -/// convenience of special applications that want to customize the creator -/// behavior for a particular type of parameters while preserving the default -/// behavior for others. -class DefaultNSEC3HashCreator : public NSEC3HashCreator { -public: - virtual NSEC3Hash* create(const rdata::generic::NSEC3PARAM& param) const; - virtual NSEC3Hash* create(const rdata::generic::NSEC3& nsec3) const; - virtual NSEC3Hash* create(uint8_t algorithm, uint16_t iterations, - const uint8_t* salt_data, - size_t salt_length) const; -}; - -/// \brief The registrar of \c NSEC3HashCreator. -/// -/// This function sets or resets the system-wide \c NSEC3HashCreator that -/// is used by \c NSEC3Hash::create(). -/// -/// If \c new_creator is non NULL, the given creator object will replace -/// any existing creator. If it's NULL, the default builtin creator will be -/// used again from that point. -/// -/// When \c new_creator is non NULL, the caller is responsible for keeping -/// the referenced object valid as long as it can be used via -/// \c NSEC3Hash::create(). -/// -/// \exception None -/// \param new_creator A pointer to the new creator object or NULL. -void setNSEC3HashCreator(const NSEC3HashCreator* new_creator); - -} -} -#endif // NSEC3HASH_H - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/opcode.h b/src/lib/dns/opcode.h index 67dd57919b..9fbd815056 100644 --- a/src/lib/dns/opcode.h +++ b/src/lib/dns/opcode.h @@ -11,7 +11,7 @@ #include <ostream> #ifndef OPCODE_H -#define OPCODE_H 1 +#define OPCODE_H namespace isc { namespace dns { @@ -75,7 +75,9 @@ public: /// This method never throws an exception. /// /// \return The underlying code value corresponding to the \c Opcode. - CodeValue getCode() const { return (code_); } + CodeValue getCode() const { + return (code_); + } /// \brief Return true iff two Opcodes are equal. /// @@ -85,11 +87,14 @@ public: /// /// \param other the \c Opcode object to compare against. /// \return true if the two Opcodes are equal; otherwise false. - bool equals(const Opcode& other) const - { return (code_ == other.code_); } + bool equals(const Opcode& other) const { + return (code_ == other.code_); + } /// \brief Same as \c equals(). - bool operator==(const Opcode& other) const { return (equals(other)); } + bool operator==(const Opcode& other) const { + return (equals(other)); + } /// \brief Return true iff two Opcodes are not equal. /// @@ -97,11 +102,14 @@ public: /// /// \param other the \c Opcode object to compare against. /// \return true if the two Opcodes are not equal; otherwise false. - bool nequals(const Opcode& other) const - { return (code_ != other.code_); } + bool nequals(const Opcode& other) const { + return (code_ != other.code_); + } /// \brief Same as \c nequals(). - bool operator!=(const Opcode& other) const { return (nequals(other)); } + bool operator!=(const Opcode& other) const { + return (nequals(other)); + } /// \brief Convert the \c Opcode to a string. /// @@ -276,7 +284,3 @@ std::ostream& operator<<(std::ostream& os, const Opcode& opcode); } } #endif // OPCODE_H - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/qid_gen.cc b/src/lib/dns/qid_gen.cc index dad2b6ff5a..207eeadb3e 100644 --- a/src/lib/dns/qid_gen.cc +++ b/src/lib/dns/qid_gen.cc @@ -26,8 +26,7 @@ QidGenerator::getInstance() { return (qid_generator_instance); } -QidGenerator::QidGenerator() -{ +QidGenerator::QidGenerator() { } uint16_t diff --git a/src/lib/dns/question.cc b/src/lib/dns/question.cc index f0170d8812..72499f2355 100644 --- a/src/lib/dns/question.cc +++ b/src/lib/dns/question.cc @@ -22,8 +22,7 @@ using namespace isc::util; namespace isc { namespace dns { Question::Question(InputBuffer& buffer) : - name_(buffer), rrtype_(0), rrclass_(0) -{ + name_(buffer), rrtype_(0), rrclass_(0) { // In theory, we could perform this in the member initialization list, // and it would be a little bit more efficient. We don't do this, however, // because the initialization ordering is crucial (type must be first) diff --git a/src/lib/dns/question.h b/src/lib/dns/question.h index 05f52eeef9..055907a315 100644 --- a/src/lib/dns/question.h +++ b/src/lib/dns/question.h @@ -5,7 +5,7 @@ // file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef QUESTION_H -#define QUESTION_H 1 +#define QUESTION_H #include <iostream> #include <string> @@ -17,14 +17,8 @@ #include <dns/rrtype.h> namespace isc { -namespace util { -class InputBuffer; -class OutputBuffer; -} namespace dns { - -class AbstractMessageRenderer; class Question; /// \brief A pointer-like type pointing to an \c Question object. @@ -126,8 +120,8 @@ public: /// \param rrclass The RR class of the \c Question. /// \param rrtype The RR type of the \c Question. Question(const Name& name, const RRClass& rrclass, const RRType& rrtype) : - name_(name), rrtype_(rrtype), rrclass_(rrclass) - {} + name_(name), rrtype_(rrtype), rrclass_(rrclass) { + } //@} /// @@ -140,7 +134,9 @@ public: /// /// \return A reference to a \c Name class object corresponding to the /// \c Question owner name. - const Name& getName() const { return (name_); } + const Name& getName() const { + return (name_); + } /// \brief Returns the RR Class of the \c Question. /// @@ -148,7 +144,9 @@ public: /// /// \return A reference to a \c RRClass class object corresponding to the /// RR class of the \c Question. - const RRType& getType() const { return (rrtype_); } + const RRType& getType() const { + return (rrtype_); + } /// \brief Returns the RR Type of the \c Question. /// @@ -156,7 +154,9 @@ public: /// /// \return A reference to a \c RRType class object corresponding to the /// RR type of the \c Question. - const RRClass& getClass() const { return (rrclass_); } + const RRClass& getClass() const { + return (rrclass_); + } //@} /// @@ -285,7 +285,3 @@ std::ostream& operator<<(std::ostream& os, const Question& question); } // end of namespace dns } // end of namespace isc #endif // QUESTION_H - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/rcode.h b/src/lib/dns/rcode.h index eb192cd520..007709e55a 100644 --- a/src/lib/dns/rcode.h +++ b/src/lib/dns/rcode.h @@ -11,7 +11,7 @@ #include <ostream> #ifndef RCODE_H -#define RCODE_H 1 +#define RCODE_H namespace isc { namespace dns { @@ -103,7 +103,9 @@ public: /// This method never throws an exception. /// /// \return The underlying code value corresponding to the \c Rcode. - uint16_t getCode() const { return (code_); } + uint16_t getCode() const { + return (code_); + } /// \brief Returns the upper 8-bit of the \c Rcode code value. /// @@ -124,11 +126,14 @@ public: /// /// \param other the \c Rcode object to compare against. /// \return true if the two Rcodes are equal; otherwise false. - bool equals(const Rcode& other) const - { return (code_ == other.code_); } + bool equals(const Rcode& other) const { + return (code_ == other.code_); + } /// \brief Same as \c equals(). - bool operator==(const Rcode& other) const { return (equals(other)); } + bool operator==(const Rcode& other) const { + return (equals(other)); + } /// \brief Return true iff two Rcodes are not equal. /// @@ -136,11 +141,14 @@ public: /// /// \param other the \c Rcode object to compare against. /// \return true if the two Rcodes are not equal; otherwise false. - bool nequals(const Rcode& other) const - { return (code_ != other.code_); } + bool nequals(const Rcode& other) const { + return (code_ != other.code_); + } /// \brief Same as \c nequals(). - bool operator!=(const Rcode& other) const { return (nequals(other)); } + bool operator!=(const Rcode& other) const { + return (nequals(other)); + } /// \brief Convert the \c Rcode to a string. /// @@ -332,7 +340,3 @@ std::ostream& operator<<(std::ostream& os, const Rcode& rcode); } } #endif // RCODE_H - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/rdata.cc b/src/lib/dns/rdata.cc index 3edfa4b8c0..25829c8d2e 100644 --- a/src/lib/dns/rdata.cc +++ b/src/lib/dns/rdata.cc @@ -54,16 +54,14 @@ Rdata::getLength() const { // function signature with that given in the header file. RdataPtr createRdata(const RRType& rrtype, const RRClass& rrclass, - const std::string& rdata_string) -{ + const std::string& rdata_string) { return (RRParamRegistry::getRegistry().createRdata(rrtype, rrclass, rdata_string)); } RdataPtr createRdata(const RRType& rrtype, const RRClass& rrclass, - isc::util::InputBuffer& buffer, size_t len) -{ + isc::util::InputBuffer& buffer, size_t len) { if (len > MAX_RDLENGTH) { isc_throw(InvalidRdataLength, "RDLENGTH too large"); } @@ -83,8 +81,7 @@ createRdata(const RRType& rrtype, const RRClass& rrclass, } RdataPtr -createRdata(const RRType& rrtype, const RRClass& rrclass, const Rdata& source) -{ +createRdata(const RRType& rrtype, const RRClass& rrclass, const Rdata& source) { return (RRParamRegistry::getRegistry().createRdata(rrtype, rrclass, source)); } @@ -93,8 +90,7 @@ namespace { void fromtextError(bool& error_issued, const MasterLexer& lexer, MasterLoaderCallbacks& callbacks, - const MasterToken* token, const char* reason) -{ + const MasterToken* token, const char* reason) { // Don't be too noisy if there are many issues for single RDATA if (error_issued) { return; @@ -133,8 +129,7 @@ RdataPtr createRdata(const RRType& rrtype, const RRClass& rrclass, MasterLexer& lexer, const Name* origin, MasterLoader::Options options, - MasterLoaderCallbacks& callbacks) -{ + MasterLoaderCallbacks& callbacks) { RdataPtr rdata; bool error_issued = false; @@ -212,10 +207,10 @@ Generic::Generic(isc::util::InputBuffer& buffer, size_t rdata_len) { buffer.readData(&data[0], rdata_len); } - impl_ = new GenericImpl(data); + impl_.reset(new GenericImpl(data)); } -GenericImpl* +boost::shared_ptr<GenericImpl> Generic::constructFromLexer(MasterLexer& lexer) { const MasterToken& token = lexer.getNextToken(MasterToken::STRING); if (token.getString() != "\\#") { @@ -274,23 +269,22 @@ Generic::constructFromLexer(MasterLexer& lexer) { << data.size() << " vs. " << rdlen); } - return (new GenericImpl(data)); + return (boost::shared_ptr<GenericImpl>(new GenericImpl(data))); } Generic::Generic(const std::string& rdata_string) : - impl_(NULL) -{ + impl_(NULL) { // We use unique_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::unique_ptr<GenericImpl> impl_ptr; + boost::shared_ptr<GenericImpl> impl_ptr; try { std::istringstream ss(rdata_string); MasterLexer lexer; lexer.pushSource(ss); - impl_ptr.reset(constructFromLexer(lexer)); + impl_ptr = constructFromLexer(lexer); if (lexer.getNextToken().getType() != MasterToken::END_OF_FILE) { isc_throw(InvalidRdataText, "extra input text for unknown RDATA: " @@ -301,23 +295,21 @@ Generic::Generic(const std::string& rdata_string) : "from '" << rdata_string << "': " << ex.what()); } - impl_ = impl_ptr.release(); + impl_ = impl_ptr; } Generic::Generic(MasterLexer& lexer, const Name*, MasterLoader::Options, - MasterLoaderCallbacks&) : - impl_(constructFromLexer(lexer)) -{ + MasterLoaderCallbacks&) { + impl_ = constructFromLexer(lexer); } Generic::~Generic() { - delete impl_; } Generic::Generic(const Generic& source) : - Rdata(), impl_(new GenericImpl(*source.impl_)) -{} + Rdata(), impl_(new GenericImpl(*source.impl_)) { +} Generic& // Our check is better than the usual if (this == &source), @@ -328,9 +320,7 @@ Generic::operator=(const Generic& source) { return (*this); } - GenericImpl* newimpl = new GenericImpl(*source.impl_); - delete impl_; - impl_ = newimpl; + impl_.reset(new GenericImpl(*source.impl_)); return (*this); } diff --git a/src/lib/dns/rdata.h b/src/lib/dns/rdata.h index a6515ef936..b04429ab12 100644 --- a/src/lib/dns/rdata.h +++ b/src/lib/dns/rdata.h @@ -5,23 +5,19 @@ // file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef RDATA_H -#define RDATA_H 1 +#define RDATA_H #include <dns/master_lexer.h> #include <dns/master_loader.h> #include <dns/master_loader_callbacks.h> - #include <dns/exceptions.h> +#include <util/buffer.h> #include <boost/shared_ptr.hpp> #include <stdint.h> namespace isc { -namespace util { -class InputBuffer; -class OutputBuffer; -} namespace dns { class AbstractMessageRenderer; class RRType; @@ -385,9 +381,9 @@ public: //@} private: - GenericImpl* constructFromLexer(MasterLexer& lexer); + boost::shared_ptr<GenericImpl> constructFromLexer(MasterLexer& lexer); - GenericImpl* impl_; + boost::shared_ptr<GenericImpl> impl_; }; /// @@ -576,7 +572,3 @@ int compareNames(const Name& n1, const Name& n2); } } #endif // RDATA_H - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/rdata/any_255/tsig_250.cc b/src/lib/dns/rdata/any_255/tsig_250.cc index 47b1107769..b5469d2bcd 100644 --- a/src/lib/dns/rdata/any_255/tsig_250.cc +++ b/src/lib/dns/rdata/any_255/tsig_250.cc @@ -41,8 +41,8 @@ struct TSIGImpl { vector<uint8_t>& other_data) : algorithm_(algorithm), time_signed_(time_signed), fudge_(fudge), mac_(mac), original_id_(original_id), error_(error), - other_data_(other_data) - {} + other_data_(other_data) { + } TSIGImpl(const Name& algorithm, uint64_t time_signed, uint16_t fudge, size_t macsize, const void* mac, uint16_t original_id, uint16_t error, size_t other_len, const void* other_data) : @@ -51,8 +51,8 @@ struct TSIGImpl { static_cast<const uint8_t*>(mac) + macsize), original_id_(original_id), error_(error), other_data_(static_cast<const uint8_t*>(other_data), - static_cast<const uint8_t*>(other_data) + other_len) - {} + static_cast<const uint8_t*>(other_data) + other_len) { + } template <typename Output> void toWireCommon(Output& output) const; @@ -66,7 +66,7 @@ struct TSIGImpl { }; // helper function for string and lexer constructors -TSIGImpl* +boost::shared_ptr<TSIGImpl> TSIG::constructFromLexer(MasterLexer& lexer, const Name* origin) { const Name& algorithm = createNameFromLexer(lexer, origin ? origin : &Name::ROOT_NAME()); @@ -160,8 +160,9 @@ TSIG::constructFromLexer(MasterLexer& lexer, const Name* origin) { // RFC2845 says Other Data is "empty unless Error == BADTIME". // However, we don't enforce that. - return (new TSIGImpl(canonical_algorithm_name, time_signed, fudge, mac, - orig_id, error, other_data)); + return (boost::shared_ptr<TSIGImpl>(new TSIGImpl(canonical_algorithm_name, + time_signed, fudge, mac, + orig_id, error, other_data))); } /// \brief Constructor from string. @@ -213,7 +214,7 @@ TSIG::TSIG(const std::string& tsig_str) : impl_(NULL) { // We use unique_ptr here because if there is an exception in this // constructor, the destructor is not called and there could be a // leak of the TSIGImpl that constructFromLexer() returns. - std::unique_ptr<TSIGImpl> impl_ptr; + boost::shared_ptr<TSIGImpl> impl_ptr; try { std::istringstream ss(tsig_str); @@ -232,7 +233,7 @@ TSIG::TSIG(const std::string& tsig_str) : impl_(NULL) { << ex.what()); } - impl_ = impl_ptr.release(); + impl_ = impl_ptr; } /// \brief Constructor with a context of MasterLexer. @@ -252,8 +253,7 @@ TSIG::TSIG(const std::string& tsig_str) : impl_(NULL) { /// RDATA to be created TSIG::TSIG(MasterLexer& lexer, const Name* origin, MasterLoader::Options, MasterLoaderCallbacks&) : - impl_(constructFromLexer(lexer, origin)) -{ + impl_(constructFromLexer(lexer, origin)) { } /// \brief Constructor from wire-format data. @@ -277,8 +277,7 @@ TSIG::TSIG(MasterLexer& lexer, const Name* origin, /// must check consistency between the length parameter and the actual /// RDATA length. TSIG::TSIG(InputBuffer& buffer, size_t) : - impl_(NULL) -{ + impl_(NULL) { Name algorithm(buffer); uint8_t time_signed_buf[6]; @@ -311,15 +310,14 @@ TSIG::TSIG(InputBuffer& buffer, size_t) : const Name& canonical_algorithm_name = (algorithm == TSIGKey::HMACMD5_SHORT_NAME()) ? TSIGKey::HMACMD5_NAME() : algorithm; - impl_ = new TSIGImpl(canonical_algorithm_name, time_signed, fudge, mac, - original_id, error, other_data); + impl_.reset(new TSIGImpl(canonical_algorithm_name, time_signed, fudge, mac, + original_id, error, other_data)); } TSIG::TSIG(const Name& algorithm, uint64_t time_signed, uint16_t fudge, uint16_t mac_size, const void* mac, uint16_t original_id, uint16_t error, uint16_t other_len, const void* other_data) : - impl_(NULL) -{ + impl_(NULL) { // Time Signed is a 48-bit value. if ((time_signed >> 48) != 0) { isc_throw(OutOfRange, "TSIG Time Signed is too large: " << @@ -336,8 +334,8 @@ TSIG::TSIG(const Name& algorithm, uint64_t time_signed, uint16_t fudge, const Name& canonical_algorithm_name = (algorithm == TSIGKey::HMACMD5_SHORT_NAME()) ? TSIGKey::HMACMD5_NAME() : algorithm; - impl_ = new TSIGImpl(canonical_algorithm_name, time_signed, fudge, mac_size, - mac, original_id, error, other_len, other_data); + impl_.reset(new TSIGImpl(canonical_algorithm_name, time_signed, fudge, mac_size, + mac, original_id, error, other_len, other_data)); } /// \brief The copy constructor. @@ -345,8 +343,8 @@ TSIG::TSIG(const Name& algorithm, uint64_t time_signed, uint16_t fudge, /// It internally allocates a resource, and if it fails a corresponding /// standard exception will be thrown. /// This constructor never throws an exception otherwise. -TSIG::TSIG(const TSIG& source) : Rdata(), impl_(new TSIGImpl(*source.impl_)) -{} +TSIG::TSIG(const TSIG& source) : Rdata(), impl_(new TSIGImpl(*source.impl_)) { +} TSIG& TSIG::operator=(const TSIG& source) { @@ -354,15 +352,12 @@ TSIG::operator=(const TSIG& source) { return (*this); } - TSIGImpl* newimpl = new TSIGImpl(*source.impl_); - delete impl_; - impl_ = newimpl; + impl_.reset(new TSIGImpl(*source.impl_)); return (*this); } TSIG::~TSIG() { - delete impl_; } /// \brief Convert the \c TSIG to a string. diff --git a/src/lib/dns/rdata/any_255/tsig_250.h b/src/lib/dns/rdata/any_255/tsig_250.h index 63c223449b..826cdbca54 100644 --- a/src/lib/dns/rdata/any_255/tsig_250.h +++ b/src/lib/dns/rdata/any_255/tsig_250.h @@ -10,8 +10,10 @@ #include <string> +#include <util/buffer.h> #include <dns/name.h> #include <dns/rdata.h> +#include <boost/shared_ptr.hpp> // BEGIN_ISC_NAMESPACE @@ -134,15 +136,11 @@ public: /// This method never throws an exception. const void* getOtherData() const; private: - TSIGImpl* constructFromLexer(MasterLexer& lexer, const Name* origin); + boost::shared_ptr<TSIGImpl> constructFromLexer(MasterLexer& lexer, const Name* origin); - TSIGImpl* impl_; + boost::shared_ptr<TSIGImpl> impl_; }; // END_RDATA_NAMESPACE // END_ISC_NAMESPACE // END_HEADER_GUARD - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/rdata/ch_3/a_1.cc b/src/lib/dns/rdata/ch_3/a_1.cc deleted file mode 100644 index cd4c824cac..0000000000 --- a/src/lib/dns/rdata/ch_3/a_1.cc +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright (C) 2010-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#include <config.h> - -#include <string> - -#include <exceptions/exceptions.h> - -#include <util/buffer.h> -#include <dns/messagerenderer.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> - -using namespace std; -using namespace isc::util; - -// BEGIN_ISC_NAMESPACE -// BEGIN_RDATA_NAMESPACE - -A::A(const std::string&) { - // TBD -} - -A::A(MasterLexer&, const Name*, - MasterLoader::Options, MasterLoaderCallbacks&) -{ - // TBD -} - -A::A(InputBuffer&, size_t) { - // TBD -} - -A::A(const A&) : Rdata() { - // TBD -} - -void -A::toWire(OutputBuffer&) const { - // TBD -} - -void -A::toWire(AbstractMessageRenderer&) const { - // TBD -} - -string -A::toText() const { - // TBD - isc_throw(InvalidRdataText, "Not implemented yet"); -} - -int -A::compare(const Rdata&) const { - return (0); // dummy. TBD -} - -// END_RDATA_NAMESPACE -// END_ISC_NAMESPACE diff --git a/src/lib/dns/rdata/ch_3/a_1.h b/src/lib/dns/rdata/ch_3/a_1.h deleted file mode 100644 index 6f319b9c7d..0000000000 --- a/src/lib/dns/rdata/ch_3/a_1.h +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (C) 2010-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -// BEGIN_HEADER_GUARD - -#include <string> - -#include <dns/rdata.h> - -// BEGIN_ISC_NAMESPACE - -// BEGIN_COMMON_DECLARATIONS -// END_COMMON_DECLARATIONS - -// BEGIN_RDATA_NAMESPACE - -class A : public Rdata { -public: - // BEGIN_COMMON_MEMBERS - // END_COMMON_MEMBERS -}; - -// END_RDATA_NAMESPACE -// END_ISC_NAMESPACE -// END_HEADER_GUARD - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/rdata/generic/afsdb_18.cc b/src/lib/dns/rdata/generic/afsdb_18.cc deleted file mode 100644 index 5e82b03efa..0000000000 --- a/src/lib/dns/rdata/generic/afsdb_18.cc +++ /dev/null @@ -1,201 +0,0 @@ -// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#include <config.h> - -#include <string> -#include <sstream> - -#include <util/buffer.h> -#include <util/strutil.h> - -#include <dns/name.h> -#include <dns/messagerenderer.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> - -#include <boost/lexical_cast.hpp> - -#include <dns/rdata/generic/detail/lexer_util.h> - -using namespace std; -using boost::lexical_cast; -using namespace isc::util; -using isc::dns::rdata::generic::detail::createNameFromLexer; - -// BEGIN_ISC_NAMESPACE -// BEGIN_RDATA_NAMESPACE - -/// \brief Constructor from string. -/// -/// \c afsdb_str must be formatted as follows: -/// \code <subtype> <server name> -/// \endcode -/// where server name field must represent a valid domain name. -/// -/// An example of valid string is: -/// \code "1 server.example.com." \endcode -/// -/// <b>Exceptions</b> -/// -/// \exception InvalidRdataText The number of RDATA fields (must be 2) is -/// incorrect. -/// \exception std::bad_alloc Memory allocation fails. -/// \exception Other The constructor of the \c Name class will throw if the -/// names in the string is invalid. -AFSDB::AFSDB(const std::string& afsdb_str) : - subtype_(0), server_(Name::ROOT_NAME()) -{ - try { - std::istringstream ss(afsdb_str); - MasterLexer lexer; - lexer.pushSource(ss); - - createFromLexer(lexer, NULL); - - if (lexer.getNextToken().getType() != MasterToken::END_OF_FILE) { - isc_throw(InvalidRdataText, "extra input text for AFSDB: " - << afsdb_str); - } - } catch (const MasterLexer::LexerError& ex) { - isc_throw(InvalidRdataText, "Failed to construct AFSDB from '" << - afsdb_str << "': " << ex.what()); - } -} - -/// \brief Constructor with a context of MasterLexer. -/// -/// The \c lexer should point to the beginning of valid textual representation -/// of an AFSDB RDATA. The SERVER field can be non-absolute if \c origin -/// is non-NULL, in which case \c origin is used to make it absolute. -/// It must not be represented as a quoted string. -/// -/// The SUBTYPE field must be a valid decimal representation of an -/// unsigned 16-bit integer. -/// -/// \throw MasterLexer::LexerError General parsing error such as missing field. -/// \throw Other Exceptions from the Name and RRTTL constructors if -/// construction of textual fields as these objects fail. -/// -/// \param lexer A \c MasterLexer object parsing a master file for the -/// RDATA to be created -/// \param origin If non NULL, specifies the origin of SERVER when it -/// is non-absolute. -AFSDB::AFSDB(MasterLexer& lexer, const Name* origin, - MasterLoader::Options, MasterLoaderCallbacks&) : - subtype_(0), server_(".") -{ - createFromLexer(lexer, origin); -} - -void -AFSDB::createFromLexer(MasterLexer& lexer, const Name* origin) -{ - const uint32_t num = lexer.getNextToken(MasterToken::NUMBER).getNumber(); - if (num > 65535) { - isc_throw(InvalidRdataText, "Invalid AFSDB subtype: " << num); - } - subtype_ = static_cast<uint16_t>(num); - - server_ = createNameFromLexer(lexer, origin); -} - -/// \brief Constructor from wire-format data. -/// -/// This constructor doesn't check the validity of the second parameter (rdata -/// length) for parsing. -/// If necessary, the caller will check consistency. -/// -/// \exception std::bad_alloc Memory allocation fails. -/// \exception Other The constructor of the \c Name class will throw if the -/// names in the wire is invalid. -AFSDB::AFSDB(InputBuffer& buffer, size_t) : - subtype_(buffer.readUint16()), server_(buffer) -{} - -/// \brief Copy constructor. -/// -/// \exception std::bad_alloc Memory allocation fails in copying internal -/// member variables (this should be very rare). -AFSDB::AFSDB(const AFSDB& other) : - Rdata(), subtype_(other.subtype_), server_(other.server_) -{} - -AFSDB& -AFSDB::operator=(const AFSDB& source) { - subtype_ = source.subtype_; - server_ = source.server_; - - return (*this); -} - -/// \brief Convert the \c AFSDB to a string. -/// -/// The output of this method is formatted as described in the "from string" -/// constructor (\c AFSDB(const std::string&))). -/// -/// \exception std::bad_alloc Internal resource allocation fails. -/// -/// \return A \c string object that represents the \c AFSDB object. -string -AFSDB::toText() const { - return (lexical_cast<string>(subtype_) + " " + server_.toText()); -} - -/// \brief Render the \c AFSDB in the wire format without name compression. -/// -/// \exception std::bad_alloc Internal resource allocation fails. -/// -/// \param buffer An output buffer to store the wire data. -void -AFSDB::toWire(OutputBuffer& buffer) const { - buffer.writeUint16(subtype_); - server_.toWire(buffer); -} - -/// \brief Render the \c AFSDB in the wire format with taking into account -/// compression. -/// -/// As specified in RFC3597, TYPE AFSDB is not "well-known", the server -/// field (domain name) will not be compressed. -/// -/// \exception std::bad_alloc Internal resource allocation fails. -/// -/// \param renderer DNS message rendering context that encapsulates the -/// output buffer and name compression information. -void -AFSDB::toWire(AbstractMessageRenderer& renderer) const { - renderer.writeUint16(subtype_); - renderer.writeName(server_, false); -} - -/// \brief Compare two instances of \c AFSDB RDATA. -/// -/// See documentation in \c Rdata. -int -AFSDB::compare(const Rdata& other) const { - const AFSDB& other_afsdb = dynamic_cast<const AFSDB&>(other); - if (subtype_ < other_afsdb.subtype_) { - return (-1); - } else if (subtype_ > other_afsdb.subtype_) { - return (1); - } - - return (compareNames(server_, other_afsdb.server_)); -} - -const Name& -AFSDB::getServer() const { - return (server_); -} - -uint16_t -AFSDB::getSubtype() const { - return (subtype_); -} - -// END_RDATA_NAMESPACE -// END_ISC_NAMESPACE diff --git a/src/lib/dns/rdata/generic/afsdb_18.h b/src/lib/dns/rdata/generic/afsdb_18.h deleted file mode 100644 index 2fd8fbaa6d..0000000000 --- a/src/lib/dns/rdata/generic/afsdb_18.h +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -// BEGIN_HEADER_GUARD - -#include <stdint.h> - -#include <string> - -#include <dns/name.h> -#include <dns/rdata.h> - -// BEGIN_ISC_NAMESPACE - -// BEGIN_COMMON_DECLARATIONS -// END_COMMON_DECLARATIONS - -// BEGIN_RDATA_NAMESPACE - -/// \brief \c rdata::AFSDB class represents the AFSDB RDATA as defined %in -/// RFC1183. -/// -/// This class implements the basic interfaces inherited from the abstract -/// \c rdata::Rdata class, and provides trivial accessors specific to the -/// AFSDB RDATA. -class AFSDB : public Rdata { -public: - // BEGIN_COMMON_MEMBERS - // END_COMMON_MEMBERS - - /// \brief Assignment operator. - /// - /// This method never throws an exception. - AFSDB& operator=(const AFSDB& source); - /// - /// Specialized methods - /// - - /// \brief Return the value of the server field. - /// - /// \return A reference to a \c Name class object corresponding to the - /// internal server name. - /// - /// This method never throws an exception. - const Name& getServer() const; - - /// \brief Return the value of the subtype field. - /// - /// This method never throws an exception. - uint16_t getSubtype() const; - -private: - void createFromLexer(MasterLexer& lexer, const Name* origin); - - uint16_t subtype_; - Name server_; -}; - -// END_RDATA_NAMESPACE -// END_ISC_NAMESPACE -// END_HEADER_GUARD - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/rdata/generic/caa_257.cc b/src/lib/dns/rdata/generic/caa_257.cc deleted file mode 100644 index 7f8b455687..0000000000 --- a/src/lib/dns/rdata/generic/caa_257.cc +++ /dev/null @@ -1,298 +0,0 @@ -// Copyright (C) 2014-2016 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#include <config.h> - -#include <boost/lexical_cast.hpp> -#include <boost/algorithm/string.hpp> - -#include <exceptions/exceptions.h> - -#include <util/buffer.h> -#include <dns/name.h> -#include <dns/messagerenderer.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> - -#include <dns/rdata/generic/detail/char_string.h> - -using namespace std; -using boost::lexical_cast; -using namespace isc::util; - -// BEGIN_ISC_NAMESPACE -// BEGIN_RDATA_NAMESPACE - -struct CAAImpl { - // straightforward representation of CAA RDATA fields - CAAImpl(uint8_t flags, const std::string& tag, - const detail::CharStringData& value) : - flags_(flags), - tag_(tag), - value_(value) - { - if ((sizeof(flags) + 1 + tag_.size() + value_.size()) > 65535) { - isc_throw(InvalidRdataLength, - "CAA Value field is too large: " << value_.size()); - } - } - - uint8_t flags_; - const std::string tag_; - const detail::CharStringData value_; -}; - -// helper function for string and lexer constructors -CAAImpl* -CAA::constructFromLexer(MasterLexer& lexer) { - const uint32_t flags = - lexer.getNextToken(MasterToken::NUMBER).getNumber(); - if (flags > 255) { - isc_throw(InvalidRdataText, - "CAA flags field out of range"); - } - - // Tag field must not be empty. - const std::string tag = - lexer.getNextToken(MasterToken::STRING).getString(); - if (tag.empty()) { - isc_throw(InvalidRdataText, "CAA tag field is empty"); - } else if (tag.size() > 255) { - isc_throw(InvalidRdataText, - "CAA tag field is too large: " << tag.size()); - } - - // Value field may be empty. - detail::CharStringData value; - MasterToken token = lexer.getNextToken(MasterToken::QSTRING, true); - if ((token.getType() != MasterToken::END_OF_FILE) && - (token.getType() != MasterToken::END_OF_LINE)) - { - detail::stringToCharStringData(token.getStringRegion(), value); - } - - return (new CAAImpl(flags, tag, value)); -} - -/// \brief Constructor from string. -/// -/// The given string must represent a valid CAA RDATA. There can be -/// extra space characters at the beginning or end of the text (which -/// are simply ignored), but other extra text, including a new line, -/// will make the construction fail with an exception. -/// -/// The Flags, Tag and Value fields must be within their valid ranges, -/// but are not constrained to the values defined in RFC6844. The Tag -/// field must not be empty. -/// -/// \throw InvalidRdataText if any fields are missing, out of their -/// valid ranges, incorrect, or empty. -/// -/// \param caa_str A string containing the RDATA to be created -CAA::CAA(const string& caa_str) : - impl_(NULL) -{ - // We use unique_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::unique_ptr<CAAImpl> impl_ptr; - - try { - std::istringstream ss(caa_str); - MasterLexer lexer; - lexer.pushSource(ss); - - impl_ptr.reset(constructFromLexer(lexer)); - - if (lexer.getNextToken().getType() != MasterToken::END_OF_FILE) { - isc_throw(InvalidRdataText, "extra input text for CAA: " - << caa_str); - } - } catch (const MasterLexer::LexerError& ex) { - isc_throw(InvalidRdataText, "Failed to construct CAA from '" << - caa_str << "': " << ex.what()); - } - - impl_ = impl_ptr.release(); -} - -/// \brief Constructor with a context of MasterLexer. -/// -/// The \c lexer should point to the beginning of valid textual -/// representation of an CAA RDATA. -/// -/// \throw MasterLexer::LexerError General parsing error such as missing -/// field. -/// \throw InvalidRdataText Fields are out of their valid ranges, -/// incorrect, or empty. -/// -/// \param lexer A \c MasterLexer object parsing a master file for the -/// RDATA to be created -CAA::CAA(MasterLexer& lexer, const Name*, - MasterLoader::Options, MasterLoaderCallbacks&) : - impl_(constructFromLexer(lexer)) -{ -} - -/// \brief Constructor from InputBuffer. -/// -/// The passed buffer must contain a valid CAA RDATA. -/// -/// The Flags, Tag and Value fields must be within their valid ranges, -/// but are not constrained to the values defined in RFC6844. The Tag -/// field must not be empty. -CAA::CAA(InputBuffer& buffer, size_t rdata_len) { - if (rdata_len < 2) { - isc_throw(InvalidRdataLength, "CAA record too short"); - } - - const uint8_t flags = buffer.readUint8(); - const uint8_t tag_length = buffer.readUint8(); - rdata_len -= 2; - if (tag_length == 0) { - isc_throw(InvalidRdataText, "CAA tag field is empty"); - } - - if (rdata_len < tag_length) { - isc_throw(InvalidRdataLength, - "RDATA is too short for CAA tag field"); - } - - std::vector<uint8_t> tag_vec(tag_length); - buffer.readData(&tag_vec[0], tag_length); - std::string tag(tag_vec.begin(), tag_vec.end()); - rdata_len -= tag_length; - - detail::CharStringData value; - value.resize(rdata_len); - if (rdata_len > 0) { - buffer.readData(&value[0], rdata_len); - } - - impl_ = new CAAImpl(flags, tag, value); -} - -CAA::CAA(uint8_t flags, const std::string& tag, const std::string& value) : - impl_(NULL) -{ - if (tag.empty()) { - isc_throw(isc::InvalidParameter, - "CAA tag field is empty"); - } else if (tag.size() > 255) { - isc_throw(isc::InvalidParameter, - "CAA tag field is too large: " << tag.size()); - } - - MasterToken::StringRegion region; - region.beg = &value[0]; // note std ensures this works even if str is empty - region.len = value.size(); - - detail::CharStringData value_vec; - detail::stringToCharStringData(region, value_vec); - - impl_ = new CAAImpl(flags, tag, value_vec); -} - -CAA::CAA(const CAA& other) : - Rdata(), impl_(new CAAImpl(*other.impl_)) -{} - -CAA& -CAA::operator=(const CAA& source) { - if (this == &source) { - return (*this); - } - - CAAImpl* newimpl = new CAAImpl(*source.impl_); - delete impl_; - impl_ = newimpl; - - return (*this); -} - -CAA::~CAA() { - delete impl_; -} - -void -CAA::toWire(OutputBuffer& buffer) const { - buffer.writeUint8(impl_->flags_); - - // The constructors must ensure that the tag field is not empty. - assert(!impl_->tag_.empty()); - buffer.writeUint8(impl_->tag_.size()); - buffer.writeData(&impl_->tag_[0], impl_->tag_.size()); - - if (!impl_->value_.empty()) { - buffer.writeData(&impl_->value_[0], - impl_->value_.size()); - } -} - -void -CAA::toWire(AbstractMessageRenderer& renderer) const { - renderer.writeUint8(impl_->flags_); - - // The constructors must ensure that the tag field is not empty. - assert(!impl_->tag_.empty()); - renderer.writeUint8(impl_->tag_.size()); - renderer.writeData(&impl_->tag_[0], impl_->tag_.size()); - - if (!impl_->value_.empty()) { - renderer.writeData(&impl_->value_[0], - impl_->value_.size()); - } -} - -std::string -CAA::toText() const { - std::string result; - - result = lexical_cast<std::string>(static_cast<int>(impl_->flags_)); - result += " " + impl_->tag_; - result += " \"" + detail::charStringDataToString(impl_->value_) + "\""; - - return (result); -} - -int -CAA::compare(const Rdata& other) const { - const CAA& other_caa = dynamic_cast<const CAA&>(other); - - if (impl_->flags_ < other_caa.impl_->flags_) { - return (-1); - } else if (impl_->flags_ > other_caa.impl_->flags_) { - return (1); - } - - // Do a case-insensitive compare of the tag strings. - const int result = boost::ilexicographical_compare - <std::string, std::string>(impl_->tag_, other_caa.impl_->tag_); - if (result != 0) { - return (result); - } - - return (detail::compareCharStringDatas(impl_->value_, - other_caa.impl_->value_)); -} - -uint8_t -CAA::getFlags() const { - return (impl_->flags_); -} - -const std::string& -CAA::getTag() const { - return (impl_->tag_); -} - -const std::vector<uint8_t>& -CAA::getValue() const { - return (impl_->value_); -} - -// END_RDATA_NAMESPACE -// END_ISC_NAMESPACE diff --git a/src/lib/dns/rdata/generic/caa_257.h b/src/lib/dns/rdata/generic/caa_257.h deleted file mode 100644 index 0e81e71c54..0000000000 --- a/src/lib/dns/rdata/generic/caa_257.h +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright (C) 2014-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -// BEGIN_HEADER_GUARD - -#include <stdint.h> - -#include <dns/name.h> -#include <dns/rdata.h> - -#include <string> -#include <vector> - -// BEGIN_ISC_NAMESPACE - -// BEGIN_COMMON_DECLARATIONS -// END_COMMON_DECLARATIONS - -// BEGIN_RDATA_NAMESPACE - -struct CAAImpl; - -class CAA : public Rdata { -public: - // BEGIN_COMMON_MEMBERS - // END_COMMON_MEMBERS - - CAA(uint8_t flags, const std::string& tag, const std::string& value); - CAA& operator=(const CAA& source); - ~CAA(); - - /// - /// Specialized methods - /// - - /// \brief Return the Flags field of the CAA RDATA. - uint8_t getFlags() const; - - /// \brief Return the Tag field of the CAA RDATA. - const std::string& getTag() const; - - /// \brief Return the Value field of the CAA RDATA. - /// - /// Note: The const reference which is returned is valid only during - /// the lifetime of this \c generic::CAA object. It should not be - /// used afterwards. - const std::vector<uint8_t>& getValue() const; - -private: - CAAImpl* constructFromLexer(MasterLexer& lexer); - - CAAImpl* impl_; -}; - -// END_RDATA_NAMESPACE -// END_ISC_NAMESPACE -// END_HEADER_GUARD - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/rdata/generic/cname_5.cc b/src/lib/dns/rdata/generic/cname_5.cc deleted file mode 100644 index 71cb4dc0c1..0000000000 --- a/src/lib/dns/rdata/generic/cname_5.cc +++ /dev/null @@ -1,125 +0,0 @@ -// Copyright (C) 2010-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#include <config.h> - -#include <string> - -#include <util/buffer.h> -#include <dns/name.h> -#include <dns/messagerenderer.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> - -#include <dns/rdata/generic/detail/lexer_util.h> - -using namespace std; -using namespace isc::util; -using isc::dns::rdata::generic::detail::createNameFromLexer; - -// BEGIN_ISC_NAMESPACE -// BEGIN_RDATA_NAMESPACE - -/// \brief Constructor from string. -/// -/// The given string must represent a valid CNAME 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 CNAME must be absolute since there's no parameter that specifies -/// the origin name; if it is not absolute, \c MissingNameOrigin -/// exception will be thrown. These must not be represented as a quoted -/// string. -/// -/// \throw Others Exception from the Name and RRTTL constructors. -/// \throw InvalidRdataText Other general syntax errors. -CNAME::CNAME(const std::string& namestr) : - // Fill in dummy name and replace it soon below. - cname_(Name::ROOT_NAME()) -{ - try { - std::istringstream ss(namestr); - MasterLexer lexer; - lexer.pushSource(ss); - - cname_ = createNameFromLexer(lexer, NULL); - - if (lexer.getNextToken().getType() != MasterToken::END_OF_FILE) { - isc_throw(InvalidRdataText, "extra input text for CNAME: " - << namestr); - } - } catch (const MasterLexer::LexerError& ex) { - isc_throw(InvalidRdataText, "Failed to construct CNAME from '" << - namestr << "': " << ex.what()); - } -} - -CNAME::CNAME(InputBuffer& buffer, size_t) : - Rdata(), cname_(buffer) -{ - // we don't need rdata_len for parsing. if necessary, the caller will - // check consistency. -} - -/// \brief Constructor with a context of MasterLexer. -/// -/// The \c lexer should point to the beginning of valid textual -/// representation of a CNAME RDATA. The CNAME field can be -/// non-absolute if \c origin is non-NULL, in which case \c origin is -/// used to make it absolute. It must not be represented as a quoted -/// string. -/// -/// \throw MasterLexer::LexerError General parsing error such as missing field. -/// \throw Other Exceptions from the Name and RRTTL constructors if -/// construction of textual fields as these objects fail. -/// -/// \param lexer A \c MasterLexer object parsing a master file for the -/// RDATA to be created -/// \param origin If non NULL, specifies the origin of CNAME when it -/// is non-absolute. -CNAME::CNAME(MasterLexer& lexer, const Name* origin, - MasterLoader::Options, MasterLoaderCallbacks&) : - cname_(createNameFromLexer(lexer, origin)) -{} - -CNAME::CNAME(const CNAME& other) : - Rdata(), cname_(other.cname_) -{} - -CNAME::CNAME(const Name& cname) : - cname_(cname) -{} - -void -CNAME::toWire(OutputBuffer& buffer) const { - cname_.toWire(buffer); -} - -void -CNAME::toWire(AbstractMessageRenderer& renderer) const { - renderer.writeName(cname_); -} - -string -CNAME::toText() const { - return (cname_.toText()); -} - -int -CNAME::compare(const Rdata& other) const { - const CNAME& other_cname = dynamic_cast<const CNAME&>(other); - - return (compareNames(cname_, other_cname.cname_)); -} - -const Name& -CNAME::getCname() const { - return (cname_); -} - -// END_RDATA_NAMESPACE -// END_ISC_NAMESPACE diff --git a/src/lib/dns/rdata/generic/cname_5.h b/src/lib/dns/rdata/generic/cname_5.h deleted file mode 100644 index 2149340709..0000000000 --- a/src/lib/dns/rdata/generic/cname_5.h +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (C) 2010-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -// BEGIN_HEADER_GUARD - -#include <string> - -#include <dns/name.h> -#include <dns/rdata.h> - -// BEGIN_ISC_NAMESPACE - -// BEGIN_COMMON_DECLARATIONS -// END_COMMON_DECLARATIONS - -// BEGIN_RDATA_NAMESPACE - -class CNAME : public Rdata { -public: - // BEGIN_COMMON_MEMBERS - // END_COMMON_MEMBERS - - // CNAME specific methods - CNAME(const Name& cname); - const Name& getCname() const; -private: - Name cname_; -}; - -// END_RDATA_NAMESPACE -// END_ISC_NAMESPACE -// END_HEADER_GUARD - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/rdata/generic/detail/char_string.cc b/src/lib/dns/rdata/generic/detail/char_string.cc deleted file mode 100644 index 1d150ed8e5..0000000000 --- a/src/lib/dns/rdata/generic/detail/char_string.cc +++ /dev/null @@ -1,267 +0,0 @@ -// Copyright (C) 2012-2024 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#include <config.h> - -#include <exceptions/exceptions.h> - -#include <dns/exceptions.h> -#include <dns/rdata.h> -#include <dns/master_lexer.h> -#include <dns/rdata/generic/detail/char_string.h> -#include <util/buffer.h> - -#include <boost/lexical_cast.hpp> - -#include <cassert> -#include <cctype> -#include <cstring> -#include <vector> - -#include <stdint.h> - -namespace isc { -namespace dns { -namespace rdata { -namespace generic { -namespace detail { - -namespace { -// Convert a DDD form to the corresponding integer -int -decimalToNumber(const char* s, const char* s_end) { - if (s_end - s < 3) { - isc_throw(InvalidRdataText, "Escaped digits too short"); - } - - const std::string num_str(s, s + 3); - try { - const int i = boost::lexical_cast<int>(num_str); - if (i > 255) { - isc_throw(InvalidRdataText, "Escaped digits too large: " - << num_str); - } - return (i); - } catch (const boost::bad_lexical_cast&) { - isc_throw(InvalidRdataText, - "Invalid form for escaped digits: " << num_str); - } -} -} - -void -stringToCharString(const MasterToken::StringRegion& str_region, - CharString& result) -{ - // make a space for the 1-byte length field; filled in at the end - result.push_back(0); - - 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 '\\'"); - } - if (result.size() > MAX_CHARSTRING_LEN + 1) { // '+ 1' due to the len field - isc_throw(CharStringTooLong, "character-string is too long: " << - (result.size() - 1) << "(+1) characters"); - } - result[0] = result.size() - 1; -} - -void -stringToCharStringData(const MasterToken::StringRegion& str_region, - CharStringData& result) -{ - bool escape = false; - const char* s = str_region.beg; - const char* const s_end = str_region.beg + str_region.len; - - for (size_t n = str_region.len; n != 0; --n, ++s) { - int c = (*s & 0xff); - if (escape && std::isdigit(c) != 0) { - c = decimalToNumber(s, s_end); - // decimalToNumber() already throws if (s_end - s) is less - // than 3, so the following assertion is unnecessary. But we - // assert it anyway. 'n' is an unsigned type (size_t) and - // can underflow. - assert(n >= 3); - // 'n' and 's' are also updated by 1 in the for statement's - // expression, so we update them by 2 instead of 3 here. - n -= 2; - s += 2; - } else if (!escape && c == '\\') { - escape = true; - continue; - } - escape = false; - result.push_back(c); - } - if (escape) { // terminated by non-escaped '\' - isc_throw(InvalidRdataText, "character-string ends with '\\'"); - } -} - -std::string -charStringToString(const CharString& char_string) { - std::string s; - bool first = true; - for (auto const& it : char_string) { - if (first) { - first = false; - continue; - } - 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); -} - -std::string -charStringDataToString(const CharStringData& char_string) { - std::string s; - for (auto const& it : char_string) { - 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) { - return (0); - } - if (self.size() == 0) { - return (-1); - } - if (other.size() == 0) { - return (1); - } - const size_t self_len = self[0]; - const size_t other_len = other[0]; - const size_t cmp_len = std::min(self_len, other_len); - if (cmp_len == 0) { - if (self_len < other_len) { - return (-1); - } else if (self_len > other_len) { - return (1); - } else { - return (0); - } - } - const int cmp = std::memcmp(&self[1], &other[1], 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); - } -} - -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) { - if (rdata_len < 1 || buffer.getLength() - buffer.getPosition() < 1) { - isc_throw(isc::dns::DNSMessageFORMERR, - "insufficient data to read character-string length"); - } - const uint8_t len = buffer.readUint8(); - if (rdata_len < len + 1) { - isc_throw(isc::dns::DNSMessageFORMERR, - "character string length is too large: " << - static_cast<int>(len)); - } - if (buffer.getLength() - buffer.getPosition() < len) { - isc_throw(isc::dns::DNSMessageFORMERR, - "not enough data in buffer to read character-string of len" - << static_cast<int>(len)); - } - - target.resize(len + 1); - target[0] = len; - buffer.readData(&target[0] + 1, len); - - return (len + 1); -} - -} // end of detail -} // end of generic -} // end of rdata -} // end of dns -} // end of isc diff --git a/src/lib/dns/rdata/generic/detail/char_string.h b/src/lib/dns/rdata/generic/detail/char_string.h deleted file mode 100644 index 2ad12fb400..0000000000 --- a/src/lib/dns/rdata/generic/detail/char_string.h +++ /dev/null @@ -1,140 +0,0 @@ -// Copyright (C) 2012-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef DNS_RDATA_CHARSTRING_H -#define DNS_RDATA_CHARSTRING_H 1 - -#include <dns/master_lexer.h> - -#include <string> -#include <vector> -#include <algorithm> -#include <stdint.h> - -namespace isc { -namespace dns { -namespace rdata { -namespace generic { -namespace detail { - -/// \brief Type for DNS character string. -/// -/// A character string can contain any unsigned 8-bit value, so this cannot -/// be the bare char basis. -typedef std::vector<uint8_t> CharString; - -/// \brief Type for DNS character string without the length prefix. -typedef std::vector<uint8_t> CharStringData; - -/// \brief Convert a DNS character-string into corresponding binary data. -/// -/// This helper function takes a string object that is expected to be a -/// textual representation of a valid DNS character-string, and dumps -/// the corresponding binary sequence in the given placeholder (passed -/// via the \c result parameter). It handles escape notations of -/// character-strings with a backslash ('\'), and checks the length -/// restriction. -/// -/// \throw CharStringTooLong The resulting binary data are too large for a -/// valid character-string. -/// \throw InvalidRdataText Other 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 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 -/// character string into a textual string representation, escaping any -/// special characters in the process. For example, characters like -/// double-quotes, semi-colon and backspace are prefixed with backspace -/// character, and characters not in the printable range of [0x20, 0x7e] -/// (inclusive) are converted to the \xxx 3-digit decimal -/// representation. -/// -/// \param char_string The \c CharString to convert. -/// \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 -/// \param other The CharString 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 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 -/// format) and places the result in the given \c CharString object. -/// Since this is expected to be used in message parsing, the exception it -/// raises is of that type. -/// -/// On success, the buffer position is advanced to the end of the char-string, -/// and the number of bytes read is returned. -/// -/// \param buffer The buffer to read from. -/// \param rdata_len The total size of the rr's rdata currently being read -/// (used for integrity checks in the wire data) -/// \param target The \c CharString where the result will be stored. Any -/// existing data in the target will be overwritten. -/// \throw DNSMessageFORMERR If the available data is not enough to read -/// the character-string, or if the character-string length is out of bounds -/// \return The number of bytes read -size_t bufferToCharString(isc::util::InputBuffer& buffer, size_t rdata_len, - CharString& target); - - -} // namespace detail -} // namespace generic -} // namespace rdata -} // namespace dns -} // namespace isc -#endif // DNS_RDATA_CHARSTRING_H - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/rdata/generic/detail/ds_like.h b/src/lib/dns/rdata/generic/detail/ds_like.h deleted file mode 100644 index 4d8c2ea3e8..0000000000 --- a/src/lib/dns/rdata/generic/detail/ds_like.h +++ /dev/null @@ -1,277 +0,0 @@ -// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef DS_LIKE_H -#define DS_LIKE_H 1 - -#include <stdint.h> - -#include <iostream> -#include <sstream> -#include <string> -#include <vector> - -#include <boost/lexical_cast.hpp> - -#include <exceptions/exceptions.h> - -#include <dns/messagerenderer.h> -#include <dns/name.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> - -namespace isc { -namespace dns { -namespace rdata { -namespace generic { -namespace detail { - -/// \brief \c rdata::DSLikeImpl class represents the DS-like RDATA for DS -/// and DLV types. -/// -/// This class implements the basic interfaces inherited by the DS and DLV -/// classes from the abstract \c rdata::Rdata class, and provides trivial -/// accessors to DS-like RDATA. -template <class Type, uint16_t typeCode> class DSLikeImpl { - // Common sequence of toWire() operations used for the two versions of - // toWire(). - template <typename Output> - void - toWireCommon(Output& output) const { - output.writeUint16(tag_); - output.writeUint8(algorithm_); - output.writeUint8(digest_type_); - output.writeData(&digest_[0], digest_.size()); - } - -public: - /// \brief Constructor from string. - /// - /// The given string must represent a valid DS-like 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 tag field must be a valid decimal representation of an - /// unsigned 16-bit integer. The protocol and algorithm fields must - /// be valid decimal representations of unsigned 8-bit integers - /// respectively. The digest field may contain whitespace. - /// - /// \throw InvalidRdataText if any fields are out of their valid range. - /// - /// \param ds_str A string containing the RDATA to be created - DSLikeImpl(const std::string& ds_str) { - try { - std::istringstream ss(ds_str); - MasterLexer lexer; - lexer.pushSource(ss); - - constructFromLexer(lexer); - - if (lexer.getNextToken().getType() != MasterToken::END_OF_FILE) { - isc_throw(InvalidRdataText, - "Extra input text for " << RRType(typeCode) << ": " - << ds_str); - } - } catch (const MasterLexer::LexerError& ex) { - isc_throw(InvalidRdataText, - "Failed to construct " << RRType(typeCode) << " from '" << - ds_str << "': " << ex.what()); - } - } - - /// \brief Constructor with a context of MasterLexer. - /// - /// The \c lexer should point to the beginning of valid textual - /// representation of a DS-like RDATA. - /// - /// The tag field must be a valid decimal representation of an - /// unsigned 16-bit integer. The protocol and algorithm fields must - /// be valid decimal representations of unsigned 8-bit integers - /// respectively. - /// - /// \throw MasterLexer::LexerError General parsing error such as - /// missing field. - /// \throw InvalidRdataText if any fields are out of their valid range. - /// - /// \param lexer A \c MasterLexer object parsing a master file for the - /// RDATA to be created - DSLikeImpl(MasterLexer& lexer, const Name*, MasterLoader::Options, - MasterLoaderCallbacks&) - { - constructFromLexer(lexer); - } - -private: - void constructFromLexer(MasterLexer& lexer) { - const uint32_t tag = - lexer.getNextToken(MasterToken::NUMBER).getNumber(); - if (tag > 0xffff) { - isc_throw(InvalidRdataText, - "Invalid " << RRType(typeCode) << " tag: " << tag); - } - - const uint32_t algorithm = - lexer.getNextToken(MasterToken::NUMBER).getNumber(); - if (algorithm > 0xff) { - isc_throw(InvalidRdataText, - "Invalid " << RRType(typeCode) << " algorithm: " - << algorithm); - } - - const uint32_t digest_type = - lexer.getNextToken(MasterToken::NUMBER).getNumber(); - if (digest_type > 0xff) { - isc_throw(InvalidRdataText, - "Invalid " << RRType(typeCode) << " digest type: " - << digest_type); - } - - std::string digest; - while (true) { - const MasterToken& token = lexer.getNextToken(); - if (token.getType() != MasterToken::STRING) { - break; - } - digest.append(token.getString()); - } - - lexer.ungetToken(); - - if (digest.size() == 0) { - isc_throw(InvalidRdataText, - "Missing " << RRType(typeCode) << " digest"); - } - - tag_ = tag; - algorithm_ = algorithm; - digest_type_ = digest_type; - decodeHex(digest, digest_); - } - -public: - /// \brief Constructor from wire-format data. - /// - /// \param buffer A buffer storing the wire format data. - /// \param rdata_len The length of the RDATA in bytes, normally expected - /// to be the value of the RDLENGTH field of the corresponding RR. - /// - /// <b>Exceptions</b> - /// - /// \c InvalidRdataLength is thrown if the input data is too short for the - /// type. - DSLikeImpl(InputBuffer& buffer, size_t rdata_len) { - if (rdata_len < 4) { - isc_throw(InvalidRdataLength, RRType(typeCode) << " too short"); - } - - tag_ = buffer.readUint16(); - algorithm_ = buffer.readUint8(); - digest_type_ = buffer.readUint8(); - - rdata_len -= 4; - digest_.resize(rdata_len); - buffer.readData(&digest_[0], rdata_len); - } - - /// \brief The copy constructor. - /// - /// Trivial for now, we could've used the default one. - DSLikeImpl(const DSLikeImpl& source) : - tag_(source.tag_), - algorithm_(source.algorithm_), - digest_type_(source.digest_type_), - digest_(source.digest_) - {} - - /// \brief Convert the DS-like data to a string. - /// - /// \return A \c string object that represents the DS-like data. - std::string - toText() const { - using namespace boost; - return (lexical_cast<string>(static_cast<int>(tag_)) + - " " + lexical_cast<string>(static_cast<int>(algorithm_)) + - " " + lexical_cast<string>(static_cast<int>(digest_type_)) + - " " + encodeHex(digest_)); - } - - /// \brief Render the DS-like data in the wire format to an OutputBuffer - /// object. - /// - /// \param buffer An output buffer to store the wire data. - void - toWire(OutputBuffer& buffer) const { - toWireCommon(buffer); - } - - /// \brief Render the DS-like data in the wire format to an - /// AbstractMessageRenderer object. - /// - /// \param renderer A renderer object to send the wire data to. - void - toWire(AbstractMessageRenderer& renderer) const { - toWireCommon(renderer); - } - - /// \brief Compare two instances of DS-like RDATA. - /// - /// It is up to the caller to make sure that \c other is an object of the - /// same \c DSLikeImpl class. - /// - /// \param other the right-hand operand to compare against. - /// \return < 0 if \c this would be sorted before \c other. - /// \return 0 if \c this is identical to \c other in terms of sorting - /// order. - /// \return > 0 if \c this would be sorted after \c other. - int - compare(const DSLikeImpl& other_ds) const { - if (tag_ != other_ds.tag_) { - return (tag_ < other_ds.tag_ ? -1 : 1); - } - if (algorithm_ != other_ds.algorithm_) { - return (algorithm_ < other_ds.algorithm_ ? -1 : 1); - } - if (digest_type_ != other_ds.digest_type_) { - return (digest_type_ < other_ds.digest_type_ ? -1 : 1); - } - - size_t this_len = digest_.size(); - size_t other_len = other_ds.digest_.size(); - size_t cmplen = min(this_len, other_len); - int cmp = memcmp(&digest_[0], &other_ds.digest_[0], cmplen); - if (cmp != 0) { - return (cmp); - } else { - return ((this_len == other_len) - ? 0 : (this_len < other_len) ? -1 : 1); - } - } - - /// \brief Accessors - uint16_t - getTag() const { - return (tag_); - } - -private: - // straightforward representation of DS RDATA fields - uint16_t tag_; - uint8_t algorithm_; - uint8_t digest_type_; - std::vector<uint8_t> digest_; -}; - -} -} -} -} -} -#endif // DS_LIKE_H - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/rdata/generic/detail/lexer_util.h b/src/lib/dns/rdata/generic/detail/lexer_util.h index 29b6c31c84..4e3d120c2a 100644 --- a/src/lib/dns/rdata/generic/detail/lexer_util.h +++ b/src/lib/dns/rdata/generic/detail/lexer_util.h @@ -5,7 +5,7 @@ // file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef DNS_RDATA_LEXER_UTIL_H -#define DNS_RDATA_LEXER_UTIL_H 1 +#define DNS_RDATA_LEXER_UTIL_H #include <dns/name.h> #include <dns/master_lexer.h> @@ -56,7 +56,3 @@ createNameFromLexer(MasterLexer& lexer, const Name* origin) { } // namespace dns } // namespace isc #endif // DNS_RDATA_LEXER_UTIL_H - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/rdata/generic/detail/nsec3param_common.cc b/src/lib/dns/rdata/generic/detail/nsec3param_common.cc deleted file mode 100644 index 6dada443a9..0000000000 --- a/src/lib/dns/rdata/generic/detail/nsec3param_common.cc +++ /dev/null @@ -1,115 +0,0 @@ -// Copyright (C) 2012-2024 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#include <config.h> - -#include <exceptions/exceptions.h> - -#include <util/encode/encode.h> -#include <util/buffer.h> - -#include <dns/exceptions.h> -#include <dns/rdata.h> -#include <dns/rdata/generic/detail/nsec3param_common.h> - -#include <boost/lexical_cast.hpp> - -#include <sstream> -#include <vector> -#include <stdint.h> - -using namespace std; -using namespace isc::util; -using namespace isc::util::encode; - -namespace isc { -namespace dns { -namespace rdata { -namespace generic { -namespace detail { -namespace nsec3 { - -ParseNSEC3ParamResult -parseNSEC3ParamFromLexer(const char* const rrtype_name, - MasterLexer& lexer, vector<uint8_t>& salt) -{ - const uint32_t hashalg = - lexer.getNextToken(MasterToken::NUMBER).getNumber(); - if (hashalg > 0xff) { - isc_throw(InvalidRdataText, rrtype_name << - " hash algorithm out of range: " << hashalg); - } - - const uint32_t flags = - lexer.getNextToken(MasterToken::NUMBER).getNumber(); - if (flags > 0xff) { - isc_throw(InvalidRdataText, rrtype_name << " flags out of range: " << - flags); - } - - const uint32_t iterations = - lexer.getNextToken(MasterToken::NUMBER).getNumber(); - if (iterations > 0xffff) { - isc_throw(InvalidRdataText, rrtype_name << - " iterations out of range: " << iterations); - } - - const string salthex = - lexer.getNextToken(MasterToken::STRING).getString(); - - // Salt is up to 255 bytes, and space is not allowed in the HEX encoding, - // so the encoded string cannot be longer than the double of max length - // of the actual salt. - if (salthex.size() > 255 * 2) { - isc_throw(InvalidRdataText, rrtype_name << " salt is too long: " - << salthex.size() << " (encoded) bytes"); - } - if (salthex != "-") { // "-" means a 0-length salt - decodeHex(salthex, salt); - } - - return (ParseNSEC3ParamResult(hashalg, flags, iterations)); -} - -ParseNSEC3ParamResult -parseNSEC3ParamWire(const char* const rrtype_name, - InputBuffer& buffer, - size_t& rdata_len, std::vector<uint8_t>& salt) -{ - // NSEC3/NSEC3PARAM RR must have at least 5 octets: - // hash algorithm(1), flags(1), iteration(2), saltlen(1) - if (rdata_len < 5) { - isc_throw(DNSMessageFORMERR, rrtype_name << " too short, length: " - << rdata_len); - } - - const uint8_t hashalg = buffer.readUint8(); - const uint8_t flags = buffer.readUint8(); - const uint16_t iterations = buffer.readUint16(); - - const uint8_t saltlen = buffer.readUint8(); - rdata_len -= 5; - if (rdata_len < saltlen) { - isc_throw(DNSMessageFORMERR, rrtype_name << - " salt length is too large: " << - static_cast<unsigned int>(saltlen)); - } - - salt.resize(saltlen); - if (saltlen > 0) { - buffer.readData(&salt[0], saltlen); - rdata_len -= saltlen; - } - - return (ParseNSEC3ParamResult(hashalg, flags, iterations)); -} - -} // end of nsec3 -} // end of detail -} // end of generic -} // end of rdata -} // end of dns -} // end of isc diff --git a/src/lib/dns/rdata/generic/detail/nsec3param_common.h b/src/lib/dns/rdata/generic/detail/nsec3param_common.h deleted file mode 100644 index 89b2596c40..0000000000 --- a/src/lib/dns/rdata/generic/detail/nsec3param_common.h +++ /dev/null @@ -1,123 +0,0 @@ -// Copyright (C) 2012-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef NSEC3PARAM_COMMON_H -#define NSEC3PARAM_COMMON_H 1 - -#include <dns/master_lexer.h> - -#include <util/buffer.h> - -#include <stdint.h> -#include <vector> - -namespace isc { -namespace dns { -namespace rdata { -namespace generic { -namespace detail { -namespace nsec3 { - -/// \file -/// -/// This helper module provides some utilities that handle NSEC3 and -/// NSEC3PARAM RDATA. They share the first few fields, and some operations -/// on these fields are sufficiently complicated, so it would make sense to -/// consolidate the processing logic into a single implementation module. -/// -/// The functions defined here are essentially private and are only expected -/// to be called from the \c NSEC3 and \c NSEC3PARAM class implementations. - -/// \brief Result values of the utilities. -/// -/// This structure encapsulates a tuple of NSEC3/NSEC3PARAM algorithm, -/// flags and iterations field values. This is used as the return value -/// of the utility functions defined in this module so the caller can -/// use it for constructing the corresponding RDATA. -struct ParseNSEC3ParamResult { - ParseNSEC3ParamResult(uint8_t param_algorithm, uint8_t param_flags, - uint16_t param_iterations) : - algorithm(param_algorithm), flags(param_flags), - iterations(param_iterations) - {} - const uint8_t algorithm; - const uint8_t flags; - const uint16_t iterations; -}; - -/// \brief Convert textual representation of NSEC3 parameters. -/// -/// This function takes an input MasterLexer that points at a complete -/// textual representation of an NSEC3 or NSEC3PARAM RDATA and parses it -/// extracting the hash algorithm, flags, iterations, and salt fields. -/// -/// The first three fields are returned as the return value of this function. -/// The salt will be stored in the given vector. The vector is expected -/// to be empty, but if not, the existing content will be overridden. -/// -/// On successful return the given MasterLexer will reach the end of the -/// salt field. -/// -/// \exception isc::BadValue The salt is not a valid hex string. -/// \exception InvalidRdataText The given RDATA is otherwise invalid for -/// NSEC3 or NSEC3PARAM fields. -/// \exception MasterLexer::LexerError There was a syntax error reading -/// a field from the MasterLexer. -/// -/// \param rrtype_name Either "NSEC3" or "NSEC3PARAM"; used as part of -/// exception messages. -/// \param lexer The MasterLexer to read NSEC3 parameter fields from. -/// \param salt A placeholder for the salt field value of the RDATA. -/// Expected to be empty, but it's not checked (and will be overridden). -/// -/// \return The hash algorithm, flags, iterations in the form of -/// ParseNSEC3ParamResult. -ParseNSEC3ParamResult parseNSEC3ParamFromLexer(const char* const rrtype_name, - isc::dns::MasterLexer& lexer, - std::vector<uint8_t>& salt); - -/// \brief Extract NSEC3 parameters from wire-format data. -/// -/// This function takes an input buffer that stores wire-format NSEC3 or -/// NSEC3PARAM RDATA and parses it extracting the hash algorithm, flags, -/// iterations, and salt fields. -/// -/// The first three fields are returned as the return value of this function. -/// The salt will be stored in the given vector. The vector is expected -/// to be empty, but if not, the existing content will be overridden. -/// -/// On successful return the input buffer will point to the end of the -/// salt field; rdata_len will be the length of the rest of RDATA -/// (in the case of a valid NSEC3PARAM, it should be 0). -/// -/// \exception DNSMessageFORMERR The wire data is invalid. -/// -/// \param rrtype_name Either "NSEC3" or "NSEC3PARAM"; used as part of -/// exception messages. -/// \param buffer An input buffer that stores wire-format RDATA. It must -/// point to the beginning of the data. -/// \param rdata_len The total length of the RDATA. -/// \param salt A placeholder for the salt field value of the RDATA. -/// Expected to be empty, but it's not checked (and will be overridden). -/// -/// \return The hash algorithm, flags, iterations in the form of -/// ParseNSEC3ParamResult. -ParseNSEC3ParamResult parseNSEC3ParamWire(const char* const rrtype_name, - isc::util::InputBuffer& buffer, - size_t& rdata_len, - std::vector<uint8_t>& salt); -} -} -} -} -} -} - -#endif // NSEC3PARAM_COMMON_H - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/rdata/generic/detail/nsec_bitmap.cc b/src/lib/dns/rdata/generic/detail/nsec_bitmap.cc deleted file mode 100644 index d02c11d04e..0000000000 --- a/src/lib/dns/rdata/generic/detail/nsec_bitmap.cc +++ /dev/null @@ -1,169 +0,0 @@ -// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#include <config.h> - -#include <exceptions/exceptions.h> - -#include <dns/exceptions.h> -#include <dns/rdata.h> -#include <dns/rrtype.h> - -#include <cassert> -#include <sstream> -#include <vector> -#include <cstring> -#include <stdint.h> - -using namespace std; - -namespace isc { -namespace dns { -namespace rdata { -namespace generic { -namespace detail { -namespace nsec { -void -checkRRTypeBitmaps(const char* const rrtype_name, - const vector<uint8_t>& typebits) -{ - bool first = true; - unsigned int lastblock = 0; - const size_t total_len = typebits.size(); - size_t i = 0; - - while (i < total_len) { - if (i + 2 > total_len) { - isc_throw(DNSMessageFORMERR, rrtype_name << - " RDATA from wire: incomplete bit map field"); - } - const unsigned int block = typebits[i]; - const size_t len = typebits[i + 1]; - // Check that bitmap window blocks are in the correct order. - if (!first && block <= lastblock) { - isc_throw(DNSMessageFORMERR, rrtype_name << - " RDATA from wire: Disordered window blocks found: " - << lastblock << " then " << block); - } - // Check for legal length - if (len < 1 || len > 32) { - isc_throw(DNSMessageFORMERR, rrtype_name << - " RDATA from wire: Invalid bitmap length: " << len); - } - // Check for overflow. - i += 2; - if (i + len > total_len) { - isc_throw(DNSMessageFORMERR, rrtype_name << - " RDATA from wire: bitmap length too large: " << len); - } - // The last octet of the bitmap must be non zero. - if (typebits[i + len - 1] == 0) { - isc_throw(DNSMessageFORMERR, rrtype_name << - " RDATA from wire: bitmap ending an all-zero byte"); - } - - i += len; - lastblock = block; - first = false; - } -} - -void -buildBitmapsFromLexer(const char* const rrtype_name, - MasterLexer& lexer, vector<uint8_t>& typebits, - bool allow_empty) -{ - uint8_t bitmap[8 * 1024]; // 64k bits - memset(bitmap, 0, sizeof(bitmap)); - - bool have_rrtypes = false; - std::string type_str; - 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 is now assured to be of type STRING. - - have_rrtypes = true; - token.getString(type_str); - try { - const int code = RRType(type_str).getCode(); - bitmap[code / 8] |= (0x80 >> (code % 8)); - } catch (const InvalidRRType&) { - isc_throw(InvalidRdataText, "Invalid RRtype in " - << rrtype_name << " bitmap: " << type_str); - } - } - - lexer.ungetToken(); - - if (!have_rrtypes) { - if (allow_empty) { - return; - } - isc_throw(InvalidRdataText, - rrtype_name << - " record does not end with RR type mnemonic"); - } - - for (int window = 0; window < 256; ++window) { - int octet; - for (octet = 31; octet >= 0; octet--) { - if (bitmap[window * 32 + octet] != 0) { - break; - } - } - if (octet < 0) { - continue; - } - typebits.push_back(window); - typebits.push_back(octet + 1); - for (int i = 0; i <= octet; ++i) { - typebits.push_back(bitmap[window * 32 + i]); - } - } -} - -void -bitmapsToText(const vector<uint8_t>& typebits, ostringstream& oss) { - // In the following loop we use string::at() rather than operator[]. - // Since the index calculation is a bit complicated, it will be safer - // and easier to find a bug (if any). Note that this conversion method - // is generally not expected to be very efficient, so the slight overhead - // of at() should be acceptable. - const size_t typebits_len = typebits.size(); - size_t len = 0; - for (size_t i = 0; i < typebits_len; i += len) { - assert(i + 2 <= typebits.size()); - const unsigned int block = typebits.at(i); - len = typebits.at(i + 1); - assert(len > 0 && len <= 32); - i += 2; - for (size_t j = 0; j < len; ++j) { - if (typebits.at(i + j) == 0) { - continue; - } - for (size_t k = 0; k < 8; ++k) { - if ((typebits.at(i + j) & (0x80 >> k)) == 0) { - continue; - } - const unsigned int t = block * 256 + j * 8 + k; - assert(t < 65536); - oss << " " << RRType(t); - } - } - } -} -} -} -} -} -} -} diff --git a/src/lib/dns/rdata/generic/detail/nsec_bitmap.h b/src/lib/dns/rdata/generic/detail/nsec_bitmap.h deleted file mode 100644 index 4e073a08af..0000000000 --- a/src/lib/dns/rdata/generic/detail/nsec_bitmap.h +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef NSECBITMAP_H -#define NSECBITMAP_H 1 - -#include <dns/master_lexer.h> - -#include <stdint.h> - -#include <sstream> -#include <vector> - -namespace isc { -namespace dns { -namespace rdata { -namespace generic { -namespace detail { -namespace nsec { - -/// \file -/// -/// This helper module provides some utilities that handle NSEC and NSEC3 -/// type bitmaps. The format and processing of the type bitmaps are generally -/// the same for these two RRs, so it would make sense to consolidate -/// the processing logic into a single implementation module. -/// -/// The functions defined here are essentially private and are only expected -/// to be called from the \c NSEC and \c NSEC3 class implementations. - -/// \brief Check if a given "type bitmap" for NSEC/NSEC3 is valid. -/// -/// This function checks given wire format data (stored in a -/// \c std::vector) is a valid type bitmaps used for the NSEC and NSEC3 RRs -/// according to RFC4034 and RFC5155. -/// -/// \exception DNSMessageFORMERR The bitmap is not valid. -/// -/// \param rrtype_name Either "NSEC" or "NSEC3"; used as part of exception -/// messages. -/// \param typebits The type bitmaps in wire format. The size of vector -/// is the total length of the bitmaps. -void checkRRTypeBitmaps(const char* const rrtype_name, - const std::vector<uint8_t>& typebits); - -/// \brief Convert textual sequence of RR types read from a lexer into -/// type bitmaps. -/// -/// See the other variant above for description. If \c allow_empty is -/// true and there are no mnemonics, \c typebits is left untouched. -/// -/// \exception InvalidRdataText Data read from the given lexer does not -/// meet the assumption (e.g. including invalid form of RR type, not -/// ending with an RR type string). -/// -/// \param rrtype_name Either "NSEC" or "NSEC3"; used as part of exception -/// messages. -/// \param lexer MasterLexer that provides consists of a complete -/// sequence of textual lexemes of RR types for which the corresponding -/// bits are set. -/// \param typebits A placeholder for the resulting bitmaps. Expected to be -/// empty, but it's not checked. -/// \param allow_empty If true, the function simply returns if no RR -/// type mnemonics are found. Otherwise, it throws an exception if no RR -/// type mnemonics are found. -void buildBitmapsFromLexer(const char* const rrtype_name, - isc::dns::MasterLexer& lexer, - std::vector<uint8_t>& typebits, - bool allow_empty = false); - -/// \brief Convert type bitmaps to textual sequence of RR types. -/// -/// This function converts wire-format data of type bitmaps for NSEC/NSEC3 -/// into a sequence of corresponding RR type strings, and inserts them -/// into the given output stream with separating them by a single space -/// character. -/// -/// This function assumes the given bitmaps are valid in terms of RFC4034 -/// and RFC5155 (in practice, it assumes it's from a validly constructed -/// NSEC or NSEC3 object); if it detects a format error, it aborts the -/// program with assert(). -/// -/// \param typebits The type bitmaps in wire format. The size of vector -/// is the total length of the bitmaps. -/// \param oss The output stream to which the converted RR type sequence -/// are to be inserted. -void bitmapsToText(const std::vector<uint8_t>& typebits, - std::ostringstream& oss); -} -} -} -} -} -} - -#endif // NSECBITMAP_H - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/rdata/generic/detail/txt_like.h b/src/lib/dns/rdata/generic/detail/txt_like.h deleted file mode 100644 index 5801b095e3..0000000000 --- a/src/lib/dns/rdata/generic/detail/txt_like.h +++ /dev/null @@ -1,237 +0,0 @@ -// Copyright (C) 2011-2015,2021 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef TXT_LIKE_H -#define TXT_LIKE_H 1 - -#include <dns/master_lexer.h> -#include <dns/rdata/generic/detail/char_string.h> - -#include <stdint.h> - -#include <string> -#include <sstream> -#include <vector> - -namespace isc { -namespace dns { -namespace rdata { -namespace generic { -namespace detail { - -/// \brief \c rdata::TXTLikeImpl class represents the TXT-like RDATA for TXT -/// and SPF types. -/// -/// This class implements the basic interfaces inherited by the TXT and SPF -/// classes from the abstract \c rdata::Rdata class, and provides trivial -/// accessors to TXT-like RDATA. -template<class Type, uint16_t typeCode>class TXTLikeImpl { -public: - /// \brief Constructor from wire-format data. - /// - /// \param buffer A buffer storing the wire format data. - /// \param rdata_len The length of the RDATA in bytes, normally expected - /// to be the value of the RDLENGTH field of the corresponding RR. - /// - /// <b>Exceptions</b> - /// - /// \c InvalidRdataLength is thrown if rdata_len exceeds the maximum. - /// \c DNSMessageFORMERR is thrown if the RR is malformed. - TXTLikeImpl(util::InputBuffer& buffer, size_t rdata_len) { - if (rdata_len > MAX_RDLENGTH) { - isc_throw(InvalidRdataLength, "RDLENGTH too large: " << rdata_len); - } - - if (rdata_len == 0) { // note that this couldn't happen in the loop. - isc_throw(DNSMessageFORMERR, "Error in parsing " << - RRType(typeCode) << " RDATA: 0-length character string"); - } - - do { - const uint8_t len = buffer.readUint8(); - if (rdata_len < len + 1) { - isc_throw(DNSMessageFORMERR, "Error in parsing " << - RRType(typeCode) << - " RDATA: character string length is too large: " << - static_cast<int>(len)); - } - std::vector<uint8_t> data(len + 1); - data[0] = len; - buffer.readData(&data[0] + 1, len); - string_list_.push_back(data); - - rdata_len -= (len + 1); - } while (rdata_len > 0); - } - - /// \brief Constructor from string. - /// - /// \throw CharStringTooLong the parameter string length exceeds maximum. - /// \throw InvalidRdataText the method cannot process the parameter data - explicit TXTLikeImpl(const std::string& txtstr) { - std::istringstream ss(txtstr); - MasterLexer lexer; - lexer.pushSource(ss); - - try { - buildFromTextHelper(lexer); - if (lexer.getNextToken().getType() != MasterToken::END_OF_FILE) { - isc_throw(InvalidRdataText, "Failed to construct " << - RRType(typeCode) << " RDATA from '" << txtstr << - "': extra new line"); - } - } catch (const MasterLexer::LexerError& ex) { - isc_throw(InvalidRdataText, "Failed to construct " << - RRType(typeCode) << " RDATA from '" << txtstr << "': " - << ex.what()); - } - } - - /// \brief Constructor using the master lexer. - /// - /// \throw CharStringTooLong the parameter string length exceeds maximum. - /// \throw InvalidRdataText the method cannot process the parameter data - /// - /// \param lexer A \c MasterLexer object parsing a master file for this - /// RDATA. - TXTLikeImpl(MasterLexer& lexer) { - buildFromTextHelper(lexer); - } - -private: - void buildFromTextHelper(MasterLexer& lexer) { - while (true) { - const MasterToken& token = lexer.getNextToken( - MasterToken::QSTRING, true); - if (token.getType() != MasterToken::STRING && - token.getType() != MasterToken::QSTRING) { - break; - } - string_list_.push_back(std::vector<uint8_t>()); - stringToCharString(token.getStringRegion(), string_list_.back()); - } - - // Let upper layer handle eol/eof. - lexer.ungetToken(); - - if (string_list_.empty()) { - isc_throw(InvalidRdataText, "Failed to construct " << - RRType(typeCode) << " RDATA: empty input"); - } - } - -public: - /// \brief The copy constructor. - /// - /// Trivial for now, we could've used the default one. - TXTLikeImpl(const TXTLikeImpl& other) : - string_list_(other.string_list_) - {} - - /// \brief Render the TXT-like data in the wire format to an OutputBuffer - /// object. - /// - /// \param buffer An output buffer to store the wire data. - void - toWire(util::OutputBuffer& buffer) const { - for (std::vector<std::vector<uint8_t> >::const_iterator it = - string_list_.begin(); - it != string_list_.end(); - ++it) - { - buffer.writeData(&(*it)[0], (*it).size()); - } - } - - /// \brief Render the TXT-like data in the wire format to an - /// AbstractMessageRenderer object. - /// - /// \param buffer An output AbstractMessageRenderer to send the wire data - /// to. - void - toWire(AbstractMessageRenderer& renderer) const { - for (std::vector<std::vector<uint8_t> >::const_iterator it = - string_list_.begin(); - it != string_list_.end(); - ++it) - { - renderer.writeData(&(*it)[0], (*it).size()); - } - } - - /// \brief Convert the TXT-like data to a string. - /// - /// \return A \c string object that represents the TXT-like data. - std::string - toText() const { - std::string s; - - for (std::vector<std::vector<uint8_t> >::const_iterator it = - string_list_.begin(); it != string_list_.end(); ++it) - { - if (!s.empty()) { - s.push_back(' '); - } - s.push_back('"'); - s.append(charStringToString(*it)); - s.push_back('"'); - } - - return (s); - } - - /// \brief Compare two instances of TXT-like RDATA. - /// - /// It is up to the caller to make sure that \c other is an object of the - /// same \c TXTLikeImpl class. - /// - /// \param other the right-hand operand to compare against. - /// \return < 0 if \c this would be sorted before \c other. - /// \return 0 if \c this is identical to \c other in terms of sorting - /// order. - /// \return > 0 if \c this would be sorted after \c other. - int - compare(const TXTLikeImpl& other) const { - // This implementation is not efficient. Revisit this (TBD). - OutputBuffer this_buffer(0); - toWire(this_buffer); - uint8_t const* const this_data = (uint8_t const*)this_buffer.getData(); - const size_t this_len = this_buffer.getLength(); - - OutputBuffer other_buffer(0); - other.toWire(other_buffer); - uint8_t const* const other_data - = (uint8_t const*)other_buffer.getData(); - const size_t other_len = other_buffer.getLength(); - - const size_t cmplen = min(this_len, other_len); - const int cmp = memcmp(this_data, other_data, cmplen); - - if (cmp != 0) { - return (cmp); - } else { - return ((this_len == other_len) ? 0 : - (this_len < other_len) ? -1 : 1); - } - } - -private: - /// Note: this is a prototype version; we may reconsider - /// this representation later. - std::vector<std::vector<uint8_t> > string_list_; -}; - -} // namespace detail -} // namespace generic -} // namespace rdata -} // namespace dns -} // namespace isc - -#endif // TXT_LIKE_H - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/rdata/generic/dlv_32769.cc b/src/lib/dns/rdata/generic/dlv_32769.cc deleted file mode 100644 index 6170209806..0000000000 --- a/src/lib/dns/rdata/generic/dlv_32769.cc +++ /dev/null @@ -1,120 +0,0 @@ -// Copyright (C) 2011-2024 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#include <config.h> - -#include <string> - -#include <util/buffer.h> -#include <util/encode/encode.h> - -#include <dns/messagerenderer.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> - -#include <dns/rdata/generic/detail/ds_like.h> - -using namespace std; -using namespace isc::util; -using namespace isc::util::encode; -using namespace isc::dns::rdata::generic::detail; - -// BEGIN_ISC_NAMESPACE -// BEGIN_RDATA_NAMESPACE - -/// \brief Constructor from string. -/// -/// A copy of the implementation object is allocated and constructed. -DLV::DLV(const std::string& ds_str) : - impl_(new DLVImpl(ds_str)) -{} - -/// \brief Constructor from wire-format data. -/// -/// A copy of the implementation object is allocated and constructed. -DLV::DLV(InputBuffer& buffer, size_t rdata_len) : - impl_(new DLVImpl(buffer, rdata_len)) -{} - -DLV::DLV(MasterLexer& lexer, const Name* origin, MasterLoader::Options options, - MasterLoaderCallbacks& callbacks) : - impl_(new DLVImpl(lexer, origin, options, callbacks)) -{} - -/// \brief Copy constructor -/// -/// A copy of the implementation object is allocated and constructed. -DLV::DLV(const DLV& source) : - Rdata(), impl_(new DLVImpl(*source.impl_)) -{} - -/// \brief Assignment operator -/// -/// PIMPL-induced logic -DLV& -DLV::operator=(const DLV& source) { - if (this == &source) { - return (*this); - } - - DLVImpl* newimpl = new DLVImpl(*source.impl_); - delete impl_; - impl_ = newimpl; - - return (*this); -} - -/// \brief Destructor -/// -/// Deallocates an internal resource. -DLV::~DLV() { - delete impl_; -} - -/// \brief Convert the \c DLV to a string. -/// -/// A pass-thru to the corresponding implementation method. -string -DLV::toText() const { - return (impl_->toText()); -} - -/// \brief Render the \c DLV in the wire format to a OutputBuffer object -/// -/// A pass-thru to the corresponding implementation method. -void -DLV::toWire(OutputBuffer& buffer) const { - impl_->toWire(buffer); -} - -/// \brief Render the \c DLV in the wire format to a AbstractMessageRenderer -/// object -/// -/// A pass-thru to the corresponding implementation method. -void -DLV::toWire(AbstractMessageRenderer& renderer) const { - impl_->toWire(renderer); -} - -/// \brief Compare two instances of \c DLV RDATA. -/// -/// The type check is performed here. Otherwise, a pass-thru to the -/// corresponding implementation method. -int -DLV::compare(const Rdata& other) const { - const DLV& other_ds = dynamic_cast<const DLV&>(other); - - return (impl_->compare(*other_ds.impl_)); -} - -/// \brief Tag accessor -uint16_t -DLV::getTag() const { - return (impl_->getTag()); -} - -// END_RDATA_NAMESPACE -// END_ISC_NAMESPACE diff --git a/src/lib/dns/rdata/generic/dlv_32769.h b/src/lib/dns/rdata/generic/dlv_32769.h deleted file mode 100644 index 26523de6fe..0000000000 --- a/src/lib/dns/rdata/generic/dlv_32769.h +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -// BEGIN_HEADER_GUARD - -#include <stdint.h> - -#include <string> - -#include <dns/name.h> -#include <dns/rrtype.h> -#include <dns/rrttl.h> -#include <dns/rdata.h> - -// BEGIN_ISC_NAMESPACE - -// BEGIN_COMMON_DECLARATIONS -// END_COMMON_DECLARATIONS - -// BEGIN_RDATA_NAMESPACE - -namespace detail { -template <class Type, uint16_t typeCode> class DSLikeImpl; -} - -/// \brief \c rdata::generic::DLV class represents the DLV RDATA as defined in -/// RFC4431. -/// -/// This class implements the basic interfaces inherited from the abstract -/// \c rdata::Rdata class, and provides trivial accessors specific to the -/// DLV RDATA. -class DLV : public Rdata { -public: - // BEGIN_COMMON_MEMBERS - // END_COMMON_MEMBERS - - /// \brief Assignment operator. - /// - /// It internally allocates a resource, and if it fails a corresponding - /// standard exception will be thrown. - /// This operator never throws an exception otherwise. - /// - /// This operator provides the strong exception guarantee: When an - /// exception is thrown the content of the assignment target will be - /// intact. - DLV& operator=(const DLV& source); - - /// \brief The destructor. - ~DLV(); - - /// \brief Return the value of the Tag field. - /// - /// This method never throws an exception. - uint16_t getTag() const; -private: - typedef detail::DSLikeImpl<DLV, 32769> DLVImpl; - DLVImpl* impl_; -}; - -// END_RDATA_NAMESPACE -// END_ISC_NAMESPACE -// END_HEADER_GUARD - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/rdata/generic/dname_39.cc b/src/lib/dns/rdata/generic/dname_39.cc deleted file mode 100644 index 9ee669baf6..0000000000 --- a/src/lib/dns/rdata/generic/dname_39.cc +++ /dev/null @@ -1,127 +0,0 @@ -// Copyright (C) 2010-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#include <config.h> - -#include <string> - -#include <util/buffer.h> -#include <dns/name.h> -#include <dns/messagerenderer.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> - -#include <dns/rdata/generic/detail/lexer_util.h> - -using namespace std; -using namespace isc::util; -using isc::dns::rdata::generic::detail::createNameFromLexer; - -// BEGIN_ISC_NAMESPACE -// BEGIN_RDATA_NAMESPACE - -/// \brief Constructor from string. -/// -/// The given string must represent a valid DNAME 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 TARGET must be absolute since there's no parameter that specifies -/// the origin name; if it is not absolute, \c MissingNameOrigin -/// exception will be thrown. These must not be represented as a quoted -/// string. -/// -/// \throw Others Exception from the Name and RRTTL constructors. -/// \throw InvalidRdataText Other general syntax errors. -DNAME::DNAME(const std::string& namestr) : - // Fill in dummy name and replace it soon below. - dname_(Name::ROOT_NAME()) -{ - try { - std::istringstream ss(namestr); - MasterLexer lexer; - lexer.pushSource(ss); - - dname_ = createNameFromLexer(lexer, NULL); - - if (lexer.getNextToken().getType() != MasterToken::END_OF_FILE) { - isc_throw(InvalidRdataText, "extra input text for DNAME: " - << namestr); - } - } catch (const MasterLexer::LexerError& ex) { - isc_throw(InvalidRdataText, "Failed to construct DNAME from '" << - namestr << "': " << ex.what()); - } -} - -DNAME::DNAME(InputBuffer& buffer, size_t) : - dname_(buffer) -{ - // we don't need rdata_len for parsing. if necessary, the caller will - // check consistency. -} - -/// \brief Constructor with a context of MasterLexer. -/// -/// The \c lexer should point to the beginning of valid textual -/// representation of a DNAME RDATA. The TARGET field can be -/// non-absolute if \c origin is non-NULL, in which case \c origin is -/// used to make it absolute. It must not be represented as a quoted -/// string. -/// -/// \throw MasterLexer::LexerError General parsing error such as missing field. -/// \throw Other Exceptions from the Name and RRTTL constructors if -/// construction of textual fields as these objects fail. -/// -/// \param lexer A \c MasterLexer object parsing a master file for the -/// RDATA to be created -/// \param origin If non NULL, specifies the origin of TARGET when it -/// is non-absolute. -DNAME::DNAME(MasterLexer& lexer, const Name* origin, - MasterLoader::Options, MasterLoaderCallbacks&) : - dname_(createNameFromLexer(lexer, origin)) -{} - -DNAME::DNAME(const DNAME& other) : - Rdata(), dname_(other.dname_) -{} - -DNAME::DNAME(const Name& dname) : - dname_(dname) -{} - -void -DNAME::toWire(OutputBuffer& buffer) const { - dname_.toWire(buffer); -} - -void -DNAME::toWire(AbstractMessageRenderer& renderer) const { - // Type DNAME is not "well-known", and name compression must be disabled - // per RFC3597. - renderer.writeName(dname_, false); -} - -string -DNAME::toText() const { - return (dname_.toText()); -} - -int -DNAME::compare(const Rdata& other) const { - const DNAME& other_dname = dynamic_cast<const DNAME&>(other); - - return (compareNames(dname_, other_dname.dname_)); -} - -const Name& -DNAME::getDname() const { - return (dname_); -} - -// END_RDATA_NAMESPACE -// END_ISC_NAMESPACE diff --git a/src/lib/dns/rdata/generic/dname_39.h b/src/lib/dns/rdata/generic/dname_39.h deleted file mode 100644 index 998fea0d5f..0000000000 --- a/src/lib/dns/rdata/generic/dname_39.h +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (C) 2010-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -// BEGIN_HEADER_GUARD - -#include <string> - -#include <dns/name.h> -#include <dns/rdata.h> - -// BEGIN_ISC_NAMESPACE - -// BEGIN_COMMON_DECLARATIONS -// END_COMMON_DECLARATIONS - -// BEGIN_RDATA_NAMESPACE - -class DNAME : public Rdata { -public: - // BEGIN_COMMON_MEMBERS - // END_COMMON_MEMBERS - - // DNAME specific methods - DNAME(const Name& dname); - const Name& getDname() const; -private: - Name dname_; -}; - -// END_RDATA_NAMESPACE -// END_ISC_NAMESPACE -// END_HEADER_GUARD - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/rdata/generic/dnskey_48.cc b/src/lib/dns/rdata/generic/dnskey_48.cc deleted file mode 100644 index ec7668b7cc..0000000000 --- a/src/lib/dns/rdata/generic/dnskey_48.cc +++ /dev/null @@ -1,315 +0,0 @@ -// Copyright (C) 2010-2024 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#include <config.h> - -#include <iostream> -#include <string> -#include <sstream> -#include <vector> - -#include <boost/lexical_cast.hpp> - -#include <util/encode/encode.h> -#include <util/buffer.h> -#include <dns/messagerenderer.h> -#include <dns/name.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> - -#include <memory> - -#include <stdio.h> -#include <time.h> - -using namespace std; -using namespace isc::util; -using namespace isc::util::encode; - -// BEGIN_ISC_NAMESPACE -// BEGIN_RDATA_NAMESPACE - -struct DNSKEYImpl { - // straightforward representation of DNSKEY RDATA fields - DNSKEYImpl(uint16_t flags, uint8_t protocol, uint8_t algorithm, - const vector<uint8_t>& keydata) : - flags_(flags), protocol_(protocol), algorithm_(algorithm), - keydata_(keydata) - {} - - uint16_t flags_; - uint8_t protocol_; - uint8_t algorithm_; - const vector<uint8_t> keydata_; -}; - -/// \brief Constructor from string. -/// -/// The given string must represent a valid DNSKEY 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 Protocol and Algorithm fields must be within their valid -/// ranges. The Public Key field must be present and must contain a -/// Base64 encoding of the public key. Whitespace is allowed within the -/// Base64 text. -/// -/// It is okay for the key data to be missing. Note: BIND 9 also accepts -/// DNSKEY missing key data. While the RFC is silent in this case, and it -/// may be debatable what an implementation should do, but since this field -/// is algorithm dependent and this implementations doesn't reject unknown -/// algorithms, it's lenient here. -/// -/// \throw InvalidRdataText if any fields are out of their valid range, -/// or are incorrect. -/// -/// \param dnskey_str A string containing the RDATA to be created -DNSKEY::DNSKEY(const std::string& dnskey_str) : - impl_(NULL) -{ - // We use unique_ptr here because if there is an exception in this - // constructor, the destructor is not called and there could be a - // leak of the DNSKEYImpl that constructFromLexer() returns. - std::unique_ptr<DNSKEYImpl> impl_ptr; - - try { - std::istringstream ss(dnskey_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 DNSKEY: " << dnskey_str); - } - } catch (const MasterLexer::LexerError& ex) { - isc_throw(InvalidRdataText, - "Failed to construct DNSKEY from '" << dnskey_str << "': " - << ex.what()); - } - - impl_ = impl_ptr.release(); -} - -/// \brief Constructor from InputBuffer. -/// -/// The passed buffer must contain a valid DNSKEY RDATA. -/// -/// The Protocol and Algorithm fields are not checked for unknown -/// values. It is okay for the key data to be missing (see the description -/// of the constructor from string). -DNSKEY::DNSKEY(InputBuffer& buffer, size_t rdata_len) : - impl_(NULL) -{ - if (rdata_len < 4) { - isc_throw(InvalidRdataLength, "DNSKEY too short: " << rdata_len); - } - - const uint16_t flags = buffer.readUint16(); - const uint16_t protocol = buffer.readUint8(); - const uint16_t algorithm = buffer.readUint8(); - - rdata_len -= 4; - - vector<uint8_t> keydata; - // If key data is missing, it's OK. See the API documentation of the - // constructor. - if (rdata_len > 0) { - keydata.resize(rdata_len); - buffer.readData(&keydata[0], rdata_len); - } - - impl_ = new DNSKEYImpl(flags, protocol, algorithm, keydata); -} - -/// \brief Constructor with a context of MasterLexer. -/// -/// The \c lexer should point to the beginning of valid textual -/// representation of an DNSKEY RDATA. -/// -/// See \c DNSKEY::DNSKEY(const std::string&) for description of the -/// expected RDATA fields. -/// -/// \throw MasterLexer::LexerError General parsing error such as -/// missing field. -/// \throw InvalidRdataText if any fields are out of their valid range, -/// or are incorrect. -/// -/// \param lexer A \c MasterLexer object parsing a master file for the -/// RDATA to be created -DNSKEY::DNSKEY(MasterLexer& lexer, const Name*, - MasterLoader::Options, MasterLoaderCallbacks&) : - impl_(NULL) -{ - impl_ = constructFromLexer(lexer); -} - -DNSKEYImpl* -DNSKEY::constructFromLexer(MasterLexer& lexer) { - const uint32_t flags = lexer.getNextToken(MasterToken::NUMBER).getNumber(); - if (flags > 0xffff) { - isc_throw(InvalidRdataText, - "DNSKEY flags out of range: " << flags); - } - - const uint32_t protocol = - lexer.getNextToken(MasterToken::NUMBER).getNumber(); - if (protocol > 0xff) { - isc_throw(InvalidRdataText, - "DNSKEY protocol out of range: " << protocol); - } - - const uint32_t algorithm = - lexer.getNextToken(MasterToken::NUMBER).getNumber(); - if (algorithm > 0xff) { - isc_throw(InvalidRdataText, - "DNSKEY algorithm out of range: " << algorithm); - } - - std::string keydata_str; - std::string keydata_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 is now assured to be of type STRING. - - token.getString(keydata_substr); - keydata_str.append(keydata_substr); - } - - lexer.ungetToken(); - - vector<uint8_t> keydata; - // If key data is missing, it's OK. See the API documentation of the - // constructor. - if (keydata_str.size() > 0) { - decodeBase64(keydata_str, keydata); - } - - return (new DNSKEYImpl(flags, protocol, algorithm, keydata)); -} - -DNSKEY::DNSKEY(const DNSKEY& source) : - Rdata(), impl_(new DNSKEYImpl(*source.impl_)) -{} - -DNSKEY& -DNSKEY::operator=(const DNSKEY& source) { - if (this == &source) { - return (*this); - } - - DNSKEYImpl* newimpl = new DNSKEYImpl(*source.impl_); - delete impl_; - impl_ = newimpl; - - return (*this); -} - -DNSKEY::~DNSKEY() { - delete impl_; -} - -string -DNSKEY::toText() const { - return (boost::lexical_cast<string>(static_cast<int>(impl_->flags_)) + - " " + boost::lexical_cast<string>(static_cast<int>(impl_->protocol_)) + - " " + boost::lexical_cast<string>(static_cast<int>(impl_->algorithm_)) + - " " + encodeBase64(impl_->keydata_)); -} - -void -DNSKEY::toWire(OutputBuffer& buffer) const { - buffer.writeUint16(impl_->flags_); - buffer.writeUint8(impl_->protocol_); - buffer.writeUint8(impl_->algorithm_); - buffer.writeData(&impl_->keydata_[0], impl_->keydata_.size()); -} - -void -DNSKEY::toWire(AbstractMessageRenderer& renderer) const { - renderer.writeUint16(impl_->flags_); - renderer.writeUint8(impl_->protocol_); - renderer.writeUint8(impl_->algorithm_); - renderer.writeData(&impl_->keydata_[0], impl_->keydata_.size()); -} - -int -DNSKEY::compare(const Rdata& other) const { - const DNSKEY& other_dnskey = dynamic_cast<const DNSKEY&>(other); - - if (impl_->flags_ != other_dnskey.impl_->flags_) { - return (impl_->flags_ < other_dnskey.impl_->flags_ ? -1 : 1); - } - if (impl_->protocol_ != other_dnskey.impl_->protocol_) { - return (impl_->protocol_ < other_dnskey.impl_->protocol_ ? -1 : 1); - } - if (impl_->algorithm_ != other_dnskey.impl_->algorithm_) { - return (impl_->algorithm_ < other_dnskey.impl_->algorithm_ ? -1 : 1); - } - - const size_t this_len = impl_->keydata_.size(); - const size_t other_len = other_dnskey.impl_->keydata_.size(); - const size_t cmplen = min(this_len, other_len); - if (cmplen == 0) { - return ((this_len == other_len) ? 0 : (this_len < other_len) ? -1 : 1); - } - const int cmp = memcmp(&impl_->keydata_[0], - &other_dnskey.impl_->keydata_[0], cmplen); - if (cmp != 0) { - return (cmp); - } else { - return ((this_len == other_len) ? 0 : (this_len < other_len) ? -1 : 1); - } -} - -uint16_t -DNSKEY::getTag() const { - if (impl_->algorithm_ == 1) { - // See RFC 4034 appendix B.1 for why the key data must contain - // at least 4 bytes with RSA/MD5: 3 trailing bytes to extract - // the tag from, and 1 byte of exponent length subfield before - // modulus. - const int len = impl_->keydata_.size(); - if (len < 4) { - isc_throw(isc::OutOfRange, - "DNSKEY keydata too short for tag extraction"); - } - - return ((impl_->keydata_[len - 3] << 8) + impl_->keydata_[len - 2]); - } - - uint32_t ac = impl_->flags_; - ac += (impl_->protocol_ << 8); - ac += impl_->algorithm_; - - const size_t size = impl_->keydata_.size(); - for (size_t i = 0; i < size; i ++) { - ac += (i & 1) ? impl_->keydata_[i] : (impl_->keydata_[i] << 8); - } - ac += (ac >> 16) & 0xffff; - return (ac & 0xffff); -} - -uint16_t -DNSKEY::getFlags() const { - return (impl_->flags_); -} - -uint8_t -DNSKEY::getAlgorithm() const { - return (impl_->algorithm_); -} - -// END_RDATA_NAMESPACE -// END_ISC_NAMESPACE diff --git a/src/lib/dns/rdata/generic/dnskey_48.h b/src/lib/dns/rdata/generic/dnskey_48.h deleted file mode 100644 index a5e9efa43f..0000000000 --- a/src/lib/dns/rdata/generic/dnskey_48.h +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright (C) 2010-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#include <stdint.h> - -#include <string> - -#include <dns/name.h> -#include <dns/rrtype.h> -#include <dns/rrttl.h> -#include <dns/rdata.h> -#include <dns/master_lexer.h> - -// BEGIN_HEADER_GUARD - -// BEGIN_ISC_NAMESPACE - -// BEGIN_COMMON_DECLARATIONS -// END_COMMON_DECLARATIONS - -// BEGIN_RDATA_NAMESPACE - -struct DNSKEYImpl; - -class DNSKEY : public Rdata { -public: - // BEGIN_COMMON_MEMBERS - // END_COMMON_MEMBERS - DNSKEY& operator=(const DNSKEY& source); - ~DNSKEY(); - - /// - /// Specialized methods - /// - - /// \brief Returns the key tag - /// - /// \throw isc::OutOfRange if the key data for RSA/MD5 is too short - /// to support tag extraction. - uint16_t getTag() const; - - uint16_t getFlags() const; - uint8_t getAlgorithm() const; - -private: - DNSKEYImpl* constructFromLexer(isc::dns::MasterLexer& lexer); - - DNSKEYImpl* impl_; -}; - -// END_RDATA_NAMESPACE -// END_ISC_NAMESPACE -// END_HEADER_GUARD - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/rdata/generic/ds_43.cc b/src/lib/dns/rdata/generic/ds_43.cc deleted file mode 100644 index 80a6a6c119..0000000000 --- a/src/lib/dns/rdata/generic/ds_43.cc +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright (C) 2011-2024 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#include <config.h> - -#include <string> - -#include <util/buffer.h> -#include <util/encode/encode.h> - -#include <dns/messagerenderer.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> - -#include <dns/rdata/generic/detail/ds_like.h> - -using namespace std; -using namespace isc::util; -using namespace isc::util::encode; -using namespace isc::dns::rdata::generic::detail; - -// BEGIN_ISC_NAMESPACE -// BEGIN_RDATA_NAMESPACE - -DS::DS(const std::string& ds_str) : - impl_(new DSImpl(ds_str)) -{} - -DS::DS(InputBuffer& buffer, size_t rdata_len) : - impl_(new DSImpl(buffer, rdata_len)) -{} - -DS::DS(MasterLexer& lexer, const Name* origin, MasterLoader::Options options, - MasterLoaderCallbacks& callbacks) : - impl_(new DSImpl(lexer, origin, options, callbacks)) -{} - -DS::DS(const DS& source) : - Rdata(), impl_(new DSImpl(*source.impl_)) -{} - -DS& -DS::operator=(const DS& source) { - if (this == &source) { - return (*this); - } - - DSImpl* newimpl = new DSImpl(*source.impl_); - delete impl_; - impl_ = newimpl; - - return (*this); -} - -DS::~DS() { - delete impl_; -} - -string -DS::toText() const { - return (impl_->toText()); -} - -void -DS::toWire(OutputBuffer& buffer) const { - impl_->toWire(buffer); -} - -void -DS::toWire(AbstractMessageRenderer& renderer) const { - impl_->toWire(renderer); -} - -int -DS::compare(const Rdata& other) const { - const DS& other_ds = dynamic_cast<const DS&>(other); - - return (impl_->compare(*other_ds.impl_)); -} - -uint16_t -DS::getTag() const { - return (impl_->getTag()); -} - -// END_RDATA_NAMESPACE -// END_ISC_NAMESPACE diff --git a/src/lib/dns/rdata/generic/ds_43.h b/src/lib/dns/rdata/generic/ds_43.h deleted file mode 100644 index a20e349ef6..0000000000 --- a/src/lib/dns/rdata/generic/ds_43.h +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -// BEGIN_HEADER_GUARD - -#include <stdint.h> - -#include <string> - -#include <dns/name.h> -#include <dns/rrtype.h> -#include <dns/rrttl.h> -#include <dns/rdata.h> - -// BEGIN_ISC_NAMESPACE - -// BEGIN_COMMON_DECLARATIONS -// END_COMMON_DECLARATIONS - -// BEGIN_RDATA_NAMESPACE - -namespace detail { -template <class Type, uint16_t typeCode> class DSLikeImpl; -} - -/// \brief \c rdata::generic::DS class represents the DS RDATA as defined in -/// RFC3658. -/// -/// This class implements the basic interfaces inherited from the abstract -/// \c rdata::Rdata class, and provides trivial accessors specific to the -/// DS RDATA. -class DS : public Rdata { -public: - // BEGIN_COMMON_MEMBERS - // END_COMMON_MEMBERS - - /// \brief Assignment operator. - /// - /// It internally allocates a resource, and if it fails a corresponding - /// standard exception will be thrown. - /// This operator never throws an exception otherwise. - /// - /// This operator provides the strong exception guarantee: When an - /// exception is thrown the content of the assignment target will be - /// intact. - DS& operator=(const DS& source); - - /// \brief The destructor. - ~DS(); - - /// \brief Return the value of the Tag field. - /// - /// This method never throws an exception. - uint16_t getTag() const; -private: - typedef detail::DSLikeImpl<DS, 43> DSImpl; - DSImpl* impl_; -}; - -// END_RDATA_NAMESPACE -// END_ISC_NAMESPACE -// END_HEADER_GUARD - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/rdata/generic/hinfo_13.cc b/src/lib/dns/rdata/generic/hinfo_13.cc deleted file mode 100644 index 3bda21979c..0000000000 --- a/src/lib/dns/rdata/generic/hinfo_13.cc +++ /dev/null @@ -1,151 +0,0 @@ -// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#include <config.h> - -#include <exceptions/exceptions.h> -#include <dns/exceptions.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> -#include <dns/rdata/generic/detail/char_string.h> -#include <util/buffer.h> - -using namespace std; -using namespace isc::util; -using namespace isc::dns; - -// BEGIN_ISC_NAMESPACE -// BEGIN_RDATA_NAMESPACE - -class HINFOImpl { -public: - HINFOImpl(const std::string& hinfo_str) { - std::istringstream ss(hinfo_str); - MasterLexer lexer; - lexer.pushSource(ss); - - try { - parseHINFOData(lexer); - // Should be at end of data now - if (lexer.getNextToken(MasterToken::QSTRING, true).getType() != - MasterToken::END_OF_FILE) { - isc_throw(InvalidRdataText, - "Invalid HINFO text format: too many fields."); - } - } catch (const MasterLexer::LexerError& ex) { - isc_throw(InvalidRdataText, "Failed to construct HINFO RDATA from " - << hinfo_str << "': " << ex.what()); - } - } - - HINFOImpl(InputBuffer& buffer, size_t rdata_len) { - rdata_len -= detail::bufferToCharString(buffer, rdata_len, cpu); - rdata_len -= detail::bufferToCharString(buffer, rdata_len, os); - if (rdata_len != 0) { - isc_throw(isc::dns::DNSMessageFORMERR, "Error in parsing " << - "HINFO RDATA: bytes left at end: " << - static_cast<int>(rdata_len)); - } - } - - HINFOImpl(MasterLexer& lexer) - { - parseHINFOData(lexer); - } - -private: - void - parseHINFOData(MasterLexer& lexer) { - MasterToken token = lexer.getNextToken(MasterToken::QSTRING); - stringToCharString(token.getStringRegion(), cpu); - token = lexer.getNextToken(MasterToken::QSTRING); - stringToCharString(token.getStringRegion(), os); - } - -public: - detail::CharString cpu; - detail::CharString os; -}; - -HINFO::HINFO(const std::string& hinfo_str) : impl_(new HINFOImpl(hinfo_str)) -{} - - -HINFO::HINFO(InputBuffer& buffer, size_t rdata_len) : - impl_(new HINFOImpl(buffer, rdata_len)) -{} - -HINFO::HINFO(const HINFO& source): - Rdata(), impl_(new HINFOImpl(*source.impl_)) -{ -} - -HINFO::HINFO(MasterLexer& lexer, const Name*, - MasterLoader::Options, MasterLoaderCallbacks&) : - impl_(new HINFOImpl(lexer)) -{} - -HINFO& -HINFO::operator=(const HINFO& source) -{ - impl_.reset(new HINFOImpl(*source.impl_)); - return (*this); -} - -HINFO::~HINFO() { -} - -std::string -HINFO::toText() const { - string result; - result += "\""; - result += detail::charStringToString(impl_->cpu); - result += "\" \""; - result += detail::charStringToString(impl_->os); - result += "\""; - return (result); -} - -void -HINFO::toWire(OutputBuffer& buffer) const { - toWireHelper(buffer); -} - -void -HINFO::toWire(AbstractMessageRenderer& renderer) const { - toWireHelper(renderer); -} - -int -HINFO::compare(const Rdata& other) const { - const HINFO& other_hinfo = dynamic_cast<const HINFO&>(other); - - const int cmp = compareCharStrings(impl_->cpu, other_hinfo.impl_->cpu); - if (cmp != 0) { - return (cmp); - } - return (compareCharStrings(impl_->os, other_hinfo.impl_->os)); -} - -const std::string -HINFO::getCPU() const { - return (detail::charStringToString(impl_->cpu)); -} - -const std::string -HINFO::getOS() const { - return (detail::charStringToString(impl_->os)); -} - -template <typename T> -void -HINFO::toWireHelper(T& outputer) const { - outputer.writeData(&impl_->cpu[0], impl_->cpu.size()); - outputer.writeData(&impl_->os[0], impl_->os.size()); -} - -// END_RDATA_NAMESPACE -// END_ISC_NAMESPACE diff --git a/src/lib/dns/rdata/generic/hinfo_13.h b/src/lib/dns/rdata/generic/hinfo_13.h deleted file mode 100644 index acceb14fdb..0000000000 --- a/src/lib/dns/rdata/generic/hinfo_13.h +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -// BEGIN_HEADER_GUARD -#include <stdint.h> - -#include <string> - -#include <boost/scoped_ptr.hpp> -#include <boost/noncopyable.hpp> - -#include <dns/name.h> -#include <dns/rdata.h> -#include <util/buffer.h> - -// BEGIN_ISC_NAMESPACE - -// BEGIN_COMMON_DECLARATIONS -// END_COMMON_DECLARATIONS - -// BEGIN_RDATA_NAMESPACE - -class HINFOImpl; - -/// \brief \c HINFO class represents the HINFO rdata defined in -/// RFC1034, RFC1035 -/// -/// This class implements the basic interfaces inherited from the -/// \c rdata::Rdata class, and provides accessors specific to the -/// HINFO rdata. -class HINFO : public Rdata { -public: - // BEGIN_COMMON_MEMBERS - // END_COMMON_MEMBERS - - // HINFO specific methods - ~HINFO(); - - HINFO& operator=(const HINFO&); - - const std::string getCPU() const; - const std::string getOS() const; - -private: - /// Helper template function for toWire() - /// - /// \param outputer Where to write data in - template <typename T> - void toWireHelper(T& outputer) const; - - boost::scoped_ptr<HINFOImpl> impl_; -}; - - -// END_RDATA_NAMESPACE -// END_ISC_NAMESPACE -// END_HEADER_GUARD - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/rdata/generic/minfo_14.cc b/src/lib/dns/rdata/generic/minfo_14.cc deleted file mode 100644 index d3dfd1e630..0000000000 --- a/src/lib/dns/rdata/generic/minfo_14.cc +++ /dev/null @@ -1,173 +0,0 @@ -// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#include <config.h> - -#include <string> -#include <sstream> - -#include <util/buffer.h> - -#include <dns/messagerenderer.h> -#include <dns/name.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> -#include <dns/rdata/generic/detail/lexer_util.h> - -using namespace std; -using namespace isc::dns; -using namespace isc::util; -using isc::dns::rdata::generic::detail::createNameFromLexer; - -// BEGIN_ISC_NAMESPACE -// BEGIN_RDATA_NAMESPACE - -/// \brief Constructor from string. -/// -/// \c minfo_str must be formatted as follows: -/// \code <rmailbox name> <emailbox name> -/// \endcode -/// where both fields must represent a valid domain name. -/// -/// An example of valid string is: -/// \code "rmail.example.com. email.example.com." \endcode -/// -/// \throw InvalidRdataText The number of RDATA fields (must be 2) is -/// incorrect. -/// \throw std::bad_alloc Memory allocation for names fails. -/// \throw Other The constructor of the \c Name class will throw if the -/// names in the string is invalid. -MINFO::MINFO(const std::string& minfo_str) : - // We cannot construct both names in the initialization list due to the - // necessary text processing, so we have to initialize them with a dummy - // name and replace them later. - rmailbox_(Name::ROOT_NAME()), emailbox_(Name::ROOT_NAME()) -{ - try { - std::istringstream ss(minfo_str); - MasterLexer lexer; - lexer.pushSource(ss); - - rmailbox_ = createNameFromLexer(lexer, NULL); - emailbox_ = createNameFromLexer(lexer, NULL); - - if (lexer.getNextToken().getType() != MasterToken::END_OF_FILE) { - isc_throw(InvalidRdataText, "extra input text for MINFO: " - << minfo_str); - } - } catch (const MasterLexer::LexerError& ex) { - isc_throw(InvalidRdataText, "Failed to construct MINFO from '" << - minfo_str << "': " << ex.what()); - } -} - -/// \brief Constructor with a context of MasterLexer. -/// -/// The \c lexer should point to the beginning of valid textual representation -/// of an MINFO RDATA. The RMAILBOX and EMAILBOX fields can be non-absolute -/// if \c origin is non-NULL, in which case \c origin is used to make them -/// absolute. -/// -/// \throw MasterLexer::LexerError General parsing error such as missing field. -/// \throw Other Exceptions from the Name and constructors if construction of -/// textual fields as these objects fail. -/// -/// \param lexer A \c MasterLexer object parsing a master file for the -/// RDATA to be created -/// \param origin If non NULL, specifies the origin of SERVER when it -/// is non-absolute. -MINFO::MINFO(MasterLexer& lexer, const Name* origin, - MasterLoader::Options, MasterLoaderCallbacks&) : - rmailbox_(createNameFromLexer(lexer, origin)), - emailbox_(createNameFromLexer(lexer, origin)) -{ -} - -/// \brief Constructor from wire-format data. -/// -/// This constructor doesn't check the validity of the second parameter (rdata -/// length) for parsing. -/// If necessary, the caller will check consistency. -/// -/// \throw std::bad_alloc Memory allocation for names fails. -/// \throw Other The constructor of the \c Name class will throw if the -/// names in the wire is invalid. -MINFO::MINFO(InputBuffer& buffer, size_t) : - rmailbox_(buffer), emailbox_(buffer) -{} - -/// \brief Copy constructor. -/// -/// \throw std::bad_alloc Memory allocation fails in copying internal -/// member variables (this should be very rare). -MINFO::MINFO(const MINFO& other) : - Rdata(), rmailbox_(other.rmailbox_), emailbox_(other.emailbox_) -{} - -/// \brief Convert the \c MINFO to a string. -/// -/// The output of this method is formatted as described in the "from string" -/// constructor (\c MINFO(const std::string&))). -/// -/// \throw std::bad_alloc Internal resource allocation fails. -/// -/// \return A \c string object that represents the \c MINFO object. -std::string -MINFO::toText() const { - return (rmailbox_.toText() + " " + emailbox_.toText()); -} - -/// \brief Render the \c MINFO in the wire format without name compression. -/// -/// \throw std::bad_alloc Internal resource allocation fails. -/// -/// \param buffer An output buffer to store the wire data. -void -MINFO::toWire(OutputBuffer& buffer) const { - rmailbox_.toWire(buffer); - emailbox_.toWire(buffer); -} - -MINFO& -MINFO::operator=(const MINFO& source) { - rmailbox_ = source.rmailbox_; - emailbox_ = source.emailbox_; - - return (*this); -} - -/// \brief Render the \c MINFO in the wire format with taking into account -/// compression. -/// -/// As specified in RFC3597, TYPE MINFO is "well-known", the rmailbox and -/// emailbox fields (domain names) will be compressed. -/// -/// \throw std::bad_alloc Internal resource allocation fails. -/// -/// \param renderer DNS message rendering context that encapsulates the -/// output buffer and name compression information. -void -MINFO::toWire(AbstractMessageRenderer& renderer) const { - renderer.writeName(rmailbox_); - renderer.writeName(emailbox_); -} - -/// \brief Compare two instances of \c MINFO RDATA. -/// -/// See documentation in \c Rdata. -int -MINFO::compare(const Rdata& other) const { - const MINFO& other_minfo = dynamic_cast<const MINFO&>(other); - - const int cmp = compareNames(rmailbox_, other_minfo.rmailbox_); - if (cmp != 0) { - return (cmp); - } - return (compareNames(emailbox_, other_minfo.emailbox_)); -} - -// END_RDATA_NAMESPACE -// END_ISC_NAMESPACE diff --git a/src/lib/dns/rdata/generic/minfo_14.h b/src/lib/dns/rdata/generic/minfo_14.h deleted file mode 100644 index ce9f43df33..0000000000 --- a/src/lib/dns/rdata/generic/minfo_14.h +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -// BEGIN_HEADER_GUARD - -#include <string> - -#include <dns/name.h> -#include <dns/rdata.h> - -// BEGIN_ISC_NAMESPACE - -// BEGIN_COMMON_DECLARATIONS -// END_COMMON_DECLARATIONS - -// BEGIN_RDATA_NAMESPACE - -/// \brief \c rdata::generic::MINFO class represents the MINFO RDATA as -/// defined in RFC1035. -/// -/// This class implements the basic interfaces inherited from the abstract -/// \c rdata::Rdata class, and provides trivial accessors specific to the -/// MINFO RDATA. -class MINFO : public Rdata { -public: - // BEGIN_COMMON_MEMBERS - // END_COMMON_MEMBERS - - /// \brief Define the assignment operator. - /// - /// \exception std::bad_alloc Memory allocation fails in copying - /// internal member variables (this should be very rare). - MINFO& operator=(const MINFO& source); - - /// \brief Return the value of the rmailbox field. - /// - /// \throw std::bad_alloc If resource allocation for the returned - /// \c Name fails. - /// - /// \note - /// Unlike the case of some other RDATA classes (such as - /// \c NS::getNSName()), this method constructs a new \c Name object - /// and returns it, instead of returning a reference to a \c Name object - /// internally maintained in the class (which is a private member). - /// This is based on the observation that this method will be rarely - /// used and even when it's used it will not be in a performance context - /// (for example, a recursive resolver won't need this field in its - /// resolution process). By returning a new object we have flexibility - /// of changing the internal representation without the risk of changing - /// the interface or method property. - /// The same note applies to the \c getEmailbox() method. - Name getRmailbox() const { return (rmailbox_); } - - /// \brief Return the value of the emailbox field. - /// - /// \throw std::bad_alloc If resource allocation for the returned - /// \c Name fails. - Name getEmailbox() const { return (emailbox_); } - -private: - Name rmailbox_; - Name emailbox_; -}; - -// END_RDATA_NAMESPACE -// END_ISC_NAMESPACE -// END_HEADER_GUARD - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/rdata/generic/mx_15.cc b/src/lib/dns/rdata/generic/mx_15.cc deleted file mode 100644 index bbe8abcacb..0000000000 --- a/src/lib/dns/rdata/generic/mx_15.cc +++ /dev/null @@ -1,160 +0,0 @@ -// Copyright (C) 2010-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#include <config.h> - -#include <string> - -#include <boost/lexical_cast.hpp> - -#include <exceptions/exceptions.h> - -#include <util/buffer.h> -#include <dns/name.h> -#include <dns/messagerenderer.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> - -#include <dns/rdata/generic/detail/lexer_util.h> - -using namespace std; -using boost::lexical_cast; -using namespace isc::util; -using isc::dns::rdata::generic::detail::createNameFromLexer; - -// BEGIN_ISC_NAMESPACE -// BEGIN_RDATA_NAMESPACE - -MX::MX(InputBuffer& buffer, size_t) : - preference_(buffer.readUint16()), mxname_(buffer) -{ - // we don't need rdata_len for parsing. if necessary, the caller will - // check consistency. -} - -/// \brief Constructor from string. -/// -/// The given string must represent a valid MX 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 EXCHANGE name must be absolute since there's no parameter that -/// specifies the origin name; if it is not absolute, \c MissingNameOrigin -/// exception will be thrown. It must not be represented as a quoted -/// string. -/// -/// See the construction that takes \c MasterLexer for other fields. -/// -/// \throw Others Exception from the Name and RRTTL constructors. -/// \throw InvalidRdataText Other general syntax errors. -MX::MX(const std::string& mx_str) : - // Fill in dummy name and replace them soon below. - preference_(0), mxname_(Name::ROOT_NAME()) -{ - try { - std::istringstream ss(mx_str); - MasterLexer lexer; - lexer.pushSource(ss); - - constructFromLexer(lexer, NULL); - - if (lexer.getNextToken().getType() != MasterToken::END_OF_FILE) { - isc_throw(InvalidRdataText, "extra input text for MX: " - << mx_str); - } - } catch (const MasterLexer::LexerError& ex) { - isc_throw(InvalidRdataText, "Failed to construct MX from '" << - mx_str << "': " << ex.what()); - } -} - -/// \brief Constructor with a context of MasterLexer. -/// -/// The \c lexer should point to the beginning of valid textual representation -/// of an MX RDATA. The EXCHANGE field can be non-absolute if \c origin -/// is non-NULL, in which case \c origin is used to make it absolute. -/// It must not be represented as a quoted string. -/// -/// The PREFERENCE field must be a valid decimal representation of an -/// unsigned 16-bit integer. -/// -/// \throw MasterLexer::LexerError General parsing error such as missing field. -/// \throw Other Exceptions from the Name and RRTTL constructors if -/// construction of textual fields as these objects fail. -/// -/// \param lexer A \c MasterLexer object parsing a master file for the -/// RDATA to be created -/// \param origin If non NULL, specifies the origin of EXCHANGE when it -/// is non-absolute. -MX::MX(MasterLexer& lexer, const Name* origin, - MasterLoader::Options, MasterLoaderCallbacks&) : - preference_(0), mxname_(Name::ROOT_NAME()) -{ - constructFromLexer(lexer, origin); -} - -void -MX::constructFromLexer(MasterLexer& lexer, const Name* origin) { - const uint32_t num = lexer.getNextToken(MasterToken::NUMBER).getNumber(); - if (num > 65535) { - isc_throw(InvalidRdataText, "Invalid MX preference: " << num); - } - preference_ = static_cast<uint16_t>(num); - - mxname_ = createNameFromLexer(lexer, origin); -} - -MX::MX(uint16_t preference, const Name& mxname) : - preference_(preference), mxname_(mxname) -{} - -MX::MX(const MX& other) : - Rdata(), preference_(other.preference_), mxname_(other.mxname_) -{} - -void -MX::toWire(OutputBuffer& buffer) const { - buffer.writeUint16(preference_); - mxname_.toWire(buffer); -} - -void -MX::toWire(AbstractMessageRenderer& renderer) const { - renderer.writeUint16(preference_); - renderer.writeName(mxname_); -} - -string -MX::toText() const { - return (lexical_cast<string>(preference_) + " " + mxname_.toText()); -} - -int -MX::compare(const Rdata& other) const { - const MX& other_mx = dynamic_cast<const MX&>(other); - - if (preference_ < other_mx.preference_) { - return (-1); - } else if (preference_ > other_mx.preference_) { - return (1); - } - - return (compareNames(mxname_, other_mx.mxname_)); -} - -const Name& -MX::getMXName() const { - return (mxname_); -} - -uint16_t -MX::getMXPref() const { - return (preference_); -} - -// END_RDATA_NAMESPACE -// END_ISC_NAMESPACE diff --git a/src/lib/dns/rdata/generic/mx_15.h b/src/lib/dns/rdata/generic/mx_15.h deleted file mode 100644 index b688f882cd..0000000000 --- a/src/lib/dns/rdata/generic/mx_15.h +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (C) 2010-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -// BEGIN_HEADER_GUARD - -#include <stdint.h> - -#include <string> - -#include <dns/name.h> -#include <dns/rdata.h> - -// BEGIN_ISC_NAMESPACE - -// BEGIN_COMMON_DECLARATIONS -// END_COMMON_DECLARATIONS - -// BEGIN_RDATA_NAMESPACE - -class MX : public Rdata { -public: - // BEGIN_COMMON_MEMBERS - // END_COMMON_MEMBERS - - MX(uint16_t preference, const Name& mxname); - - /// - /// Specialized methods - /// - const Name& getMXName() const; - uint16_t getMXPref() const; - -private: - void constructFromLexer(isc::dns::MasterLexer& lexer, - const isc::dns::Name* origin); - - /// Note: this is a prototype version; we may reconsider - /// this representation later. - uint16_t preference_; - Name mxname_; -}; - -// END_RDATA_NAMESPACE -// END_ISC_NAMESPACE -// END_HEADER_GUARD - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/rdata/generic/naptr_35.cc b/src/lib/dns/rdata/generic/naptr_35.cc deleted file mode 100644 index aa2d7f54c6..0000000000 --- a/src/lib/dns/rdata/generic/naptr_35.cc +++ /dev/null @@ -1,256 +0,0 @@ -// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#include <config.h> - -#include <dns/name.h> -#include <dns/messagerenderer.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> -#include <dns/rdata/generic/detail/char_string.h> -#include <exceptions/exceptions.h> - -#include <string> -#include <boost/lexical_cast.hpp> - -using namespace std; -using boost::lexical_cast; -using namespace isc::util; -using namespace isc::dns; - -// BEGIN_ISC_NAMESPACE -// BEGIN_RDATA_NAMESPACE - -class NAPTRImpl { -public: - NAPTRImpl() : order(0), preference(0), replacement(".") {} - - NAPTRImpl(InputBuffer& buffer, size_t rdata_len) : replacement(".") { - if (rdata_len < 4 || buffer.getLength() - buffer.getPosition() < 4) { - isc_throw(isc::dns::DNSMessageFORMERR, "Error in parsing " - "NAPTR RDATA wire format: insufficient length "); - } - order = buffer.readUint16(); - preference = buffer.readUint16(); - rdata_len -= 4; - - rdata_len -= detail::bufferToCharString(buffer, rdata_len, flags); - rdata_len -= detail::bufferToCharString(buffer, rdata_len, services); - rdata_len -= detail::bufferToCharString(buffer, rdata_len, regexp); - replacement = Name(buffer); - if (rdata_len < 1) { - isc_throw(isc::dns::DNSMessageFORMERR, "Error in parsing " - "NAPTR RDATA wire format: missing replacement name"); - } - rdata_len -= replacement.getLength(); - - if (rdata_len != 0) { - isc_throw(isc::dns::DNSMessageFORMERR, "Error in parsing " << - "NAPTR RDATA: bytes left at end: " << - static_cast<int>(rdata_len)); - } - } - - NAPTRImpl(const std::string& naptr_str) : replacement(".") { - std::istringstream ss(naptr_str); - MasterLexer lexer; - lexer.pushSource(ss); - - try { - parseNAPTRData(lexer); - // Should be at end of data now - if (lexer.getNextToken(MasterToken::QSTRING, true).getType() != - MasterToken::END_OF_FILE) { - isc_throw(InvalidRdataText, - "Invalid NAPTR text format: too many fields."); - } - } catch (const MasterLexer::LexerError& ex) { - isc_throw(InvalidRdataText, "Failed to construct NAPTR RDATA from " - << naptr_str << "': " << ex.what()); - } - } - - NAPTRImpl(MasterLexer& lexer) : replacement(".") - { - parseNAPTRData(lexer); - } - -private: - void - parseNAPTRData(MasterLexer& lexer) { - MasterToken token = lexer.getNextToken(MasterToken::NUMBER); - if (token.getNumber() > 65535) { - isc_throw(InvalidRdataText, - "Invalid NAPTR text format: order out of range: " - << token.getNumber()); - } - order = token.getNumber(); - token = lexer.getNextToken(MasterToken::NUMBER); - if (token.getNumber() > 65535) { - isc_throw(InvalidRdataText, - "Invalid NAPTR text format: preference out of range: " - << token.getNumber()); - } - preference = token.getNumber(); - - token = lexer.getNextToken(MasterToken::QSTRING); - stringToCharString(token.getStringRegion(), flags); - token = lexer.getNextToken(MasterToken::QSTRING); - stringToCharString(token.getStringRegion(), services); - token = lexer.getNextToken(MasterToken::QSTRING); - stringToCharString(token.getStringRegion(), regexp); - - token = lexer.getNextToken(MasterToken::STRING); - replacement = Name(token.getString()); - } - - -public: - uint16_t order; - uint16_t preference; - detail::CharString flags; - detail::CharString services; - detail::CharString regexp; - Name replacement; -}; - -NAPTR::NAPTR(InputBuffer& buffer, size_t rdata_len) : - impl_(new NAPTRImpl(buffer, rdata_len)) -{} - -NAPTR::NAPTR(const std::string& naptr_str) : impl_(new NAPTRImpl(naptr_str)) -{} - -NAPTR::NAPTR(MasterLexer& lexer, const Name*, - MasterLoader::Options, MasterLoaderCallbacks&) : - impl_(new NAPTRImpl(lexer)) -{} - -NAPTR::NAPTR(const NAPTR& naptr) : Rdata(), - impl_(new NAPTRImpl(*naptr.impl_)) -{} - -NAPTR& -NAPTR::operator=(const NAPTR& source) -{ - impl_.reset(new NAPTRImpl(*source.impl_)); - return (*this); -} - -NAPTR::~NAPTR() { -} - -void -NAPTR::toWire(OutputBuffer& buffer) const { - toWireHelper(buffer); - impl_->replacement.toWire(buffer); -} - -void -NAPTR::toWire(AbstractMessageRenderer& renderer) const { - toWireHelper(renderer); - // Type NAPTR is not "well-known", and name compression must be disabled - // per RFC3597. - renderer.writeName(impl_->replacement, false); -} - -string -NAPTR::toText() const { - string result; - result += lexical_cast<string>(impl_->order); - result += " "; - result += lexical_cast<string>(impl_->preference); - result += " \""; - result += detail::charStringToString(impl_->flags); - result += "\" \""; - result += detail::charStringToString(impl_->services); - result += "\" \""; - result += detail::charStringToString(impl_->regexp); - result += "\" "; - result += impl_->replacement.toText(); - return (result); -} - -int -NAPTR::compare(const Rdata& other) const { - const NAPTR other_naptr = dynamic_cast<const NAPTR&>(other); - - if (impl_->order < other_naptr.impl_->order) { - return (-1); - } else if (impl_->order > other_naptr.impl_->order) { - return (1); - } - - if (impl_->preference < other_naptr.impl_->preference) { - return (-1); - } else if (impl_->preference > other_naptr.impl_->preference) { - return (1); - } - - const int fcmp = detail::compareCharStrings(impl_->flags, - other_naptr.impl_->flags); - if (fcmp != 0) { - return (fcmp); - } - - const int scmp = detail::compareCharStrings(impl_->services, - other_naptr.impl_->services); - if (scmp != 0) { - return (scmp); - } - - const int rcmp = detail::compareCharStrings(impl_->regexp, - other_naptr.impl_->regexp); - if (rcmp != 0) { - return (rcmp); - } - - return (compareNames(impl_->replacement, other_naptr.impl_->replacement)); -} - -uint16_t -NAPTR::getOrder() const { - return (impl_->order); -} - -uint16_t -NAPTR::getPreference() const { - return (impl_->preference); -} - -const std::string -NAPTR::getFlags() const { - return (detail::charStringToString(impl_->flags)); -} - -const std::string -NAPTR::getServices() const { - return (detail::charStringToString(impl_->services)); -} - -const std::string -NAPTR::getRegexp() const { - return (detail::charStringToString(impl_->regexp)); -} - -const Name& -NAPTR::getReplacement() const { - return (impl_->replacement); -} - -template <typename T> -void -NAPTR::toWireHelper(T& outputer) const { - outputer.writeUint16(impl_->order); - outputer.writeUint16(impl_->preference); - - outputer.writeData(&impl_->flags[0], impl_->flags.size()); - outputer.writeData(&impl_->services[0], impl_->services.size()); - outputer.writeData(&impl_->regexp[0], impl_->regexp.size()); -} - -// END_RDATA_NAMESPACE -// END_ISC_NAMESPACE diff --git a/src/lib/dns/rdata/generic/naptr_35.h b/src/lib/dns/rdata/generic/naptr_35.h deleted file mode 100644 index c77b95d0a8..0000000000 --- a/src/lib/dns/rdata/generic/naptr_35.h +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -// BEGIN_HEADER_GUARD - -#include <string> - -#include <boost/scoped_ptr.hpp> - -#include <dns/name.h> -#include <dns/rdata.h> -#include <util/buffer.h> - -// BEGIN_ISC_NAMESPACE - -// BEGIN_COMMON_DECLARATIONS -// END_COMMON_DECLARATIONS - -// BEGIN_RDATA_NAMESPACE - -class NAPTRImpl; - -/// \brief \c NAPTR class represents the NAPTR rdata defined in -/// RFC2915, RFC2168 and RFC3403 -/// -/// This class implements the basic interfaces inherited from the -/// \c rdata::Rdata class, and provides accessors specific to the -/// NAPTR rdata. -class NAPTR : public Rdata { -public: - // BEGIN_COMMON_MEMBERS - // END_COMMON_MEMBERS - - // NAPTR specific methods - ~NAPTR(); - - NAPTR& operator=(const NAPTR& source); - - uint16_t getOrder() const; - uint16_t getPreference() const; - const std::string getFlags() const; - const std::string getServices() const; - const std::string getRegexp() const; - const Name& getReplacement() const; -private: - /// Helper template function for toWire() - /// - /// \param outputer Where to write data in - template <typename T> - void toWireHelper(T& outputer) const; - - boost::scoped_ptr<NAPTRImpl> impl_; -}; - -// END_RDATA_NAMESPACE -// END_ISC_NAMESPACE -// END_HEADER_GUARD - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/rdata/generic/ns_2.cc b/src/lib/dns/rdata/generic/ns_2.cc deleted file mode 100644 index 7c1fd01257..0000000000 --- a/src/lib/dns/rdata/generic/ns_2.cc +++ /dev/null @@ -1,121 +0,0 @@ -// Copyright (C) 2010-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#include <config.h> - -#include <string> - -#include <util/buffer.h> -#include <dns/name.h> -#include <dns/messagerenderer.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> - -#include <dns/rdata/generic/detail/lexer_util.h> - -using namespace std; -using namespace isc::util; -using isc::dns::rdata::generic::detail::createNameFromLexer; - -// BEGIN_ISC_NAMESPACE -// BEGIN_RDATA_NAMESPACE - -/// \brief Constructor from string. -/// -/// The given string must represent a valid NS 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 NSDNAME must be absolute since there's no parameter that -/// specifies the origin name; if it is not absolute, \c -/// MissingNameOrigin exception will be thrown. These must not be -/// represented as a quoted string. -/// -/// \throw Others Exception from the Name and RRTTL constructors. -/// \throw InvalidRdataText Other general syntax errors. -NS::NS(const std::string& namestr) : - // Fill in dummy name and replace them soon below. - nsname_(Name::ROOT_NAME()) -{ - try { - std::istringstream ss(namestr); - MasterLexer lexer; - lexer.pushSource(ss); - - nsname_ = createNameFromLexer(lexer, NULL); - - if (lexer.getNextToken().getType() != MasterToken::END_OF_FILE) { - isc_throw(InvalidRdataText, "extra input text for NS: " - << namestr); - } - } catch (const MasterLexer::LexerError& ex) { - isc_throw(InvalidRdataText, "Failed to construct NS from '" << - namestr << "': " << ex.what()); - } -} - -NS::NS(InputBuffer& buffer, size_t) : - nsname_(buffer) -{ - // we don't need rdata_len for parsing. if necessary, the caller will - // check consistency. -} - -/// \brief Constructor with a context of MasterLexer. -/// -/// The \c lexer should point to the beginning of valid textual -/// representation of an NS RDATA. The NSDNAME field can be -/// non-absolute if \c origin is non-NULL, in which case \c origin is -/// used to make it absolute. It must not be represented as a quoted -/// string. -/// -/// \throw MasterLexer::LexerError General parsing error such as missing field. -/// \throw Other Exceptions from the Name and RRTTL constructors if -/// construction of textual fields as these objects fail. -/// -/// \param lexer A \c MasterLexer object parsing a master file for the -/// RDATA to be created -/// \param origin If non NULL, specifies the origin of NSDNAME when it -/// is non-absolute. -NS::NS(MasterLexer& lexer, const Name* origin, - MasterLoader::Options, MasterLoaderCallbacks&) : - nsname_(createNameFromLexer(lexer, origin)) -{} - -NS::NS(const NS& other) : - Rdata(), nsname_(other.nsname_) -{} - -void -NS::toWire(OutputBuffer& buffer) const { - nsname_.toWire(buffer); -} - -void -NS::toWire(AbstractMessageRenderer& renderer) const { - renderer.writeName(nsname_); -} - -string -NS::toText() const { - return (nsname_.toText()); -} - -int -NS::compare(const Rdata& other) const { - const NS& other_ns = dynamic_cast<const NS&>(other); - - return (compareNames(nsname_, other_ns.nsname_)); -} - -const Name& -NS::getNSName() const { - return (nsname_); -} - -// END_RDATA_NAMESPACE -// END_ISC_NAMESPACE diff --git a/src/lib/dns/rdata/generic/ns_2.h b/src/lib/dns/rdata/generic/ns_2.h deleted file mode 100644 index 18c3cf671f..0000000000 --- a/src/lib/dns/rdata/generic/ns_2.h +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (C) 2010-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -// BEGIN_HEADER_GUARD - -#include <string> - -#include <dns/name.h> -#include <dns/rdata.h> - -// BEGIN_ISC_NAMESPACE - -// BEGIN_COMMON_DECLARATIONS -// END_COMMON_DECLARATIONS - -// BEGIN_RDATA_NAMESPACE - -class NS : public Rdata { -public: - // BEGIN_COMMON_MEMBERS - // END_COMMON_MEMBERS - /// - /// Specialized constructor - /// - explicit NS(const Name& nsname) : nsname_(nsname) {} - /// - /// Specialized methods - /// - const Name& getNSName() const; -private: - Name nsname_; -}; - -// END_RDATA_NAMESPACE -// END_ISC_NAMESPACE -// END_HEADER_GUARD - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/rdata/generic/nsec3_50.cc b/src/lib/dns/rdata/generic/nsec3_50.cc deleted file mode 100644 index 398757931c..0000000000 --- a/src/lib/dns/rdata/generic/nsec3_50.cc +++ /dev/null @@ -1,342 +0,0 @@ -// Copyright (C) 2010-2024 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#include <config.h> - -#include <iostream> -#include <iomanip> -#include <string> -#include <sstream> -#include <vector> -#include <cassert> - -#include <boost/lexical_cast.hpp> - -#include <util/encode/encode.h> -#include <util/buffer.h> - -#include <dns/exceptions.h> -#include <dns/messagerenderer.h> -#include <dns/name.h> -#include <dns/rrtype.h> -#include <dns/rrttl.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> -#include <dns/rdata/generic/detail/nsec_bitmap.h> -#include <dns/rdata/generic/detail/nsec3param_common.h> - -#include <memory> - -#include <stdio.h> -#include <time.h> - -using namespace std; -using namespace isc::dns::rdata::generic::detail::nsec; -using namespace isc::dns::rdata::generic::detail::nsec3; -using namespace isc::util::encode; -using namespace isc::util; - -// BEGIN_ISC_NAMESPACE -// BEGIN_RDATA_NAMESPACE - -struct NSEC3Impl { - // straightforward representation of NSEC3 RDATA fields - NSEC3Impl(uint8_t hashalg, uint8_t flags, uint16_t iterations, - vector<uint8_t>salt, vector<uint8_t>next, - vector<uint8_t> typebits) : - hashalg_(hashalg), flags_(flags), iterations_(iterations), - salt_(salt), next_(next), typebits_(typebits) - {} - - const uint8_t hashalg_; - const uint8_t flags_; - const uint16_t iterations_; - const vector<uint8_t> salt_; - const vector<uint8_t> next_; - const vector<uint8_t> typebits_; -}; - -/// \brief Constructor from string. -/// -/// The given string must represent a valid NSEC3 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 Hash Algorithm, Flags and Iterations fields must be within their -/// valid ranges. The Salt field may contain "-" to indicate that the -/// salt is of length 0. The Salt field must not contain any whitespace. -/// The type mnemonics must be valid, and separated by whitespace. If -/// any invalid mnemonics are found, InvalidRdataText exception is -/// thrown. -/// -/// \throw InvalidRdataText if any fields are out of their valid range, -/// or are incorrect. -/// -/// \param nsec3_str A string containing the RDATA to be created -NSEC3::NSEC3(const std::string& nsec3_str) : - impl_(NULL) -{ - // We use unique_ptr here because if there is an exception in this - // constructor, the destructor is not called and there could be a - // leak of the NSEC3Impl that constructFromLexer() returns. - std::unique_ptr<NSEC3Impl> impl_ptr; - - try { - std::istringstream ss(nsec3_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 NSEC3: " << nsec3_str); - } - } catch (const MasterLexer::LexerError& ex) { - isc_throw(InvalidRdataText, - "Failed to construct NSEC3 from '" << nsec3_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 NSEC3 RDATA. -/// -/// See \c NSEC3::NSEC3(const std::string&) for description of the -/// expected RDATA fields. -/// -/// \throw MasterLexer::LexerError General parsing error such as -/// missing field. -/// \throw InvalidRdataText if any fields are out of their valid range, -/// or are incorrect. -/// -/// \param lexer A \c MasterLexer object parsing a master file for the -/// RDATA to be created -NSEC3::NSEC3(MasterLexer& lexer, const Name*, MasterLoader::Options, - MasterLoaderCallbacks&) : - impl_(NULL) -{ - impl_ = constructFromLexer(lexer); -} - -NSEC3Impl* -NSEC3::constructFromLexer(MasterLexer& lexer) { - vector<uint8_t> salt; - const ParseNSEC3ParamResult params = - parseNSEC3ParamFromLexer("NSEC3", lexer, salt); - - const string& nexthash = - lexer.getNextToken(MasterToken::STRING).getString(); - if (*nexthash.rbegin() == '=') { - isc_throw(InvalidRdataText, "NSEC3 hash has padding: " << nexthash); - } - - vector<uint8_t> next; - decodeBase32Hex(nexthash, next); - if (next.size() > 255) { - isc_throw(InvalidRdataText, "NSEC3 hash is too long: " - << next.size() << " bytes"); - } - - vector<uint8_t> typebits; - // For NSEC3 empty bitmap is possible and allowed. - buildBitmapsFromLexer("NSEC3", lexer, typebits, true); - return (new NSEC3Impl(params.algorithm, params.flags, params.iterations, - salt, next, typebits)); -} - -NSEC3::NSEC3(InputBuffer& buffer, size_t rdata_len) : - impl_(NULL) -{ - vector<uint8_t> salt; - const ParseNSEC3ParamResult params = - parseNSEC3ParamWire("NSEC3", buffer, rdata_len, salt); - - if (rdata_len < 1) { - isc_throw(DNSMessageFORMERR, "NSEC3 too short to contain hash length, " - "length: " << rdata_len + salt.size() + 5); - } - const uint8_t nextlen = buffer.readUint8(); - --rdata_len; - if (nextlen == 0 || rdata_len < nextlen) { - isc_throw(DNSMessageFORMERR, "NSEC3 invalid hash length: " << - static_cast<unsigned int>(nextlen)); - } - - vector<uint8_t> next(nextlen); - buffer.readData(&next[0], nextlen); - rdata_len -= nextlen; - - vector<uint8_t> typebits(rdata_len); - if (rdata_len > 0) { - // Read and parse the bitmaps only when they exist; empty bitmap - // is possible for NSEC3. - buffer.readData(&typebits[0], rdata_len); - checkRRTypeBitmaps("NSEC3", typebits); - } - - impl_ = new NSEC3Impl(params.algorithm, params.flags, params.iterations, - salt, next, typebits); -} - -NSEC3::NSEC3(const NSEC3& source) : - Rdata(), impl_(new NSEC3Impl(*source.impl_)) -{} - -NSEC3& -NSEC3::operator=(const NSEC3& source) { - if (this == &source) { - return (*this); - } - - NSEC3Impl* newimpl = new NSEC3Impl(*source.impl_); - delete impl_; - impl_ = newimpl; - - return (*this); -} - -NSEC3::~NSEC3() { - delete impl_; -} - -string -NSEC3::toText() const { - ostringstream s; - bitmapsToText(impl_->typebits_, s); - - using boost::lexical_cast; - return (lexical_cast<string>(static_cast<int>(impl_->hashalg_)) + - " " + lexical_cast<string>(static_cast<int>(impl_->flags_)) + - " " + lexical_cast<string>(static_cast<int>(impl_->iterations_)) + - " " + (impl_->salt_.empty() ? "-" : encodeHex(impl_->salt_)) + - " " + encodeBase32Hex(impl_->next_) + s.str()); -} - -template <typename OUTPUT_TYPE> -void -toWireHelper(const NSEC3Impl& impl, OUTPUT_TYPE& output) { - output.writeUint8(impl.hashalg_); - output.writeUint8(impl.flags_); - output.writeUint16(impl.iterations_); - output.writeUint8(impl.salt_.size()); - if (!impl.salt_.empty()) { - output.writeData(&impl.salt_[0], impl.salt_.size()); - } - assert(!impl.next_.empty()); - output.writeUint8(impl.next_.size()); - output.writeData(&impl.next_[0], impl.next_.size()); - if (!impl.typebits_.empty()) { - output.writeData(&impl.typebits_[0], impl.typebits_.size()); - } -} - -void -NSEC3::toWire(OutputBuffer& buffer) const { - toWireHelper(*impl_, buffer); -} - -void -NSEC3::toWire(AbstractMessageRenderer& renderer) const { - toWireHelper(*impl_, renderer); -} - -namespace { -// This is a helper subroutine for compare(). It compares two binary -// data stored in vector<uint8_t> objects based on the "Canonical RR Ordering" -// as defined in Section 6.3 of RFC4034, that is, the data are treated -// "as a left-justified unsigned octet sequence in which the absence of an -// octet sorts before a zero octet." -// -// If check_length_first is true, it treats the compared data as if they -// began with a single-octet "length" field whose value is the size of the -// corresponding vector. In this case, if the sizes of the two vectors are -// different the shorter one is always considered the "smaller"; the contents -// of the vector don't matter. -// -// This function returns: -// -1 if v1 is considered smaller than v2 -// 1 if v1 is considered larger than v2 -// 0 otherwise -int -compareVectors(const vector<uint8_t>& v1, const vector<uint8_t>& v2, - bool check_length_first = true) -{ - const size_t len1 = v1.size(); - const size_t len2 = v2.size(); - if (check_length_first && len1 != len2) { - return (len1 - len2); - } - const size_t cmplen = min(len1, len2); - const int cmp = cmplen == 0 ? 0 : memcmp(&v1.at(0), &v2.at(0), cmplen); - if (cmp != 0) { - return (cmp); - } else { - return (len1 - len2); - } -} -} - -int -NSEC3::compare(const Rdata& other) const { - const NSEC3& other_nsec3 = dynamic_cast<const NSEC3&>(other); - - if (impl_->hashalg_ != other_nsec3.impl_->hashalg_) { - return (impl_->hashalg_ < other_nsec3.impl_->hashalg_ ? -1 : 1); - } - if (impl_->flags_ != other_nsec3.impl_->flags_) { - return (impl_->flags_ < other_nsec3.impl_->flags_ ? -1 : 1); - } - if (impl_->iterations_ != other_nsec3.impl_->iterations_) { - return (impl_->iterations_ < other_nsec3.impl_->iterations_ ? -1 : 1); - } - - int cmp = compareVectors(impl_->salt_, other_nsec3.impl_->salt_); - if (cmp != 0) { - return (cmp); - } - cmp = compareVectors(impl_->next_, other_nsec3.impl_->next_); - if (cmp != 0) { - return (cmp); - } - // Note that bitmap doesn't have a dedicated length field, so we shouldn't - // terminate the comparison just because the lengths are different. - return (compareVectors(impl_->typebits_, other_nsec3.impl_->typebits_, - false)); -} - -uint8_t -NSEC3::getHashalg() const { - return (impl_->hashalg_); -} - -uint8_t -NSEC3::getFlags() const { - return (impl_->flags_); -} - -uint16_t -NSEC3::getIterations() const { - return (impl_->iterations_); -} - -const vector<uint8_t>& -NSEC3::getSalt() const { - return (impl_->salt_); -} - -const vector<uint8_t>& -NSEC3::getNext() const { - return (impl_->next_); -} - -// END_RDATA_NAMESPACE -// END_ISC_NAMESPACE diff --git a/src/lib/dns/rdata/generic/nsec3_50.h b/src/lib/dns/rdata/generic/nsec3_50.h deleted file mode 100644 index cf73624f58..0000000000 --- a/src/lib/dns/rdata/generic/nsec3_50.h +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright (C) 2010-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#include <stdint.h> - -#include <string> -#include <vector> - -#include <dns/name.h> -#include <dns/rrtype.h> -#include <dns/rrttl.h> -#include <dns/rdata.h> -#include <dns/master_lexer.h> - -// BEGIN_HEADER_GUARD - -// BEGIN_ISC_NAMESPACE - -// BEGIN_COMMON_DECLARATIONS -// END_COMMON_DECLARATIONS - -// BEGIN_RDATA_NAMESPACE - -struct NSEC3Impl; - -class NSEC3 : public Rdata { -public: - // BEGIN_COMMON_MEMBERS - // END_COMMON_MEMBERS - NSEC3& operator=(const NSEC3& source); - ~NSEC3(); - - uint8_t getHashalg() const; - uint8_t getFlags() const; - uint16_t getIterations() const; - const std::vector<uint8_t>& getSalt() const; - const std::vector<uint8_t>& getNext() const; - -private: - NSEC3Impl* constructFromLexer(isc::dns::MasterLexer& lexer); - - NSEC3Impl* impl_; -}; - -// END_RDATA_NAMESPACE -// END_ISC_NAMESPACE -// END_HEADER_GUARD - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/rdata/generic/nsec3param_51.cc b/src/lib/dns/rdata/generic/nsec3param_51.cc deleted file mode 100644 index 74a7109f23..0000000000 --- a/src/lib/dns/rdata/generic/nsec3param_51.cc +++ /dev/null @@ -1,232 +0,0 @@ -// Copyright (C) 2010-2024 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#include <config.h> - -#include <util/buffer.h> -#include <util/encode/encode.h> - -#include <dns/messagerenderer.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> -#include <dns/rdata/generic/detail/nsec3param_common.h> - -#include <boost/lexical_cast.hpp> - -#include <memory> -#include <string> -#include <sstream> -#include <vector> - -using namespace std; -using namespace isc::util; -using namespace isc::util::encode; - -// BEGIN_ISC_NAMESPACE -// BEGIN_RDATA_NAMESPACE - -struct NSEC3PARAMImpl { - // straightforward representation of NSEC3PARAM RDATA fields - NSEC3PARAMImpl(uint8_t hashalg, uint8_t flags, uint16_t iterations, - const vector<uint8_t>& salt) : - hashalg_(hashalg), flags_(flags), iterations_(iterations), salt_(salt) - {} - - const uint8_t hashalg_; - const uint8_t flags_; - const uint16_t iterations_; - const vector<uint8_t> salt_; -}; - -/// \brief Constructor from string. -/// -/// The given string must represent a valid NSEC3PARAM 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 Hash Algorithm, Flags and Iterations fields must be within their -/// valid ranges. The Salt field may contain "-" to indicate that the -/// salt is of length 0. The Salt field must not contain any whitespace. -/// -/// \throw InvalidRdataText if any fields are out of their valid range, -/// or are incorrect. -/// -/// \param nsec3param_str A string containing the RDATA to be created -NSEC3PARAM::NSEC3PARAM(const std::string& nsec3param_str) : - impl_(NULL) -{ - // We use unique_ptr here because if there is an exception in this - // constructor, the destructor is not called and there could be a - // leak of the NSEC3PARAMImpl that constructFromLexer() returns. - std::unique_ptr<NSEC3PARAMImpl> impl_ptr; - - try { - std::istringstream ss(nsec3param_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 NSEC3PARAM: " << nsec3param_str); - } - } catch (const MasterLexer::LexerError& ex) { - isc_throw(InvalidRdataText, - "Failed to construct NSEC3PARAM from '" << nsec3param_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 NSEC3PARAM RDATA. -/// -/// See \c NSEC3PARAM::NSEC3PARAM(const std::string&) for description of -/// the expected RDATA fields. -/// -/// \throw MasterLexer::LexerError General parsing error such as -/// missing field. -/// \throw InvalidRdataText if any fields are out of their valid range, -/// or are incorrect. -/// -/// \param lexer A \c MasterLexer object parsing a master file for the -/// RDATA to be created -NSEC3PARAM::NSEC3PARAM(MasterLexer& lexer, const Name*, MasterLoader::Options, - MasterLoaderCallbacks&) : - impl_(NULL) -{ - impl_ = constructFromLexer(lexer); -} - -NSEC3PARAMImpl* -NSEC3PARAM::constructFromLexer(MasterLexer& lexer) { - vector<uint8_t> salt; - const ParseNSEC3ParamResult params = - parseNSEC3ParamFromLexer("NSEC3PARAM", lexer, salt); - - return (new NSEC3PARAMImpl(params.algorithm, params.flags, - params.iterations, salt)); -} - -NSEC3PARAM::NSEC3PARAM(InputBuffer& buffer, size_t rdata_len) : - impl_(NULL) -{ - vector<uint8_t> salt; - const ParseNSEC3ParamResult params = - parseNSEC3ParamWire("NSEC3PARAM", buffer, rdata_len, salt); - - impl_ = new NSEC3PARAMImpl(params.algorithm, params.flags, - params.iterations, salt); -} - -NSEC3PARAM::NSEC3PARAM(const NSEC3PARAM& source) : - Rdata(), impl_(new NSEC3PARAMImpl(*source.impl_)) -{} - -NSEC3PARAM& -NSEC3PARAM::operator=(const NSEC3PARAM& source) { - if (this == &source) { - return (*this); - } - - NSEC3PARAMImpl* newimpl = new NSEC3PARAMImpl(*source.impl_); - delete impl_; - impl_ = newimpl; - - return (*this); -} - -NSEC3PARAM::~NSEC3PARAM() { - delete impl_; -} - -string -NSEC3PARAM::toText() const { - using boost::lexical_cast; - return (lexical_cast<string>(static_cast<int>(impl_->hashalg_)) + - " " + lexical_cast<string>(static_cast<int>(impl_->flags_)) + - " " + lexical_cast<string>(static_cast<int>(impl_->iterations_)) + - " " + (impl_->salt_.empty() ? "-" : encodeHex(impl_->salt_))); -} - -template <typename OUTPUT_TYPE> -void -toWireHelper(const NSEC3PARAMImpl& impl, OUTPUT_TYPE& output) { - output.writeUint8(impl.hashalg_); - output.writeUint8(impl.flags_); - output.writeUint16(impl.iterations_); - output.writeUint8(impl.salt_.size()); - if (!impl.salt_.empty()) { - output.writeData(&impl.salt_[0], impl.salt_.size()); - } -} - -void -NSEC3PARAM::toWire(OutputBuffer& buffer) const { - toWireHelper(*impl_, buffer); -} - -void -NSEC3PARAM::toWire(AbstractMessageRenderer& renderer) const { - toWireHelper(*impl_, renderer); -} - -int -NSEC3PARAM::compare(const Rdata& other) const { - const NSEC3PARAM& other_param = dynamic_cast<const NSEC3PARAM&>(other); - - if (impl_->hashalg_ != other_param.impl_->hashalg_) { - return (impl_->hashalg_ < other_param.impl_->hashalg_ ? -1 : 1); - } - if (impl_->flags_ != other_param.impl_->flags_) { - return (impl_->flags_ < other_param.impl_->flags_ ? -1 : 1); - } - if (impl_->iterations_ != other_param.impl_->iterations_) { - return (impl_->iterations_ < other_param.impl_->iterations_ ? -1 : 1); - } - - const size_t this_len = impl_->salt_.size(); - const size_t other_len = other_param.impl_->salt_.size(); - if (this_len != other_len) { - return (this_len - other_len); - } - const size_t cmplen = min(this_len, other_len); - const int cmp = (cmplen == 0) ? 0 : - memcmp(&impl_->salt_.at(0), &other_param.impl_->salt_.at(0), cmplen); - if (cmp != 0) { - return (cmp); - } else { - return (this_len - other_len); - } -} - -uint8_t -NSEC3PARAM::getHashalg() const { - return (impl_->hashalg_); -} - -uint8_t -NSEC3PARAM::getFlags() const { - return (impl_->flags_); -} - -uint16_t -NSEC3PARAM::getIterations() const { - return (impl_->iterations_); -} - -const vector<uint8_t>& -NSEC3PARAM::getSalt() const { - return (impl_->salt_); -} - -// END_RDATA_NAMESPACE -// END_ISC_NAMESPACE diff --git a/src/lib/dns/rdata/generic/nsec3param_51.h b/src/lib/dns/rdata/generic/nsec3param_51.h deleted file mode 100644 index 1c7bf03251..0000000000 --- a/src/lib/dns/rdata/generic/nsec3param_51.h +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright (C) 2010-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#include <stdint.h> - -#include <string> -#include <vector> - -#include <dns/name.h> -#include <dns/rrtype.h> -#include <dns/rrttl.h> -#include <dns/rdata.h> -#include <dns/master_lexer.h> - -// BEGIN_HEADER_GUARD - -// BEGIN_ISC_NAMESPACE - -// BEGIN_COMMON_DECLARATIONS -// END_COMMON_DECLARATIONS - -// BEGIN_RDATA_NAMESPACE - -struct NSEC3PARAMImpl; - -class NSEC3PARAM : public Rdata { -public: - // BEGIN_COMMON_MEMBERS - // END_COMMON_MEMBERS - NSEC3PARAM& operator=(const NSEC3PARAM& source); - ~NSEC3PARAM(); - - /// - /// Specialized methods - /// - uint8_t getHashalg() const; - uint8_t getFlags() const; - uint16_t getIterations() const; - const std::vector<uint8_t>& getSalt() const; - -private: - NSEC3PARAMImpl* constructFromLexer(isc::dns::MasterLexer& lexer); - - NSEC3PARAMImpl* impl_; -}; - -// END_RDATA_NAMESPACE -// END_ISC_NAMESPACE -// END_HEADER_GUARD - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/rdata/generic/nsec_47.cc b/src/lib/dns/rdata/generic/nsec_47.cc deleted file mode 100644 index e78e18aa77..0000000000 --- a/src/lib/dns/rdata/generic/nsec_47.cc +++ /dev/null @@ -1,216 +0,0 @@ -// Copyright (C) 2010-2024 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#include <config.h> - -#include <iostream> -#include <string> -#include <sstream> -#include <vector> - -#include <util/encode/encode.h> -#include <util/buffer.h> -#include <dns/exceptions.h> -#include <dns/messagerenderer.h> -#include <dns/name.h> -#include <dns/rrtype.h> -#include <dns/rrttl.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> -#include <dns/rdata/generic/detail/nsec_bitmap.h> -#include <dns/rdata/generic/detail/lexer_util.h> - -#include <stdio.h> -#include <time.h> - -using namespace std; -using namespace isc::util; -using namespace isc::util::encode; -using namespace isc::dns::rdata::generic::detail::nsec; -using isc::dns::rdata::generic::detail::createNameFromLexer; - -// BEGIN_ISC_NAMESPACE -// BEGIN_RDATA_NAMESPACE - -struct NSECImpl { - // straightforward representation of NSEC RDATA fields - NSECImpl(const Name& next, vector<uint8_t> typebits) : - nextname_(next), typebits_(typebits) - {} - - Name nextname_; - vector<uint8_t> typebits_; -}; - -/// \brief Constructor from string. -/// -/// The given string must represent a valid NSEC 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 Next Domain Name field must be absolute since there's no -/// parameter that specifies the origin name; if it is not absolute, -/// \c MissingNameOrigin exception will be thrown. This must not be -/// represented as a quoted string. -/// -/// The type mnemonics must be valid, and separated by whitespace. If -/// any invalid mnemonics are found, InvalidRdataText exception is -/// thrown. -/// -/// \throw MissingNameOrigin Thrown when the Next Domain Name is not absolute. -/// \throw InvalidRdataText if any fields are out of their valid range. -/// -/// \param nsec_str A string containing the RDATA to be created -NSEC::NSEC(const std::string& nsec_str) : - impl_(NULL) -{ - try { - std::istringstream ss(nsec_str); - MasterLexer lexer; - lexer.pushSource(ss); - - const Name origin_name(createNameFromLexer(lexer, NULL)); - - vector<uint8_t> typebits; - buildBitmapsFromLexer("NSEC", lexer, typebits); - - impl_ = new NSECImpl(origin_name, typebits); - - if (lexer.getNextToken().getType() != MasterToken::END_OF_FILE) { - isc_throw(InvalidRdataText, - "Extra input text for NSEC: " << nsec_str); - } - } catch (const MasterLexer::LexerError& ex) { - isc_throw(InvalidRdataText, - "Failed to construct NSEC from '" << nsec_str << "': " - << ex.what()); - } -} - -NSEC::NSEC(InputBuffer& buffer, size_t rdata_len) { - const size_t pos = buffer.getPosition(); - const Name nextname(buffer); - - // rdata_len must be sufficiently large to hold non empty bitmap. - if (rdata_len <= buffer.getPosition() - pos) { - isc_throw(DNSMessageFORMERR, - "NSEC RDATA from wire too short: " << rdata_len << "bytes"); - } - rdata_len -= (buffer.getPosition() - pos); - - vector<uint8_t> typebits(rdata_len); - buffer.readData(&typebits[0], rdata_len); - checkRRTypeBitmaps("NSEC", typebits); - - impl_ = new NSECImpl(nextname, typebits); -} - -/// \brief Constructor with a context of MasterLexer. -/// -/// The \c lexer should point to the beginning of valid textual -/// representation of an NSEC RDATA. -/// -/// The Next Domain Name field can be non-absolute if \c origin is -/// non-NULL, in which case \c origin is used to make it absolute. It -/// must not be represented as a quoted string. -/// -/// The type mnemonics must be valid, and separated by whitespace. If -/// any invalid mnemonics are found, InvalidRdataText exception is -/// thrown. -/// -/// \throw MasterLexer::LexerError General parsing error such as -/// missing field. -/// \throw MissingNameOrigin Thrown when the Next Domain Name is not -/// absolute and \c origin is NULL. -/// \throw InvalidRdataText if any fields are out of their valid range. -/// -/// \param lexer A \c MasterLexer object parsing a master file for the -/// RDATA to be created -/// \param origin The origin to use with a relative Next Domain Name -/// field -NSEC::NSEC(MasterLexer& lexer, const Name* origin, MasterLoader::Options, - MasterLoaderCallbacks&) -{ - const Name next_name(createNameFromLexer(lexer, origin)); - - vector<uint8_t> typebits; - buildBitmapsFromLexer("NSEC", lexer, typebits); - - impl_ = new NSECImpl(next_name, typebits); -} - -NSEC::NSEC(const NSEC& source) : - Rdata(), impl_(new NSECImpl(*source.impl_)) -{} - -NSEC& -NSEC::operator=(const NSEC& source) { - if (this == &source) { - return (*this); - } - - NSECImpl* newimpl = new NSECImpl(*source.impl_); - delete impl_; - impl_ = newimpl; - - return (*this); -} - -NSEC::~NSEC() { - delete impl_; -} - -string -NSEC::toText() const { - ostringstream s; - s << impl_->nextname_; - bitmapsToText(impl_->typebits_, s); - return (s.str()); -} - -void -NSEC::toWire(OutputBuffer& buffer) const { - impl_->nextname_.toWire(buffer); - buffer.writeData(&impl_->typebits_[0], impl_->typebits_.size()); -} - -void -NSEC::toWire(AbstractMessageRenderer& renderer) const { - // Type NSEC is not "well-known", and name compression must be disabled - // per RFC3597. - renderer.writeName(impl_->nextname_, false); - renderer.writeData(&impl_->typebits_[0], impl_->typebits_.size()); -} - -const Name& -NSEC::getNextName() const { - return (impl_->nextname_); -} - -int -NSEC::compare(const Rdata& other) const { - const NSEC& other_nsec = dynamic_cast<const NSEC&>(other); - - int cmp = compareNames(impl_->nextname_, other_nsec.impl_->nextname_); - if (cmp != 0) { - return (cmp); - } - - const size_t this_len = impl_->typebits_.size(); - const size_t other_len = other_nsec.impl_->typebits_.size(); - const size_t cmplen = min(this_len, other_len); - cmp = memcmp(&impl_->typebits_[0], &other_nsec.impl_->typebits_[0], - cmplen); - if (cmp != 0) { - return (cmp); - } else { - return ((this_len == other_len) ? 0 : (this_len < other_len) ? -1 : 1); - } -} - -// END_RDATA_NAMESPACE -// END_ISC_NAMESPACE diff --git a/src/lib/dns/rdata/generic/nsec_47.h b/src/lib/dns/rdata/generic/nsec_47.h deleted file mode 100644 index 299d381598..0000000000 --- a/src/lib/dns/rdata/generic/nsec_47.h +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (C) 2010-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#include <stdint.h> - -#include <string> - -#include <dns/name.h> -#include <dns/rrtype.h> -#include <dns/rrttl.h> -#include <dns/rdata.h> - -// BEGIN_HEADER_GUARD - -// BEGIN_ISC_NAMESPACE - -// BEGIN_COMMON_DECLARATIONS -// END_COMMON_DECLARATIONS - -// BEGIN_RDATA_NAMESPACE - -struct NSECImpl; - -class NSEC : public Rdata { -public: - // BEGIN_COMMON_MEMBERS - // END_COMMON_MEMBERS - NSEC& operator=(const NSEC& source); - ~NSEC(); - - // specialized methods - - /// Return the next domain name. - /// - /// \exception std::bad_alloc Resource allocation failure in name copy. - /// - /// \return The next domain name field in the form of \c Name object. - const Name& getNextName() const; - -private: - NSECImpl* impl_; -}; - -// END_RDATA_NAMESPACE -// END_ISC_NAMESPACE -// END_HEADER_GUARD - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/rdata/generic/opt_41.cc b/src/lib/dns/rdata/generic/opt_41.cc index 326ec383ab..c382955904 100644 --- a/src/lib/dns/rdata/generic/opt_41.cc +++ b/src/lib/dns/rdata/generic/opt_41.cc @@ -24,8 +24,7 @@ using namespace isc::util; OPT::PseudoRR::PseudoRR(uint16_t code, boost::shared_ptr<std::vector<uint8_t> >& data) : code_(code), - data_(data) -{ + data_(data) { } uint16_t @@ -45,8 +44,8 @@ OPT::PseudoRR::getLength() const { struct OPTImpl { OPTImpl() : - rdlength_(0) - {} + rdlength_(0) { + } uint16_t rdlength_; std::vector<OPT::PseudoRR> pseudo_rrs_; @@ -54,8 +53,7 @@ struct OPTImpl { /// \brief Default constructor. OPT::OPT() : - impl_(new OPTImpl()) -{ + impl_(new OPTImpl()) { } /// \brief Constructor from string. @@ -64,8 +62,7 @@ OPT::OPT() : /// /// \throw InvalidRdataText OPT RR cannot be constructed from text. OPT::OPT(const std::string&) : - impl_(NULL) -{ + impl_(NULL) { isc_throw(InvalidRdataText, "OPT RR cannot be constructed from text"); } @@ -76,15 +73,13 @@ OPT::OPT(const std::string&) : /// \throw InvalidRdataText OPT RR cannot be constructed from text. OPT::OPT(MasterLexer&, const Name*, MasterLoader::Options, MasterLoaderCallbacks&) : - impl_(NULL) -{ + impl_(NULL) { isc_throw(InvalidRdataText, "OPT RR cannot be constructed from text"); } OPT::OPT(InputBuffer& buffer, size_t rdata_len) : - impl_(NULL) -{ - std::unique_ptr<OPTImpl> impl_ptr(new OPTImpl()); + impl_(NULL) { + boost::shared_ptr<OPTImpl> impl_ptr(new OPTImpl()); while (true) { if (rdata_len == 0) { @@ -102,8 +97,7 @@ OPT::OPT(InputBuffer& buffer, size_t rdata_len) : rdata_len -= 4; if (static_cast<uint16_t>(impl_ptr->rdlength_ + option_length) < - impl_ptr->rdlength_) - { + impl_ptr->rdlength_) { isc_throw(InvalidRdataText, "Option length " << option_length << " would overflow OPT RR RDLEN (currently " @@ -122,12 +116,11 @@ OPT::OPT(InputBuffer& buffer, size_t rdata_len) : rdata_len -= option_length; } - impl_ = impl_ptr.release(); + impl_ = impl_ptr; } OPT::OPT(const OPT& other) : - Rdata(), impl_(new OPTImpl(*other.impl_)) -{ + Rdata(), impl_(new OPTImpl(*other.impl_)) { } OPT& @@ -137,14 +130,12 @@ OPT::operator=(const OPT& source) { } OPTImpl* newimpl = new OPTImpl(*source.impl_); - delete impl_; impl_ = newimpl; return (*this); } OPT::~OPT() { - delete impl_; } std::string @@ -191,8 +182,7 @@ OPT::appendPseudoRR(uint16_t code, const uint8_t* data, uint16_t length) { // pseudo-RR length here, not the whole message length (which should // be checked and enforced elsewhere). if (static_cast<uint16_t>(impl_->rdlength_ + length) < - impl_->rdlength_) - { + impl_->rdlength_) { isc_throw(isc::InvalidParameter, "Option length " << length << " would overflow OPT RR RDLEN (currently " diff --git a/src/lib/dns/rdata/generic/opt_41.h b/src/lib/dns/rdata/generic/opt_41.h index 0c00aed20c..e2d3ccb516 100644 --- a/src/lib/dns/rdata/generic/opt_41.h +++ b/src/lib/dns/rdata/generic/opt_41.h @@ -78,7 +78,7 @@ public: const std::vector<PseudoRR>& getPseudoRRs() const; private: - OPTImpl* impl_; + boost::shared_ptr<OPTImpl> impl_; }; // END_RDATA_NAMESPACE diff --git a/src/lib/dns/rdata/generic/ptr_12.cc b/src/lib/dns/rdata/generic/ptr_12.cc index b3596e8905..d33a6d8a45 100644 --- a/src/lib/dns/rdata/generic/ptr_12.cc +++ b/src/lib/dns/rdata/generic/ptr_12.cc @@ -39,8 +39,7 @@ using isc::dns::rdata::generic::detail::createNameFromLexer; /// \throw InvalidRdataText Other general syntax errors. PTR::PTR(const std::string& type_str) : // Fill in dummy name and replace them soon below. - ptr_name_(Name::ROOT_NAME()) -{ + ptr_name_(Name::ROOT_NAME()) { try { std::istringstream ss(type_str); MasterLexer lexer; @@ -59,8 +58,7 @@ PTR::PTR(const std::string& type_str) : } PTR::PTR(InputBuffer& buffer, size_t) : - ptr_name_(buffer) -{ + ptr_name_(buffer) { // we don't need rdata_len for parsing. if necessary, the caller will // check consistency. } @@ -83,12 +81,12 @@ PTR::PTR(InputBuffer& buffer, size_t) : /// is non-absolute. PTR::PTR(MasterLexer& lexer, const Name* origin, MasterLoader::Options, MasterLoaderCallbacks&) : - ptr_name_(createNameFromLexer(lexer, origin)) -{} + ptr_name_(createNameFromLexer(lexer, origin)) { +} PTR::PTR(const PTR& source) : - Rdata(), ptr_name_(source.ptr_name_) -{} + Rdata(), ptr_name_(source.ptr_name_) { +} std::string PTR::toText() const { @@ -111,7 +109,6 @@ PTR::compare(const Rdata& other) const { const PTR& other_ptr = dynamic_cast<const PTR&>(other); return (compareNames(ptr_name_, other_ptr.ptr_name_)); - } const Name& diff --git a/src/lib/dns/rdata/generic/ptr_12.h b/src/lib/dns/rdata/generic/ptr_12.h index e562ef7f11..101d60c263 100644 --- a/src/lib/dns/rdata/generic/ptr_12.h +++ b/src/lib/dns/rdata/generic/ptr_12.h @@ -26,7 +26,8 @@ public: /// /// Specialized constructor /// - explicit PTR(const Name& ptr_name) : ptr_name_(ptr_name) {} + explicit PTR(const Name& ptr_name) : ptr_name_(ptr_name) { + } /// /// Specialized methods /// @@ -38,7 +39,3 @@ private: // END_RDATA_NAMESPACE // END_ISC_NAMESPACE // END_HEADER_GUARD - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/rdata/generic/rp_17.cc b/src/lib/dns/rdata/generic/rp_17.cc deleted file mode 100644 index 43bf64761e..0000000000 --- a/src/lib/dns/rdata/generic/rp_17.cc +++ /dev/null @@ -1,160 +0,0 @@ -// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#include <config.h> - -#include <string> -#include <sstream> - -#include <util/buffer.h> - -#include <dns/messagerenderer.h> -#include <dns/name.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> -#include <dns/rdata/generic/detail/lexer_util.h> - -using namespace std; -using namespace isc::dns; -using namespace isc::util; -using isc::dns::rdata::generic::detail::createNameFromLexer; - -// BEGIN_ISC_NAMESPACE -// BEGIN_RDATA_NAMESPACE - -/// \brief Constructor from string. -/// -/// \c rp_str must be formatted as follows: -/// \code <mailbox name> <text name> -/// \endcode -/// where both fields must represent a valid domain name. -/// -/// \throw InvalidRdataText The number of RDATA fields (must be 2) is -/// incorrect. -/// \throw std::bad_alloc Memory allocation for names fails. -/// \throw Other The constructor of the \c Name class will throw if the -/// given name is invalid. -RP::RP(const std::string& rp_str) : - // We cannot construct both names in the initialization list due to the - // necessary text processing, so we have to initialize them with a dummy - // name and replace them later. - mailbox_(Name::ROOT_NAME()), text_(Name::ROOT_NAME()) -{ - try { - std::istringstream ss(rp_str); - MasterLexer lexer; - lexer.pushSource(ss); - - mailbox_ = createNameFromLexer(lexer, NULL); - text_ = createNameFromLexer(lexer, NULL); - - if (lexer.getNextToken().getType() != MasterToken::END_OF_FILE) { - isc_throw(InvalidRdataText, "extra input text for RP: " - << rp_str); - } - } catch (const MasterLexer::LexerError& ex) { - isc_throw(InvalidRdataText, "Failed to construct RP from '" << - rp_str << "': " << ex.what()); - } -} - -/// \brief Constructor with a context of MasterLexer. -/// -/// The \c lexer should point to the beginning of valid textual representation -/// of an RP RDATA. The MAILBOX and TEXT fields can be non-absolute if \c -/// origin is non-NULL, in which case \c origin is used to make them absolute. -/// -/// \throw MasterLexer::LexerError General parsing error such as missing field. -/// \throw Other Exceptions from the Name and constructors if construction of -/// textual fields as these objects fail. -/// -/// \param lexer A \c MasterLexer object parsing a master file for the -/// RDATA to be created -/// \param origin If non NULL, specifies the origin of SERVER when it -/// is non-absolute. -RP::RP(MasterLexer& lexer, const Name* origin, - MasterLoader::Options, MasterLoaderCallbacks&) : - mailbox_(createNameFromLexer(lexer, origin)), - text_(createNameFromLexer(lexer, origin)) -{ -} - -/// \brief Constructor from wire-format data. -/// -/// This constructor doesn't check the validity of the second parameter (rdata -/// length) for parsing. -/// If necessary, the caller will check consistency. -/// -/// \throw std::bad_alloc Memory allocation for names fails. -/// \throw Other The constructor of the \c Name class will throw if the -/// names in the wire is invalid. -RP::RP(InputBuffer& buffer, size_t) : mailbox_(buffer), text_(buffer) { -} - -/// \brief Copy constructor. -/// -/// \throw std::bad_alloc Memory allocation fails in copying internal -/// member variables (this should be very rare). -RP::RP(const RP& other) : - Rdata(), mailbox_(other.mailbox_), text_(other.text_) -{} - -/// \brief Convert the \c RP to a string. -/// -/// The output of this method is formatted as described in the "from string" -/// constructor (\c RP(const std::string&))). -/// -/// \throw std::bad_alloc Internal resource allocation fails. -/// -/// \return A \c string object that represents the \c RP object. -std::string -RP::toText() const { - return (mailbox_.toText() + " " + text_.toText()); -} - -/// \brief Render the \c RP in the wire format without name compression. -/// -/// \throw std::bad_alloc Internal resource allocation fails. -/// -/// \param buffer An output buffer to store the wire data. -void -RP::toWire(OutputBuffer& buffer) const { - mailbox_.toWire(buffer); - text_.toWire(buffer); -} - -/// \brief Render the \c RP in the wire format with taking into account -/// compression. -/// -// Type RP is not "well-known", and name compression must be disabled -// per RFC3597. -/// -/// \throw std::bad_alloc Internal resource allocation fails. -/// -/// \param renderer DNS message rendering context that encapsulates the -/// output buffer and name compression information. -void -RP::toWire(AbstractMessageRenderer& renderer) const { - renderer.writeName(mailbox_, false); - renderer.writeName(text_, false); -} - -/// \brief Compare two instances of \c RP RDATA. -/// -/// See documentation in \c Rdata. -int -RP::compare(const Rdata& other) const { - const RP& other_rp = dynamic_cast<const RP&>(other); - - const int cmp = compareNames(mailbox_, other_rp.mailbox_); - if (cmp != 0) { - return (cmp); - } - return (compareNames(text_, other_rp.text_)); -} - -// END_RDATA_NAMESPACE -// END_ISC_NAMESPACE diff --git a/src/lib/dns/rdata/generic/rp_17.h b/src/lib/dns/rdata/generic/rp_17.h deleted file mode 100644 index 9536ee9cff..0000000000 --- a/src/lib/dns/rdata/generic/rp_17.h +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -// BEGIN_HEADER_GUARD - -#include <string> - -#include <dns/name.h> -#include <dns/rdata.h> - -// BEGIN_ISC_NAMESPACE - -// BEGIN_COMMON_DECLARATIONS -// END_COMMON_DECLARATIONS - -// BEGIN_RDATA_NAMESPACE - -/// \brief \c rdata::generic::RP class represents the RP RDATA as defined in -/// RFC1183. -/// -/// This class implements the basic interfaces inherited from the abstract -/// \c rdata::Rdata class, and provides trivial accessors specific to the -/// RP RDATA. -class RP : public Rdata { -public: - // BEGIN_COMMON_MEMBERS - // END_COMMON_MEMBERS - - /// We use the default copy constructor and assignment operator. - - /// \brief Constructor from RDATA field parameters. - /// - /// The parameters are a straightforward mapping of %RP RDATA - /// fields as defined in RFC1183. - RP(const Name& mailbox, const Name& text) : - mailbox_(mailbox), text_(text) - {} - - /// \brief Return the value of the mailbox field. - /// - /// \throw std::bad_alloc If resource allocation for the returned - /// \c Name fails. - /// - /// \note - /// Unlike the case of some other RDATA classes (such as - /// \c NS::getNSName()), this method constructs a new \c Name object - /// and returns it, instead of returning a reference to a \c Name object - /// internally maintained in the class (which is a private member). - /// This is based on the observation that this method will be rarely used - /// and even when it's used it will not be in a performance context - /// (for example, a recursive resolver won't need this field in its - /// resolution process). By returning a new object we have flexibility of - /// changing the internal representation without the risk of changing - /// the interface or method property. - /// The same note applies to the \c getText() method. - Name getMailbox() const { return (mailbox_); } - - /// \brief Return the value of the text field. - /// - /// \throw std::bad_alloc If resource allocation for the returned - /// \c Name fails. - Name getText() const { return (text_); } - -private: - Name mailbox_; - Name text_; -}; - -// END_RDATA_NAMESPACE -// END_ISC_NAMESPACE -// END_HEADER_GUARD - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/rdata/generic/rrsig_46.cc b/src/lib/dns/rdata/generic/rrsig_46.cc index c9f91a7b9f..94d62f5e16 100644 --- a/src/lib/dns/rdata/generic/rrsig_46.cc +++ b/src/lib/dns/rdata/generic/rrsig_46.cc @@ -53,8 +53,8 @@ struct RRSIGImpl { covered_(covered), algorithm_(algorithm), labels_(labels), originalttl_(originalttl), timeexpire_(timeexpire), timeinception_(timeinception), tag_(tag), signer_(signer), - signature_(signature) - {} + signature_(signature) { + } const RRType covered_; uint8_t algorithm_; @@ -68,7 +68,7 @@ struct RRSIGImpl { }; // helper function for string and lexer constructors -RRSIGImpl* +boost::shared_ptr<RRSIGImpl> RRSIG::constructFromLexer(MasterLexer& lexer, const Name* origin) { const RRType covered(lexer.getNextToken(MasterToken::STRING).getString()); const uint32_t algorithm = @@ -115,9 +115,9 @@ RRSIG::constructFromLexer(MasterLexer& lexer, const Name* origin) { decodeBase64(signature_txt, signature); } - return (new RRSIGImpl(covered, algorithm, labels, - originalttl, timeexpire, timeinception, - static_cast<uint16_t>(tag), signer, signature)); + return (boost::shared_ptr<RRSIGImpl>(new RRSIGImpl(covered, algorithm, labels, + originalttl, timeexpire, timeinception, + static_cast<uint16_t>(tag), signer, signature))); } /// \brief Constructor from string. @@ -137,12 +137,11 @@ RRSIG::constructFromLexer(MasterLexer& lexer, const Name* origin) { /// \throw Others Exception from the Name constructor. /// \throw InvalidRdataText Other general syntax errors. RRSIG::RRSIG(const std::string& rrsig_str) : - impl_(NULL) -{ + impl_(NULL) { // We use unique_ptr here because if there is an exception in this // constructor, the destructor is not called and there could be a // leak of the RRSIGImpl that constructFromLexer() returns. - std::unique_ptr<RRSIGImpl> impl_ptr; + boost::shared_ptr<RRSIGImpl> impl_ptr; try { std::istringstream iss(rrsig_str); @@ -160,7 +159,7 @@ RRSIG::RRSIG(const std::string& rrsig_str) : rrsig_str << "': " << ex.what()); } - impl_ = impl_ptr.release(); + impl_ = impl_ptr; } /// \brief Constructor with a context of MasterLexer. @@ -184,8 +183,7 @@ RRSIG::RRSIG(const std::string& rrsig_str) : /// it is non absolute. RRSIG::RRSIG(MasterLexer& lexer, const Name* origin, MasterLoader::Options, MasterLoaderCallbacks&) : - impl_(constructFromLexer(lexer, origin)) -{ + impl_(constructFromLexer(lexer, origin)) { } RRSIG::RRSIG(InputBuffer& buffer, size_t rdata_len) { @@ -213,14 +211,14 @@ RRSIG::RRSIG(InputBuffer& buffer, size_t rdata_len) { vector<uint8_t> signature(rdata_len); buffer.readData(&signature[0], rdata_len); - impl_ = new RRSIGImpl(covered, algorithm, labels, - originalttl, timeexpire, timeinception, tag, - signer, signature); + impl_.reset(new RRSIGImpl(covered, algorithm, labels, + originalttl, timeexpire, timeinception, tag, + signer, signature)); } RRSIG::RRSIG(const RRSIG& source) : - Rdata(), impl_(new RRSIGImpl(*source.impl_)) -{} + Rdata(), impl_(new RRSIGImpl(*source.impl_)) { +} RRSIG& RRSIG::operator=(const RRSIG& source) { @@ -228,15 +226,12 @@ RRSIG::operator=(const RRSIG& source) { return (*this); } - RRSIGImpl* newimpl = new RRSIGImpl(*source.impl_); - delete impl_; - impl_ = newimpl; + impl_.reset(new RRSIGImpl(*source.impl_)); return (*this); } RRSIG::~RRSIG() { - delete impl_; } string diff --git a/src/lib/dns/rdata/generic/rrsig_46.h b/src/lib/dns/rdata/generic/rrsig_46.h index aca26bacab..8443ad79e8 100644 --- a/src/lib/dns/rdata/generic/rrsig_46.h +++ b/src/lib/dns/rdata/generic/rrsig_46.h @@ -11,6 +11,7 @@ #include <dns/name.h> #include <dns/rrtype.h> #include <dns/rdata.h> +#include <boost/shared_ptr.hpp> // BEGIN_HEADER_GUARD @@ -40,15 +41,11 @@ public: const RRType& typeCovered() const; private: // helper function for string and lexer constructors - RRSIGImpl* constructFromLexer(MasterLexer& lexer, const Name* origin); + boost::shared_ptr<RRSIGImpl> constructFromLexer(MasterLexer& lexer, const Name* origin); - RRSIGImpl* impl_; + boost::shared_ptr<RRSIGImpl> impl_; }; // END_RDATA_NAMESPACE // END_ISC_NAMESPACE // END_HEADER_GUARD - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/rdata/generic/soa_6.cc b/src/lib/dns/rdata/generic/soa_6.cc index ee4e43d48d..945d4b99cd 100644 --- a/src/lib/dns/rdata/generic/soa_6.cc +++ b/src/lib/dns/rdata/generic/soa_6.cc @@ -34,8 +34,7 @@ using isc::dns::rdata::generic::detail::createNameFromLexer; // BEGIN_RDATA_NAMESPACE SOA::SOA(InputBuffer& buffer, size_t) : - mname_(buffer), rname_(buffer) -{ + mname_(buffer), rname_(buffer) { // we don't need rdata_len for parsing. if necessary, the caller will // check consistency. buffer.readData(numdata_, sizeof(numdata_)); @@ -74,8 +73,7 @@ fillParameters(MasterLexer& lexer, uint8_t numdata[20]) { /// \throw InvalidRdataText Other general syntax errors. SOA::SOA(const std::string& soastr) : // Fill in dummy name and replace them soon below. - mname_(Name::ROOT_NAME()), rname_(Name::ROOT_NAME()) -{ + mname_(Name::ROOT_NAME()), rname_(Name::ROOT_NAME()) { try { std::istringstream ss(soastr); MasterLexer lexer; @@ -117,15 +115,13 @@ SOA::SOA(const std::string& soastr) : SOA::SOA(MasterLexer& lexer, const Name* origin, MasterLoader::Options, MasterLoaderCallbacks&) : mname_(createNameFromLexer(lexer, origin)), - rname_(createNameFromLexer(lexer, origin)) -{ + rname_(createNameFromLexer(lexer, origin)) { fillParameters(lexer, numdata_); } SOA::SOA(const Name& mname, const Name& rname, uint32_t serial, uint32_t refresh, uint32_t retry, uint32_t expire, uint32_t minimum) : - mname_(mname), rname_(rname) -{ + mname_(mname), rname_(rname) { OutputBuffer b(20); b.writeUint32(serial); b.writeUint32(refresh); @@ -137,8 +133,7 @@ SOA::SOA(const Name& mname, const Name& rname, uint32_t serial, } SOA::SOA(const SOA& other) : - Rdata(), mname_(other.mname_), rname_(other.rname_) -{ + Rdata(), mname_(other.mname_), rname_(other.rname_) { memcpy(numdata_, other.numdata_, sizeof(numdata_)); } diff --git a/src/lib/dns/rdata/generic/soa_6.h b/src/lib/dns/rdata/generic/soa_6.h index 50a062eb45..509663311f 100644 --- a/src/lib/dns/rdata/generic/soa_6.h +++ b/src/lib/dns/rdata/generic/soa_6.h @@ -10,6 +10,7 @@ #include <dns/name.h> #include <dns/rdata.h> +#include <dns/rrttl.h> #include <dns/serial.h> // BEGIN_ISC_NAMESPACE @@ -45,7 +46,3 @@ private: // END_RDATA_NAMESPACE // END_ISC_NAMESPACE // END_HEADER_GUARD - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/rdata/generic/spf_99.cc b/src/lib/dns/rdata/generic/spf_99.cc deleted file mode 100644 index f25585ab53..0000000000 --- a/src/lib/dns/rdata/generic/spf_99.cc +++ /dev/null @@ -1,139 +0,0 @@ -// Copyright (C) 2010-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#include <config.h> - -#include <stdint.h> -#include <string.h> - -#include <string> -#include <vector> - -#include <util/buffer.h> -#include <dns/exceptions.h> -#include <dns/messagerenderer.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> - -/// This class implements the basic interfaces inherited from the abstract -/// \c rdata::Rdata class. The semantics of the class is provided by -/// a copy of instantiated TXTLikeImpl class common to both TXT and SPF. -#include <dns/rdata/generic/detail/txt_like.h> - -using namespace std; -using namespace isc::util; - -// BEGIN_ISC_NAMESPACE -// BEGIN_RDATA_NAMESPACE - -/// \brief The assignment operator -/// -/// It internally allocates a resource, and if it fails a corresponding -/// standard exception will be thrown. -/// This method never throws an exception otherwise. -SPF& -SPF::operator=(const SPF& source) { - if (this == &source) { - return (*this); - } - - SPFImpl* newimpl = new SPFImpl(*source.impl_); - delete impl_; - impl_ = newimpl; - - return (*this); -} - -/// \brief The destructor -SPF::~SPF() { - delete impl_; -} - -/// \brief Constructor from wire-format data. -/// -/// It internally allocates a resource, and if it fails a corresponding -/// standard exception will be thrown. -SPF::SPF(InputBuffer& buffer, size_t rdata_len) : - impl_(new SPFImpl(buffer, rdata_len)) -{} - -/// \brief Constructor using the master lexer. -/// -/// This implementation only uses the \c lexer parameters; others are -/// ignored. -/// -/// \throw CharStringTooLong the parameter string length exceeds maximum. -/// \throw InvalidRdataText the method cannot process the parameter data -/// -/// \param lexer A \c MasterLexer object parsing a master file for this -/// RDATA. -SPF::SPF(MasterLexer& lexer, const Name*, MasterLoader::Options, - MasterLoaderCallbacks&) : - impl_(new SPFImpl(lexer)) -{} - -/// \brief Constructor from string. -/// -/// It internally allocates a resource, and if it fails a corresponding -/// standard exception will be thrown. -SPF::SPF(const std::string& txtstr) : - impl_(new SPFImpl(txtstr)) -{} - -/// \brief Copy constructor -/// -/// It internally allocates a resource, and if it fails a corresponding -/// standard exception will be thrown. -SPF::SPF(const SPF& other) : - Rdata(), impl_(new SPFImpl(*other.impl_)) -{} - -/// \brief Render the \c SPF in the wire format to a OutputBuffer object -/// -/// \return is the return of the corresponding implementation method. -void -SPF::toWire(OutputBuffer& buffer) const { - impl_->toWire(buffer); -} - -/// \brief Render the \c SPF in the wire format to an AbstractMessageRenderer -/// object -/// -/// \return is the return of the corresponding implementation method. -void -SPF::toWire(AbstractMessageRenderer& renderer) const { - impl_->toWire(renderer); -} - -/// \brief Convert the \c SPF to a string. -/// -/// \return is the return of the corresponding implementation method. -string -SPF::toText() const { - return (impl_->toText()); -} - -/// \brief Compare two instances of \c SPF RDATA. -/// -/// This method compares \c this and the \c other \c SPF objects. -/// -/// This method is expected to be used in a polymorphic way, and the -/// parameter to compare against is therefore of the abstract \c Rdata class. -/// However, comparing two \c Rdata objects of different RR types -/// is meaningless, and \c other must point to a \c SPF object; -/// otherwise, the standard \c bad_cast exception will be thrown. -/// -/// \param other the right-hand operand to compare against. -/// \return is the return of the corresponding implementation method. -int -SPF::compare(const Rdata& other) const { - const SPF& other_txt = dynamic_cast<const SPF&>(other); - - return (impl_->compare(*other_txt.impl_)); -} - -// END_RDATA_NAMESPACE -// END_ISC_NAMESPACE diff --git a/src/lib/dns/rdata/generic/spf_99.h b/src/lib/dns/rdata/generic/spf_99.h deleted file mode 100644 index 3a84d9deb8..0000000000 --- a/src/lib/dns/rdata/generic/spf_99.h +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright (C) 2010-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -// BEGIN_HEADER_GUARD - -#include <stdint.h> - -#include <string> -#include <vector> - -#include <dns/rdata.h> - -// BEGIN_ISC_NAMESPACE - -// BEGIN_COMMON_DECLARATIONS -// END_COMMON_DECLARATIONS - -// BEGIN_RDATA_NAMESPACE - -namespace detail { -template<class Type, uint16_t typeCode> class TXTLikeImpl; -} - -/// \brief \c rdata::SPF class represents the SPF RDATA as defined %in -/// RFC4408. -/// -/// This class implements the basic interfaces inherited from the abstract -/// \c rdata::Rdata class. The semantics of the class is provided by -/// a copy of instantiated TXTLikeImpl class common to both TXT and SPF. -class SPF : public Rdata { -public: - // BEGIN_COMMON_MEMBERS - // END_COMMON_MEMBERS - - /// \brief Assignment operator. - /// - /// It internally allocates a resource, and if it fails a corresponding - /// standard exception will be thrown. - /// This operator never throws an exception otherwise. - /// - /// This operator provides the strong exception guarantee: When an - /// exception is thrown the content of the assignment target will be - /// intact. - SPF& operator=(const SPF& source); - - /// \brief The destructor. - ~SPF(); - - /// - /// Specialized methods - /// - - /// \brief Return a reference to the data strings - /// - /// This method never throws an exception. - const std::vector<std::vector<uint8_t> >& getString() const; - -private: - typedef isc::dns::rdata::generic::detail::TXTLikeImpl<SPF, 99> SPFImpl; - SPFImpl* impl_; -}; - -// END_RDATA_NAMESPACE -// END_ISC_NAMESPACE -// END_HEADER_GUARD - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/rdata/generic/sshfp_44.cc b/src/lib/dns/rdata/generic/sshfp_44.cc deleted file mode 100644 index 168e631643..0000000000 --- a/src/lib/dns/rdata/generic/sshfp_44.cc +++ /dev/null @@ -1,298 +0,0 @@ -// Copyright (C) 2012-2024 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#include <config.h> - -#include <boost/lexical_cast.hpp> - -#include <exceptions/exceptions.h> - -#include <util/buffer.h> -#include <util/encode/encode.h> -#include <dns/name.h> -#include <dns/messagerenderer.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> - -using namespace std; -using boost::lexical_cast; -using namespace isc::util; -using namespace isc::util::encode; - -// BEGIN_ISC_NAMESPACE -// BEGIN_RDATA_NAMESPACE - -struct SSHFPImpl { - // straightforward representation of SSHFP RDATA fields - SSHFPImpl(uint8_t algorithm, uint8_t fingerprint_type, - const vector<uint8_t>& fingerprint) : - algorithm_(algorithm), - fingerprint_type_(fingerprint_type), - fingerprint_(fingerprint) - {} - - uint8_t algorithm_; - uint8_t fingerprint_type_; - const vector<uint8_t> fingerprint_; -}; - -// helper function for string and lexer constructors -SSHFPImpl* -SSHFP::constructFromLexer(MasterLexer& lexer) { - const uint32_t algorithm = - lexer.getNextToken(MasterToken::NUMBER).getNumber(); - if (algorithm > 255) { - isc_throw(InvalidRdataText, "SSHFP algorithm number out of range"); - } - - const uint32_t fingerprint_type = - lexer.getNextToken(MasterToken::NUMBER).getNumber(); - if (fingerprint_type > 255) { - isc_throw(InvalidRdataText, "SSHFP fingerprint type out of range"); - } - - std::string fingerprint_str; - std::string fingerprint_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(fingerprint_substr); - fingerprint_str.append(fingerprint_substr); - } - lexer.ungetToken(); - - vector<uint8_t> fingerprint; - // If fingerprint is missing, it's OK. See the API documentation of the - // constructor. - if (fingerprint_str.size() > 0) { - 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)); -} - -/// \brief Constructor from string. -/// -/// The given string must represent a valid SSHFP 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 Algorithm and Fingerprint Type fields must be within their valid -/// ranges, but are not constrained to the values defined in RFC4255. -/// -/// The Fingerprint field may be absent, but if present it must contain a -/// 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, 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) : - impl_(NULL) -{ - // We use unique_ptr here because if there is an exception in this - // constructor, the destructor is not called and there could be a - // leak of the SSHFPImpl that constructFromLexer() returns. - std::unique_ptr<SSHFPImpl> impl_ptr; - - try { - std::istringstream ss(sshfp_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 SSHFP: " - << sshfp_str); - } - } catch (const MasterLexer::LexerError& ex) { - isc_throw(InvalidRdataText, "Failed to construct SSHFP from '" << - sshfp_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 SSHFP RDATA. -/// -/// \throw MasterLexer::LexerError General parsing error such as missing field. -/// \throw InvalidRdataText Fields are out of their valid range or are -/// incorrect, or if the fingerprint is not a valid hex string. -/// -/// \param lexer A \c MasterLexer object parsing a master file for the -/// RDATA to be created -SSHFP::SSHFP(MasterLexer& lexer, const Name*, - MasterLoader::Options, MasterLoaderCallbacks&) : - impl_(constructFromLexer(lexer)) -{ -} - -/// \brief Constructor from InputBuffer. -/// -/// The passed buffer must contain a valid SSHFP RDATA. -/// -/// The Algorithm and Fingerprint Type fields are not checked for unknown -/// values. It is okay for the fingerprint data to be missing (see the -/// description of the constructor from string). -SSHFP::SSHFP(InputBuffer& buffer, size_t rdata_len) { - if (rdata_len < 2) { - isc_throw(InvalidRdataLength, "SSHFP record too short"); - } - - const uint8_t algorithm = buffer.readUint8(); - const uint8_t fingerprint_type = buffer.readUint8(); - - vector<uint8_t> fingerprint; - rdata_len -= 2; - if (rdata_len > 0) { - fingerprint.resize(rdata_len); - buffer.readData(&fingerprint[0], rdata_len); - } - - impl_ = new SSHFPImpl(algorithm, fingerprint_type, fingerprint); -} - -SSHFP::SSHFP(uint8_t algorithm, uint8_t fingerprint_type, - const string& fingerprint_txt) : - impl_(NULL) -{ - vector<uint8_t> fingerprint; - try { - decodeHex(fingerprint_txt, fingerprint); - } catch (const isc::BadValue& e) { - isc_throw(InvalidRdataText, "Bad SSHFP fingerprint: " << e.what()); - } - - impl_ = new SSHFPImpl(algorithm, fingerprint_type, fingerprint); -} - -SSHFP::SSHFP(const SSHFP& other) : - Rdata(), impl_(new SSHFPImpl(*other.impl_)) -{} - -SSHFP& -SSHFP::operator=(const SSHFP& source) { - if (this == &source) { - return (*this); - } - - SSHFPImpl* newimpl = new SSHFPImpl(*source.impl_); - delete impl_; - impl_ = newimpl; - - return (*this); -} - -SSHFP::~SSHFP() { - delete impl_; -} - -void -SSHFP::toWire(OutputBuffer& buffer) const { - buffer.writeUint8(impl_->algorithm_); - buffer.writeUint8(impl_->fingerprint_type_); - - if (!impl_->fingerprint_.empty()) { - buffer.writeData(&impl_->fingerprint_[0], - impl_->fingerprint_.size()); - } -} - -void -SSHFP::toWire(AbstractMessageRenderer& renderer) const { - renderer.writeUint8(impl_->algorithm_); - renderer.writeUint8(impl_->fingerprint_type_); - - if (!impl_->fingerprint_.empty()) { - renderer.writeData(&impl_->fingerprint_[0], - impl_->fingerprint_.size()); - } -} - -string -SSHFP::toText() const { - return (lexical_cast<string>(static_cast<int>(impl_->algorithm_)) + " " + - lexical_cast<string>(static_cast<int>(impl_->fingerprint_type_)) + - (impl_->fingerprint_.empty() ? "" : - " " + encodeHex(impl_->fingerprint_))); -} - -int -SSHFP::compare(const Rdata& other) const { - const SSHFP& other_sshfp = dynamic_cast<const SSHFP&>(other); - - if (impl_->algorithm_ < other_sshfp.impl_->algorithm_) { - return (-1); - } else if (impl_->algorithm_ > other_sshfp.impl_->algorithm_) { - return (1); - } - - if (impl_->fingerprint_type_ < other_sshfp.impl_->fingerprint_type_) { - return (-1); - } else if (impl_->fingerprint_type_ > - other_sshfp.impl_->fingerprint_type_) { - return (1); - } - - const size_t this_len = impl_->fingerprint_.size(); - const size_t other_len = other_sshfp.impl_->fingerprint_.size(); - const size_t cmplen = min(this_len, other_len); - - if (cmplen > 0) { - const int cmp = memcmp(&impl_->fingerprint_[0], - &other_sshfp.impl_->fingerprint_[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 -SSHFP::getAlgorithmNumber() const { - return (impl_->algorithm_); -} - -uint8_t -SSHFP::getFingerprintType() const { - return (impl_->fingerprint_type_); -} - -const std::vector<uint8_t>& -SSHFP::getFingerprint() const { - return (impl_->fingerprint_); -} - -size_t -SSHFP::getFingerprintLength() const { - return (impl_->fingerprint_.size()); -} - -// END_RDATA_NAMESPACE -// END_ISC_NAMESPACE diff --git a/src/lib/dns/rdata/generic/sshfp_44.h b/src/lib/dns/rdata/generic/sshfp_44.h deleted file mode 100644 index 4eae696bdc..0000000000 --- a/src/lib/dns/rdata/generic/sshfp_44.h +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright (C) 2012-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -// BEGIN_HEADER_GUARD - -#include <stdint.h> - -#include <string> -#include <vector> - -#include <dns/name.h> -#include <dns/rdata.h> - -// BEGIN_ISC_NAMESPACE - -// BEGIN_COMMON_DECLARATIONS -// END_COMMON_DECLARATIONS - -// BEGIN_RDATA_NAMESPACE - -struct SSHFPImpl; - -class SSHFP : public Rdata { -public: - // BEGIN_COMMON_MEMBERS - // END_COMMON_MEMBERS - - SSHFP(uint8_t algorithm, uint8_t fingerprint_type, - const std::string& fingerprint); - SSHFP& operator=(const SSHFP& source); - ~SSHFP(); - - /// - /// Specialized methods - /// - uint8_t getAlgorithmNumber() const; - uint8_t getFingerprintType() const; - const std::vector<uint8_t>& getFingerprint() const; - size_t getFingerprintLength() const; - -private: - SSHFPImpl* constructFromLexer(MasterLexer& lexer); - - SSHFPImpl* impl_; -}; - -// END_RDATA_NAMESPACE -// END_ISC_NAMESPACE -// END_HEADER_GUARD - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/rdata/generic/tkey_249.cc b/src/lib/dns/rdata/generic/tkey_249.cc index 7952065440..d12e2c6295 100644 --- a/src/lib/dns/rdata/generic/tkey_249.cc +++ b/src/lib/dns/rdata/generic/tkey_249.cc @@ -16,6 +16,7 @@ #include <util/encode/encode.h> #include <util/time_utilities.h> +#include <dns/tsigerror.h> #include <dns/messagerenderer.h> #include <dns/name.h> #include <dns/rdata.h> @@ -50,8 +51,8 @@ struct TKEYImpl { uint16_t mode, uint16_t error, vector<uint8_t>& key, vector<uint8_t>& other_data) : algorithm_(algorithm), inception_(inception), expire_(expire), - mode_(mode), error_(error), key_(key), other_data_(other_data) - {} + mode_(mode), error_(error), key_(key), other_data_(other_data) { + } /// \brief Constructor from RDATA field parameters. /// @@ -77,8 +78,8 @@ struct TKEYImpl { vector<uint8_t>(static_cast<const uint8_t*>(other_data), static_cast<const uint8_t*>(other_data) + other_len) : - vector<uint8_t>(other_len)) - {} + vector<uint8_t>(other_len)) { + } /// \brief Common part of toWire methods. /// \tparam Output \c OutputBuffer or \c AbstractMessageRenderer. @@ -108,7 +109,7 @@ struct TKEYImpl { }; // helper function for string and lexer constructors -TKEYImpl* +boost::shared_ptr<TKEYImpl> TKEY::constructFromLexer(MasterLexer& lexer, const Name* origin) { const Name& algorithm = createNameFromLexer(lexer, origin ? origin : &Name::ROOT_NAME()); @@ -203,8 +204,8 @@ TKEY::constructFromLexer(MasterLexer& lexer, const Name* origin) { // RFC2845 says Other Data is "empty unless Error == BADTIME". // However, we don't enforce that. - return (new TKEYImpl(algorithm, inception, expire, mode, error, - key_data, other_data)); + return (new boost::shared_ptr<TKEYImpl>(algorithm, inception, expire, mode, error, + key_data, other_data)); } /// \brief Constructor from string. @@ -263,7 +264,7 @@ TKEY::TKEY(const std::string& tkey_str) : impl_(0) { // We use unique_ptr here because if there is an exception in this // constructor, the destructor is not called and there could be a // leak of the TKEYImpl that constructFromLexer() returns. - std::unique_ptr<TKEYImpl> impl_ptr; + boost::shared_ptr<TKEYImpl> impl_ptr; try { std::istringstream ss(tkey_str); @@ -282,7 +283,7 @@ TKEY::TKEY(const std::string& tkey_str) : impl_(0) { << ex.what()); } - impl_ = impl_ptr.release(); + impl_ = impl_ptr; } /// \brief Constructor with a context of MasterLexer. @@ -302,8 +303,7 @@ TKEY::TKEY(const std::string& tkey_str) : impl_(0) { /// RDATA to be created TKEY::TKEY(MasterLexer& lexer, const Name* origin, MasterLoader::Options, MasterLoaderCallbacks&) : - impl_(constructFromLexer(lexer, origin)) -{ + impl_(constructFromLexer(lexer, origin)) { } /// \brief Constructor from wire-format data. @@ -327,8 +327,7 @@ TKEY::TKEY(MasterLexer& lexer, const Name* origin, /// must check consistency between the length parameter and the actual /// RDATA length. TKEY::TKEY(InputBuffer& buffer, size_t) : - impl_(0) -{ + impl_(0) { Name algorithm(buffer); const uint32_t inception = buffer.readUint32(); @@ -351,15 +350,14 @@ TKEY::TKEY(InputBuffer& buffer, size_t) : buffer.readData(&other_data[0], other_len); } - impl_ = new TKEYImpl(algorithm, inception, expire, mode, error, - key, other_data); + impl_.reset(new TKEYImpl(algorithm, inception, expire, mode, error, + key, other_data)); } TKEY::TKEY(const Name& algorithm, uint32_t inception, uint32_t expire, uint16_t mode, uint16_t error, uint16_t key_len, const void* key, uint16_t other_len, const void* other_data) : - impl_(0) -{ + impl_(0) { if ((key_len == 0 && key != 0) || (key_len > 0 && key == 0)) { isc_throw(InvalidParameter, "TKEY Key length and data inconsistent"); } @@ -368,8 +366,8 @@ TKEY::TKEY(const Name& algorithm, uint32_t inception, uint32_t expire, isc_throw(InvalidParameter, "TKEY Other data length and data inconsistent"); } - impl_ = new TKEYImpl(algorithm, inception, expire, mode, error, - key_len, key, other_len, other_data); + impl_.reset(new TKEYImpl(algorithm, inception, expire, mode, error, + key_len, key, other_len, other_data)); } /// \brief The copy constructor. @@ -377,8 +375,8 @@ TKEY::TKEY(const Name& algorithm, uint32_t inception, uint32_t expire, /// It internally allocates a resource, and if it fails a corresponding /// standard exception will be thrown. /// This constructor never throws an exception otherwise. -TKEY::TKEY(const TKEY& source) : Rdata(), impl_(new TKEYImpl(*source.impl_)) -{} +TKEY::TKEY(const TKEY& source) : Rdata(), impl_(new TKEYImpl(*source.impl_)) { +} TKEY& TKEY::operator=(const TKEY& source) { @@ -386,15 +384,12 @@ TKEY::operator=(const TKEY& source) { return (*this); } - TKEYImpl* newimpl = new TKEYImpl(*source.impl_); - delete impl_; - impl_ = newimpl; + impl_.reset(new TKEYImpl(*source.impl_)); return (*this); } TKEY::~TKEY() { - delete impl_; } /// \brief Convert the \c TKEY to a string. diff --git a/src/lib/dns/rdata/generic/tkey_249.h b/src/lib/dns/rdata/generic/tkey_249.h index d63012132d..cd7278d374 100644 --- a/src/lib/dns/rdata/generic/tkey_249.h +++ b/src/lib/dns/rdata/generic/tkey_249.h @@ -12,6 +12,7 @@ #include <dns/name.h> #include <dns/rdata.h> +#include <boost/shared_ptr.hpp> // BEGIN_ISC_NAMESPACE @@ -128,15 +129,11 @@ public: static const uint16_t GSS_API_MODE; private: - TKEYImpl* constructFromLexer(MasterLexer& lexer, const Name* origin); + boost::shared_ptr<TKEYImpl> constructFromLexer(MasterLexer& lexer, const Name* origin); - TKEYImpl* impl_; + boost::shared_ptr<TKEYImpl> impl_; }; // END_RDATA_NAMESPACE // END_ISC_NAMESPACE // END_HEADER_GUARD - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/rdata/generic/tlsa_52.cc b/src/lib/dns/rdata/generic/tlsa_52.cc deleted file mode 100644 index c05ef16518..0000000000 --- a/src/lib/dns/rdata/generic/tlsa_52.cc +++ /dev/null @@ -1,342 +0,0 @@ -// Copyright (C) 2014-2024 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#include <config.h> - -#include <boost/lexical_cast.hpp> - -#include <exceptions/exceptions.h> - -#include <util/buffer.h> -#include <util/encode/encode.h> -#include <dns/name.h> -#include <dns/messagerenderer.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> -#include <dns/rdata_pimpl_holder.h> - -using namespace std; -using boost::lexical_cast; -using namespace isc::util; -using namespace isc::util::encode; - -// BEGIN_ISC_NAMESPACE -// BEGIN_RDATA_NAMESPACE - -struct TLSAImpl { - // straightforward representation of TLSA RDATA fields - TLSAImpl(uint8_t certificate_usage, uint8_t selector, - uint8_t matching_type, const vector<uint8_t>& data) : - certificate_usage_(certificate_usage), - selector_(selector), - matching_type_(matching_type), - data_(data) - {} - - uint8_t certificate_usage_; - uint8_t selector_; - uint8_t matching_type_; - const vector<uint8_t> data_; -}; - -// helper function for string and lexer constructors -TLSAImpl* -TLSA::constructFromLexer(MasterLexer& lexer) { - const uint32_t certificate_usage = - lexer.getNextToken(MasterToken::NUMBER).getNumber(); - if (certificate_usage > 255) { - isc_throw(InvalidRdataText, - "TLSA certificate usage field out of range"); - } - - const uint32_t selector = - lexer.getNextToken(MasterToken::NUMBER).getNumber(); - if (selector > 255) { - isc_throw(InvalidRdataText, - "TLSA selector field out of range"); - } - - const uint32_t matching_type = - lexer.getNextToken(MasterToken::NUMBER).getNumber(); - if (matching_type > 255) { - isc_throw(InvalidRdataText, - "TLSA matching type field out of range"); - } - - std::string certificate_assoc_data; - std::string data_substr; - while (true) { - const MasterToken& token = - lexer.getNextToken(MasterToken::STRING, true); - if ((token.getType() == MasterToken::END_OF_FILE) || - (token.getType() == MasterToken::END_OF_LINE)) { - break; - } - - token.getString(data_substr); - certificate_assoc_data.append(data_substr); - } - lexer.ungetToken(); - - if (certificate_assoc_data.empty()) { - isc_throw(InvalidRdataText, "Empty TLSA certificate association data"); - } - - vector<uint8_t> data; - try { - decodeHex(certificate_assoc_data, data); - } catch (const isc::BadValue& e) { - isc_throw(InvalidRdataText, - "Bad TLSA certificate association data: " << e.what()); - } - - return (new TLSAImpl(certificate_usage, selector, matching_type, data)); -} - -/// \brief Constructor from string. -/// -/// The given string must represent a valid TLSA RDATA. There can be -/// extra space characters at the beginning or end of the text (which -/// are simply ignored), but other extra text, including a new line, -/// will make the construction fail with an exception. -/// -/// The Certificate Usage, Selector and Matching Type fields must be -/// within their valid ranges, but are not constrained to the values -/// defined in RFC6698. -/// -/// The Certificate Association Data Field field may be absent, but if -/// present it must contain a valid hex encoding of the data. Whitespace -/// is allowed in the hex text. -/// -/// \throw InvalidRdataText if any fields are missing, out of their -/// valid ranges, or are incorrect, or Certificate Association Data is -/// not a valid hex string. -/// -/// \param tlsa_str A string containing the RDATA to be created -TLSA::TLSA(const string& tlsa_str) : - impl_(NULL) -{ - // We use a smart pointer here because if there is an exception in - // this constructor, the destructor is not called and there could be - // a leak of the TLSAImpl that constructFromLexer() returns. - RdataPimplHolder<TLSAImpl> impl_ptr; - - try { - std::istringstream ss(tlsa_str); - MasterLexer lexer; - lexer.pushSource(ss); - - impl_ptr.reset(constructFromLexer(lexer)); - - if (lexer.getNextToken().getType() != MasterToken::END_OF_FILE) { - isc_throw(InvalidRdataText, "extra input text for TLSA: " - << tlsa_str); - } - } catch (const MasterLexer::LexerError& ex) { - isc_throw(InvalidRdataText, "Failed to construct TLSA from '" << - tlsa_str << "': " << ex.what()); - } - - impl_ = impl_ptr.release(); -} - -/// \brief Constructor with a context of MasterLexer. -/// -/// The \c lexer should point to the beginning of valid textual representation -/// of an TLSA RDATA. -/// -/// \throw MasterLexer::LexerError General parsing error such as missing field. -/// \throw InvalidRdataText Fields are out of their valid range, or are -/// incorrect, or Certificate Association Data is not a valid hex string. -/// -/// \param lexer A \c MasterLexer object parsing a master file for the -/// RDATA to be created -TLSA::TLSA(MasterLexer& lexer, const Name*, - MasterLoader::Options, MasterLoaderCallbacks&) : - impl_(constructFromLexer(lexer)) -{ -} - -/// \brief Constructor from InputBuffer. -/// -/// The passed buffer must contain a valid TLSA RDATA. -/// -/// The Certificate Usage, Selector and Matching Type fields must be -/// within their valid ranges, but are not constrained to the values -/// defined in RFC6698. It is okay for the certificate association data -/// to be missing (see the description of the constructor from string). -TLSA::TLSA(InputBuffer& buffer, size_t rdata_len) { - if (rdata_len < 3) { - isc_throw(InvalidRdataLength, "TLSA record too short"); - } - - const uint8_t certificate_usage = buffer.readUint8(); - const uint8_t selector = buffer.readUint8(); - const uint8_t matching_type = buffer.readUint8(); - - vector<uint8_t> data; - rdata_len -= 3; - - if (rdata_len == 0) { - isc_throw(InvalidRdataLength, - "Empty TLSA certificate association data"); - } - - data.resize(rdata_len); - buffer.readData(&data[0], rdata_len); - - impl_ = new TLSAImpl(certificate_usage, selector, matching_type, data); -} - -TLSA::TLSA(uint8_t certificate_usage, uint8_t selector, - uint8_t matching_type, const std::string& certificate_assoc_data) : - impl_(NULL) -{ - if (certificate_assoc_data.empty()) { - isc_throw(InvalidRdataText, "Empty TLSA certificate association data"); - } - - vector<uint8_t> data; - try { - decodeHex(certificate_assoc_data, data); - } catch (const isc::BadValue& e) { - isc_throw(InvalidRdataText, - "Bad TLSA certificate association data: " << e.what()); - } - - impl_ = new TLSAImpl(certificate_usage, selector, matching_type, data); -} - -TLSA::TLSA(const TLSA& other) : - Rdata(), impl_(new TLSAImpl(*other.impl_)) -{} - -TLSA& -TLSA::operator=(const TLSA& source) { - if (this == &source) { - return (*this); - } - - TLSAImpl* newimpl = new TLSAImpl(*source.impl_); - delete impl_; - impl_ = newimpl; - - return (*this); -} - -TLSA::~TLSA() { - delete impl_; -} - -void -TLSA::toWire(OutputBuffer& buffer) const { - buffer.writeUint8(impl_->certificate_usage_); - buffer.writeUint8(impl_->selector_); - buffer.writeUint8(impl_->matching_type_); - - // The constructors must ensure that the certificate association - // data field is not empty. - assert(!impl_->data_.empty()); - buffer.writeData(&impl_->data_[0], impl_->data_.size()); -} - -void -TLSA::toWire(AbstractMessageRenderer& renderer) const { - renderer.writeUint8(impl_->certificate_usage_); - renderer.writeUint8(impl_->selector_); - renderer.writeUint8(impl_->matching_type_); - - // The constructors must ensure that the certificate association - // data field is not empty. - assert(!impl_->data_.empty()); - renderer.writeData(&impl_->data_[0], impl_->data_.size()); -} - -string -TLSA::toText() const { - // The constructors must ensure that the certificate association - // data field is not empty. - assert(!impl_->data_.empty()); - - return (lexical_cast<string>(static_cast<int>(impl_->certificate_usage_)) + " " + - lexical_cast<string>(static_cast<int>(impl_->selector_)) + " " + - lexical_cast<string>(static_cast<int>(impl_->matching_type_)) + " " + - encodeHex(impl_->data_)); -} - -int -TLSA::compare(const Rdata& other) const { - const TLSA& other_tlsa = dynamic_cast<const TLSA&>(other); - - if (impl_->certificate_usage_ < other_tlsa.impl_->certificate_usage_) { - return (-1); - } else if (impl_->certificate_usage_ > - other_tlsa.impl_->certificate_usage_) { - return (1); - } - - if (impl_->selector_ < other_tlsa.impl_->selector_) { - return (-1); - } else if (impl_->selector_ > other_tlsa.impl_->selector_) { - return (1); - } - - if (impl_->matching_type_ < other_tlsa.impl_->matching_type_) { - return (-1); - } else if (impl_->matching_type_ > - other_tlsa.impl_->matching_type_) { - return (1); - } - - const size_t this_len = impl_->data_.size(); - const size_t other_len = other_tlsa.impl_->data_.size(); - const size_t cmplen = min(this_len, other_len); - - if (cmplen > 0) { - const int cmp = memcmp(&impl_->data_[0], - &other_tlsa.impl_->data_[0], - cmplen); - if (cmp != 0) { - return (cmp); - } - } - - if (this_len == other_len) { - return (0); - } else if (this_len < other_len) { - return (-1); - } else { - return (1); - } -} - -uint8_t -TLSA::getCertificateUsage() const { - return (impl_->certificate_usage_); -} - -uint8_t -TLSA::getSelector() const { - return (impl_->selector_); -} - -uint8_t -TLSA::getMatchingType() const { - return (impl_->matching_type_); -} - -const std::vector<uint8_t>& -TLSA::getData() const { - return (impl_->data_); -} - -size_t -TLSA::getDataLength() const { - return (impl_->data_.size()); -} - -// END_RDATA_NAMESPACE -// END_ISC_NAMESPACE diff --git a/src/lib/dns/rdata/generic/tlsa_52.h b/src/lib/dns/rdata/generic/tlsa_52.h deleted file mode 100644 index 007aa43ddc..0000000000 --- a/src/lib/dns/rdata/generic/tlsa_52.h +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright (C) 2014-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -// BEGIN_HEADER_GUARD - -#include <stdint.h> - -#include <dns/name.h> -#include <dns/rdata.h> - -#include <string> -#include <vector> - -// BEGIN_ISC_NAMESPACE - -// BEGIN_COMMON_DECLARATIONS -// END_COMMON_DECLARATIONS - -// BEGIN_RDATA_NAMESPACE - -struct TLSAImpl; - -class TLSA : public Rdata { -public: - // BEGIN_COMMON_MEMBERS - // END_COMMON_MEMBERS - - TLSA(uint8_t certificate_usage, uint8_t selector, - uint8_t matching_type, const std::string& certificate_assoc_data); - TLSA& operator=(const TLSA& source); - ~TLSA(); - - /// - /// Specialized methods - /// - uint8_t getCertificateUsage() const; - uint8_t getSelector() const; - uint8_t getMatchingType() const; - const std::vector<uint8_t>& getData() const; - size_t getDataLength() const; - -private: - TLSAImpl* constructFromLexer(MasterLexer& lexer); - - TLSAImpl* impl_; -}; - -// END_RDATA_NAMESPACE -// END_ISC_NAMESPACE -// END_HEADER_GUARD - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/rdata/generic/txt_16.cc b/src/lib/dns/rdata/generic/txt_16.cc deleted file mode 100644 index 52d6b6473c..0000000000 --- a/src/lib/dns/rdata/generic/txt_16.cc +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright (C) 2010-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#include <config.h> - -#include <stdint.h> -#include <string.h> - -#include <string> -#include <vector> - -#include <util/buffer.h> -#include <dns/exceptions.h> -#include <dns/messagerenderer.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> -#include <dns/rdata/generic/detail/txt_like.h> - -using namespace std; -using namespace isc::util; - -// BEGIN_ISC_NAMESPACE -// BEGIN_RDATA_NAMESPACE - -TXT& -TXT::operator=(const TXT& source) { - if (this == &source) { - return (*this); - } - - TXTImpl* newimpl = new TXTImpl(*source.impl_); - delete impl_; - impl_ = newimpl; - - return (*this); -} - -TXT::~TXT() { - delete impl_; -} - -TXT::TXT(InputBuffer& buffer, size_t rdata_len) : - impl_(new TXTImpl(buffer, rdata_len)) -{} - -/// \brief Constructor using the master lexer. -/// -/// This implementation only uses the \c lexer parameters; others are -/// ignored. -/// -/// \throw CharStringTooLong the parameter string length exceeds maximum. -/// \throw InvalidRdataText the method cannot process the parameter data -/// -/// \param lexer A \c MasterLexer object parsing a master file for this -/// RDATA. -TXT::TXT(MasterLexer& lexer, const Name*, MasterLoader::Options, - MasterLoaderCallbacks&) : - impl_(new TXTImpl(lexer)) -{} - -TXT::TXT(const std::string& txtstr) : - impl_(new TXTImpl(txtstr)) -{} - -TXT::TXT(const TXT& other) : - Rdata(), impl_(new TXTImpl(*other.impl_)) -{} - -void -TXT::toWire(OutputBuffer& buffer) const { - impl_->toWire(buffer); -} - -void -TXT::toWire(AbstractMessageRenderer& renderer) const { - impl_->toWire(renderer); -} - -string -TXT::toText() const { - return (impl_->toText()); -} - -int -TXT::compare(const Rdata& other) const { - const TXT& other_txt = dynamic_cast<const TXT&>(other); - - return (impl_->compare(*other_txt.impl_)); -} - -// END_RDATA_NAMESPACE -// END_ISC_NAMESPACE diff --git a/src/lib/dns/rdata/generic/txt_16.h b/src/lib/dns/rdata/generic/txt_16.h deleted file mode 100644 index 83979c4765..0000000000 --- a/src/lib/dns/rdata/generic/txt_16.h +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (C) 2010-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -// BEGIN_HEADER_GUARD - -#include <stdint.h> - -#include <string> -#include <vector> - -#include <dns/rdata.h> - -// BEGIN_ISC_NAMESPACE - -// BEGIN_COMMON_DECLARATIONS -// END_COMMON_DECLARATIONS - -// BEGIN_RDATA_NAMESPACE - -namespace detail { -template<class Type, uint16_t typeCode> class TXTLikeImpl; -} - -class TXT : public Rdata { -public: - // BEGIN_COMMON_MEMBERS - // END_COMMON_MEMBERS - - TXT& operator=(const TXT& source); - ~TXT(); - -private: - typedef isc::dns::rdata::generic::detail::TXTLikeImpl<TXT, 16> TXTImpl; - TXTImpl* impl_; -}; - -// END_RDATA_NAMESPACE -// END_ISC_NAMESPACE -// END_HEADER_GUARD - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/rdata/hs_4/a_1.cc b/src/lib/dns/rdata/hs_4/a_1.cc deleted file mode 100644 index cd4c824cac..0000000000 --- a/src/lib/dns/rdata/hs_4/a_1.cc +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright (C) 2010-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#include <config.h> - -#include <string> - -#include <exceptions/exceptions.h> - -#include <util/buffer.h> -#include <dns/messagerenderer.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> - -using namespace std; -using namespace isc::util; - -// BEGIN_ISC_NAMESPACE -// BEGIN_RDATA_NAMESPACE - -A::A(const std::string&) { - // TBD -} - -A::A(MasterLexer&, const Name*, - MasterLoader::Options, MasterLoaderCallbacks&) -{ - // TBD -} - -A::A(InputBuffer&, size_t) { - // TBD -} - -A::A(const A&) : Rdata() { - // TBD -} - -void -A::toWire(OutputBuffer&) const { - // TBD -} - -void -A::toWire(AbstractMessageRenderer&) const { - // TBD -} - -string -A::toText() const { - // TBD - isc_throw(InvalidRdataText, "Not implemented yet"); -} - -int -A::compare(const Rdata&) const { - return (0); // dummy. TBD -} - -// END_RDATA_NAMESPACE -// END_ISC_NAMESPACE diff --git a/src/lib/dns/rdata/hs_4/a_1.h b/src/lib/dns/rdata/hs_4/a_1.h deleted file mode 100644 index 6f319b9c7d..0000000000 --- a/src/lib/dns/rdata/hs_4/a_1.h +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (C) 2010-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -// BEGIN_HEADER_GUARD - -#include <string> - -#include <dns/rdata.h> - -// BEGIN_ISC_NAMESPACE - -// BEGIN_COMMON_DECLARATIONS -// END_COMMON_DECLARATIONS - -// BEGIN_RDATA_NAMESPACE - -class A : public Rdata { -public: - // BEGIN_COMMON_MEMBERS - // END_COMMON_MEMBERS -}; - -// END_RDATA_NAMESPACE -// END_ISC_NAMESPACE -// END_HEADER_GUARD - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/rdata/in_1/a_1.cc b/src/lib/dns/rdata/in_1/a_1.cc index c6585b98eb..2a7b3efbb8 100644 --- a/src/lib/dns/rdata/in_1/a_1.cc +++ b/src/lib/dns/rdata/in_1/a_1.cc @@ -113,8 +113,7 @@ A::A(const std::string& addrstr) { /// \param lexer A \c MasterLexer object parsing a master file for the /// RDATA to be created A::A(MasterLexer& lexer, const Name*, - MasterLoader::Options, MasterLoaderCallbacks&) -{ + MasterLoader::Options, MasterLoaderCallbacks&) { const MasterToken& token = lexer.getNextToken(MasterToken::STRING); convertToIPv4Addr(token.getStringRegion().beg, token.getStringRegion().len, &addr_); @@ -136,8 +135,8 @@ A::A(InputBuffer& buffer, size_t rdata_len) { } /// \brief Copy constructor. -A::A(const A& other) : Rdata(), addr_(other.addr_) -{} +A::A(const A& other) : Rdata(), addr_(other.addr_) { +} void A::toWire(OutputBuffer& buffer) const { diff --git a/src/lib/dns/rdata/in_1/a_1.h b/src/lib/dns/rdata/in_1/a_1.h index 9aaeea8e3f..f8061d7d22 100644 --- a/src/lib/dns/rdata/in_1/a_1.h +++ b/src/lib/dns/rdata/in_1/a_1.h @@ -32,7 +32,3 @@ private: // END_RDATA_NAMESPACE // END_ISC_NAMESPACE // END_HEADER_GUARD - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/rdata/in_1/aaaa_28.cc b/src/lib/dns/rdata/in_1/aaaa_28.cc index c967935e8d..51243f48e8 100644 --- a/src/lib/dns/rdata/in_1/aaaa_28.cc +++ b/src/lib/dns/rdata/in_1/aaaa_28.cc @@ -89,8 +89,7 @@ AAAA::AAAA(const std::string& addrstr) { /// \param lexer A \c MasterLexer object parsing a master file for the /// RDATA to be created AAAA::AAAA(MasterLexer& lexer, const Name*, - MasterLoader::Options, MasterLoaderCallbacks&) -{ + MasterLoader::Options, MasterLoaderCallbacks&) { const MasterToken& token = lexer.getNextToken(MasterToken::STRING); convertToIPv6Addr(token.getStringRegion().beg, token.getStringRegion().len, addr_); diff --git a/src/lib/dns/rdata/in_1/aaaa_28.h b/src/lib/dns/rdata/in_1/aaaa_28.h index a5cabf41c9..c8829344b4 100644 --- a/src/lib/dns/rdata/in_1/aaaa_28.h +++ b/src/lib/dns/rdata/in_1/aaaa_28.h @@ -32,7 +32,3 @@ private: // END_RDATA_NAMESPACE // END_ISC_NAMESPACE // END_HEADER_GUARD - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/rdata/in_1/dhcid_49.cc b/src/lib/dns/rdata/in_1/dhcid_49.cc index fc5f51bd23..89c3f89360 100644 --- a/src/lib/dns/rdata/in_1/dhcid_49.cc +++ b/src/lib/dns/rdata/in_1/dhcid_49.cc @@ -100,8 +100,8 @@ DHCID::DHCID(InputBuffer& buffer, size_t rdata_len) { /// \brief The copy constructor. /// /// This trivial copy constructor never throws an exception. -DHCID::DHCID(const DHCID& other) : Rdata(), digest_(other.digest_) -{} +DHCID::DHCID(const DHCID& other) : Rdata(), digest_(other.digest_) { +} /// \brief Render the \c DHCID in the wire format. /// diff --git a/src/lib/dns/rdata/in_1/dhcid_49.h b/src/lib/dns/rdata/in_1/dhcid_49.h index 7f79602fbc..e5602c1cce 100644 --- a/src/lib/dns/rdata/in_1/dhcid_49.h +++ b/src/lib/dns/rdata/in_1/dhcid_49.h @@ -47,7 +47,3 @@ private: // END_RDATA_NAMESPACE // END_ISC_NAMESPACE // END_HEADER_GUARD - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/rdata/in_1/srv_33.cc b/src/lib/dns/rdata/in_1/srv_33.cc deleted file mode 100644 index a8a050ca27..0000000000 --- a/src/lib/dns/rdata/in_1/srv_33.cc +++ /dev/null @@ -1,298 +0,0 @@ -// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#include <config.h> - -#include <iostream> -#include <sstream> - -#include <boost/lexical_cast.hpp> - -#include <util/buffer.h> -#include <util/strutil.h> - -#include <dns/messagerenderer.h> -#include <dns/name.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> - -#include <dns/rdata/generic/detail/lexer_util.h> - -using namespace std; -using namespace isc::util; -using namespace isc::util::str; -using isc::dns::rdata::generic::detail::createNameFromLexer; - -// BEGIN_ISC_NAMESPACE -// BEGIN_RDATA_NAMESPACE - -struct SRVImpl { - // straightforward representation of SRV RDATA fields - SRVImpl(uint16_t priority, uint16_t weight, uint16_t port, - const Name& target) : - priority_(priority), weight_(weight), port_(port), - target_(target) - {} - - uint16_t priority_; - uint16_t weight_; - uint16_t port_; - Name target_; -}; - -/// \brief Constructor from string. -/// -/// The given string must represent a valid SRV 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 TARGET name must be absolute since there's no parameter that -/// specifies the origin name; if it is not absolute, \c MissingNameOrigin -/// exception will be thrown. It must not be represented as a quoted -/// string. -/// -/// See the construction that takes \c MasterLexer for other fields. -/// -/// \throw Others Exception from the Name and RRTTL constructors. -/// \throw InvalidRdataText Other general syntax errors. -SRV::SRV(const std::string& srv_str) : - impl_(NULL) -{ - try { - std::istringstream ss(srv_str); - MasterLexer lexer; - lexer.pushSource(ss); - - uint32_t num = lexer.getNextToken(MasterToken::NUMBER).getNumber(); - if (num > 65535) { - isc_throw(InvalidRdataText, "Invalid SRV priority in: " << srv_str); - } - const uint16_t priority = static_cast<uint16_t>(num); - - num = lexer.getNextToken(MasterToken::NUMBER).getNumber(); - if (num > 65535) { - isc_throw(InvalidRdataText, "Invalid SRV weight in: " << srv_str); - } - const uint16_t weight = static_cast<uint16_t>(num); - - num = lexer.getNextToken(MasterToken::NUMBER).getNumber(); - if (num > 65535) { - isc_throw(InvalidRdataText, "Invalid SRV port in: " << srv_str); - } - const uint16_t port = static_cast<uint16_t>(num); - - const Name targetname = createNameFromLexer(lexer, NULL); - - if (lexer.getNextToken().getType() != MasterToken::END_OF_FILE) { - isc_throw(InvalidRdataText, "extra input text for SRV: " - << srv_str); - } - - impl_ = new SRVImpl(priority, weight, port, targetname); - } catch (const MasterLexer::LexerError& ex) { - isc_throw(InvalidRdataText, "Failed to construct SRV from '" << - srv_str << "': " << ex.what()); - } -} - -/// \brief Constructor from wire-format data. -/// -/// When a read operation on \c buffer fails (e.g., due to a corrupted -/// message) a corresponding exception from the \c InputBuffer class will -/// be thrown. -/// If the wire-format data does not end with a valid domain name, -/// a corresponding exception from the \c Name class will be thrown. -/// In addition, this constructor internally involves resource allocation, -/// and if it fails a corresponding standard exception will be thrown. -/// -/// According to RFC2782, the Target field must be a non compressed form -/// of domain name. But this implementation accepts a %SRV RR even if that -/// field is compressed as suggested in RFC3597. -/// -/// \param buffer A buffer storing the wire format data. -/// \param rdata_len The length of the RDATA in bytes, normally expected -/// to be the value of the RDLENGTH field of the corresponding RR. -SRV::SRV(InputBuffer& buffer, size_t rdata_len) { - if (rdata_len < 6) { - isc_throw(InvalidRdataLength, "SRV too short"); - } - - const uint16_t priority = buffer.readUint16(); - const uint16_t weight = buffer.readUint16(); - const uint16_t port = buffer.readUint16(); - const Name targetname(buffer); - - impl_ = new SRVImpl(priority, weight, port, targetname); -} - -/// \brief Constructor with a context of MasterLexer. -/// -/// The \c lexer should point to the beginning of valid textual representation -/// of an SRV RDATA. The TARGET field can be non-absolute if \c origin -/// is non-NULL, in which case \c origin is used to make it absolute. -/// It must not be represented as a quoted string. -/// -/// The PRIORITY, WEIGHT and PORT fields must each be a valid decimal -/// representation of an unsigned 16-bit integers respectively. -/// -/// \throw MasterLexer::LexerError General parsing error such as missing field. -/// \throw Other Exceptions from the Name and RRTTL constructors if -/// construction of textual fields as these objects fail. -/// -/// \param lexer A \c MasterLexer object parsing a master file for the -/// RDATA to be created -/// \param origin If non NULL, specifies the origin of TARGET when it -/// is non-absolute. -SRV::SRV(MasterLexer& lexer, const Name* origin, - MasterLoader::Options, MasterLoaderCallbacks&) -{ - uint32_t num = lexer.getNextToken(MasterToken::NUMBER).getNumber(); - if (num > 65535) { - isc_throw(InvalidRdataText, "Invalid SRV priority: " << num); - } - const uint16_t priority = static_cast<uint16_t>(num); - - num = lexer.getNextToken(MasterToken::NUMBER).getNumber(); - if (num > 65535) { - isc_throw(InvalidRdataText, "Invalid SRV weight: " << num); - } - const uint16_t weight = static_cast<uint16_t>(num); - - num = lexer.getNextToken(MasterToken::NUMBER).getNumber(); - if (num > 65535) { - isc_throw(InvalidRdataText, "Invalid SRV port: " << num); - } - const uint16_t port = static_cast<uint16_t>(num); - - const Name targetname = createNameFromLexer(lexer, origin); - - impl_ = new SRVImpl(priority, weight, port, targetname); -} - -/// \brief The copy constructor. -/// -/// It internally allocates a resource, and if it fails a corresponding -/// standard exception will be thrown. -/// This constructor never throws an exception otherwise. -SRV::SRV(const SRV& source) : - Rdata(), impl_(new SRVImpl(*source.impl_)) -{} - -SRV& -SRV::operator=(const SRV& source) { - if (this == &source) { - return (*this); - } - - SRVImpl* newimpl = new SRVImpl(*source.impl_); - delete impl_; - impl_ = newimpl; - - return (*this); -} - -SRV::~SRV() { - delete impl_; -} - -/// \brief Convert the \c SRV to a string. -/// -/// The output of this method is formatted as described in the "from string" -/// constructor (\c SRV(const std::string&))). -/// -/// If internal resource allocation fails, a corresponding -/// standard exception will be thrown. -/// -/// \return A \c string object that represents the \c SRV object. -string -SRV::toText() const { - using boost::lexical_cast; - return (lexical_cast<string>(impl_->priority_) + - " " + lexical_cast<string>(impl_->weight_) + - " " + lexical_cast<string>(impl_->port_) + - " " + impl_->target_.toText()); -} - -/// \brief Render the \c SRV in the wire format without name compression. -/// -/// If internal resource allocation fails, a corresponding -/// standard exception will be thrown. -/// This method never throws an exception otherwise. -/// -/// \param buffer An output buffer to store the wire data. -void -SRV::toWire(OutputBuffer& buffer) const { - buffer.writeUint16(impl_->priority_); - buffer.writeUint16(impl_->weight_); - buffer.writeUint16(impl_->port_); - impl_->target_.toWire(buffer); -} - -/// \brief Render the \c SRV in the wire format with taking into account -/// compression. -/// -/// As specified in RFC2782, the Target field (a domain name) will not be -/// compressed. However, the domain name could be a target of compression -/// of other compressible names (though pretty unlikely), the offset -/// information of the algorithm name may be recorded in \c renderer. -/// -/// If internal resource allocation fails, a corresponding -/// standard exception will be thrown. -/// This method never throws an exception otherwise. -/// -/// \param renderer DNS message rendering context that encapsulates the -/// output buffer and name compression information. -void -SRV::toWire(AbstractMessageRenderer& renderer) const { - renderer.writeUint16(impl_->priority_); - renderer.writeUint16(impl_->weight_); - renderer.writeUint16(impl_->port_); - renderer.writeName(impl_->target_, false); -} - -/// \brief Compare two instances of \c SRV RDATA. -/// -/// See documentation in \c Rdata. -int -SRV::compare(const Rdata& other) const { - const SRV& other_srv = dynamic_cast<const SRV&>(other); - - if (impl_->priority_ != other_srv.impl_->priority_) { - return (impl_->priority_ < other_srv.impl_->priority_ ? -1 : 1); - } - if (impl_->weight_ != other_srv.impl_->weight_) { - return (impl_->weight_ < other_srv.impl_->weight_ ? -1 : 1); - } - if (impl_->port_ != other_srv.impl_->port_) { - return (impl_->port_ < other_srv.impl_->port_ ? -1 : 1); - } - - return (compareNames(impl_->target_, other_srv.impl_->target_)); -} - -uint16_t -SRV::getPriority() const { - return (impl_->priority_); -} - -uint16_t -SRV::getWeight() const { - return (impl_->weight_); -} - -uint16_t -SRV::getPort() const { - return (impl_->port_); -} - -const Name& -SRV::getTarget() const { - return (impl_->target_); -} - -// END_RDATA_NAMESPACE -// END_ISC_NAMESPACE diff --git a/src/lib/dns/rdata/in_1/srv_33.h b/src/lib/dns/rdata/in_1/srv_33.h deleted file mode 100644 index aca210e038..0000000000 --- a/src/lib/dns/rdata/in_1/srv_33.h +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -// BEGIN_HEADER_GUARD - -#include <stdint.h> - -#include <dns/name.h> -#include <dns/rdata.h> - -// BEGIN_ISC_NAMESPACE - -// BEGIN_COMMON_DECLARATIONS -// END_COMMON_DECLARATIONS - -// BEGIN_RDATA_NAMESPACE - -struct SRVImpl; - -/// \brief \c rdata::SRV class represents the SRV RDATA as defined %in -/// RFC2782. -/// -/// This class implements the basic interfaces inherited from the abstract -/// \c rdata::Rdata class, and provides trivial accessors specific to the -/// SRV RDATA. -class SRV : public Rdata { -public: - // BEGIN_COMMON_MEMBERS - // END_COMMON_MEMBERS - - /// \brief Assignment operator. - /// - /// It internally allocates a resource, and if it fails a corresponding - /// standard exception will be thrown. - /// This operator never throws an exception otherwise. - /// - /// This operator provides the strong exception guarantee: When an - /// exception is thrown the content of the assignment target will be - /// intact. - SRV& operator=(const SRV& source); - - /// \brief The destructor. - ~SRV(); - - /// - /// Specialized methods - /// - - /// \brief Return the value of the priority field. - /// - /// This method never throws an exception. - uint16_t getPriority() const; - - /// \brief Return the value of the weight field. - /// - /// This method never throws an exception. - uint16_t getWeight() const; - - /// \brief Return the value of the port field. - /// - /// This method never throws an exception. - uint16_t getPort() const; - - /// \brief Return the value of the target field. - /// - /// \return A reference to a \c Name class object corresponding to the - /// internal target name. - /// - /// This method never throws an exception. - const Name& getTarget() const; - -private: - SRVImpl* impl_; -}; - -// END_RDATA_NAMESPACE -// END_ISC_NAMESPACE -// END_HEADER_GUARD - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/rdata/template.cc b/src/lib/dns/rdata/template.cc index d20585597a..8b13789179 100644 --- a/src/lib/dns/rdata/template.cc +++ b/src/lib/dns/rdata/template.cc @@ -1,67 +1 @@ -// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. -#include <config.h> - -#include <string> - -#include <util/buffer.h> -#include <dns/messagerenderer.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> -#include <dns/rrtype.h> - -using namespace std; -using namespace isc::util; - -// BEGIN_ISC_NAMESPACE -// BEGIN_RDATA_NAMESPACE - -// To add RDATA implementation of a new RR type (say "MyType"), copy this -// template into the appropriate subdirectory with the appropriate name -// (see template.h). -// Then define (at least) the following common methods (that are inherited -// from the base abstract class). -// If you added member functions specific to this derived class, you'll need -// to implement them here, of course. - -MyType::MyType(MasterLexer& lexer, const Name* origin, - MasterLoader::Options options, MasterLoaderCallbacks& callbacks) -{ -} - -MyType::MyType(const string& type_str) { -} - -MyType::MyType(InputBuffer& buffer, size_t rdata_len) { -} - -MyType::MyType(const MyType& source) { -} - -std::string -MyType::toText() const { -} - -void -MyType::toWire(OutputBuffer& buffer) const { -} - -void -MyType::toWire(AbstractMessageRenderer& renderer) const { -} - -int -MyType::compare(const Rdata&) const { - // The compare method normally begins with this dynamic cast. - // cppcheck-suppress unreadVariable - // const MyType& other_mytype = dynamic_cast<const MyType&>(other); - // ... - return (0); -} - -// END_RDATA_NAMESPACE -// END_ISC_NAMESPACE diff --git a/src/lib/dns/rdata/template.h b/src/lib/dns/rdata/template.h index d74790eefe..8b13789179 100644 --- a/src/lib/dns/rdata/template.h +++ b/src/lib/dns/rdata/template.h @@ -1,54 +1 @@ -// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. -// BEGIN_HEADER_GUARD - -#include <string> - -#include <dns/rdata.h> - -// BEGIN_ISC_NAMESPACE - -// BEGIN_COMMON_DECLARATIONS -// END_COMMON_DECLARATIONS - -// BEGIN_RDATA_NAMESPACE - -// To add RDATA class definition of a new RR type (say "MyType"), copy this -// file to an appropriate subdirectory (if it's class-independent type, it -// should go to "generic/", if it's IN-class specific, it should be in -// "in_1/", and so on). The copied file should be named as type_nn.h where -// "type" is textual representation (all lower cased) of the RR type, and "nn" -// is the 16-bit type code of the RR type. -// Normally, you'll need to define some specific member variables in the -// "RR-type specific members" space (please make them private). In addition, -// you may want to define some specific member functions, either public or -// private (or, though unlikely for a leaf class, protected). -// -// Note: do not remove the comment lines beginning with "BEGIN_" and "END_". -// These are markers used by a script for auto-generating build-able source -// files. -// -// On completion of implementing a new type of Rdata, remove the corresponding -// entry from the meta_types dictionary of gen-rdatacode.py.in. Otherwise -// it will cause build failure. - -class MyType : public Rdata { -public: - // BEGIN_COMMON_MEMBERS - // Do not remove the BEGIN_xxx and END_xxx comment lines. - // END_COMMON_MEMBERS -private: - // RR-type specific members are here. -}; - -// END_RDATA_NAMESPACE -// END_ISC_NAMESPACE -// END_HEADER_GUARD - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/rdata_pimpl_holder.h b/src/lib/dns/rdata_pimpl_holder.h deleted file mode 100644 index baa343a529..0000000000 --- a/src/lib/dns/rdata_pimpl_holder.h +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (C) 2014-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef DNS_RDATA_PIMPL_HOLDER_H -#define DNS_RDATA_PIMPL_HOLDER_H 1 - -#include <boost/noncopyable.hpp> - -#include <cstddef> // for NULL - -namespace isc { -namespace dns { -namespace rdata { - -template <typename T> -class RdataPimplHolder : boost::noncopyable { -public: - RdataPimplHolder(T* obj = NULL) : - obj_(obj) - {} - - ~RdataPimplHolder() { - delete obj_; - } - - void reset(T* obj = NULL) { - delete obj_; - obj_ = obj; - } - - T* get() { - return (obj_); - } - - T* release() { - T* obj = obj_; - obj_ = NULL; - return (obj); - } - -private: - T* obj_; -}; - -} // namespace rdata -} // namespace dns -} // namespace isc - -#endif // DNS_RDATA_PIMPL_HOLDER_H diff --git a/src/lib/dns/rdataclass.cc b/src/lib/dns/rdataclass.cc index f41db8da62..699f6aaaa4 100644 --- a/src/lib/dns/rdataclass.cc +++ b/src/lib/dns/rdataclass.cc @@ -18,6 +18,7 @@ #include <vector> #include <boost/lexical_cast.hpp> +#include <boost/shared_ptr.hpp> #include <util/buffer.h> #include <util/encode/encode.h> @@ -50,8 +51,8 @@ struct TSIGImpl { vector<uint8_t>& other_data) : algorithm_(algorithm), time_signed_(time_signed), fudge_(fudge), mac_(mac), original_id_(original_id), error_(error), - other_data_(other_data) - {} + other_data_(other_data) { + } TSIGImpl(const Name& algorithm, uint64_t time_signed, uint16_t fudge, size_t macsize, const void* mac, uint16_t original_id, uint16_t error, size_t other_len, const void* other_data) : @@ -60,8 +61,8 @@ struct TSIGImpl { static_cast<const uint8_t*>(mac) + macsize), original_id_(original_id), error_(error), other_data_(static_cast<const uint8_t*>(other_data), - static_cast<const uint8_t*>(other_data) + other_len) - {} + static_cast<const uint8_t*>(other_data) + other_len) { + } template <typename Output> void toWireCommon(Output& output) const; @@ -75,7 +76,7 @@ struct TSIGImpl { }; // helper function for string and lexer constructors -TSIGImpl* +boost::shared_ptr<TSIGImpl> TSIG::constructFromLexer(MasterLexer& lexer, const Name* origin) { const Name& algorithm = createNameFromLexer(lexer, origin ? origin : &Name::ROOT_NAME()); @@ -169,8 +170,8 @@ TSIG::constructFromLexer(MasterLexer& lexer, const Name* origin) { // RFC2845 says Other Data is "empty unless Error == BADTIME". // However, we don't enforce that. - return (new TSIGImpl(canonical_algorithm_name, time_signed, fudge, mac, - orig_id, error, other_data)); + return (boost::shared_ptr<TSIGImpl>(new TSIGImpl(canonical_algorithm_name, time_signed, fudge, mac, + orig_id, error, other_data))); } /// \brief Constructor from string. @@ -222,14 +223,14 @@ TSIG::TSIG(const std::string& tsig_str) : impl_(NULL) { // We use unique_ptr here because if there is an exception in this // constructor, the destructor is not called and there could be a // leak of the TSIGImpl that constructFromLexer() returns. - std::unique_ptr<TSIGImpl> impl_ptr; + boost::shared_ptr<TSIGImpl> impl_ptr; try { std::istringstream ss(tsig_str); MasterLexer lexer; lexer.pushSource(ss); - impl_ptr.reset(constructFromLexer(lexer, NULL)); + impl_ptr = constructFromLexer(lexer, NULL); if (lexer.getNextToken().getType() != MasterToken::END_OF_FILE) { isc_throw(InvalidRdataText, @@ -241,7 +242,7 @@ TSIG::TSIG(const std::string& tsig_str) : impl_(NULL) { << ex.what()); } - impl_ = impl_ptr.release(); + impl_ = impl_ptr; } /// \brief Constructor with a context of MasterLexer. @@ -260,9 +261,8 @@ TSIG::TSIG(const std::string& tsig_str) : impl_(NULL) { /// \param lexer A \c MasterLexer object parsing a master file for the /// RDATA to be created TSIG::TSIG(MasterLexer& lexer, const Name* origin, - MasterLoader::Options, MasterLoaderCallbacks&) : - impl_(constructFromLexer(lexer, origin)) -{ + MasterLoader::Options, MasterLoaderCallbacks&) { + impl_ = constructFromLexer(lexer, origin); } /// \brief Constructor from wire-format data. @@ -286,8 +286,7 @@ TSIG::TSIG(MasterLexer& lexer, const Name* origin, /// must check consistency between the length parameter and the actual /// RDATA length. TSIG::TSIG(InputBuffer& buffer, size_t) : - impl_(NULL) -{ + impl_(NULL) { Name algorithm(buffer); uint8_t time_signed_buf[6]; @@ -320,15 +319,14 @@ TSIG::TSIG(InputBuffer& buffer, size_t) : const Name& canonical_algorithm_name = (algorithm == TSIGKey::HMACMD5_SHORT_NAME()) ? TSIGKey::HMACMD5_NAME() : algorithm; - impl_ = new TSIGImpl(canonical_algorithm_name, time_signed, fudge, mac, - original_id, error, other_data); + impl_.reset(new TSIGImpl(canonical_algorithm_name, time_signed, fudge, mac, + original_id, error, other_data)); } TSIG::TSIG(const Name& algorithm, uint64_t time_signed, uint16_t fudge, uint16_t mac_size, const void* mac, uint16_t original_id, uint16_t error, uint16_t other_len, const void* other_data) : - impl_(NULL) -{ + impl_(NULL) { // Time Signed is a 48-bit value. if ((time_signed >> 48) != 0) { isc_throw(OutOfRange, "TSIG Time Signed is too large: " << @@ -345,8 +343,8 @@ TSIG::TSIG(const Name& algorithm, uint64_t time_signed, uint16_t fudge, const Name& canonical_algorithm_name = (algorithm == TSIGKey::HMACMD5_SHORT_NAME()) ? TSIGKey::HMACMD5_NAME() : algorithm; - impl_ = new TSIGImpl(canonical_algorithm_name, time_signed, fudge, mac_size, - mac, original_id, error, other_len, other_data); + impl_.reset(new TSIGImpl(canonical_algorithm_name, time_signed, fudge, mac_size, + mac, original_id, error, other_len, other_data)); } /// \brief The copy constructor. @@ -354,8 +352,8 @@ TSIG::TSIG(const Name& algorithm, uint64_t time_signed, uint16_t fudge, /// It internally allocates a resource, and if it fails a corresponding /// standard exception will be thrown. /// This constructor never throws an exception otherwise. -TSIG::TSIG(const TSIG& source) : Rdata(), impl_(new TSIGImpl(*source.impl_)) -{} +TSIG::TSIG(const TSIG& source) : Rdata(), impl_(new TSIGImpl(*source.impl_)) { +} TSIG& TSIG::operator=(const TSIG& source) { @@ -363,15 +361,12 @@ TSIG::operator=(const TSIG& source) { return (*this); } - TSIGImpl* newimpl = new TSIGImpl(*source.impl_); - delete impl_; - impl_ = newimpl; + impl_.reset(new TSIGImpl(*source.impl_)); return (*this); } TSIG::~TSIG() { - delete impl_; } /// \brief Convert the \c TSIG to a string. @@ -584,3061 +579,6 @@ TSIG::getOtherData() const { #include <config.h> -#include <string> - -#include <exceptions/exceptions.h> - -#include <util/buffer.h> -#include <dns/messagerenderer.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> - -using namespace std; -using namespace isc::util; - -namespace isc { -namespace dns { -namespace rdata { -namespace ch { - -A::A(const std::string&) { - // TBD -} - -A::A(MasterLexer&, const Name*, - MasterLoader::Options, MasterLoaderCallbacks&) -{ - // TBD -} - -A::A(InputBuffer&, size_t) { - // TBD -} - -A::A(const A&) : Rdata() { - // TBD -} - -void -A::toWire(OutputBuffer&) const { - // TBD -} - -void -A::toWire(AbstractMessageRenderer&) const { - // TBD -} - -string -A::toText() const { - // TBD - isc_throw(InvalidRdataText, "Not implemented yet"); -} - -int -A::compare(const Rdata&) const { - return (0); // dummy. TBD -} - -} // end of namespace "ch" -} // end of namespace "rdata" -} // end of namespace "dns" -} // end of namespace "isc" -// Copyright (C) 2011-2024 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#include <config.h> - -#include <string> -#include <sstream> - -#include <util/buffer.h> -#include <util/strutil.h> - -#include <dns/name.h> -#include <dns/messagerenderer.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> - -#include <boost/lexical_cast.hpp> - -#include <dns/rdata/generic/detail/lexer_util.h> - -using namespace std; -using boost::lexical_cast; -using namespace isc::util; -using isc::dns::rdata::generic::detail::createNameFromLexer; - -namespace isc { -namespace dns { -namespace rdata { -namespace generic { - -/// \brief Constructor from string. -/// -/// \c afsdb_str must be formatted as follows: -/// \code <subtype> <server name> -/// \endcode -/// where server name field must represent a valid domain name. -/// -/// An example of valid string is: -/// \code "1 server.example.com." \endcode -/// -/// <b>Exceptions</b> -/// -/// \exception InvalidRdataText The number of RDATA fields (must be 2) is -/// incorrect. -/// \exception std::bad_alloc Memory allocation fails. -/// \exception Other The constructor of the \c Name class will throw if the -/// names in the string is invalid. -AFSDB::AFSDB(const std::string& afsdb_str) : - subtype_(0), server_(Name::ROOT_NAME()) -{ - try { - std::istringstream ss(afsdb_str); - MasterLexer lexer; - lexer.pushSource(ss); - - createFromLexer(lexer, NULL); - - if (lexer.getNextToken().getType() != MasterToken::END_OF_FILE) { - isc_throw(InvalidRdataText, "extra input text for AFSDB: " - << afsdb_str); - } - } catch (const MasterLexer::LexerError& ex) { - isc_throw(InvalidRdataText, "Failed to construct AFSDB from '" << - afsdb_str << "': " << ex.what()); - } -} - -/// \brief Constructor with a context of MasterLexer. -/// -/// The \c lexer should point to the beginning of valid textual representation -/// of an AFSDB RDATA. The SERVER field can be non-absolute if \c origin -/// is non-NULL, in which case \c origin is used to make it absolute. -/// It must not be represented as a quoted string. -/// -/// The SUBTYPE field must be a valid decimal representation of an -/// unsigned 16-bit integer. -/// -/// \throw MasterLexer::LexerError General parsing error such as missing field. -/// \throw Other Exceptions from the Name and RRTTL constructors if -/// construction of textual fields as these objects fail. -/// -/// \param lexer A \c MasterLexer object parsing a master file for the -/// RDATA to be created -/// \param origin If non NULL, specifies the origin of SERVER when it -/// is non-absolute. -AFSDB::AFSDB(MasterLexer& lexer, const Name* origin, - MasterLoader::Options, MasterLoaderCallbacks&) : - subtype_(0), server_(".") -{ - createFromLexer(lexer, origin); -} - -void -AFSDB::createFromLexer(MasterLexer& lexer, const Name* origin) -{ - const uint32_t num = lexer.getNextToken(MasterToken::NUMBER).getNumber(); - if (num > 65535) { - isc_throw(InvalidRdataText, "Invalid AFSDB subtype: " << num); - } - subtype_ = static_cast<uint16_t>(num); - - server_ = createNameFromLexer(lexer, origin); -} - -/// \brief Constructor from wire-format data. -/// -/// This constructor doesn't check the validity of the second parameter (rdata -/// length) for parsing. -/// If necessary, the caller will check consistency. -/// -/// \exception std::bad_alloc Memory allocation fails. -/// \exception Other The constructor of the \c Name class will throw if the -/// names in the wire is invalid. -AFSDB::AFSDB(InputBuffer& buffer, size_t) : - subtype_(buffer.readUint16()), server_(buffer) -{} - -/// \brief Copy constructor. -/// -/// \exception std::bad_alloc Memory allocation fails in copying internal -/// member variables (this should be very rare). -AFSDB::AFSDB(const AFSDB& other) : - Rdata(), subtype_(other.subtype_), server_(other.server_) -{} - -AFSDB& -AFSDB::operator=(const AFSDB& source) { - subtype_ = source.subtype_; - server_ = source.server_; - - return (*this); -} - -/// \brief Convert the \c AFSDB to a string. -/// -/// The output of this method is formatted as described in the "from string" -/// constructor (\c AFSDB(const std::string&))). -/// -/// \exception std::bad_alloc Internal resource allocation fails. -/// -/// \return A \c string object that represents the \c AFSDB object. -string -AFSDB::toText() const { - return (lexical_cast<string>(subtype_) + " " + server_.toText()); -} - -/// \brief Render the \c AFSDB in the wire format without name compression. -/// -/// \exception std::bad_alloc Internal resource allocation fails. -/// -/// \param buffer An output buffer to store the wire data. -void -AFSDB::toWire(OutputBuffer& buffer) const { - buffer.writeUint16(subtype_); - server_.toWire(buffer); -} - -/// \brief Render the \c AFSDB in the wire format with taking into account -/// compression. -/// -/// As specified in RFC3597, TYPE AFSDB is not "well-known", the server -/// field (domain name) will not be compressed. -/// -/// \exception std::bad_alloc Internal resource allocation fails. -/// -/// \param renderer DNS message rendering context that encapsulates the -/// output buffer and name compression information. -void -AFSDB::toWire(AbstractMessageRenderer& renderer) const { - renderer.writeUint16(subtype_); - renderer.writeName(server_, false); -} - -/// \brief Compare two instances of \c AFSDB RDATA. -/// -/// See documentation in \c Rdata. -int -AFSDB::compare(const Rdata& other) const { - const AFSDB& other_afsdb = dynamic_cast<const AFSDB&>(other); - if (subtype_ < other_afsdb.subtype_) { - return (-1); - } else if (subtype_ > other_afsdb.subtype_) { - return (1); - } - - return (compareNames(server_, other_afsdb.server_)); -} - -const Name& -AFSDB::getServer() const { - return (server_); -} - -uint16_t -AFSDB::getSubtype() const { - return (subtype_); -} - -} // end of namespace "generic" -} // end of namespace "rdata" -} // end of namespace "dns" -} // end of namespace "isc" -// Copyright (C) 2014-2024 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#include <config.h> - -#include <boost/lexical_cast.hpp> -#include <boost/algorithm/string.hpp> - -#include <exceptions/exceptions.h> - -#include <util/buffer.h> -#include <dns/name.h> -#include <dns/messagerenderer.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> - -#include <dns/rdata/generic/detail/char_string.h> - -using namespace std; -using boost::lexical_cast; -using namespace isc::util; - -namespace isc { -namespace dns { -namespace rdata { -namespace generic { - -struct CAAImpl { - // straightforward representation of CAA RDATA fields - CAAImpl(uint8_t flags, const std::string& tag, - const detail::CharStringData& value) : - flags_(flags), - tag_(tag), - value_(value) - { - if ((sizeof(flags) + 1 + tag_.size() + value_.size()) > 65535) { - isc_throw(InvalidRdataLength, - "CAA Value field is too large: " << value_.size()); - } - } - - uint8_t flags_; - const std::string tag_; - const detail::CharStringData value_; -}; - -// helper function for string and lexer constructors -CAAImpl* -CAA::constructFromLexer(MasterLexer& lexer) { - const uint32_t flags = - lexer.getNextToken(MasterToken::NUMBER).getNumber(); - if (flags > 255) { - isc_throw(InvalidRdataText, - "CAA flags field out of range"); - } - - // Tag field must not be empty. - const std::string tag = - lexer.getNextToken(MasterToken::STRING).getString(); - if (tag.empty()) { - isc_throw(InvalidRdataText, "CAA tag field is empty"); - } else if (tag.size() > 255) { - isc_throw(InvalidRdataText, - "CAA tag field is too large: " << tag.size()); - } - - // Value field may be empty. - detail::CharStringData value; - MasterToken token = lexer.getNextToken(MasterToken::QSTRING, true); - if ((token.getType() != MasterToken::END_OF_FILE) && - (token.getType() != MasterToken::END_OF_LINE)) - { - detail::stringToCharStringData(token.getStringRegion(), value); - } - - return (new CAAImpl(flags, tag, value)); -} - -/// \brief Constructor from string. -/// -/// The given string must represent a valid CAA RDATA. There can be -/// extra space characters at the beginning or end of the text (which -/// are simply ignored), but other extra text, including a new line, -/// will make the construction fail with an exception. -/// -/// The Flags, Tag and Value fields must be within their valid ranges, -/// but are not constrained to the values defined in RFC6844. The Tag -/// field must not be empty. -/// -/// \throw InvalidRdataText if any fields are missing, out of their -/// valid ranges, incorrect, or empty. -/// -/// \param caa_str A string containing the RDATA to be created -CAA::CAA(const string& caa_str) : - impl_(NULL) -{ - // We use unique_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::unique_ptr<CAAImpl> impl_ptr; - - try { - std::istringstream ss(caa_str); - MasterLexer lexer; - lexer.pushSource(ss); - - impl_ptr.reset(constructFromLexer(lexer)); - - if (lexer.getNextToken().getType() != MasterToken::END_OF_FILE) { - isc_throw(InvalidRdataText, "extra input text for CAA: " - << caa_str); - } - } catch (const MasterLexer::LexerError& ex) { - isc_throw(InvalidRdataText, "Failed to construct CAA from '" << - caa_str << "': " << ex.what()); - } - - impl_ = impl_ptr.release(); -} - -/// \brief Constructor with a context of MasterLexer. -/// -/// The \c lexer should point to the beginning of valid textual -/// representation of an CAA RDATA. -/// -/// \throw MasterLexer::LexerError General parsing error such as missing -/// field. -/// \throw InvalidRdataText Fields are out of their valid ranges, -/// incorrect, or empty. -/// -/// \param lexer A \c MasterLexer object parsing a master file for the -/// RDATA to be created -CAA::CAA(MasterLexer& lexer, const Name*, - MasterLoader::Options, MasterLoaderCallbacks&) : - impl_(constructFromLexer(lexer)) -{ -} - -/// \brief Constructor from InputBuffer. -/// -/// The passed buffer must contain a valid CAA RDATA. -/// -/// The Flags, Tag and Value fields must be within their valid ranges, -/// but are not constrained to the values defined in RFC6844. The Tag -/// field must not be empty. -CAA::CAA(InputBuffer& buffer, size_t rdata_len) { - if (rdata_len < 2) { - isc_throw(InvalidRdataLength, "CAA record too short"); - } - - const uint8_t flags = buffer.readUint8(); - const uint8_t tag_length = buffer.readUint8(); - rdata_len -= 2; - if (tag_length == 0) { - isc_throw(InvalidRdataText, "CAA tag field is empty"); - } - - if (rdata_len < tag_length) { - isc_throw(InvalidRdataLength, - "RDATA is too short for CAA tag field"); - } - - std::vector<uint8_t> tag_vec(tag_length); - buffer.readData(&tag_vec[0], tag_length); - std::string tag(tag_vec.begin(), tag_vec.end()); - rdata_len -= tag_length; - - detail::CharStringData value; - value.resize(rdata_len); - if (rdata_len > 0) { - buffer.readData(&value[0], rdata_len); - } - - impl_ = new CAAImpl(flags, tag, value); -} - -CAA::CAA(uint8_t flags, const std::string& tag, const std::string& value) : - impl_(NULL) -{ - if (tag.empty()) { - isc_throw(isc::InvalidParameter, - "CAA tag field is empty"); - } else if (tag.size() > 255) { - isc_throw(isc::InvalidParameter, - "CAA tag field is too large: " << tag.size()); - } - - MasterToken::StringRegion region; - region.beg = &value[0]; // note std ensures this works even if str is empty - region.len = value.size(); - - detail::CharStringData value_vec; - detail::stringToCharStringData(region, value_vec); - - impl_ = new CAAImpl(flags, tag, value_vec); -} - -CAA::CAA(const CAA& other) : - Rdata(), impl_(new CAAImpl(*other.impl_)) -{} - -CAA& -CAA::operator=(const CAA& source) { - if (this == &source) { - return (*this); - } - - CAAImpl* newimpl = new CAAImpl(*source.impl_); - delete impl_; - impl_ = newimpl; - - return (*this); -} - -CAA::~CAA() { - delete impl_; -} - -void -CAA::toWire(OutputBuffer& buffer) const { - buffer.writeUint8(impl_->flags_); - - // The constructors must ensure that the tag field is not empty. - assert(!impl_->tag_.empty()); - buffer.writeUint8(impl_->tag_.size()); - buffer.writeData(&impl_->tag_[0], impl_->tag_.size()); - - if (!impl_->value_.empty()) { - buffer.writeData(&impl_->value_[0], - impl_->value_.size()); - } -} - -void -CAA::toWire(AbstractMessageRenderer& renderer) const { - renderer.writeUint8(impl_->flags_); - - // The constructors must ensure that the tag field is not empty. - assert(!impl_->tag_.empty()); - renderer.writeUint8(impl_->tag_.size()); - renderer.writeData(&impl_->tag_[0], impl_->tag_.size()); - - if (!impl_->value_.empty()) { - renderer.writeData(&impl_->value_[0], - impl_->value_.size()); - } -} - -std::string -CAA::toText() const { - std::string result; - - result = lexical_cast<std::string>(static_cast<int>(impl_->flags_)); - result += " " + impl_->tag_; - result += " \"" + detail::charStringDataToString(impl_->value_) + "\""; - - return (result); -} - -int -CAA::compare(const Rdata& other) const { - const CAA& other_caa = dynamic_cast<const CAA&>(other); - - if (impl_->flags_ < other_caa.impl_->flags_) { - return (-1); - } else if (impl_->flags_ > other_caa.impl_->flags_) { - return (1); - } - - // Do a case-insensitive compare of the tag strings. - const int result = boost::ilexicographical_compare - <std::string, std::string>(impl_->tag_, other_caa.impl_->tag_); - if (result != 0) { - return (result); - } - - return (detail::compareCharStringDatas(impl_->value_, - other_caa.impl_->value_)); -} - -uint8_t -CAA::getFlags() const { - return (impl_->flags_); -} - -const std::string& -CAA::getTag() const { - return (impl_->tag_); -} - -const std::vector<uint8_t>& -CAA::getValue() const { - return (impl_->value_); -} - -} // end of namespace "generic" -} // end of namespace "rdata" -} // end of namespace "dns" -} // end of namespace "isc" -// Copyright (C) 2010-2024 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#include <config.h> - -#include <string> - -#include <util/buffer.h> -#include <dns/name.h> -#include <dns/messagerenderer.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> - -#include <dns/rdata/generic/detail/lexer_util.h> - -using namespace std; -using namespace isc::util; -using isc::dns::rdata::generic::detail::createNameFromLexer; - -namespace isc { -namespace dns { -namespace rdata { -namespace generic { - -/// \brief Constructor from string. -/// -/// The given string must represent a valid CNAME 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 CNAME must be absolute since there's no parameter that specifies -/// the origin name; if it is not absolute, \c MissingNameOrigin -/// exception will be thrown. These must not be represented as a quoted -/// string. -/// -/// \throw Others Exception from the Name and RRTTL constructors. -/// \throw InvalidRdataText Other general syntax errors. -CNAME::CNAME(const std::string& namestr) : - // Fill in dummy name and replace it soon below. - cname_(Name::ROOT_NAME()) -{ - try { - std::istringstream ss(namestr); - MasterLexer lexer; - lexer.pushSource(ss); - - cname_ = createNameFromLexer(lexer, NULL); - - if (lexer.getNextToken().getType() != MasterToken::END_OF_FILE) { - isc_throw(InvalidRdataText, "extra input text for CNAME: " - << namestr); - } - } catch (const MasterLexer::LexerError& ex) { - isc_throw(InvalidRdataText, "Failed to construct CNAME from '" << - namestr << "': " << ex.what()); - } -} - -CNAME::CNAME(InputBuffer& buffer, size_t) : - Rdata(), cname_(buffer) -{ - // we don't need rdata_len for parsing. if necessary, the caller will - // check consistency. -} - -/// \brief Constructor with a context of MasterLexer. -/// -/// The \c lexer should point to the beginning of valid textual -/// representation of a CNAME RDATA. The CNAME field can be -/// non-absolute if \c origin is non-NULL, in which case \c origin is -/// used to make it absolute. It must not be represented as a quoted -/// string. -/// -/// \throw MasterLexer::LexerError General parsing error such as missing field. -/// \throw Other Exceptions from the Name and RRTTL constructors if -/// construction of textual fields as these objects fail. -/// -/// \param lexer A \c MasterLexer object parsing a master file for the -/// RDATA to be created -/// \param origin If non NULL, specifies the origin of CNAME when it -/// is non-absolute. -CNAME::CNAME(MasterLexer& lexer, const Name* origin, - MasterLoader::Options, MasterLoaderCallbacks&) : - cname_(createNameFromLexer(lexer, origin)) -{} - -CNAME::CNAME(const CNAME& other) : - Rdata(), cname_(other.cname_) -{} - -CNAME::CNAME(const Name& cname) : - cname_(cname) -{} - -void -CNAME::toWire(OutputBuffer& buffer) const { - cname_.toWire(buffer); -} - -void -CNAME::toWire(AbstractMessageRenderer& renderer) const { - renderer.writeName(cname_); -} - -string -CNAME::toText() const { - return (cname_.toText()); -} - -int -CNAME::compare(const Rdata& other) const { - const CNAME& other_cname = dynamic_cast<const CNAME&>(other); - - return (compareNames(cname_, other_cname.cname_)); -} - -const Name& -CNAME::getCname() const { - return (cname_); -} - -} // end of namespace "generic" -} // end of namespace "rdata" -} // end of namespace "dns" -} // end of namespace "isc" -// Copyright (C) 2011-2024 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#include <config.h> - -#include <string> - -#include <util/buffer.h> -#include <util/encode/encode.h> - -#include <dns/messagerenderer.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> - -#include <dns/rdata/generic/detail/ds_like.h> - -using namespace std; -using namespace isc::util; -using namespace isc::util::encode; -using namespace isc::dns::rdata::generic::detail; - -namespace isc { -namespace dns { -namespace rdata { -namespace generic { - -/// \brief Constructor from string. -/// -/// A copy of the implementation object is allocated and constructed. -DLV::DLV(const std::string& ds_str) : - impl_(new DLVImpl(ds_str)) -{} - -/// \brief Constructor from wire-format data. -/// -/// A copy of the implementation object is allocated and constructed. -DLV::DLV(InputBuffer& buffer, size_t rdata_len) : - impl_(new DLVImpl(buffer, rdata_len)) -{} - -DLV::DLV(MasterLexer& lexer, const Name* origin, MasterLoader::Options options, - MasterLoaderCallbacks& callbacks) : - impl_(new DLVImpl(lexer, origin, options, callbacks)) -{} - -/// \brief Copy constructor -/// -/// A copy of the implementation object is allocated and constructed. -DLV::DLV(const DLV& source) : - Rdata(), impl_(new DLVImpl(*source.impl_)) -{} - -/// \brief Assignment operator -/// -/// PIMPL-induced logic -DLV& -DLV::operator=(const DLV& source) { - if (this == &source) { - return (*this); - } - - DLVImpl* newimpl = new DLVImpl(*source.impl_); - delete impl_; - impl_ = newimpl; - - return (*this); -} - -/// \brief Destructor -/// -/// Deallocates an internal resource. -DLV::~DLV() { - delete impl_; -} - -/// \brief Convert the \c DLV to a string. -/// -/// A pass-thru to the corresponding implementation method. -string -DLV::toText() const { - return (impl_->toText()); -} - -/// \brief Render the \c DLV in the wire format to a OutputBuffer object -/// -/// A pass-thru to the corresponding implementation method. -void -DLV::toWire(OutputBuffer& buffer) const { - impl_->toWire(buffer); -} - -/// \brief Render the \c DLV in the wire format to a AbstractMessageRenderer -/// object -/// -/// A pass-thru to the corresponding implementation method. -void -DLV::toWire(AbstractMessageRenderer& renderer) const { - impl_->toWire(renderer); -} - -/// \brief Compare two instances of \c DLV RDATA. -/// -/// The type check is performed here. Otherwise, a pass-thru to the -/// corresponding implementation method. -int -DLV::compare(const Rdata& other) const { - const DLV& other_ds = dynamic_cast<const DLV&>(other); - - return (impl_->compare(*other_ds.impl_)); -} - -/// \brief Tag accessor -uint16_t -DLV::getTag() const { - return (impl_->getTag()); -} - -} // end of namespace "generic" -} // end of namespace "rdata" -} // end of namespace "dns" -} // end of namespace "isc" -// Copyright (C) 2010-2024 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#include <config.h> - -#include <string> - -#include <util/buffer.h> -#include <dns/name.h> -#include <dns/messagerenderer.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> - -#include <dns/rdata/generic/detail/lexer_util.h> - -using namespace std; -using namespace isc::util; -using isc::dns::rdata::generic::detail::createNameFromLexer; - -namespace isc { -namespace dns { -namespace rdata { -namespace generic { - -/// \brief Constructor from string. -/// -/// The given string must represent a valid DNAME 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 TARGET must be absolute since there's no parameter that specifies -/// the origin name; if it is not absolute, \c MissingNameOrigin -/// exception will be thrown. These must not be represented as a quoted -/// string. -/// -/// \throw Others Exception from the Name and RRTTL constructors. -/// \throw InvalidRdataText Other general syntax errors. -DNAME::DNAME(const std::string& namestr) : - // Fill in dummy name and replace it soon below. - dname_(Name::ROOT_NAME()) -{ - try { - std::istringstream ss(namestr); - MasterLexer lexer; - lexer.pushSource(ss); - - dname_ = createNameFromLexer(lexer, NULL); - - if (lexer.getNextToken().getType() != MasterToken::END_OF_FILE) { - isc_throw(InvalidRdataText, "extra input text for DNAME: " - << namestr); - } - } catch (const MasterLexer::LexerError& ex) { - isc_throw(InvalidRdataText, "Failed to construct DNAME from '" << - namestr << "': " << ex.what()); - } -} - -DNAME::DNAME(InputBuffer& buffer, size_t) : - dname_(buffer) -{ - // we don't need rdata_len for parsing. if necessary, the caller will - // check consistency. -} - -/// \brief Constructor with a context of MasterLexer. -/// -/// The \c lexer should point to the beginning of valid textual -/// representation of a DNAME RDATA. The TARGET field can be -/// non-absolute if \c origin is non-NULL, in which case \c origin is -/// used to make it absolute. It must not be represented as a quoted -/// string. -/// -/// \throw MasterLexer::LexerError General parsing error such as missing field. -/// \throw Other Exceptions from the Name and RRTTL constructors if -/// construction of textual fields as these objects fail. -/// -/// \param lexer A \c MasterLexer object parsing a master file for the -/// RDATA to be created -/// \param origin If non NULL, specifies the origin of TARGET when it -/// is non-absolute. -DNAME::DNAME(MasterLexer& lexer, const Name* origin, - MasterLoader::Options, MasterLoaderCallbacks&) : - dname_(createNameFromLexer(lexer, origin)) -{} - -DNAME::DNAME(const DNAME& other) : - Rdata(), dname_(other.dname_) -{} - -DNAME::DNAME(const Name& dname) : - dname_(dname) -{} - -void -DNAME::toWire(OutputBuffer& buffer) const { - dname_.toWire(buffer); -} - -void -DNAME::toWire(AbstractMessageRenderer& renderer) const { - // Type DNAME is not "well-known", and name compression must be disabled - // per RFC3597. - renderer.writeName(dname_, false); -} - -string -DNAME::toText() const { - return (dname_.toText()); -} - -int -DNAME::compare(const Rdata& other) const { - const DNAME& other_dname = dynamic_cast<const DNAME&>(other); - - return (compareNames(dname_, other_dname.dname_)); -} - -const Name& -DNAME::getDname() const { - return (dname_); -} - -} // end of namespace "generic" -} // end of namespace "rdata" -} // end of namespace "dns" -} // end of namespace "isc" -// Copyright (C) 2010-2024 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#include <config.h> - -#include <iostream> -#include <string> -#include <sstream> -#include <vector> - -#include <boost/lexical_cast.hpp> - -#include <util/encode/encode.h> -#include <util/buffer.h> -#include <dns/messagerenderer.h> -#include <dns/name.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> - -#include <memory> - -#include <stdio.h> -#include <time.h> - -using namespace std; -using namespace isc::util; -using namespace isc::util::encode; - -namespace isc { -namespace dns { -namespace rdata { -namespace generic { - -struct DNSKEYImpl { - // straightforward representation of DNSKEY RDATA fields - DNSKEYImpl(uint16_t flags, uint8_t protocol, uint8_t algorithm, - const vector<uint8_t>& keydata) : - flags_(flags), protocol_(protocol), algorithm_(algorithm), - keydata_(keydata) - {} - - uint16_t flags_; - uint8_t protocol_; - uint8_t algorithm_; - const vector<uint8_t> keydata_; -}; - -/// \brief Constructor from string. -/// -/// The given string must represent a valid DNSKEY 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 Protocol and Algorithm fields must be within their valid -/// ranges. The Public Key field must be present and must contain a -/// Base64 encoding of the public key. Whitespace is allowed within the -/// Base64 text. -/// -/// It is okay for the key data to be missing. Note: BIND 9 also accepts -/// DNSKEY missing key data. While the RFC is silent in this case, and it -/// may be debatable what an implementation should do, but since this field -/// is algorithm dependent and this implementations doesn't reject unknown -/// algorithms, it's lenient here. -/// -/// \throw InvalidRdataText if any fields are out of their valid range, -/// or are incorrect. -/// -/// \param dnskey_str A string containing the RDATA to be created -DNSKEY::DNSKEY(const std::string& dnskey_str) : - impl_(NULL) -{ - // We use unique_ptr here because if there is an exception in this - // constructor, the destructor is not called and there could be a - // leak of the DNSKEYImpl that constructFromLexer() returns. - std::unique_ptr<DNSKEYImpl> impl_ptr; - - try { - std::istringstream ss(dnskey_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 DNSKEY: " << dnskey_str); - } - } catch (const MasterLexer::LexerError& ex) { - isc_throw(InvalidRdataText, - "Failed to construct DNSKEY from '" << dnskey_str << "': " - << ex.what()); - } - - impl_ = impl_ptr.release(); -} - -/// \brief Constructor from InputBuffer. -/// -/// The passed buffer must contain a valid DNSKEY RDATA. -/// -/// The Protocol and Algorithm fields are not checked for unknown -/// values. It is okay for the key data to be missing (see the description -/// of the constructor from string). -DNSKEY::DNSKEY(InputBuffer& buffer, size_t rdata_len) : - impl_(NULL) -{ - if (rdata_len < 4) { - isc_throw(InvalidRdataLength, "DNSKEY too short: " << rdata_len); - } - - const uint16_t flags = buffer.readUint16(); - const uint16_t protocol = buffer.readUint8(); - const uint16_t algorithm = buffer.readUint8(); - - rdata_len -= 4; - - vector<uint8_t> keydata; - // If key data is missing, it's OK. See the API documentation of the - // constructor. - if (rdata_len > 0) { - keydata.resize(rdata_len); - buffer.readData(&keydata[0], rdata_len); - } - - impl_ = new DNSKEYImpl(flags, protocol, algorithm, keydata); -} - -/// \brief Constructor with a context of MasterLexer. -/// -/// The \c lexer should point to the beginning of valid textual -/// representation of an DNSKEY RDATA. -/// -/// See \c DNSKEY::DNSKEY(const std::string&) for description of the -/// expected RDATA fields. -/// -/// \throw MasterLexer::LexerError General parsing error such as -/// missing field. -/// \throw InvalidRdataText if any fields are out of their valid range, -/// or are incorrect. -/// -/// \param lexer A \c MasterLexer object parsing a master file for the -/// RDATA to be created -DNSKEY::DNSKEY(MasterLexer& lexer, const Name*, - MasterLoader::Options, MasterLoaderCallbacks&) : - impl_(NULL) -{ - impl_ = constructFromLexer(lexer); -} - -DNSKEYImpl* -DNSKEY::constructFromLexer(MasterLexer& lexer) { - const uint32_t flags = lexer.getNextToken(MasterToken::NUMBER).getNumber(); - if (flags > 0xffff) { - isc_throw(InvalidRdataText, - "DNSKEY flags out of range: " << flags); - } - - const uint32_t protocol = - lexer.getNextToken(MasterToken::NUMBER).getNumber(); - if (protocol > 0xff) { - isc_throw(InvalidRdataText, - "DNSKEY protocol out of range: " << protocol); - } - - const uint32_t algorithm = - lexer.getNextToken(MasterToken::NUMBER).getNumber(); - if (algorithm > 0xff) { - isc_throw(InvalidRdataText, - "DNSKEY algorithm out of range: " << algorithm); - } - - std::string keydata_str; - std::string keydata_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 is now assured to be of type STRING. - - token.getString(keydata_substr); - keydata_str.append(keydata_substr); - } - - lexer.ungetToken(); - - vector<uint8_t> keydata; - // If key data is missing, it's OK. See the API documentation of the - // constructor. - if (keydata_str.size() > 0) { - decodeBase64(keydata_str, keydata); - } - - return (new DNSKEYImpl(flags, protocol, algorithm, keydata)); -} - -DNSKEY::DNSKEY(const DNSKEY& source) : - Rdata(), impl_(new DNSKEYImpl(*source.impl_)) -{} - -DNSKEY& -DNSKEY::operator=(const DNSKEY& source) { - if (this == &source) { - return (*this); - } - - DNSKEYImpl* newimpl = new DNSKEYImpl(*source.impl_); - delete impl_; - impl_ = newimpl; - - return (*this); -} - -DNSKEY::~DNSKEY() { - delete impl_; -} - -string -DNSKEY::toText() const { - return (boost::lexical_cast<string>(static_cast<int>(impl_->flags_)) + - " " + boost::lexical_cast<string>(static_cast<int>(impl_->protocol_)) + - " " + boost::lexical_cast<string>(static_cast<int>(impl_->algorithm_)) + - " " + encodeBase64(impl_->keydata_)); -} - -void -DNSKEY::toWire(OutputBuffer& buffer) const { - buffer.writeUint16(impl_->flags_); - buffer.writeUint8(impl_->protocol_); - buffer.writeUint8(impl_->algorithm_); - buffer.writeData(&impl_->keydata_[0], impl_->keydata_.size()); -} - -void -DNSKEY::toWire(AbstractMessageRenderer& renderer) const { - renderer.writeUint16(impl_->flags_); - renderer.writeUint8(impl_->protocol_); - renderer.writeUint8(impl_->algorithm_); - renderer.writeData(&impl_->keydata_[0], impl_->keydata_.size()); -} - -int -DNSKEY::compare(const Rdata& other) const { - const DNSKEY& other_dnskey = dynamic_cast<const DNSKEY&>(other); - - if (impl_->flags_ != other_dnskey.impl_->flags_) { - return (impl_->flags_ < other_dnskey.impl_->flags_ ? -1 : 1); - } - if (impl_->protocol_ != other_dnskey.impl_->protocol_) { - return (impl_->protocol_ < other_dnskey.impl_->protocol_ ? -1 : 1); - } - if (impl_->algorithm_ != other_dnskey.impl_->algorithm_) { - return (impl_->algorithm_ < other_dnskey.impl_->algorithm_ ? -1 : 1); - } - - const size_t this_len = impl_->keydata_.size(); - const size_t other_len = other_dnskey.impl_->keydata_.size(); - const size_t cmplen = min(this_len, other_len); - if (cmplen == 0) { - return ((this_len == other_len) ? 0 : (this_len < other_len) ? -1 : 1); - } - const int cmp = memcmp(&impl_->keydata_[0], - &other_dnskey.impl_->keydata_[0], cmplen); - if (cmp != 0) { - return (cmp); - } else { - return ((this_len == other_len) ? 0 : (this_len < other_len) ? -1 : 1); - } -} - -uint16_t -DNSKEY::getTag() const { - if (impl_->algorithm_ == 1) { - // See RFC 4034 appendix B.1 for why the key data must contain - // at least 4 bytes with RSA/MD5: 3 trailing bytes to extract - // the tag from, and 1 byte of exponent length subfield before - // modulus. - const int len = impl_->keydata_.size(); - if (len < 4) { - isc_throw(isc::OutOfRange, - "DNSKEY keydata too short for tag extraction"); - } - - return ((impl_->keydata_[len - 3] << 8) + impl_->keydata_[len - 2]); - } - - uint32_t ac = impl_->flags_; - ac += (impl_->protocol_ << 8); - ac += impl_->algorithm_; - - const size_t size = impl_->keydata_.size(); - for (size_t i = 0; i < size; i ++) { - ac += (i & 1) ? impl_->keydata_[i] : (impl_->keydata_[i] << 8); - } - ac += (ac >> 16) & 0xffff; - return (ac & 0xffff); -} - -uint16_t -DNSKEY::getFlags() const { - return (impl_->flags_); -} - -uint8_t -DNSKEY::getAlgorithm() const { - return (impl_->algorithm_); -} - -} // end of namespace "generic" -} // end of namespace "rdata" -} // end of namespace "dns" -} // end of namespace "isc" -// Copyright (C) 2011-2024 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#include <config.h> - -#include <string> - -#include <util/buffer.h> -#include <util/encode/encode.h> - -#include <dns/messagerenderer.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> - -#include <dns/rdata/generic/detail/ds_like.h> - -using namespace std; -using namespace isc::util; -using namespace isc::util::encode; -using namespace isc::dns::rdata::generic::detail; - -namespace isc { -namespace dns { -namespace rdata { -namespace generic { - -DS::DS(const std::string& ds_str) : - impl_(new DSImpl(ds_str)) -{} - -DS::DS(InputBuffer& buffer, size_t rdata_len) : - impl_(new DSImpl(buffer, rdata_len)) -{} - -DS::DS(MasterLexer& lexer, const Name* origin, MasterLoader::Options options, - MasterLoaderCallbacks& callbacks) : - impl_(new DSImpl(lexer, origin, options, callbacks)) -{} - -DS::DS(const DS& source) : - Rdata(), impl_(new DSImpl(*source.impl_)) -{} - -DS& -DS::operator=(const DS& source) { - if (this == &source) { - return (*this); - } - - DSImpl* newimpl = new DSImpl(*source.impl_); - delete impl_; - impl_ = newimpl; - - return (*this); -} - -DS::~DS() { - delete impl_; -} - -string -DS::toText() const { - return (impl_->toText()); -} - -void -DS::toWire(OutputBuffer& buffer) const { - impl_->toWire(buffer); -} - -void -DS::toWire(AbstractMessageRenderer& renderer) const { - impl_->toWire(renderer); -} - -int -DS::compare(const Rdata& other) const { - const DS& other_ds = dynamic_cast<const DS&>(other); - - return (impl_->compare(*other_ds.impl_)); -} - -uint16_t -DS::getTag() const { - return (impl_->getTag()); -} - -} // end of namespace "generic" -} // end of namespace "rdata" -} // end of namespace "dns" -} // end of namespace "isc" -// Copyright (C) 2011-2024 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#include <config.h> - -#include <exceptions/exceptions.h> -#include <dns/exceptions.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> -#include <dns/rdata/generic/detail/char_string.h> -#include <util/buffer.h> - -using namespace std; -using namespace isc::util; -using namespace isc::dns; - -namespace isc { -namespace dns { -namespace rdata { -namespace generic { - -class HINFOImpl { -public: - HINFOImpl(const std::string& hinfo_str) { - std::istringstream ss(hinfo_str); - MasterLexer lexer; - lexer.pushSource(ss); - - try { - parseHINFOData(lexer); - // Should be at end of data now - if (lexer.getNextToken(MasterToken::QSTRING, true).getType() != - MasterToken::END_OF_FILE) { - isc_throw(InvalidRdataText, - "Invalid HINFO text format: too many fields."); - } - } catch (const MasterLexer::LexerError& ex) { - isc_throw(InvalidRdataText, "Failed to construct HINFO RDATA from " - << hinfo_str << "': " << ex.what()); - } - } - - HINFOImpl(InputBuffer& buffer, size_t rdata_len) { - rdata_len -= detail::bufferToCharString(buffer, rdata_len, cpu); - rdata_len -= detail::bufferToCharString(buffer, rdata_len, os); - if (rdata_len != 0) { - isc_throw(isc::dns::DNSMessageFORMERR, "Error in parsing " << - "HINFO RDATA: bytes left at end: " << - static_cast<int>(rdata_len)); - } - } - - HINFOImpl(MasterLexer& lexer) - { - parseHINFOData(lexer); - } - -private: - void - parseHINFOData(MasterLexer& lexer) { - MasterToken token = lexer.getNextToken(MasterToken::QSTRING); - stringToCharString(token.getStringRegion(), cpu); - token = lexer.getNextToken(MasterToken::QSTRING); - stringToCharString(token.getStringRegion(), os); - } - -public: - detail::CharString cpu; - detail::CharString os; -}; - -HINFO::HINFO(const std::string& hinfo_str) : impl_(new HINFOImpl(hinfo_str)) -{} - - -HINFO::HINFO(InputBuffer& buffer, size_t rdata_len) : - impl_(new HINFOImpl(buffer, rdata_len)) -{} - -HINFO::HINFO(const HINFO& source): - Rdata(), impl_(new HINFOImpl(*source.impl_)) -{ -} - -HINFO::HINFO(MasterLexer& lexer, const Name*, - MasterLoader::Options, MasterLoaderCallbacks&) : - impl_(new HINFOImpl(lexer)) -{} - -HINFO& -HINFO::operator=(const HINFO& source) -{ - impl_.reset(new HINFOImpl(*source.impl_)); - return (*this); -} - -HINFO::~HINFO() { -} - -std::string -HINFO::toText() const { - string result; - result += "\""; - result += detail::charStringToString(impl_->cpu); - result += "\" \""; - result += detail::charStringToString(impl_->os); - result += "\""; - return (result); -} - -void -HINFO::toWire(OutputBuffer& buffer) const { - toWireHelper(buffer); -} - -void -HINFO::toWire(AbstractMessageRenderer& renderer) const { - toWireHelper(renderer); -} - -int -HINFO::compare(const Rdata& other) const { - const HINFO& other_hinfo = dynamic_cast<const HINFO&>(other); - - const int cmp = compareCharStrings(impl_->cpu, other_hinfo.impl_->cpu); - if (cmp != 0) { - return (cmp); - } - return (compareCharStrings(impl_->os, other_hinfo.impl_->os)); -} - -const std::string -HINFO::getCPU() const { - return (detail::charStringToString(impl_->cpu)); -} - -const std::string -HINFO::getOS() const { - return (detail::charStringToString(impl_->os)); -} - -template <typename T> -void -HINFO::toWireHelper(T& outputer) const { - outputer.writeData(&impl_->cpu[0], impl_->cpu.size()); - outputer.writeData(&impl_->os[0], impl_->os.size()); -} - -} // end of namespace "generic" -} // end of namespace "rdata" -} // end of namespace "dns" -} // end of namespace "isc" -// Copyright (C) 2011-2024 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#include <config.h> - -#include <string> -#include <sstream> - -#include <util/buffer.h> - -#include <dns/messagerenderer.h> -#include <dns/name.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> -#include <dns/rdata/generic/detail/lexer_util.h> - -using namespace std; -using namespace isc::dns; -using namespace isc::util; -using isc::dns::rdata::generic::detail::createNameFromLexer; - -namespace isc { -namespace dns { -namespace rdata { -namespace generic { - -/// \brief Constructor from string. -/// -/// \c minfo_str must be formatted as follows: -/// \code <rmailbox name> <emailbox name> -/// \endcode -/// where both fields must represent a valid domain name. -/// -/// An example of valid string is: -/// \code "rmail.example.com. email.example.com." \endcode -/// -/// \throw InvalidRdataText The number of RDATA fields (must be 2) is -/// incorrect. -/// \throw std::bad_alloc Memory allocation for names fails. -/// \throw Other The constructor of the \c Name class will throw if the -/// names in the string is invalid. -MINFO::MINFO(const std::string& minfo_str) : - // We cannot construct both names in the initialization list due to the - // necessary text processing, so we have to initialize them with a dummy - // name and replace them later. - rmailbox_(Name::ROOT_NAME()), emailbox_(Name::ROOT_NAME()) -{ - try { - std::istringstream ss(minfo_str); - MasterLexer lexer; - lexer.pushSource(ss); - - rmailbox_ = createNameFromLexer(lexer, NULL); - emailbox_ = createNameFromLexer(lexer, NULL); - - if (lexer.getNextToken().getType() != MasterToken::END_OF_FILE) { - isc_throw(InvalidRdataText, "extra input text for MINFO: " - << minfo_str); - } - } catch (const MasterLexer::LexerError& ex) { - isc_throw(InvalidRdataText, "Failed to construct MINFO from '" << - minfo_str << "': " << ex.what()); - } -} - -/// \brief Constructor with a context of MasterLexer. -/// -/// The \c lexer should point to the beginning of valid textual representation -/// of an MINFO RDATA. The RMAILBOX and EMAILBOX fields can be non-absolute -/// if \c origin is non-NULL, in which case \c origin is used to make them -/// absolute. -/// -/// \throw MasterLexer::LexerError General parsing error such as missing field. -/// \throw Other Exceptions from the Name and constructors if construction of -/// textual fields as these objects fail. -/// -/// \param lexer A \c MasterLexer object parsing a master file for the -/// RDATA to be created -/// \param origin If non NULL, specifies the origin of SERVER when it -/// is non-absolute. -MINFO::MINFO(MasterLexer& lexer, const Name* origin, - MasterLoader::Options, MasterLoaderCallbacks&) : - rmailbox_(createNameFromLexer(lexer, origin)), - emailbox_(createNameFromLexer(lexer, origin)) -{ -} - -/// \brief Constructor from wire-format data. -/// -/// This constructor doesn't check the validity of the second parameter (rdata -/// length) for parsing. -/// If necessary, the caller will check consistency. -/// -/// \throw std::bad_alloc Memory allocation for names fails. -/// \throw Other The constructor of the \c Name class will throw if the -/// names in the wire is invalid. -MINFO::MINFO(InputBuffer& buffer, size_t) : - rmailbox_(buffer), emailbox_(buffer) -{} - -/// \brief Copy constructor. -/// -/// \throw std::bad_alloc Memory allocation fails in copying internal -/// member variables (this should be very rare). -MINFO::MINFO(const MINFO& other) : - Rdata(), rmailbox_(other.rmailbox_), emailbox_(other.emailbox_) -{} - -/// \brief Convert the \c MINFO to a string. -/// -/// The output of this method is formatted as described in the "from string" -/// constructor (\c MINFO(const std::string&))). -/// -/// \throw std::bad_alloc Internal resource allocation fails. -/// -/// \return A \c string object that represents the \c MINFO object. -std::string -MINFO::toText() const { - return (rmailbox_.toText() + " " + emailbox_.toText()); -} - -/// \brief Render the \c MINFO in the wire format without name compression. -/// -/// \throw std::bad_alloc Internal resource allocation fails. -/// -/// \param buffer An output buffer to store the wire data. -void -MINFO::toWire(OutputBuffer& buffer) const { - rmailbox_.toWire(buffer); - emailbox_.toWire(buffer); -} - -MINFO& -MINFO::operator=(const MINFO& source) { - rmailbox_ = source.rmailbox_; - emailbox_ = source.emailbox_; - - return (*this); -} - -/// \brief Render the \c MINFO in the wire format with taking into account -/// compression. -/// -/// As specified in RFC3597, TYPE MINFO is "well-known", the rmailbox and -/// emailbox fields (domain names) will be compressed. -/// -/// \throw std::bad_alloc Internal resource allocation fails. -/// -/// \param renderer DNS message rendering context that encapsulates the -/// output buffer and name compression information. -void -MINFO::toWire(AbstractMessageRenderer& renderer) const { - renderer.writeName(rmailbox_); - renderer.writeName(emailbox_); -} - -/// \brief Compare two instances of \c MINFO RDATA. -/// -/// See documentation in \c Rdata. -int -MINFO::compare(const Rdata& other) const { - const MINFO& other_minfo = dynamic_cast<const MINFO&>(other); - - const int cmp = compareNames(rmailbox_, other_minfo.rmailbox_); - if (cmp != 0) { - return (cmp); - } - return (compareNames(emailbox_, other_minfo.emailbox_)); -} - -} // end of namespace "generic" -} // end of namespace "rdata" -} // end of namespace "dns" -} // end of namespace "isc" -// Copyright (C) 2010-2024 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#include <config.h> - -#include <string> - -#include <boost/lexical_cast.hpp> - -#include <exceptions/exceptions.h> - -#include <util/buffer.h> -#include <dns/name.h> -#include <dns/messagerenderer.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> - -#include <dns/rdata/generic/detail/lexer_util.h> - -using namespace std; -using boost::lexical_cast; -using namespace isc::util; -using isc::dns::rdata::generic::detail::createNameFromLexer; - -namespace isc { -namespace dns { -namespace rdata { -namespace generic { - -MX::MX(InputBuffer& buffer, size_t) : - preference_(buffer.readUint16()), mxname_(buffer) -{ - // we don't need rdata_len for parsing. if necessary, the caller will - // check consistency. -} - -/// \brief Constructor from string. -/// -/// The given string must represent a valid MX 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 EXCHANGE name must be absolute since there's no parameter that -/// specifies the origin name; if it is not absolute, \c MissingNameOrigin -/// exception will be thrown. It must not be represented as a quoted -/// string. -/// -/// See the construction that takes \c MasterLexer for other fields. -/// -/// \throw Others Exception from the Name and RRTTL constructors. -/// \throw InvalidRdataText Other general syntax errors. -MX::MX(const std::string& mx_str) : - // Fill in dummy name and replace them soon below. - preference_(0), mxname_(Name::ROOT_NAME()) -{ - try { - std::istringstream ss(mx_str); - MasterLexer lexer; - lexer.pushSource(ss); - - constructFromLexer(lexer, NULL); - - if (lexer.getNextToken().getType() != MasterToken::END_OF_FILE) { - isc_throw(InvalidRdataText, "extra input text for MX: " - << mx_str); - } - } catch (const MasterLexer::LexerError& ex) { - isc_throw(InvalidRdataText, "Failed to construct MX from '" << - mx_str << "': " << ex.what()); - } -} - -/// \brief Constructor with a context of MasterLexer. -/// -/// The \c lexer should point to the beginning of valid textual representation -/// of an MX RDATA. The EXCHANGE field can be non-absolute if \c origin -/// is non-NULL, in which case \c origin is used to make it absolute. -/// It must not be represented as a quoted string. -/// -/// The PREFERENCE field must be a valid decimal representation of an -/// unsigned 16-bit integer. -/// -/// \throw MasterLexer::LexerError General parsing error such as missing field. -/// \throw Other Exceptions from the Name and RRTTL constructors if -/// construction of textual fields as these objects fail. -/// -/// \param lexer A \c MasterLexer object parsing a master file for the -/// RDATA to be created -/// \param origin If non NULL, specifies the origin of EXCHANGE when it -/// is non-absolute. -MX::MX(MasterLexer& lexer, const Name* origin, - MasterLoader::Options, MasterLoaderCallbacks&) : - preference_(0), mxname_(Name::ROOT_NAME()) -{ - constructFromLexer(lexer, origin); -} - -void -MX::constructFromLexer(MasterLexer& lexer, const Name* origin) { - const uint32_t num = lexer.getNextToken(MasterToken::NUMBER).getNumber(); - if (num > 65535) { - isc_throw(InvalidRdataText, "Invalid MX preference: " << num); - } - preference_ = static_cast<uint16_t>(num); - - mxname_ = createNameFromLexer(lexer, origin); -} - -MX::MX(uint16_t preference, const Name& mxname) : - preference_(preference), mxname_(mxname) -{} - -MX::MX(const MX& other) : - Rdata(), preference_(other.preference_), mxname_(other.mxname_) -{} - -void -MX::toWire(OutputBuffer& buffer) const { - buffer.writeUint16(preference_); - mxname_.toWire(buffer); -} - -void -MX::toWire(AbstractMessageRenderer& renderer) const { - renderer.writeUint16(preference_); - renderer.writeName(mxname_); -} - -string -MX::toText() const { - return (lexical_cast<string>(preference_) + " " + mxname_.toText()); -} - -int -MX::compare(const Rdata& other) const { - const MX& other_mx = dynamic_cast<const MX&>(other); - - if (preference_ < other_mx.preference_) { - return (-1); - } else if (preference_ > other_mx.preference_) { - return (1); - } - - return (compareNames(mxname_, other_mx.mxname_)); -} - -const Name& -MX::getMXName() const { - return (mxname_); -} - -uint16_t -MX::getMXPref() const { - return (preference_); -} - -} // end of namespace "generic" -} // end of namespace "rdata" -} // end of namespace "dns" -} // end of namespace "isc" -// Copyright (C) 2011-2024 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#include <config.h> - -#include <dns/name.h> -#include <dns/messagerenderer.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> -#include <dns/rdata/generic/detail/char_string.h> -#include <exceptions/exceptions.h> - -#include <string> -#include <boost/lexical_cast.hpp> - -using namespace std; -using boost::lexical_cast; -using namespace isc::util; -using namespace isc::dns; - -namespace isc { -namespace dns { -namespace rdata { -namespace generic { - -class NAPTRImpl { -public: - NAPTRImpl() : order(0), preference(0), replacement(".") {} - - NAPTRImpl(InputBuffer& buffer, size_t rdata_len) : replacement(".") { - if (rdata_len < 4 || buffer.getLength() - buffer.getPosition() < 4) { - isc_throw(isc::dns::DNSMessageFORMERR, "Error in parsing " - "NAPTR RDATA wire format: insufficient length "); - } - order = buffer.readUint16(); - preference = buffer.readUint16(); - rdata_len -= 4; - - rdata_len -= detail::bufferToCharString(buffer, rdata_len, flags); - rdata_len -= detail::bufferToCharString(buffer, rdata_len, services); - rdata_len -= detail::bufferToCharString(buffer, rdata_len, regexp); - replacement = Name(buffer); - if (rdata_len < 1) { - isc_throw(isc::dns::DNSMessageFORMERR, "Error in parsing " - "NAPTR RDATA wire format: missing replacement name"); - } - rdata_len -= replacement.getLength(); - - if (rdata_len != 0) { - isc_throw(isc::dns::DNSMessageFORMERR, "Error in parsing " << - "NAPTR RDATA: bytes left at end: " << - static_cast<int>(rdata_len)); - } - } - - NAPTRImpl(const std::string& naptr_str) : replacement(".") { - std::istringstream ss(naptr_str); - MasterLexer lexer; - lexer.pushSource(ss); - - try { - parseNAPTRData(lexer); - // Should be at end of data now - if (lexer.getNextToken(MasterToken::QSTRING, true).getType() != - MasterToken::END_OF_FILE) { - isc_throw(InvalidRdataText, - "Invalid NAPTR text format: too many fields."); - } - } catch (const MasterLexer::LexerError& ex) { - isc_throw(InvalidRdataText, "Failed to construct NAPTR RDATA from " - << naptr_str << "': " << ex.what()); - } - } - - NAPTRImpl(MasterLexer& lexer) : replacement(".") - { - parseNAPTRData(lexer); - } - -private: - void - parseNAPTRData(MasterLexer& lexer) { - MasterToken token = lexer.getNextToken(MasterToken::NUMBER); - if (token.getNumber() > 65535) { - isc_throw(InvalidRdataText, - "Invalid NAPTR text format: order out of range: " - << token.getNumber()); - } - order = token.getNumber(); - token = lexer.getNextToken(MasterToken::NUMBER); - if (token.getNumber() > 65535) { - isc_throw(InvalidRdataText, - "Invalid NAPTR text format: preference out of range: " - << token.getNumber()); - } - preference = token.getNumber(); - - token = lexer.getNextToken(MasterToken::QSTRING); - stringToCharString(token.getStringRegion(), flags); - token = lexer.getNextToken(MasterToken::QSTRING); - stringToCharString(token.getStringRegion(), services); - token = lexer.getNextToken(MasterToken::QSTRING); - stringToCharString(token.getStringRegion(), regexp); - - token = lexer.getNextToken(MasterToken::STRING); - replacement = Name(token.getString()); - } - - -public: - uint16_t order; - uint16_t preference; - detail::CharString flags; - detail::CharString services; - detail::CharString regexp; - Name replacement; -}; - -NAPTR::NAPTR(InputBuffer& buffer, size_t rdata_len) : - impl_(new NAPTRImpl(buffer, rdata_len)) -{} - -NAPTR::NAPTR(const std::string& naptr_str) : impl_(new NAPTRImpl(naptr_str)) -{} - -NAPTR::NAPTR(MasterLexer& lexer, const Name*, - MasterLoader::Options, MasterLoaderCallbacks&) : - impl_(new NAPTRImpl(lexer)) -{} - -NAPTR::NAPTR(const NAPTR& naptr) : Rdata(), - impl_(new NAPTRImpl(*naptr.impl_)) -{} - -NAPTR& -NAPTR::operator=(const NAPTR& source) -{ - impl_.reset(new NAPTRImpl(*source.impl_)); - return (*this); -} - -NAPTR::~NAPTR() { -} - -void -NAPTR::toWire(OutputBuffer& buffer) const { - toWireHelper(buffer); - impl_->replacement.toWire(buffer); -} - -void -NAPTR::toWire(AbstractMessageRenderer& renderer) const { - toWireHelper(renderer); - // Type NAPTR is not "well-known", and name compression must be disabled - // per RFC3597. - renderer.writeName(impl_->replacement, false); -} - -string -NAPTR::toText() const { - string result; - result += lexical_cast<string>(impl_->order); - result += " "; - result += lexical_cast<string>(impl_->preference); - result += " \""; - result += detail::charStringToString(impl_->flags); - result += "\" \""; - result += detail::charStringToString(impl_->services); - result += "\" \""; - result += detail::charStringToString(impl_->regexp); - result += "\" "; - result += impl_->replacement.toText(); - return (result); -} - -int -NAPTR::compare(const Rdata& other) const { - const NAPTR other_naptr = dynamic_cast<const NAPTR&>(other); - - if (impl_->order < other_naptr.impl_->order) { - return (-1); - } else if (impl_->order > other_naptr.impl_->order) { - return (1); - } - - if (impl_->preference < other_naptr.impl_->preference) { - return (-1); - } else if (impl_->preference > other_naptr.impl_->preference) { - return (1); - } - - const int fcmp = detail::compareCharStrings(impl_->flags, - other_naptr.impl_->flags); - if (fcmp != 0) { - return (fcmp); - } - - const int scmp = detail::compareCharStrings(impl_->services, - other_naptr.impl_->services); - if (scmp != 0) { - return (scmp); - } - - const int rcmp = detail::compareCharStrings(impl_->regexp, - other_naptr.impl_->regexp); - if (rcmp != 0) { - return (rcmp); - } - - return (compareNames(impl_->replacement, other_naptr.impl_->replacement)); -} - -uint16_t -NAPTR::getOrder() const { - return (impl_->order); -} - -uint16_t -NAPTR::getPreference() const { - return (impl_->preference); -} - -const std::string -NAPTR::getFlags() const { - return (detail::charStringToString(impl_->flags)); -} - -const std::string -NAPTR::getServices() const { - return (detail::charStringToString(impl_->services)); -} - -const std::string -NAPTR::getRegexp() const { - return (detail::charStringToString(impl_->regexp)); -} - -const Name& -NAPTR::getReplacement() const { - return (impl_->replacement); -} - -template <typename T> -void -NAPTR::toWireHelper(T& outputer) const { - outputer.writeUint16(impl_->order); - outputer.writeUint16(impl_->preference); - - outputer.writeData(&impl_->flags[0], impl_->flags.size()); - outputer.writeData(&impl_->services[0], impl_->services.size()); - outputer.writeData(&impl_->regexp[0], impl_->regexp.size()); -} - -} // end of namespace "generic" -} // end of namespace "rdata" -} // end of namespace "dns" -} // end of namespace "isc" -// Copyright (C) 2010-2024 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#include <config.h> - -#include <string> - -#include <util/buffer.h> -#include <dns/name.h> -#include <dns/messagerenderer.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> - -#include <dns/rdata/generic/detail/lexer_util.h> - -using namespace std; -using namespace isc::util; -using isc::dns::rdata::generic::detail::createNameFromLexer; - -namespace isc { -namespace dns { -namespace rdata { -namespace generic { - -/// \brief Constructor from string. -/// -/// The given string must represent a valid NS 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 NSDNAME must be absolute since there's no parameter that -/// specifies the origin name; if it is not absolute, \c -/// MissingNameOrigin exception will be thrown. These must not be -/// represented as a quoted string. -/// -/// \throw Others Exception from the Name and RRTTL constructors. -/// \throw InvalidRdataText Other general syntax errors. -NS::NS(const std::string& namestr) : - // Fill in dummy name and replace them soon below. - nsname_(Name::ROOT_NAME()) -{ - try { - std::istringstream ss(namestr); - MasterLexer lexer; - lexer.pushSource(ss); - - nsname_ = createNameFromLexer(lexer, NULL); - - if (lexer.getNextToken().getType() != MasterToken::END_OF_FILE) { - isc_throw(InvalidRdataText, "extra input text for NS: " - << namestr); - } - } catch (const MasterLexer::LexerError& ex) { - isc_throw(InvalidRdataText, "Failed to construct NS from '" << - namestr << "': " << ex.what()); - } -} - -NS::NS(InputBuffer& buffer, size_t) : - nsname_(buffer) -{ - // we don't need rdata_len for parsing. if necessary, the caller will - // check consistency. -} - -/// \brief Constructor with a context of MasterLexer. -/// -/// The \c lexer should point to the beginning of valid textual -/// representation of an NS RDATA. The NSDNAME field can be -/// non-absolute if \c origin is non-NULL, in which case \c origin is -/// used to make it absolute. It must not be represented as a quoted -/// string. -/// -/// \throw MasterLexer::LexerError General parsing error such as missing field. -/// \throw Other Exceptions from the Name and RRTTL constructors if -/// construction of textual fields as these objects fail. -/// -/// \param lexer A \c MasterLexer object parsing a master file for the -/// RDATA to be created -/// \param origin If non NULL, specifies the origin of NSDNAME when it -/// is non-absolute. -NS::NS(MasterLexer& lexer, const Name* origin, - MasterLoader::Options, MasterLoaderCallbacks&) : - nsname_(createNameFromLexer(lexer, origin)) -{} - -NS::NS(const NS& other) : - Rdata(), nsname_(other.nsname_) -{} - -void -NS::toWire(OutputBuffer& buffer) const { - nsname_.toWire(buffer); -} - -void -NS::toWire(AbstractMessageRenderer& renderer) const { - renderer.writeName(nsname_); -} - -string -NS::toText() const { - return (nsname_.toText()); -} - -int -NS::compare(const Rdata& other) const { - const NS& other_ns = dynamic_cast<const NS&>(other); - - return (compareNames(nsname_, other_ns.nsname_)); -} - -const Name& -NS::getNSName() const { - return (nsname_); -} - -} // end of namespace "generic" -} // end of namespace "rdata" -} // end of namespace "dns" -} // end of namespace "isc" -// Copyright (C) 2010-2024 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#include <config.h> - -#include <iostream> -#include <iomanip> -#include <string> -#include <sstream> -#include <vector> -#include <cassert> - -#include <boost/lexical_cast.hpp> - -#include <util/encode/encode.h> -#include <util/buffer.h> - -#include <dns/exceptions.h> -#include <dns/messagerenderer.h> -#include <dns/name.h> -#include <dns/rrtype.h> -#include <dns/rrttl.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> -#include <dns/rdata/generic/detail/nsec_bitmap.h> -#include <dns/rdata/generic/detail/nsec3param_common.h> - -#include <memory> - -#include <stdio.h> -#include <time.h> - -using namespace std; -using namespace isc::dns::rdata::generic::detail::nsec; -using namespace isc::dns::rdata::generic::detail::nsec3; -using namespace isc::util::encode; -using namespace isc::util; - -namespace isc { -namespace dns { -namespace rdata { -namespace generic { - -struct NSEC3Impl { - // straightforward representation of NSEC3 RDATA fields - NSEC3Impl(uint8_t hashalg, uint8_t flags, uint16_t iterations, - vector<uint8_t>salt, vector<uint8_t>next, - vector<uint8_t> typebits) : - hashalg_(hashalg), flags_(flags), iterations_(iterations), - salt_(salt), next_(next), typebits_(typebits) - {} - - const uint8_t hashalg_; - const uint8_t flags_; - const uint16_t iterations_; - const vector<uint8_t> salt_; - const vector<uint8_t> next_; - const vector<uint8_t> typebits_; -}; - -/// \brief Constructor from string. -/// -/// The given string must represent a valid NSEC3 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 Hash Algorithm, Flags and Iterations fields must be within their -/// valid ranges. The Salt field may contain "-" to indicate that the -/// salt is of length 0. The Salt field must not contain any whitespace. -/// The type mnemonics must be valid, and separated by whitespace. If -/// any invalid mnemonics are found, InvalidRdataText exception is -/// thrown. -/// -/// \throw InvalidRdataText if any fields are out of their valid range, -/// or are incorrect. -/// -/// \param nsec3_str A string containing the RDATA to be created -NSEC3::NSEC3(const std::string& nsec3_str) : - impl_(NULL) -{ - // We use unique_ptr here because if there is an exception in this - // constructor, the destructor is not called and there could be a - // leak of the NSEC3Impl that constructFromLexer() returns. - std::unique_ptr<NSEC3Impl> impl_ptr; - - try { - std::istringstream ss(nsec3_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 NSEC3: " << nsec3_str); - } - } catch (const MasterLexer::LexerError& ex) { - isc_throw(InvalidRdataText, - "Failed to construct NSEC3 from '" << nsec3_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 NSEC3 RDATA. -/// -/// See \c NSEC3::NSEC3(const std::string&) for description of the -/// expected RDATA fields. -/// -/// \throw MasterLexer::LexerError General parsing error such as -/// missing field. -/// \throw InvalidRdataText if any fields are out of their valid range, -/// or are incorrect. -/// -/// \param lexer A \c MasterLexer object parsing a master file for the -/// RDATA to be created -NSEC3::NSEC3(MasterLexer& lexer, const Name*, MasterLoader::Options, - MasterLoaderCallbacks&) : - impl_(NULL) -{ - impl_ = constructFromLexer(lexer); -} - -NSEC3Impl* -NSEC3::constructFromLexer(MasterLexer& lexer) { - vector<uint8_t> salt; - const ParseNSEC3ParamResult params = - parseNSEC3ParamFromLexer("NSEC3", lexer, salt); - - const string& nexthash = - lexer.getNextToken(MasterToken::STRING).getString(); - if (*nexthash.rbegin() == '=') { - isc_throw(InvalidRdataText, "NSEC3 hash has padding: " << nexthash); - } - - vector<uint8_t> next; - decodeBase32Hex(nexthash, next); - if (next.size() > 255) { - isc_throw(InvalidRdataText, "NSEC3 hash is too long: " - << next.size() << " bytes"); - } - - vector<uint8_t> typebits; - // For NSEC3 empty bitmap is possible and allowed. - buildBitmapsFromLexer("NSEC3", lexer, typebits, true); - return (new NSEC3Impl(params.algorithm, params.flags, params.iterations, - salt, next, typebits)); -} - -NSEC3::NSEC3(InputBuffer& buffer, size_t rdata_len) : - impl_(NULL) -{ - vector<uint8_t> salt; - const ParseNSEC3ParamResult params = - parseNSEC3ParamWire("NSEC3", buffer, rdata_len, salt); - - if (rdata_len < 1) { - isc_throw(DNSMessageFORMERR, "NSEC3 too short to contain hash length, " - "length: " << rdata_len + salt.size() + 5); - } - const uint8_t nextlen = buffer.readUint8(); - --rdata_len; - if (nextlen == 0 || rdata_len < nextlen) { - isc_throw(DNSMessageFORMERR, "NSEC3 invalid hash length: " << - static_cast<unsigned int>(nextlen)); - } - - vector<uint8_t> next(nextlen); - buffer.readData(&next[0], nextlen); - rdata_len -= nextlen; - - vector<uint8_t> typebits(rdata_len); - if (rdata_len > 0) { - // Read and parse the bitmaps only when they exist; empty bitmap - // is possible for NSEC3. - buffer.readData(&typebits[0], rdata_len); - checkRRTypeBitmaps("NSEC3", typebits); - } - - impl_ = new NSEC3Impl(params.algorithm, params.flags, params.iterations, - salt, next, typebits); -} - -NSEC3::NSEC3(const NSEC3& source) : - Rdata(), impl_(new NSEC3Impl(*source.impl_)) -{} - -NSEC3& -NSEC3::operator=(const NSEC3& source) { - if (this == &source) { - return (*this); - } - - NSEC3Impl* newimpl = new NSEC3Impl(*source.impl_); - delete impl_; - impl_ = newimpl; - - return (*this); -} - -NSEC3::~NSEC3() { - delete impl_; -} - -string -NSEC3::toText() const { - ostringstream s; - bitmapsToText(impl_->typebits_, s); - - using boost::lexical_cast; - return (lexical_cast<string>(static_cast<int>(impl_->hashalg_)) + - " " + lexical_cast<string>(static_cast<int>(impl_->flags_)) + - " " + lexical_cast<string>(static_cast<int>(impl_->iterations_)) + - " " + (impl_->salt_.empty() ? "-" : encodeHex(impl_->salt_)) + - " " + encodeBase32Hex(impl_->next_) + s.str()); -} - -template <typename OUTPUT_TYPE> -void -toWireHelper(const NSEC3Impl& impl, OUTPUT_TYPE& output) { - output.writeUint8(impl.hashalg_); - output.writeUint8(impl.flags_); - output.writeUint16(impl.iterations_); - output.writeUint8(impl.salt_.size()); - if (!impl.salt_.empty()) { - output.writeData(&impl.salt_[0], impl.salt_.size()); - } - assert(!impl.next_.empty()); - output.writeUint8(impl.next_.size()); - output.writeData(&impl.next_[0], impl.next_.size()); - if (!impl.typebits_.empty()) { - output.writeData(&impl.typebits_[0], impl.typebits_.size()); - } -} - -void -NSEC3::toWire(OutputBuffer& buffer) const { - toWireHelper(*impl_, buffer); -} - -void -NSEC3::toWire(AbstractMessageRenderer& renderer) const { - toWireHelper(*impl_, renderer); -} - -namespace { -// This is a helper subroutine for compare(). It compares two binary -// data stored in vector<uint8_t> objects based on the "Canonical RR Ordering" -// as defined in Section 6.3 of RFC4034, that is, the data are treated -// "as a left-justified unsigned octet sequence in which the absence of an -// octet sorts before a zero octet." -// -// If check_length_first is true, it treats the compared data as if they -// began with a single-octet "length" field whose value is the size of the -// corresponding vector. In this case, if the sizes of the two vectors are -// different the shorter one is always considered the "smaller"; the contents -// of the vector don't matter. -// -// This function returns: -// -1 if v1 is considered smaller than v2 -// 1 if v1 is considered larger than v2 -// 0 otherwise -int -compareVectors(const vector<uint8_t>& v1, const vector<uint8_t>& v2, - bool check_length_first = true) -{ - const size_t len1 = v1.size(); - const size_t len2 = v2.size(); - if (check_length_first && len1 != len2) { - return (len1 - len2); - } - const size_t cmplen = min(len1, len2); - const int cmp = cmplen == 0 ? 0 : memcmp(&v1.at(0), &v2.at(0), cmplen); - if (cmp != 0) { - return (cmp); - } else { - return (len1 - len2); - } -} -} - -int -NSEC3::compare(const Rdata& other) const { - const NSEC3& other_nsec3 = dynamic_cast<const NSEC3&>(other); - - if (impl_->hashalg_ != other_nsec3.impl_->hashalg_) { - return (impl_->hashalg_ < other_nsec3.impl_->hashalg_ ? -1 : 1); - } - if (impl_->flags_ != other_nsec3.impl_->flags_) { - return (impl_->flags_ < other_nsec3.impl_->flags_ ? -1 : 1); - } - if (impl_->iterations_ != other_nsec3.impl_->iterations_) { - return (impl_->iterations_ < other_nsec3.impl_->iterations_ ? -1 : 1); - } - - int cmp = compareVectors(impl_->salt_, other_nsec3.impl_->salt_); - if (cmp != 0) { - return (cmp); - } - cmp = compareVectors(impl_->next_, other_nsec3.impl_->next_); - if (cmp != 0) { - return (cmp); - } - // Note that bitmap doesn't have a dedicated length field, so we shouldn't - // terminate the comparison just because the lengths are different. - return (compareVectors(impl_->typebits_, other_nsec3.impl_->typebits_, - false)); -} - -uint8_t -NSEC3::getHashalg() const { - return (impl_->hashalg_); -} - -uint8_t -NSEC3::getFlags() const { - return (impl_->flags_); -} - -uint16_t -NSEC3::getIterations() const { - return (impl_->iterations_); -} - -const vector<uint8_t>& -NSEC3::getSalt() const { - return (impl_->salt_); -} - -const vector<uint8_t>& -NSEC3::getNext() const { - return (impl_->next_); -} - -} // end of namespace "generic" -} // end of namespace "rdata" -} // end of namespace "dns" -} // end of namespace "isc" -// Copyright (C) 2010-2024 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#include <config.h> - -#include <util/buffer.h> -#include <util/encode/encode.h> - -#include <dns/messagerenderer.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> -#include <dns/rdata/generic/detail/nsec3param_common.h> - -#include <boost/lexical_cast.hpp> - -#include <memory> -#include <string> -#include <sstream> -#include <vector> - -using namespace std; -using namespace isc::util; -using namespace isc::util::encode; - -namespace isc { -namespace dns { -namespace rdata { -namespace generic { - -struct NSEC3PARAMImpl { - // straightforward representation of NSEC3PARAM RDATA fields - NSEC3PARAMImpl(uint8_t hashalg, uint8_t flags, uint16_t iterations, - const vector<uint8_t>& salt) : - hashalg_(hashalg), flags_(flags), iterations_(iterations), salt_(salt) - {} - - const uint8_t hashalg_; - const uint8_t flags_; - const uint16_t iterations_; - const vector<uint8_t> salt_; -}; - -/// \brief Constructor from string. -/// -/// The given string must represent a valid NSEC3PARAM 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 Hash Algorithm, Flags and Iterations fields must be within their -/// valid ranges. The Salt field may contain "-" to indicate that the -/// salt is of length 0. The Salt field must not contain any whitespace. -/// -/// \throw InvalidRdataText if any fields are out of their valid range, -/// or are incorrect. -/// -/// \param nsec3param_str A string containing the RDATA to be created -NSEC3PARAM::NSEC3PARAM(const std::string& nsec3param_str) : - impl_(NULL) -{ - // We use unique_ptr here because if there is an exception in this - // constructor, the destructor is not called and there could be a - // leak of the NSEC3PARAMImpl that constructFromLexer() returns. - std::unique_ptr<NSEC3PARAMImpl> impl_ptr; - - try { - std::istringstream ss(nsec3param_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 NSEC3PARAM: " << nsec3param_str); - } - } catch (const MasterLexer::LexerError& ex) { - isc_throw(InvalidRdataText, - "Failed to construct NSEC3PARAM from '" << nsec3param_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 NSEC3PARAM RDATA. -/// -/// See \c NSEC3PARAM::NSEC3PARAM(const std::string&) for description of -/// the expected RDATA fields. -/// -/// \throw MasterLexer::LexerError General parsing error such as -/// missing field. -/// \throw InvalidRdataText if any fields are out of their valid range, -/// or are incorrect. -/// -/// \param lexer A \c MasterLexer object parsing a master file for the -/// RDATA to be created -NSEC3PARAM::NSEC3PARAM(MasterLexer& lexer, const Name*, MasterLoader::Options, - MasterLoaderCallbacks&) : - impl_(NULL) -{ - impl_ = constructFromLexer(lexer); -} - -NSEC3PARAMImpl* -NSEC3PARAM::constructFromLexer(MasterLexer& lexer) { - vector<uint8_t> salt; - const ParseNSEC3ParamResult params = - parseNSEC3ParamFromLexer("NSEC3PARAM", lexer, salt); - - return (new NSEC3PARAMImpl(params.algorithm, params.flags, - params.iterations, salt)); -} - -NSEC3PARAM::NSEC3PARAM(InputBuffer& buffer, size_t rdata_len) : - impl_(NULL) -{ - vector<uint8_t> salt; - const ParseNSEC3ParamResult params = - parseNSEC3ParamWire("NSEC3PARAM", buffer, rdata_len, salt); - - impl_ = new NSEC3PARAMImpl(params.algorithm, params.flags, - params.iterations, salt); -} - -NSEC3PARAM::NSEC3PARAM(const NSEC3PARAM& source) : - Rdata(), impl_(new NSEC3PARAMImpl(*source.impl_)) -{} - -NSEC3PARAM& -NSEC3PARAM::operator=(const NSEC3PARAM& source) { - if (this == &source) { - return (*this); - } - - NSEC3PARAMImpl* newimpl = new NSEC3PARAMImpl(*source.impl_); - delete impl_; - impl_ = newimpl; - - return (*this); -} - -NSEC3PARAM::~NSEC3PARAM() { - delete impl_; -} - -string -NSEC3PARAM::toText() const { - using boost::lexical_cast; - return (lexical_cast<string>(static_cast<int>(impl_->hashalg_)) + - " " + lexical_cast<string>(static_cast<int>(impl_->flags_)) + - " " + lexical_cast<string>(static_cast<int>(impl_->iterations_)) + - " " + (impl_->salt_.empty() ? "-" : encodeHex(impl_->salt_))); -} - -template <typename OUTPUT_TYPE> -void -toWireHelper(const NSEC3PARAMImpl& impl, OUTPUT_TYPE& output) { - output.writeUint8(impl.hashalg_); - output.writeUint8(impl.flags_); - output.writeUint16(impl.iterations_); - output.writeUint8(impl.salt_.size()); - if (!impl.salt_.empty()) { - output.writeData(&impl.salt_[0], impl.salt_.size()); - } -} - -void -NSEC3PARAM::toWire(OutputBuffer& buffer) const { - toWireHelper(*impl_, buffer); -} - -void -NSEC3PARAM::toWire(AbstractMessageRenderer& renderer) const { - toWireHelper(*impl_, renderer); -} - -int -NSEC3PARAM::compare(const Rdata& other) const { - const NSEC3PARAM& other_param = dynamic_cast<const NSEC3PARAM&>(other); - - if (impl_->hashalg_ != other_param.impl_->hashalg_) { - return (impl_->hashalg_ < other_param.impl_->hashalg_ ? -1 : 1); - } - if (impl_->flags_ != other_param.impl_->flags_) { - return (impl_->flags_ < other_param.impl_->flags_ ? -1 : 1); - } - if (impl_->iterations_ != other_param.impl_->iterations_) { - return (impl_->iterations_ < other_param.impl_->iterations_ ? -1 : 1); - } - - const size_t this_len = impl_->salt_.size(); - const size_t other_len = other_param.impl_->salt_.size(); - if (this_len != other_len) { - return (this_len - other_len); - } - const size_t cmplen = min(this_len, other_len); - const int cmp = (cmplen == 0) ? 0 : - memcmp(&impl_->salt_.at(0), &other_param.impl_->salt_.at(0), cmplen); - if (cmp != 0) { - return (cmp); - } else { - return (this_len - other_len); - } -} - -uint8_t -NSEC3PARAM::getHashalg() const { - return (impl_->hashalg_); -} - -uint8_t -NSEC3PARAM::getFlags() const { - return (impl_->flags_); -} - -uint16_t -NSEC3PARAM::getIterations() const { - return (impl_->iterations_); -} - -const vector<uint8_t>& -NSEC3PARAM::getSalt() const { - return (impl_->salt_); -} - -} // end of namespace "generic" -} // end of namespace "rdata" -} // end of namespace "dns" -} // end of namespace "isc" -// Copyright (C) 2010-2024 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#include <config.h> - -#include <iostream> -#include <string> -#include <sstream> -#include <vector> - -#include <util/encode/encode.h> -#include <util/buffer.h> -#include <dns/exceptions.h> -#include <dns/messagerenderer.h> -#include <dns/name.h> -#include <dns/rrtype.h> -#include <dns/rrttl.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> -#include <dns/rdata/generic/detail/nsec_bitmap.h> -#include <dns/rdata/generic/detail/lexer_util.h> - -#include <stdio.h> -#include <time.h> - -using namespace std; -using namespace isc::util; -using namespace isc::util::encode; -using namespace isc::dns::rdata::generic::detail::nsec; -using isc::dns::rdata::generic::detail::createNameFromLexer; - -namespace isc { -namespace dns { -namespace rdata { -namespace generic { - -struct NSECImpl { - // straightforward representation of NSEC RDATA fields - NSECImpl(const Name& next, vector<uint8_t> typebits) : - nextname_(next), typebits_(typebits) - {} - - Name nextname_; - vector<uint8_t> typebits_; -}; - -/// \brief Constructor from string. -/// -/// The given string must represent a valid NSEC 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 Next Domain Name field must be absolute since there's no -/// parameter that specifies the origin name; if it is not absolute, -/// \c MissingNameOrigin exception will be thrown. This must not be -/// represented as a quoted string. -/// -/// The type mnemonics must be valid, and separated by whitespace. If -/// any invalid mnemonics are found, InvalidRdataText exception is -/// thrown. -/// -/// \throw MissingNameOrigin Thrown when the Next Domain Name is not absolute. -/// \throw InvalidRdataText if any fields are out of their valid range. -/// -/// \param nsec_str A string containing the RDATA to be created -NSEC::NSEC(const std::string& nsec_str) : - impl_(NULL) -{ - try { - std::istringstream ss(nsec_str); - MasterLexer lexer; - lexer.pushSource(ss); - - const Name origin_name(createNameFromLexer(lexer, NULL)); - - vector<uint8_t> typebits; - buildBitmapsFromLexer("NSEC", lexer, typebits); - - impl_ = new NSECImpl(origin_name, typebits); - - if (lexer.getNextToken().getType() != MasterToken::END_OF_FILE) { - isc_throw(InvalidRdataText, - "Extra input text for NSEC: " << nsec_str); - } - } catch (const MasterLexer::LexerError& ex) { - isc_throw(InvalidRdataText, - "Failed to construct NSEC from '" << nsec_str << "': " - << ex.what()); - } -} - -NSEC::NSEC(InputBuffer& buffer, size_t rdata_len) { - const size_t pos = buffer.getPosition(); - const Name nextname(buffer); - - // rdata_len must be sufficiently large to hold non empty bitmap. - if (rdata_len <= buffer.getPosition() - pos) { - isc_throw(DNSMessageFORMERR, - "NSEC RDATA from wire too short: " << rdata_len << "bytes"); - } - rdata_len -= (buffer.getPosition() - pos); - - vector<uint8_t> typebits(rdata_len); - buffer.readData(&typebits[0], rdata_len); - checkRRTypeBitmaps("NSEC", typebits); - - impl_ = new NSECImpl(nextname, typebits); -} - -/// \brief Constructor with a context of MasterLexer. -/// -/// The \c lexer should point to the beginning of valid textual -/// representation of an NSEC RDATA. -/// -/// The Next Domain Name field can be non-absolute if \c origin is -/// non-NULL, in which case \c origin is used to make it absolute. It -/// must not be represented as a quoted string. -/// -/// The type mnemonics must be valid, and separated by whitespace. If -/// any invalid mnemonics are found, InvalidRdataText exception is -/// thrown. -/// -/// \throw MasterLexer::LexerError General parsing error such as -/// missing field. -/// \throw MissingNameOrigin Thrown when the Next Domain Name is not -/// absolute and \c origin is NULL. -/// \throw InvalidRdataText if any fields are out of their valid range. -/// -/// \param lexer A \c MasterLexer object parsing a master file for the -/// RDATA to be created -/// \param origin The origin to use with a relative Next Domain Name -/// field -NSEC::NSEC(MasterLexer& lexer, const Name* origin, MasterLoader::Options, - MasterLoaderCallbacks&) -{ - const Name next_name(createNameFromLexer(lexer, origin)); - - vector<uint8_t> typebits; - buildBitmapsFromLexer("NSEC", lexer, typebits); - - impl_ = new NSECImpl(next_name, typebits); -} - -NSEC::NSEC(const NSEC& source) : - Rdata(), impl_(new NSECImpl(*source.impl_)) -{} - -NSEC& -NSEC::operator=(const NSEC& source) { - if (this == &source) { - return (*this); - } - - NSECImpl* newimpl = new NSECImpl(*source.impl_); - delete impl_; - impl_ = newimpl; - - return (*this); -} - -NSEC::~NSEC() { - delete impl_; -} - -string -NSEC::toText() const { - ostringstream s; - s << impl_->nextname_; - bitmapsToText(impl_->typebits_, s); - return (s.str()); -} - -void -NSEC::toWire(OutputBuffer& buffer) const { - impl_->nextname_.toWire(buffer); - buffer.writeData(&impl_->typebits_[0], impl_->typebits_.size()); -} - -void -NSEC::toWire(AbstractMessageRenderer& renderer) const { - // Type NSEC is not "well-known", and name compression must be disabled - // per RFC3597. - renderer.writeName(impl_->nextname_, false); - renderer.writeData(&impl_->typebits_[0], impl_->typebits_.size()); -} - -const Name& -NSEC::getNextName() const { - return (impl_->nextname_); -} - -int -NSEC::compare(const Rdata& other) const { - const NSEC& other_nsec = dynamic_cast<const NSEC&>(other); - - int cmp = compareNames(impl_->nextname_, other_nsec.impl_->nextname_); - if (cmp != 0) { - return (cmp); - } - - const size_t this_len = impl_->typebits_.size(); - const size_t other_len = other_nsec.impl_->typebits_.size(); - const size_t cmplen = min(this_len, other_len); - cmp = memcmp(&impl_->typebits_[0], &other_nsec.impl_->typebits_[0], - cmplen); - if (cmp != 0) { - return (cmp); - } else { - return ((this_len == other_len) ? 0 : (this_len < other_len) ? -1 : 1); - } -} - -} // end of namespace "generic" -} // end of namespace "rdata" -} // end of namespace "dns" -} // end of namespace "isc" -// Copyright (C) 2010-2024 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#include <config.h> - #include <util/buffer.h> #include <dns/messagerenderer.h> #include <dns/rdata.h> @@ -3659,8 +599,7 @@ namespace generic { OPT::PseudoRR::PseudoRR(uint16_t code, boost::shared_ptr<std::vector<uint8_t> >& data) : code_(code), - data_(data) -{ + data_(data) { } uint16_t @@ -3680,8 +619,8 @@ OPT::PseudoRR::getLength() const { struct OPTImpl { OPTImpl() : - rdlength_(0) - {} + rdlength_(0) { + } uint16_t rdlength_; std::vector<OPT::PseudoRR> pseudo_rrs_; @@ -3689,8 +628,7 @@ struct OPTImpl { /// \brief Default constructor. OPT::OPT() : - impl_(new OPTImpl()) -{ + impl_(new OPTImpl()) { } /// \brief Constructor from string. @@ -3699,8 +637,7 @@ OPT::OPT() : /// /// \throw InvalidRdataText OPT RR cannot be constructed from text. OPT::OPT(const std::string&) : - impl_(NULL) -{ + impl_(NULL) { isc_throw(InvalidRdataText, "OPT RR cannot be constructed from text"); } @@ -3711,15 +648,13 @@ OPT::OPT(const std::string&) : /// \throw InvalidRdataText OPT RR cannot be constructed from text. OPT::OPT(MasterLexer&, const Name*, MasterLoader::Options, MasterLoaderCallbacks&) : - impl_(NULL) -{ + impl_(NULL) { isc_throw(InvalidRdataText, "OPT RR cannot be constructed from text"); } OPT::OPT(InputBuffer& buffer, size_t rdata_len) : - impl_(NULL) -{ - std::unique_ptr<OPTImpl> impl_ptr(new OPTImpl()); + impl_(NULL) { + boost::shared_ptr<OPTImpl> impl_ptr(new OPTImpl()); while (true) { if (rdata_len == 0) { @@ -3737,8 +672,7 @@ OPT::OPT(InputBuffer& buffer, size_t rdata_len) : rdata_len -= 4; if (static_cast<uint16_t>(impl_ptr->rdlength_ + option_length) < - impl_ptr->rdlength_) - { + impl_ptr->rdlength_) { isc_throw(InvalidRdataText, "Option length " << option_length << " would overflow OPT RR RDLEN (currently " @@ -3757,12 +691,11 @@ OPT::OPT(InputBuffer& buffer, size_t rdata_len) : rdata_len -= option_length; } - impl_ = impl_ptr.release(); + impl_ = impl_ptr; } OPT::OPT(const OPT& other) : - Rdata(), impl_(new OPTImpl(*other.impl_)) -{ + Rdata(), impl_(new OPTImpl(*other.impl_)) { } OPT& @@ -3771,15 +704,12 @@ OPT::operator=(const OPT& source) { return (*this); } - OPTImpl* newimpl = new OPTImpl(*source.impl_); - delete impl_; - impl_ = newimpl; + impl_.reset(new OPTImpl(*source.impl_)); return (*this); } OPT::~OPT() { - delete impl_; } std::string @@ -3826,8 +756,7 @@ OPT::appendPseudoRR(uint16_t code, const uint8_t* data, uint16_t length) { // pseudo-RR length here, not the whole message length (which should // be checked and enforced elsewhere). if (static_cast<uint16_t>(impl_->rdlength_ + length) < - impl_->rdlength_) - { + impl_->rdlength_) { isc_throw(isc::InvalidParameter, "Option length " << length << " would overflow OPT RR RDLEN (currently " @@ -3852,6 +781,7 @@ OPT::getPseudoRRs() const { } // end of namespace "rdata" } // end of namespace "dns" } // end of namespace "isc" + // Copyright (C) 2010-2024 Internet Systems Consortium, Inc. ("ISC") // // This Source Code Form is subject to the terms of the Mozilla Public @@ -3895,8 +825,7 @@ namespace generic { /// \throw InvalidRdataText Other general syntax errors. PTR::PTR(const std::string& type_str) : // Fill in dummy name and replace them soon below. - ptr_name_(Name::ROOT_NAME()) -{ + ptr_name_(Name::ROOT_NAME()) { try { std::istringstream ss(type_str); MasterLexer lexer; @@ -3915,8 +844,7 @@ PTR::PTR(const std::string& type_str) : } PTR::PTR(InputBuffer& buffer, size_t) : - ptr_name_(buffer) -{ + ptr_name_(buffer) { // we don't need rdata_len for parsing. if necessary, the caller will // check consistency. } @@ -3939,12 +867,12 @@ PTR::PTR(InputBuffer& buffer, size_t) : /// is non-absolute. PTR::PTR(MasterLexer& lexer, const Name* origin, MasterLoader::Options, MasterLoaderCallbacks&) : - ptr_name_(createNameFromLexer(lexer, origin)) -{} + ptr_name_(createNameFromLexer(lexer, origin)) { +} PTR::PTR(const PTR& source) : - Rdata(), ptr_name_(source.ptr_name_) -{} + Rdata(), ptr_name_(source.ptr_name_) { +} std::string PTR::toText() const { @@ -3979,170 +907,7 @@ PTR::getPTRName() const { } // end of namespace "rdata" } // end of namespace "dns" } // end of namespace "isc" -// Copyright (C) 2011-2024 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#include <config.h> - -#include <string> -#include <sstream> - -#include <util/buffer.h> - -#include <dns/messagerenderer.h> -#include <dns/name.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> -#include <dns/rdata/generic/detail/lexer_util.h> -using namespace std; -using namespace isc::dns; -using namespace isc::util; -using isc::dns::rdata::generic::detail::createNameFromLexer; - -namespace isc { -namespace dns { -namespace rdata { -namespace generic { - -/// \brief Constructor from string. -/// -/// \c rp_str must be formatted as follows: -/// \code <mailbox name> <text name> -/// \endcode -/// where both fields must represent a valid domain name. -/// -/// \throw InvalidRdataText The number of RDATA fields (must be 2) is -/// incorrect. -/// \throw std::bad_alloc Memory allocation for names fails. -/// \throw Other The constructor of the \c Name class will throw if the -/// given name is invalid. -RP::RP(const std::string& rp_str) : - // We cannot construct both names in the initialization list due to the - // necessary text processing, so we have to initialize them with a dummy - // name and replace them later. - mailbox_(Name::ROOT_NAME()), text_(Name::ROOT_NAME()) -{ - try { - std::istringstream ss(rp_str); - MasterLexer lexer; - lexer.pushSource(ss); - - mailbox_ = createNameFromLexer(lexer, NULL); - text_ = createNameFromLexer(lexer, NULL); - - if (lexer.getNextToken().getType() != MasterToken::END_OF_FILE) { - isc_throw(InvalidRdataText, "extra input text for RP: " - << rp_str); - } - } catch (const MasterLexer::LexerError& ex) { - isc_throw(InvalidRdataText, "Failed to construct RP from '" << - rp_str << "': " << ex.what()); - } -} - -/// \brief Constructor with a context of MasterLexer. -/// -/// The \c lexer should point to the beginning of valid textual representation -/// of an RP RDATA. The MAILBOX and TEXT fields can be non-absolute if \c -/// origin is non-NULL, in which case \c origin is used to make them absolute. -/// -/// \throw MasterLexer::LexerError General parsing error such as missing field. -/// \throw Other Exceptions from the Name and constructors if construction of -/// textual fields as these objects fail. -/// -/// \param lexer A \c MasterLexer object parsing a master file for the -/// RDATA to be created -/// \param origin If non NULL, specifies the origin of SERVER when it -/// is non-absolute. -RP::RP(MasterLexer& lexer, const Name* origin, - MasterLoader::Options, MasterLoaderCallbacks&) : - mailbox_(createNameFromLexer(lexer, origin)), - text_(createNameFromLexer(lexer, origin)) -{ -} - -/// \brief Constructor from wire-format data. -/// -/// This constructor doesn't check the validity of the second parameter (rdata -/// length) for parsing. -/// If necessary, the caller will check consistency. -/// -/// \throw std::bad_alloc Memory allocation for names fails. -/// \throw Other The constructor of the \c Name class will throw if the -/// names in the wire is invalid. -RP::RP(InputBuffer& buffer, size_t) : mailbox_(buffer), text_(buffer) { -} - -/// \brief Copy constructor. -/// -/// \throw std::bad_alloc Memory allocation fails in copying internal -/// member variables (this should be very rare). -RP::RP(const RP& other) : - Rdata(), mailbox_(other.mailbox_), text_(other.text_) -{} - -/// \brief Convert the \c RP to a string. -/// -/// The output of this method is formatted as described in the "from string" -/// constructor (\c RP(const std::string&))). -/// -/// \throw std::bad_alloc Internal resource allocation fails. -/// -/// \return A \c string object that represents the \c RP object. -std::string -RP::toText() const { - return (mailbox_.toText() + " " + text_.toText()); -} - -/// \brief Render the \c RP in the wire format without name compression. -/// -/// \throw std::bad_alloc Internal resource allocation fails. -/// -/// \param buffer An output buffer to store the wire data. -void -RP::toWire(OutputBuffer& buffer) const { - mailbox_.toWire(buffer); - text_.toWire(buffer); -} - -/// \brief Render the \c RP in the wire format with taking into account -/// compression. -/// -// Type RP is not "well-known", and name compression must be disabled -// per RFC3597. -/// -/// \throw std::bad_alloc Internal resource allocation fails. -/// -/// \param renderer DNS message rendering context that encapsulates the -/// output buffer and name compression information. -void -RP::toWire(AbstractMessageRenderer& renderer) const { - renderer.writeName(mailbox_, false); - renderer.writeName(text_, false); -} - -/// \brief Compare two instances of \c RP RDATA. -/// -/// See documentation in \c Rdata. -int -RP::compare(const Rdata& other) const { - const RP& other_rp = dynamic_cast<const RP&>(other); - - const int cmp = compareNames(mailbox_, other_rp.mailbox_); - if (cmp != 0) { - return (cmp); - } - return (compareNames(text_, other_rp.text_)); -} - -} // end of namespace "generic" -} // end of namespace "rdata" -} // end of namespace "dns" -} // end of namespace "isc" // Copyright (C) 2010-2024 Internet Systems Consortium, Inc. ("ISC") // // This Source Code Form is subject to the terms of the Mozilla Public @@ -4200,8 +965,8 @@ struct RRSIGImpl { covered_(covered), algorithm_(algorithm), labels_(labels), originalttl_(originalttl), timeexpire_(timeexpire), timeinception_(timeinception), tag_(tag), signer_(signer), - signature_(signature) - {} + signature_(signature) { + } const RRType covered_; uint8_t algorithm_; @@ -4215,7 +980,7 @@ struct RRSIGImpl { }; // helper function for string and lexer constructors -RRSIGImpl* +boost::shared_ptr<RRSIGImpl> RRSIG::constructFromLexer(MasterLexer& lexer, const Name* origin) { const RRType covered(lexer.getNextToken(MasterToken::STRING).getString()); const uint32_t algorithm = @@ -4262,9 +1027,9 @@ RRSIG::constructFromLexer(MasterLexer& lexer, const Name* origin) { decodeBase64(signature_txt, signature); } - return (new RRSIGImpl(covered, algorithm, labels, - originalttl, timeexpire, timeinception, - static_cast<uint16_t>(tag), signer, signature)); + return (boost::shared_ptr<RRSIGImpl>(new RRSIGImpl(covered, algorithm, labels, + originalttl, timeexpire, timeinception, + static_cast<uint16_t>(tag), signer, signature))); } /// \brief Constructor from string. @@ -4284,19 +1049,18 @@ RRSIG::constructFromLexer(MasterLexer& lexer, const Name* origin) { /// \throw Others Exception from the Name constructor. /// \throw InvalidRdataText Other general syntax errors. RRSIG::RRSIG(const std::string& rrsig_str) : - impl_(NULL) -{ + impl_(NULL) { // We use unique_ptr here because if there is an exception in this // constructor, the destructor is not called and there could be a // leak of the RRSIGImpl that constructFromLexer() returns. - std::unique_ptr<RRSIGImpl> impl_ptr; + boost::shared_ptr<RRSIGImpl> impl_ptr; try { std::istringstream iss(rrsig_str); MasterLexer lexer; lexer.pushSource(iss); - impl_ptr.reset(constructFromLexer(lexer, NULL)); + impl_ptr = constructFromLexer(lexer, NULL); if (lexer.getNextToken().getType() != MasterToken::END_OF_FILE) { isc_throw(InvalidRdataText, "extra input text for RRSIG: " @@ -4307,7 +1071,7 @@ RRSIG::RRSIG(const std::string& rrsig_str) : rrsig_str << "': " << ex.what()); } - impl_ = impl_ptr.release(); + impl_ = impl_ptr; } /// \brief Constructor with a context of MasterLexer. @@ -4330,9 +1094,8 @@ RRSIG::RRSIG(const std::string& rrsig_str) : /// \param origin If non NULL, specifies the origin of Signer's Name when /// it is non absolute. RRSIG::RRSIG(MasterLexer& lexer, const Name* origin, - MasterLoader::Options, MasterLoaderCallbacks&) : - impl_(constructFromLexer(lexer, origin)) -{ + MasterLoader::Options, MasterLoaderCallbacks&) { + impl_ = constructFromLexer(lexer, origin); } RRSIG::RRSIG(InputBuffer& buffer, size_t rdata_len) { @@ -4360,14 +1123,14 @@ RRSIG::RRSIG(InputBuffer& buffer, size_t rdata_len) { vector<uint8_t> signature(rdata_len); buffer.readData(&signature[0], rdata_len); - impl_ = new RRSIGImpl(covered, algorithm, labels, - originalttl, timeexpire, timeinception, tag, - signer, signature); + impl_.reset(new RRSIGImpl(covered, algorithm, labels, + originalttl, timeexpire, timeinception, tag, + signer, signature)); } RRSIG::RRSIG(const RRSIG& source) : - Rdata(), impl_(new RRSIGImpl(*source.impl_)) -{} + Rdata(), impl_(new RRSIGImpl(*source.impl_)) { +} RRSIG& RRSIG::operator=(const RRSIG& source) { @@ -4375,15 +1138,12 @@ RRSIG::operator=(const RRSIG& source) { return (*this); } - RRSIGImpl* newimpl = new RRSIGImpl(*source.impl_); - delete impl_; - impl_ = newimpl; + impl_.reset(new RRSIGImpl(*source.impl_)); return (*this); } RRSIG::~RRSIG() { - delete impl_; } string @@ -4481,6 +1241,7 @@ RRSIG::typeCovered() const { } // end of namespace "rdata" } // end of namespace "dns" } // end of namespace "isc" + // Copyright (C) 2010-2024 Internet Systems Consortium, Inc. ("ISC") // // This Source Code Form is subject to the terms of the Mozilla Public @@ -4519,8 +1280,7 @@ namespace rdata { namespace generic { SOA::SOA(InputBuffer& buffer, size_t) : - mname_(buffer), rname_(buffer) -{ + mname_(buffer), rname_(buffer) { // we don't need rdata_len for parsing. if necessary, the caller will // check consistency. buffer.readData(numdata_, sizeof(numdata_)); @@ -4559,8 +1319,7 @@ fillParameters(MasterLexer& lexer, uint8_t numdata[20]) { /// \throw InvalidRdataText Other general syntax errors. SOA::SOA(const std::string& soastr) : // Fill in dummy name and replace them soon below. - mname_(Name::ROOT_NAME()), rname_(Name::ROOT_NAME()) -{ + mname_(Name::ROOT_NAME()), rname_(Name::ROOT_NAME()) { try { std::istringstream ss(soastr); MasterLexer lexer; @@ -4602,15 +1361,13 @@ SOA::SOA(const std::string& soastr) : SOA::SOA(MasterLexer& lexer, const Name* origin, MasterLoader::Options, MasterLoaderCallbacks&) : mname_(createNameFromLexer(lexer, origin)), - rname_(createNameFromLexer(lexer, origin)) -{ + rname_(createNameFromLexer(lexer, origin)) { fillParameters(lexer, numdata_); } SOA::SOA(const Name& mname, const Name& rname, uint32_t serial, uint32_t refresh, uint32_t retry, uint32_t expire, uint32_t minimum) : - mname_(mname), rname_(rname) -{ + mname_(mname), rname_(rname) { OutputBuffer b(20); b.writeUint32(serial); b.writeUint32(refresh); @@ -4622,8 +1379,7 @@ SOA::SOA(const Name& mname, const Name& rname, uint32_t serial, } SOA::SOA(const SOA& other) : - Rdata(), mname_(other.mname_), rname_(other.rname_) -{ + Rdata(), mname_(other.mname_), rname_(other.rname_) { memcpy(numdata_, other.numdata_, sizeof(numdata_)); } @@ -4695,451 +1451,7 @@ SOA::compare(const Rdata& other) const { } // end of namespace "rdata" } // end of namespace "dns" } // end of namespace "isc" -// Copyright (C) 2010-2024 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#include <config.h> - -#include <stdint.h> -#include <string.h> - -#include <string> -#include <vector> - -#include <util/buffer.h> -#include <dns/exceptions.h> -#include <dns/messagerenderer.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> - -/// This class implements the basic interfaces inherited from the abstract -/// \c rdata::Rdata class. The semantics of the class is provided by -/// a copy of instantiated TXTLikeImpl class common to both TXT and SPF. -#include <dns/rdata/generic/detail/txt_like.h> - -using namespace std; -using namespace isc::util; - -namespace isc { -namespace dns { -namespace rdata { -namespace generic { - -/// \brief The assignment operator -/// -/// It internally allocates a resource, and if it fails a corresponding -/// standard exception will be thrown. -/// This method never throws an exception otherwise. -SPF& -SPF::operator=(const SPF& source) { - if (this == &source) { - return (*this); - } - - SPFImpl* newimpl = new SPFImpl(*source.impl_); - delete impl_; - impl_ = newimpl; - - return (*this); -} - -/// \brief The destructor -SPF::~SPF() { - delete impl_; -} - -/// \brief Constructor from wire-format data. -/// -/// It internally allocates a resource, and if it fails a corresponding -/// standard exception will be thrown. -SPF::SPF(InputBuffer& buffer, size_t rdata_len) : - impl_(new SPFImpl(buffer, rdata_len)) -{} - -/// \brief Constructor using the master lexer. -/// -/// This implementation only uses the \c lexer parameters; others are -/// ignored. -/// -/// \throw CharStringTooLong the parameter string length exceeds maximum. -/// \throw InvalidRdataText the method cannot process the parameter data -/// -/// \param lexer A \c MasterLexer object parsing a master file for this -/// RDATA. -SPF::SPF(MasterLexer& lexer, const Name*, MasterLoader::Options, - MasterLoaderCallbacks&) : - impl_(new SPFImpl(lexer)) -{} - -/// \brief Constructor from string. -/// -/// It internally allocates a resource, and if it fails a corresponding -/// standard exception will be thrown. -SPF::SPF(const std::string& txtstr) : - impl_(new SPFImpl(txtstr)) -{} - -/// \brief Copy constructor -/// -/// It internally allocates a resource, and if it fails a corresponding -/// standard exception will be thrown. -SPF::SPF(const SPF& other) : - Rdata(), impl_(new SPFImpl(*other.impl_)) -{} - -/// \brief Render the \c SPF in the wire format to a OutputBuffer object -/// -/// \return is the return of the corresponding implementation method. -void -SPF::toWire(OutputBuffer& buffer) const { - impl_->toWire(buffer); -} - -/// \brief Render the \c SPF in the wire format to an AbstractMessageRenderer -/// object -/// -/// \return is the return of the corresponding implementation method. -void -SPF::toWire(AbstractMessageRenderer& renderer) const { - impl_->toWire(renderer); -} - -/// \brief Convert the \c SPF to a string. -/// -/// \return is the return of the corresponding implementation method. -string -SPF::toText() const { - return (impl_->toText()); -} - -/// \brief Compare two instances of \c SPF RDATA. -/// -/// This method compares \c this and the \c other \c SPF objects. -/// -/// This method is expected to be used in a polymorphic way, and the -/// parameter to compare against is therefore of the abstract \c Rdata class. -/// However, comparing two \c Rdata objects of different RR types -/// is meaningless, and \c other must point to a \c SPF object; -/// otherwise, the standard \c bad_cast exception will be thrown. -/// -/// \param other the right-hand operand to compare against. -/// \return is the return of the corresponding implementation method. -int -SPF::compare(const Rdata& other) const { - const SPF& other_txt = dynamic_cast<const SPF&>(other); - - return (impl_->compare(*other_txt.impl_)); -} - -} // end of namespace "generic" -} // end of namespace "rdata" -} // end of namespace "dns" -} // end of namespace "isc" -// Copyright (C) 2012-2024 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#include <config.h> - -#include <boost/lexical_cast.hpp> - -#include <exceptions/exceptions.h> - -#include <util/buffer.h> -#include <util/encode/encode.h> -#include <dns/name.h> -#include <dns/messagerenderer.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> - -using namespace std; -using boost::lexical_cast; -using namespace isc::util; -using namespace isc::util::encode; - -namespace isc { -namespace dns { -namespace rdata { -namespace generic { - -struct SSHFPImpl { - // straightforward representation of SSHFP RDATA fields - SSHFPImpl(uint8_t algorithm, uint8_t fingerprint_type, - const vector<uint8_t>& fingerprint) : - algorithm_(algorithm), - fingerprint_type_(fingerprint_type), - fingerprint_(fingerprint) - {} - - uint8_t algorithm_; - uint8_t fingerprint_type_; - const vector<uint8_t> fingerprint_; -}; - -// helper function for string and lexer constructors -SSHFPImpl* -SSHFP::constructFromLexer(MasterLexer& lexer) { - const uint32_t algorithm = - lexer.getNextToken(MasterToken::NUMBER).getNumber(); - if (algorithm > 255) { - isc_throw(InvalidRdataText, "SSHFP algorithm number out of range"); - } - - const uint32_t fingerprint_type = - lexer.getNextToken(MasterToken::NUMBER).getNumber(); - if (fingerprint_type > 255) { - isc_throw(InvalidRdataText, "SSHFP fingerprint type out of range"); - } - - std::string fingerprint_str; - std::string fingerprint_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(fingerprint_substr); - fingerprint_str.append(fingerprint_substr); - } - lexer.ungetToken(); - - vector<uint8_t> fingerprint; - // If fingerprint is missing, it's OK. See the API documentation of the - // constructor. - if (fingerprint_str.size() > 0) { - 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)); -} - -/// \brief Constructor from string. -/// -/// The given string must represent a valid SSHFP 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 Algorithm and Fingerprint Type fields must be within their valid -/// ranges, but are not constrained to the values defined in RFC4255. -/// -/// The Fingerprint field may be absent, but if present it must contain a -/// 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, 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) : - impl_(NULL) -{ - // We use unique_ptr here because if there is an exception in this - // constructor, the destructor is not called and there could be a - // leak of the SSHFPImpl that constructFromLexer() returns. - std::unique_ptr<SSHFPImpl> impl_ptr; - - try { - std::istringstream ss(sshfp_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 SSHFP: " - << sshfp_str); - } - } catch (const MasterLexer::LexerError& ex) { - isc_throw(InvalidRdataText, "Failed to construct SSHFP from '" << - sshfp_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 SSHFP RDATA. -/// -/// \throw MasterLexer::LexerError General parsing error such as missing field. -/// \throw InvalidRdataText Fields are out of their valid range or are -/// incorrect, or if the fingerprint is not a valid hex string. -/// -/// \param lexer A \c MasterLexer object parsing a master file for the -/// RDATA to be created -SSHFP::SSHFP(MasterLexer& lexer, const Name*, - MasterLoader::Options, MasterLoaderCallbacks&) : - impl_(constructFromLexer(lexer)) -{ -} - -/// \brief Constructor from InputBuffer. -/// -/// The passed buffer must contain a valid SSHFP RDATA. -/// -/// The Algorithm and Fingerprint Type fields are not checked for unknown -/// values. It is okay for the fingerprint data to be missing (see the -/// description of the constructor from string). -SSHFP::SSHFP(InputBuffer& buffer, size_t rdata_len) { - if (rdata_len < 2) { - isc_throw(InvalidRdataLength, "SSHFP record too short"); - } - - const uint8_t algorithm = buffer.readUint8(); - const uint8_t fingerprint_type = buffer.readUint8(); - - vector<uint8_t> fingerprint; - rdata_len -= 2; - if (rdata_len > 0) { - fingerprint.resize(rdata_len); - buffer.readData(&fingerprint[0], rdata_len); - } - - impl_ = new SSHFPImpl(algorithm, fingerprint_type, fingerprint); -} - -SSHFP::SSHFP(uint8_t algorithm, uint8_t fingerprint_type, - const string& fingerprint_txt) : - impl_(NULL) -{ - vector<uint8_t> fingerprint; - try { - decodeHex(fingerprint_txt, fingerprint); - } catch (const isc::BadValue& e) { - isc_throw(InvalidRdataText, "Bad SSHFP fingerprint: " << e.what()); - } - - impl_ = new SSHFPImpl(algorithm, fingerprint_type, fingerprint); -} - -SSHFP::SSHFP(const SSHFP& other) : - Rdata(), impl_(new SSHFPImpl(*other.impl_)) -{} - -SSHFP& -SSHFP::operator=(const SSHFP& source) { - if (this == &source) { - return (*this); - } - - SSHFPImpl* newimpl = new SSHFPImpl(*source.impl_); - delete impl_; - impl_ = newimpl; - - return (*this); -} - -SSHFP::~SSHFP() { - delete impl_; -} - -void -SSHFP::toWire(OutputBuffer& buffer) const { - buffer.writeUint8(impl_->algorithm_); - buffer.writeUint8(impl_->fingerprint_type_); - - if (!impl_->fingerprint_.empty()) { - buffer.writeData(&impl_->fingerprint_[0], - impl_->fingerprint_.size()); - } -} - -void -SSHFP::toWire(AbstractMessageRenderer& renderer) const { - renderer.writeUint8(impl_->algorithm_); - renderer.writeUint8(impl_->fingerprint_type_); - - if (!impl_->fingerprint_.empty()) { - renderer.writeData(&impl_->fingerprint_[0], - impl_->fingerprint_.size()); - } -} - -string -SSHFP::toText() const { - return (lexical_cast<string>(static_cast<int>(impl_->algorithm_)) + " " + - lexical_cast<string>(static_cast<int>(impl_->fingerprint_type_)) + - (impl_->fingerprint_.empty() ? "" : - " " + encodeHex(impl_->fingerprint_))); -} - -int -SSHFP::compare(const Rdata& other) const { - const SSHFP& other_sshfp = dynamic_cast<const SSHFP&>(other); - - if (impl_->algorithm_ < other_sshfp.impl_->algorithm_) { - return (-1); - } else if (impl_->algorithm_ > other_sshfp.impl_->algorithm_) { - return (1); - } - - if (impl_->fingerprint_type_ < other_sshfp.impl_->fingerprint_type_) { - return (-1); - } else if (impl_->fingerprint_type_ > - other_sshfp.impl_->fingerprint_type_) { - return (1); - } - - const size_t this_len = impl_->fingerprint_.size(); - const size_t other_len = other_sshfp.impl_->fingerprint_.size(); - const size_t cmplen = min(this_len, other_len); - - if (cmplen > 0) { - const int cmp = memcmp(&impl_->fingerprint_[0], - &other_sshfp.impl_->fingerprint_[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 -SSHFP::getAlgorithmNumber() const { - return (impl_->algorithm_); -} - -uint8_t -SSHFP::getFingerprintType() const { - return (impl_->fingerprint_type_); -} - -const std::vector<uint8_t>& -SSHFP::getFingerprint() const { - return (impl_->fingerprint_); -} - -size_t -SSHFP::getFingerprintLength() const { - return (impl_->fingerprint_.size()); -} - -} // end of namespace "generic" -} // end of namespace "rdata" -} // end of namespace "dns" -} // end of namespace "isc" // Copyright (C) 2021-2024 Internet Systems Consortium, Inc. ("ISC") // // This Source Code Form is subject to the terms of the Mozilla Public @@ -5158,6 +1470,7 @@ SSHFP::getFingerprintLength() const { #include <util/encode/encode.h> #include <util/time_utilities.h> +#include <dns/tsigerror.h> #include <dns/messagerenderer.h> #include <dns/name.h> #include <dns/rdata.h> @@ -5194,8 +1507,8 @@ struct TKEYImpl { uint16_t mode, uint16_t error, vector<uint8_t>& key, vector<uint8_t>& other_data) : algorithm_(algorithm), inception_(inception), expire_(expire), - mode_(mode), error_(error), key_(key), other_data_(other_data) - {} + mode_(mode), error_(error), key_(key), other_data_(other_data) { + } /// \brief Constructor from RDATA field parameters. /// @@ -5221,8 +1534,8 @@ struct TKEYImpl { vector<uint8_t>(static_cast<const uint8_t*>(other_data), static_cast<const uint8_t*>(other_data) + other_len) : - vector<uint8_t>(other_len)) - {} + vector<uint8_t>(other_len)) { + } /// \brief Common part of toWire methods. /// \tparam Output \c OutputBuffer or \c AbstractMessageRenderer. @@ -5252,7 +1565,7 @@ struct TKEYImpl { }; // helper function for string and lexer constructors -TKEYImpl* +boost::shared_ptr<TKEYImpl> TKEY::constructFromLexer(MasterLexer& lexer, const Name* origin) { const Name& algorithm = createNameFromLexer(lexer, origin ? origin : &Name::ROOT_NAME()); @@ -5347,8 +1660,9 @@ TKEY::constructFromLexer(MasterLexer& lexer, const Name* origin) { // RFC2845 says Other Data is "empty unless Error == BADTIME". // However, we don't enforce that. - return (new TKEYImpl(algorithm, inception, expire, mode, error, - key_data, other_data)); + return (boost::shared_ptr<TKEYImpl>(new TKEYImpl(algorithm, inception, + expire, mode, error, + key_data, other_data))); } /// \brief Constructor from string. @@ -5407,14 +1721,14 @@ TKEY::TKEY(const std::string& tkey_str) : impl_(0) { // We use unique_ptr here because if there is an exception in this // constructor, the destructor is not called and there could be a // leak of the TKEYImpl that constructFromLexer() returns. - std::unique_ptr<TKEYImpl> impl_ptr; + boost::shared_ptr<TKEYImpl> impl_ptr; try { std::istringstream ss(tkey_str); MasterLexer lexer; lexer.pushSource(ss); - impl_ptr.reset(constructFromLexer(lexer, 0)); + impl_ptr = constructFromLexer(lexer, 0); if (lexer.getNextToken().getType() != MasterToken::END_OF_FILE) { isc_throw(InvalidRdataText, @@ -5426,7 +1740,7 @@ TKEY::TKEY(const std::string& tkey_str) : impl_(0) { << ex.what()); } - impl_ = impl_ptr.release(); + impl_ = impl_ptr; } /// \brief Constructor with a context of MasterLexer. @@ -5445,9 +1759,8 @@ TKEY::TKEY(const std::string& tkey_str) : impl_(0) { /// \param lexer A \c MasterLexer object parsing a master file for the /// RDATA to be created TKEY::TKEY(MasterLexer& lexer, const Name* origin, - MasterLoader::Options, MasterLoaderCallbacks&) : - impl_(constructFromLexer(lexer, origin)) -{ + MasterLoader::Options, MasterLoaderCallbacks&) { + impl_ = constructFromLexer(lexer, origin); } /// \brief Constructor from wire-format data. @@ -5471,8 +1784,7 @@ TKEY::TKEY(MasterLexer& lexer, const Name* origin, /// must check consistency between the length parameter and the actual /// RDATA length. TKEY::TKEY(InputBuffer& buffer, size_t) : - impl_(0) -{ + impl_(0) { Name algorithm(buffer); const uint32_t inception = buffer.readUint32(); @@ -5495,15 +1807,14 @@ TKEY::TKEY(InputBuffer& buffer, size_t) : buffer.readData(&other_data[0], other_len); } - impl_ = new TKEYImpl(algorithm, inception, expire, mode, error, - key, other_data); + impl_.reset(new TKEYImpl(algorithm, inception, expire, mode, error, + key, other_data)); } TKEY::TKEY(const Name& algorithm, uint32_t inception, uint32_t expire, uint16_t mode, uint16_t error, uint16_t key_len, const void* key, uint16_t other_len, const void* other_data) : - impl_(0) -{ + impl_(0) { if ((key_len == 0 && key != 0) || (key_len > 0 && key == 0)) { isc_throw(InvalidParameter, "TKEY Key length and data inconsistent"); } @@ -5512,8 +1823,8 @@ TKEY::TKEY(const Name& algorithm, uint32_t inception, uint32_t expire, isc_throw(InvalidParameter, "TKEY Other data length and data inconsistent"); } - impl_ = new TKEYImpl(algorithm, inception, expire, mode, error, - key_len, key, other_len, other_data); + impl_.reset(new TKEYImpl(algorithm, inception, expire, mode, error, + key_len, key, other_len, other_data)); } /// \brief The copy constructor. @@ -5521,8 +1832,8 @@ TKEY::TKEY(const Name& algorithm, uint32_t inception, uint32_t expire, /// It internally allocates a resource, and if it fails a corresponding /// standard exception will be thrown. /// This constructor never throws an exception otherwise. -TKEY::TKEY(const TKEY& source) : Rdata(), impl_(new TKEYImpl(*source.impl_)) -{} +TKEY::TKEY(const TKEY& source) : Rdata(), impl_(new TKEYImpl(*source.impl_)) { +} TKEY& TKEY::operator=(const TKEY& source) { @@ -5530,15 +1841,12 @@ TKEY::operator=(const TKEY& source) { return (*this); } - TKEYImpl* newimpl = new TKEYImpl(*source.impl_); - delete impl_; - impl_ = newimpl; + impl_.reset(new TKEYImpl(*source.impl_)); return (*this); } TKEY::~TKEY() { - delete impl_; } /// \brief Convert the \c TKEY to a string. @@ -5757,519 +2065,7 @@ TKEY::getOtherData() const { } // end of namespace "rdata" } // end of namespace "dns" } // end of namespace "isc" -// Copyright (C) 2014-2024 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#include <config.h> - -#include <boost/lexical_cast.hpp> - -#include <exceptions/exceptions.h> - -#include <util/buffer.h> -#include <util/encode/encode.h> -#include <dns/name.h> -#include <dns/messagerenderer.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> -#include <dns/rdata_pimpl_holder.h> - -using namespace std; -using boost::lexical_cast; -using namespace isc::util; -using namespace isc::util::encode; - -namespace isc { -namespace dns { -namespace rdata { -namespace generic { - -struct TLSAImpl { - // straightforward representation of TLSA RDATA fields - TLSAImpl(uint8_t certificate_usage, uint8_t selector, - uint8_t matching_type, const vector<uint8_t>& data) : - certificate_usage_(certificate_usage), - selector_(selector), - matching_type_(matching_type), - data_(data) - {} - - uint8_t certificate_usage_; - uint8_t selector_; - uint8_t matching_type_; - const vector<uint8_t> data_; -}; - -// helper function for string and lexer constructors -TLSAImpl* -TLSA::constructFromLexer(MasterLexer& lexer) { - const uint32_t certificate_usage = - lexer.getNextToken(MasterToken::NUMBER).getNumber(); - if (certificate_usage > 255) { - isc_throw(InvalidRdataText, - "TLSA certificate usage field out of range"); - } - - const uint32_t selector = - lexer.getNextToken(MasterToken::NUMBER).getNumber(); - if (selector > 255) { - isc_throw(InvalidRdataText, - "TLSA selector field out of range"); - } - - const uint32_t matching_type = - lexer.getNextToken(MasterToken::NUMBER).getNumber(); - if (matching_type > 255) { - isc_throw(InvalidRdataText, - "TLSA matching type field out of range"); - } - - std::string certificate_assoc_data; - std::string data_substr; - while (true) { - const MasterToken& token = - lexer.getNextToken(MasterToken::STRING, true); - if ((token.getType() == MasterToken::END_OF_FILE) || - (token.getType() == MasterToken::END_OF_LINE)) { - break; - } - - token.getString(data_substr); - certificate_assoc_data.append(data_substr); - } - lexer.ungetToken(); - - if (certificate_assoc_data.empty()) { - isc_throw(InvalidRdataText, "Empty TLSA certificate association data"); - } - - vector<uint8_t> data; - try { - decodeHex(certificate_assoc_data, data); - } catch (const isc::BadValue& e) { - isc_throw(InvalidRdataText, - "Bad TLSA certificate association data: " << e.what()); - } - - return (new TLSAImpl(certificate_usage, selector, matching_type, data)); -} -/// \brief Constructor from string. -/// -/// The given string must represent a valid TLSA RDATA. There can be -/// extra space characters at the beginning or end of the text (which -/// are simply ignored), but other extra text, including a new line, -/// will make the construction fail with an exception. -/// -/// The Certificate Usage, Selector and Matching Type fields must be -/// within their valid ranges, but are not constrained to the values -/// defined in RFC6698. -/// -/// The Certificate Association Data Field field may be absent, but if -/// present it must contain a valid hex encoding of the data. Whitespace -/// is allowed in the hex text. -/// -/// \throw InvalidRdataText if any fields are missing, out of their -/// valid ranges, or are incorrect, or Certificate Association Data is -/// not a valid hex string. -/// -/// \param tlsa_str A string containing the RDATA to be created -TLSA::TLSA(const string& tlsa_str) : - impl_(NULL) -{ - // We use a smart pointer here because if there is an exception in - // this constructor, the destructor is not called and there could be - // a leak of the TLSAImpl that constructFromLexer() returns. - RdataPimplHolder<TLSAImpl> impl_ptr; - - try { - std::istringstream ss(tlsa_str); - MasterLexer lexer; - lexer.pushSource(ss); - - impl_ptr.reset(constructFromLexer(lexer)); - - if (lexer.getNextToken().getType() != MasterToken::END_OF_FILE) { - isc_throw(InvalidRdataText, "extra input text for TLSA: " - << tlsa_str); - } - } catch (const MasterLexer::LexerError& ex) { - isc_throw(InvalidRdataText, "Failed to construct TLSA from '" << - tlsa_str << "': " << ex.what()); - } - - impl_ = impl_ptr.release(); -} - -/// \brief Constructor with a context of MasterLexer. -/// -/// The \c lexer should point to the beginning of valid textual representation -/// of an TLSA RDATA. -/// -/// \throw MasterLexer::LexerError General parsing error such as missing field. -/// \throw InvalidRdataText Fields are out of their valid range, or are -/// incorrect, or Certificate Association Data is not a valid hex string. -/// -/// \param lexer A \c MasterLexer object parsing a master file for the -/// RDATA to be created -TLSA::TLSA(MasterLexer& lexer, const Name*, - MasterLoader::Options, MasterLoaderCallbacks&) : - impl_(constructFromLexer(lexer)) -{ -} - -/// \brief Constructor from InputBuffer. -/// -/// The passed buffer must contain a valid TLSA RDATA. -/// -/// The Certificate Usage, Selector and Matching Type fields must be -/// within their valid ranges, but are not constrained to the values -/// defined in RFC6698. It is okay for the certificate association data -/// to be missing (see the description of the constructor from string). -TLSA::TLSA(InputBuffer& buffer, size_t rdata_len) { - if (rdata_len < 3) { - isc_throw(InvalidRdataLength, "TLSA record too short"); - } - - const uint8_t certificate_usage = buffer.readUint8(); - const uint8_t selector = buffer.readUint8(); - const uint8_t matching_type = buffer.readUint8(); - - vector<uint8_t> data; - rdata_len -= 3; - - if (rdata_len == 0) { - isc_throw(InvalidRdataLength, - "Empty TLSA certificate association data"); - } - - data.resize(rdata_len); - buffer.readData(&data[0], rdata_len); - - impl_ = new TLSAImpl(certificate_usage, selector, matching_type, data); -} - -TLSA::TLSA(uint8_t certificate_usage, uint8_t selector, - uint8_t matching_type, const std::string& certificate_assoc_data) : - impl_(NULL) -{ - if (certificate_assoc_data.empty()) { - isc_throw(InvalidRdataText, "Empty TLSA certificate association data"); - } - - vector<uint8_t> data; - try { - decodeHex(certificate_assoc_data, data); - } catch (const isc::BadValue& e) { - isc_throw(InvalidRdataText, - "Bad TLSA certificate association data: " << e.what()); - } - - impl_ = new TLSAImpl(certificate_usage, selector, matching_type, data); -} - -TLSA::TLSA(const TLSA& other) : - Rdata(), impl_(new TLSAImpl(*other.impl_)) -{} - -TLSA& -TLSA::operator=(const TLSA& source) { - if (this == &source) { - return (*this); - } - - TLSAImpl* newimpl = new TLSAImpl(*source.impl_); - delete impl_; - impl_ = newimpl; - - return (*this); -} - -TLSA::~TLSA() { - delete impl_; -} - -void -TLSA::toWire(OutputBuffer& buffer) const { - buffer.writeUint8(impl_->certificate_usage_); - buffer.writeUint8(impl_->selector_); - buffer.writeUint8(impl_->matching_type_); - - // The constructors must ensure that the certificate association - // data field is not empty. - assert(!impl_->data_.empty()); - buffer.writeData(&impl_->data_[0], impl_->data_.size()); -} - -void -TLSA::toWire(AbstractMessageRenderer& renderer) const { - renderer.writeUint8(impl_->certificate_usage_); - renderer.writeUint8(impl_->selector_); - renderer.writeUint8(impl_->matching_type_); - - // The constructors must ensure that the certificate association - // data field is not empty. - assert(!impl_->data_.empty()); - renderer.writeData(&impl_->data_[0], impl_->data_.size()); -} - -string -TLSA::toText() const { - // The constructors must ensure that the certificate association - // data field is not empty. - assert(!impl_->data_.empty()); - - return (lexical_cast<string>(static_cast<int>(impl_->certificate_usage_)) + " " + - lexical_cast<string>(static_cast<int>(impl_->selector_)) + " " + - lexical_cast<string>(static_cast<int>(impl_->matching_type_)) + " " + - encodeHex(impl_->data_)); -} - -int -TLSA::compare(const Rdata& other) const { - const TLSA& other_tlsa = dynamic_cast<const TLSA&>(other); - - if (impl_->certificate_usage_ < other_tlsa.impl_->certificate_usage_) { - return (-1); - } else if (impl_->certificate_usage_ > - other_tlsa.impl_->certificate_usage_) { - return (1); - } - - if (impl_->selector_ < other_tlsa.impl_->selector_) { - return (-1); - } else if (impl_->selector_ > other_tlsa.impl_->selector_) { - return (1); - } - - if (impl_->matching_type_ < other_tlsa.impl_->matching_type_) { - return (-1); - } else if (impl_->matching_type_ > - other_tlsa.impl_->matching_type_) { - return (1); - } - - const size_t this_len = impl_->data_.size(); - const size_t other_len = other_tlsa.impl_->data_.size(); - const size_t cmplen = min(this_len, other_len); - - if (cmplen > 0) { - const int cmp = memcmp(&impl_->data_[0], - &other_tlsa.impl_->data_[0], - cmplen); - if (cmp != 0) { - return (cmp); - } - } - - if (this_len == other_len) { - return (0); - } else if (this_len < other_len) { - return (-1); - } else { - return (1); - } -} - -uint8_t -TLSA::getCertificateUsage() const { - return (impl_->certificate_usage_); -} - -uint8_t -TLSA::getSelector() const { - return (impl_->selector_); -} - -uint8_t -TLSA::getMatchingType() const { - return (impl_->matching_type_); -} - -const std::vector<uint8_t>& -TLSA::getData() const { - return (impl_->data_); -} - -size_t -TLSA::getDataLength() const { - return (impl_->data_.size()); -} - -} // end of namespace "generic" -} // end of namespace "rdata" -} // end of namespace "dns" -} // end of namespace "isc" -// Copyright (C) 2010-2024 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#include <config.h> - -#include <stdint.h> -#include <string.h> - -#include <string> -#include <vector> - -#include <util/buffer.h> -#include <dns/exceptions.h> -#include <dns/messagerenderer.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> -#include <dns/rdata/generic/detail/txt_like.h> - -using namespace std; -using namespace isc::util; - -namespace isc { -namespace dns { -namespace rdata { -namespace generic { - -TXT& -TXT::operator=(const TXT& source) { - if (this == &source) { - return (*this); - } - - TXTImpl* newimpl = new TXTImpl(*source.impl_); - delete impl_; - impl_ = newimpl; - - return (*this); -} - -TXT::~TXT() { - delete impl_; -} - -TXT::TXT(InputBuffer& buffer, size_t rdata_len) : - impl_(new TXTImpl(buffer, rdata_len)) -{} - -/// \brief Constructor using the master lexer. -/// -/// This implementation only uses the \c lexer parameters; others are -/// ignored. -/// -/// \throw CharStringTooLong the parameter string length exceeds maximum. -/// \throw InvalidRdataText the method cannot process the parameter data -/// -/// \param lexer A \c MasterLexer object parsing a master file for this -/// RDATA. -TXT::TXT(MasterLexer& lexer, const Name*, MasterLoader::Options, - MasterLoaderCallbacks&) : - impl_(new TXTImpl(lexer)) -{} - -TXT::TXT(const std::string& txtstr) : - impl_(new TXTImpl(txtstr)) -{} - -TXT::TXT(const TXT& other) : - Rdata(), impl_(new TXTImpl(*other.impl_)) -{} - -void -TXT::toWire(OutputBuffer& buffer) const { - impl_->toWire(buffer); -} - -void -TXT::toWire(AbstractMessageRenderer& renderer) const { - impl_->toWire(renderer); -} - -string -TXT::toText() const { - return (impl_->toText()); -} - -int -TXT::compare(const Rdata& other) const { - const TXT& other_txt = dynamic_cast<const TXT&>(other); - - return (impl_->compare(*other_txt.impl_)); -} - -} // end of namespace "generic" -} // end of namespace "rdata" -} // end of namespace "dns" -} // end of namespace "isc" -// Copyright (C) 2010-2024 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#include <config.h> - -#include <string> - -#include <exceptions/exceptions.h> - -#include <util/buffer.h> -#include <dns/messagerenderer.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> - -using namespace std; -using namespace isc::util; - -namespace isc { -namespace dns { -namespace rdata { -namespace hs { - -A::A(const std::string&) { - // TBD -} - -A::A(MasterLexer&, const Name*, - MasterLoader::Options, MasterLoaderCallbacks&) -{ - // TBD -} - -A::A(InputBuffer&, size_t) { - // TBD -} - -A::A(const A&) : Rdata() { - // TBD -} - -void -A::toWire(OutputBuffer&) const { - // TBD -} - -void -A::toWire(AbstractMessageRenderer&) const { - // TBD -} - -string -A::toText() const { - // TBD - isc_throw(InvalidRdataText, "Not implemented yet"); -} - -int -A::compare(const Rdata&) const { - return (0); // dummy. TBD -} - -} // end of namespace "hs" -} // end of namespace "rdata" -} // end of namespace "dns" -} // end of namespace "isc" // Copyright (C) 2010-2024 Internet Systems Consortium, Inc. ("ISC") // // This Source Code Form is subject to the terms of the Mozilla Public @@ -6387,8 +2183,7 @@ A::A(const std::string& addrstr) { /// \param lexer A \c MasterLexer object parsing a master file for the /// RDATA to be created A::A(MasterLexer& lexer, const Name*, - MasterLoader::Options, MasterLoaderCallbacks&) -{ + MasterLoader::Options, MasterLoaderCallbacks&) { const MasterToken& token = lexer.getNextToken(MasterToken::STRING); convertToIPv4Addr(token.getStringRegion().beg, token.getStringRegion().len, &addr_); @@ -6410,8 +2205,8 @@ A::A(InputBuffer& buffer, size_t rdata_len) { } /// \brief Copy constructor. -A::A(const A& other) : Rdata(), addr_(other.addr_) -{} +A::A(const A& other) : Rdata(), addr_(other.addr_) { +} void A::toWire(OutputBuffer& buffer) const { @@ -6541,8 +2336,7 @@ AAAA::AAAA(const std::string& addrstr) { /// \param lexer A \c MasterLexer object parsing a master file for the /// RDATA to be created AAAA::AAAA(MasterLexer& lexer, const Name*, - MasterLoader::Options, MasterLoaderCallbacks&) -{ + MasterLoader::Options, MasterLoaderCallbacks&) { const MasterToken& token = lexer.getNextToken(MasterToken::STRING); convertToIPv6Addr(token.getStringRegion().beg, token.getStringRegion().len, addr_); @@ -6709,8 +2503,8 @@ DHCID::DHCID(InputBuffer& buffer, size_t rdata_len) { /// \brief The copy constructor. /// /// This trivial copy constructor never throws an exception. -DHCID::DHCID(const DHCID& other) : Rdata(), digest_(other.digest_) -{} +DHCID::DHCID(const DHCID& other) : Rdata(), digest_(other.digest_) { +} /// \brief Render the \c DHCID in the wire format. /// @@ -6770,305 +2564,3 @@ DHCID::getDigest() const { } // end of namespace "rdata" } // end of namespace "dns" } // end of namespace "isc" -// Copyright (C) 2011-2024 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#include <config.h> - -#include <iostream> -#include <sstream> - -#include <boost/lexical_cast.hpp> - -#include <util/buffer.h> -#include <util/strutil.h> - -#include <dns/messagerenderer.h> -#include <dns/name.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> - -#include <dns/rdata/generic/detail/lexer_util.h> - -using namespace std; -using namespace isc::util; -using namespace isc::util::str; -using isc::dns::rdata::generic::detail::createNameFromLexer; - -namespace isc { -namespace dns { -namespace rdata { -namespace in { - -struct SRVImpl { - // straightforward representation of SRV RDATA fields - SRVImpl(uint16_t priority, uint16_t weight, uint16_t port, - const Name& target) : - priority_(priority), weight_(weight), port_(port), - target_(target) - {} - - uint16_t priority_; - uint16_t weight_; - uint16_t port_; - Name target_; -}; - -/// \brief Constructor from string. -/// -/// The given string must represent a valid SRV 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 TARGET name must be absolute since there's no parameter that -/// specifies the origin name; if it is not absolute, \c MissingNameOrigin -/// exception will be thrown. It must not be represented as a quoted -/// string. -/// -/// See the construction that takes \c MasterLexer for other fields. -/// -/// \throw Others Exception from the Name and RRTTL constructors. -/// \throw InvalidRdataText Other general syntax errors. -SRV::SRV(const std::string& srv_str) : - impl_(NULL) -{ - try { - std::istringstream ss(srv_str); - MasterLexer lexer; - lexer.pushSource(ss); - - uint32_t num = lexer.getNextToken(MasterToken::NUMBER).getNumber(); - if (num > 65535) { - isc_throw(InvalidRdataText, "Invalid SRV priority in: " << srv_str); - } - const uint16_t priority = static_cast<uint16_t>(num); - - num = lexer.getNextToken(MasterToken::NUMBER).getNumber(); - if (num > 65535) { - isc_throw(InvalidRdataText, "Invalid SRV weight in: " << srv_str); - } - const uint16_t weight = static_cast<uint16_t>(num); - - num = lexer.getNextToken(MasterToken::NUMBER).getNumber(); - if (num > 65535) { - isc_throw(InvalidRdataText, "Invalid SRV port in: " << srv_str); - } - const uint16_t port = static_cast<uint16_t>(num); - - const Name targetname = createNameFromLexer(lexer, NULL); - - if (lexer.getNextToken().getType() != MasterToken::END_OF_FILE) { - isc_throw(InvalidRdataText, "extra input text for SRV: " - << srv_str); - } - - impl_ = new SRVImpl(priority, weight, port, targetname); - } catch (const MasterLexer::LexerError& ex) { - isc_throw(InvalidRdataText, "Failed to construct SRV from '" << - srv_str << "': " << ex.what()); - } -} - -/// \brief Constructor from wire-format data. -/// -/// When a read operation on \c buffer fails (e.g., due to a corrupted -/// message) a corresponding exception from the \c InputBuffer class will -/// be thrown. -/// If the wire-format data does not end with a valid domain name, -/// a corresponding exception from the \c Name class will be thrown. -/// In addition, this constructor internally involves resource allocation, -/// and if it fails a corresponding standard exception will be thrown. -/// -/// According to RFC2782, the Target field must be a non compressed form -/// of domain name. But this implementation accepts a %SRV RR even if that -/// field is compressed as suggested in RFC3597. -/// -/// \param buffer A buffer storing the wire format data. -/// \param rdata_len The length of the RDATA in bytes, normally expected -/// to be the value of the RDLENGTH field of the corresponding RR. -SRV::SRV(InputBuffer& buffer, size_t rdata_len) { - if (rdata_len < 6) { - isc_throw(InvalidRdataLength, "SRV too short"); - } - - const uint16_t priority = buffer.readUint16(); - const uint16_t weight = buffer.readUint16(); - const uint16_t port = buffer.readUint16(); - const Name targetname(buffer); - - impl_ = new SRVImpl(priority, weight, port, targetname); -} - -/// \brief Constructor with a context of MasterLexer. -/// -/// The \c lexer should point to the beginning of valid textual representation -/// of an SRV RDATA. The TARGET field can be non-absolute if \c origin -/// is non-NULL, in which case \c origin is used to make it absolute. -/// It must not be represented as a quoted string. -/// -/// The PRIORITY, WEIGHT and PORT fields must each be a valid decimal -/// representation of an unsigned 16-bit integers respectively. -/// -/// \throw MasterLexer::LexerError General parsing error such as missing field. -/// \throw Other Exceptions from the Name and RRTTL constructors if -/// construction of textual fields as these objects fail. -/// -/// \param lexer A \c MasterLexer object parsing a master file for the -/// RDATA to be created -/// \param origin If non NULL, specifies the origin of TARGET when it -/// is non-absolute. -SRV::SRV(MasterLexer& lexer, const Name* origin, - MasterLoader::Options, MasterLoaderCallbacks&) -{ - uint32_t num = lexer.getNextToken(MasterToken::NUMBER).getNumber(); - if (num > 65535) { - isc_throw(InvalidRdataText, "Invalid SRV priority: " << num); - } - const uint16_t priority = static_cast<uint16_t>(num); - - num = lexer.getNextToken(MasterToken::NUMBER).getNumber(); - if (num > 65535) { - isc_throw(InvalidRdataText, "Invalid SRV weight: " << num); - } - const uint16_t weight = static_cast<uint16_t>(num); - - num = lexer.getNextToken(MasterToken::NUMBER).getNumber(); - if (num > 65535) { - isc_throw(InvalidRdataText, "Invalid SRV port: " << num); - } - const uint16_t port = static_cast<uint16_t>(num); - - const Name targetname = createNameFromLexer(lexer, origin); - - impl_ = new SRVImpl(priority, weight, port, targetname); -} - -/// \brief The copy constructor. -/// -/// It internally allocates a resource, and if it fails a corresponding -/// standard exception will be thrown. -/// This constructor never throws an exception otherwise. -SRV::SRV(const SRV& source) : - Rdata(), impl_(new SRVImpl(*source.impl_)) -{} - -SRV& -SRV::operator=(const SRV& source) { - if (this == &source) { - return (*this); - } - - SRVImpl* newimpl = new SRVImpl(*source.impl_); - delete impl_; - impl_ = newimpl; - - return (*this); -} - -SRV::~SRV() { - delete impl_; -} - -/// \brief Convert the \c SRV to a string. -/// -/// The output of this method is formatted as described in the "from string" -/// constructor (\c SRV(const std::string&))). -/// -/// If internal resource allocation fails, a corresponding -/// standard exception will be thrown. -/// -/// \return A \c string object that represents the \c SRV object. -string -SRV::toText() const { - using boost::lexical_cast; - return (lexical_cast<string>(impl_->priority_) + - " " + lexical_cast<string>(impl_->weight_) + - " " + lexical_cast<string>(impl_->port_) + - " " + impl_->target_.toText()); -} - -/// \brief Render the \c SRV in the wire format without name compression. -/// -/// If internal resource allocation fails, a corresponding -/// standard exception will be thrown. -/// This method never throws an exception otherwise. -/// -/// \param buffer An output buffer to store the wire data. -void -SRV::toWire(OutputBuffer& buffer) const { - buffer.writeUint16(impl_->priority_); - buffer.writeUint16(impl_->weight_); - buffer.writeUint16(impl_->port_); - impl_->target_.toWire(buffer); -} - -/// \brief Render the \c SRV in the wire format with taking into account -/// compression. -/// -/// As specified in RFC2782, the Target field (a domain name) will not be -/// compressed. However, the domain name could be a target of compression -/// of other compressible names (though pretty unlikely), the offset -/// information of the algorithm name may be recorded in \c renderer. -/// -/// If internal resource allocation fails, a corresponding -/// standard exception will be thrown. -/// This method never throws an exception otherwise. -/// -/// \param renderer DNS message rendering context that encapsulates the -/// output buffer and name compression information. -void -SRV::toWire(AbstractMessageRenderer& renderer) const { - renderer.writeUint16(impl_->priority_); - renderer.writeUint16(impl_->weight_); - renderer.writeUint16(impl_->port_); - renderer.writeName(impl_->target_, false); -} - -/// \brief Compare two instances of \c SRV RDATA. -/// -/// See documentation in \c Rdata. -int -SRV::compare(const Rdata& other) const { - const SRV& other_srv = dynamic_cast<const SRV&>(other); - - if (impl_->priority_ != other_srv.impl_->priority_) { - return (impl_->priority_ < other_srv.impl_->priority_ ? -1 : 1); - } - if (impl_->weight_ != other_srv.impl_->weight_) { - return (impl_->weight_ < other_srv.impl_->weight_ ? -1 : 1); - } - if (impl_->port_ != other_srv.impl_->port_) { - return (impl_->port_ < other_srv.impl_->port_ ? -1 : 1); - } - - return (compareNames(impl_->target_, other_srv.impl_->target_)); -} - -uint16_t -SRV::getPriority() const { - return (impl_->priority_); -} - -uint16_t -SRV::getWeight() const { - return (impl_->weight_); -} - -uint16_t -SRV::getPort() const { - return (impl_->port_); -} - -const Name& -SRV::getTarget() const { - return (impl_->target_); -} - -} // end of namespace "in" -} // end of namespace "rdata" -} // end of namespace "dns" -} // end of namespace "isc" diff --git a/src/lib/dns/rdataclass.h b/src/lib/dns/rdataclass.h index 85e65516cd..da60839f0d 100644 --- a/src/lib/dns/rdataclass.h +++ b/src/lib/dns/rdataclass.h @@ -5,9 +5,8 @@ /////////////// /////////////// - #ifndef DNS_RDATACLASS_H -#define DNS_RDATACLASS_H 1 +#define DNS_RDATACLASS_H #include <dns/master_loader.h> @@ -25,22 +24,18 @@ class MasterLoaderCallbacks; // file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef ANY_TSIG_250_H -#define ANY_TSIG_250_H 1 +#define ANY_TSIG_250_H #include <stdint.h> #include <string> +#include <util/buffer.h> #include <dns/name.h> #include <dns/rdata.h> +#include <boost/shared_ptr.hpp> namespace isc { -namespace util { - -class InputBuffer; -class OutputBuffer; -} - namespace dns { // BEGIN_COMMON_DECLARATIONS @@ -178,9 +173,9 @@ public: /// This method never throws an exception. const void* getOtherData() const; private: - TSIGImpl* constructFromLexer(MasterLexer& lexer, const Name* origin); + boost::shared_ptr<TSIGImpl> constructFromLexer(MasterLexer& lexer, const Name* origin); - TSIGImpl* impl_; + boost::shared_ptr<TSIGImpl> impl_; }; } // end of namespace "any" @@ -195,1279 +190,12 @@ private: // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. -#ifndef CH_A_1_H -#define CH_A_1_H 1 - -#include <string> - -#include <dns/rdata.h> - -namespace isc { -namespace util { - -class InputBuffer; -class OutputBuffer; -} - -namespace dns { - -// BEGIN_COMMON_DECLARATIONS - -class AbstractMessageRenderer; - -// END_COMMON_DECLARATIONS - -namespace rdata { -namespace ch { - -class A : public Rdata { -public: - // BEGIN_COMMON_MEMBERS - - explicit A(const std::string& type_str); - A(isc::util::InputBuffer& buffer, size_t rdata_len); - A(const A& other); - A( - MasterLexer& lexer, const Name* name, - MasterLoader::Options options, MasterLoaderCallbacks& callbacks); - virtual std::string toText() const; - virtual void toWire(isc::util::OutputBuffer& buffer) const; - virtual void toWire(AbstractMessageRenderer& renderer) const; - virtual int compare(const Rdata& other) const; - - // END_COMMON_MEMBERS -}; - -} // end of namespace "ch" -} // end of namespace "rdata" -} // end of namespace "dns" -} // end of namespace "isc" -#endif // CH_A_1_H - -// Copyright (C) 2011-2021 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef GENERIC_AFSDB_18_H -#define GENERIC_AFSDB_18_H 1 - -#include <stdint.h> - -#include <string> - -#include <dns/name.h> -#include <dns/rdata.h> - -namespace isc { -namespace util { - -class InputBuffer; -class OutputBuffer; -} - -namespace dns { - -// BEGIN_COMMON_DECLARATIONS - -class AbstractMessageRenderer; - -// END_COMMON_DECLARATIONS - -namespace rdata { -namespace generic { - -/// \brief \c rdata::AFSDB class represents the AFSDB RDATA as defined %in -/// RFC1183. -/// -/// This class implements the basic interfaces inherited from the abstract -/// \c rdata::Rdata class, and provides trivial accessors specific to the -/// AFSDB RDATA. -class AFSDB : public Rdata { -public: - // BEGIN_COMMON_MEMBERS - - explicit AFSDB(const std::string& type_str); - AFSDB(isc::util::InputBuffer& buffer, size_t rdata_len); - AFSDB(const AFSDB& other); - AFSDB( - MasterLexer& lexer, const Name* name, - MasterLoader::Options options, MasterLoaderCallbacks& callbacks); - virtual std::string toText() const; - virtual void toWire(isc::util::OutputBuffer& buffer) const; - virtual void toWire(AbstractMessageRenderer& renderer) const; - virtual int compare(const Rdata& other) const; - - // END_COMMON_MEMBERS - - /// \brief Assignment operator. - /// - /// This method never throws an exception. - AFSDB& operator=(const AFSDB& source); - /// - /// Specialized methods - /// - - /// \brief Return the value of the server field. - /// - /// \return A reference to a \c Name class object corresponding to the - /// internal server name. - /// - /// This method never throws an exception. - const Name& getServer() const; - - /// \brief Return the value of the subtype field. - /// - /// This method never throws an exception. - uint16_t getSubtype() const; - -private: - void createFromLexer(MasterLexer& lexer, const Name* origin); - - uint16_t subtype_; - Name server_; -}; - -} // end of namespace "generic" -} // end of namespace "rdata" -} // end of namespace "dns" -} // end of namespace "isc" -#endif // GENERIC_AFSDB_18_H - -// Copyright (C) 2014-2021 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef GENERIC_CAA_257_H -#define GENERIC_CAA_257_H 1 - -#include <stdint.h> - -#include <dns/name.h> -#include <dns/rdata.h> - -#include <string> -#include <vector> - -namespace isc { -namespace util { - -class InputBuffer; -class OutputBuffer; -} - -namespace dns { - -// BEGIN_COMMON_DECLARATIONS - -class AbstractMessageRenderer; - -// END_COMMON_DECLARATIONS - -namespace rdata { -namespace generic { - -struct CAAImpl; - -class CAA : public Rdata { -public: - // BEGIN_COMMON_MEMBERS - - explicit CAA(const std::string& type_str); - CAA(isc::util::InputBuffer& buffer, size_t rdata_len); - CAA(const CAA& other); - CAA( - MasterLexer& lexer, const Name* name, - MasterLoader::Options options, MasterLoaderCallbacks& callbacks); - virtual std::string toText() const; - virtual void toWire(isc::util::OutputBuffer& buffer) const; - virtual void toWire(AbstractMessageRenderer& renderer) const; - virtual int compare(const Rdata& other) const; - - // END_COMMON_MEMBERS - - CAA(uint8_t flags, const std::string& tag, const std::string& value); - CAA& operator=(const CAA& source); - ~CAA(); - - /// - /// Specialized methods - /// - - /// \brief Return the Flags field of the CAA RDATA. - uint8_t getFlags() const; - - /// \brief Return the Tag field of the CAA RDATA. - const std::string& getTag() const; - - /// \brief Return the Value field of the CAA RDATA. - /// - /// Note: The const reference which is returned is valid only during - /// the lifetime of this \c generic::CAA object. It should not be - /// used afterwards. - const std::vector<uint8_t>& getValue() const; - -private: - CAAImpl* constructFromLexer(MasterLexer& lexer); - - CAAImpl* impl_; -}; - -} // end of namespace "generic" -} // end of namespace "rdata" -} // end of namespace "dns" -} // end of namespace "isc" -#endif // GENERIC_CAA_257_H - -// Copyright (C) 2010-2021 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef GENERIC_CNAME_5_H -#define GENERIC_CNAME_5_H 1 - -#include <string> - -#include <dns/name.h> -#include <dns/rdata.h> - -namespace isc { -namespace util { - -class InputBuffer; -class OutputBuffer; -} - -namespace dns { - -// BEGIN_COMMON_DECLARATIONS - -class AbstractMessageRenderer; - -// END_COMMON_DECLARATIONS - -namespace rdata { -namespace generic { - -class CNAME : public Rdata { -public: - // BEGIN_COMMON_MEMBERS - - explicit CNAME(const std::string& type_str); - CNAME(isc::util::InputBuffer& buffer, size_t rdata_len); - CNAME(const CNAME& other); - CNAME( - MasterLexer& lexer, const Name* name, - MasterLoader::Options options, MasterLoaderCallbacks& callbacks); - virtual std::string toText() const; - virtual void toWire(isc::util::OutputBuffer& buffer) const; - virtual void toWire(AbstractMessageRenderer& renderer) const; - virtual int compare(const Rdata& other) const; - - // END_COMMON_MEMBERS - - // CNAME specific methods - CNAME(const Name& cname); - const Name& getCname() const; -private: - Name cname_; -}; - -} // end of namespace "generic" -} // end of namespace "rdata" -} // end of namespace "dns" -} // end of namespace "isc" -#endif // GENERIC_CNAME_5_H - -// Copyright (C) 2011-2021 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef GENERIC_DLV_32769_H -#define GENERIC_DLV_32769_H 1 - -#include <stdint.h> - -#include <string> - -#include <dns/name.h> -#include <dns/rrtype.h> -#include <dns/rrttl.h> -#include <dns/rdata.h> - -namespace isc { -namespace util { - -class InputBuffer; -class OutputBuffer; -} - -namespace dns { - -// BEGIN_COMMON_DECLARATIONS - -class AbstractMessageRenderer; - -// END_COMMON_DECLARATIONS - -namespace rdata { -namespace generic { - -namespace detail { -template <class Type, uint16_t typeCode> class DSLikeImpl; -} - -/// \brief \c rdata::generic::DLV class represents the DLV RDATA as defined in -/// RFC4431. -/// -/// This class implements the basic interfaces inherited from the abstract -/// \c rdata::Rdata class, and provides trivial accessors specific to the -/// DLV RDATA. -class DLV : public Rdata { -public: - // BEGIN_COMMON_MEMBERS - - explicit DLV(const std::string& type_str); - DLV(isc::util::InputBuffer& buffer, size_t rdata_len); - DLV(const DLV& other); - DLV( - MasterLexer& lexer, const Name* name, - MasterLoader::Options options, MasterLoaderCallbacks& callbacks); - virtual std::string toText() const; - virtual void toWire(isc::util::OutputBuffer& buffer) const; - virtual void toWire(AbstractMessageRenderer& renderer) const; - virtual int compare(const Rdata& other) const; - - // END_COMMON_MEMBERS - - /// \brief Assignment operator. - /// - /// It internally allocates a resource, and if it fails a corresponding - /// standard exception will be thrown. - /// This operator never throws an exception otherwise. - /// - /// This operator provides the strong exception guarantee: When an - /// exception is thrown the content of the assignment target will be - /// intact. - DLV& operator=(const DLV& source); - - /// \brief The destructor. - ~DLV(); - - /// \brief Return the value of the Tag field. - /// - /// This method never throws an exception. - uint16_t getTag() const; -private: - typedef detail::DSLikeImpl<DLV, 32769> DLVImpl; - DLVImpl* impl_; -}; - -} // end of namespace "generic" -} // end of namespace "rdata" -} // end of namespace "dns" -} // end of namespace "isc" -#endif // GENERIC_DLV_32769_H - -// Copyright (C) 2010-2021 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef GENERIC_DNAME_39_H -#define GENERIC_DNAME_39_H 1 - -#include <string> - -#include <dns/name.h> -#include <dns/rdata.h> - -namespace isc { -namespace util { - -class InputBuffer; -class OutputBuffer; -} - -namespace dns { - -// BEGIN_COMMON_DECLARATIONS - -class AbstractMessageRenderer; - -// END_COMMON_DECLARATIONS - -namespace rdata { -namespace generic { - -class DNAME : public Rdata { -public: - // BEGIN_COMMON_MEMBERS - - explicit DNAME(const std::string& type_str); - DNAME(isc::util::InputBuffer& buffer, size_t rdata_len); - DNAME(const DNAME& other); - DNAME( - MasterLexer& lexer, const Name* name, - MasterLoader::Options options, MasterLoaderCallbacks& callbacks); - virtual std::string toText() const; - virtual void toWire(isc::util::OutputBuffer& buffer) const; - virtual void toWire(AbstractMessageRenderer& renderer) const; - virtual int compare(const Rdata& other) const; - - // END_COMMON_MEMBERS - - // DNAME specific methods - DNAME(const Name& dname); - const Name& getDname() const; -private: - Name dname_; -}; - -} // end of namespace "generic" -} // end of namespace "rdata" -} // end of namespace "dns" -} // end of namespace "isc" -#endif // GENERIC_DNAME_39_H - -// Copyright (C) 2010-2021 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#include <stdint.h> - -#include <string> - -#include <dns/name.h> -#include <dns/rrtype.h> -#include <dns/rrttl.h> -#include <dns/rdata.h> -#include <dns/master_lexer.h> - -#ifndef GENERIC_DNSKEY_48_H -#define GENERIC_DNSKEY_48_H 1 - -namespace isc { -namespace util { - -class InputBuffer; -class OutputBuffer; -} - -namespace dns { - -// BEGIN_COMMON_DECLARATIONS - -class AbstractMessageRenderer; - -// END_COMMON_DECLARATIONS - -namespace rdata { -namespace generic { - -struct DNSKEYImpl; - -class DNSKEY : public Rdata { -public: - // BEGIN_COMMON_MEMBERS - - explicit DNSKEY(const std::string& type_str); - DNSKEY(isc::util::InputBuffer& buffer, size_t rdata_len); - DNSKEY(const DNSKEY& other); - DNSKEY( - MasterLexer& lexer, const Name* name, - MasterLoader::Options options, MasterLoaderCallbacks& callbacks); - virtual std::string toText() const; - virtual void toWire(isc::util::OutputBuffer& buffer) const; - virtual void toWire(AbstractMessageRenderer& renderer) const; - virtual int compare(const Rdata& other) const; - - // END_COMMON_MEMBERS - DNSKEY& operator=(const DNSKEY& source); - ~DNSKEY(); - - /// - /// Specialized methods - /// - - /// \brief Returns the key tag - /// - /// \throw isc::OutOfRange if the key data for RSA/MD5 is too short - /// to support tag extraction. - uint16_t getTag() const; - - uint16_t getFlags() const; - uint8_t getAlgorithm() const; - -private: - DNSKEYImpl* constructFromLexer(isc::dns::MasterLexer& lexer); - - DNSKEYImpl* impl_; -}; - -} // end of namespace "generic" -} // end of namespace "rdata" -} // end of namespace "dns" -} // end of namespace "isc" -#endif // GENERIC_DNSKEY_48_H - -// Copyright (C) 2011-2021 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef GENERIC_DS_43_H -#define GENERIC_DS_43_H 1 - -#include <stdint.h> - -#include <string> - -#include <dns/name.h> -#include <dns/rrtype.h> -#include <dns/rrttl.h> -#include <dns/rdata.h> - -namespace isc { -namespace util { - -class InputBuffer; -class OutputBuffer; -} - -namespace dns { - -// BEGIN_COMMON_DECLARATIONS - -class AbstractMessageRenderer; - -// END_COMMON_DECLARATIONS - -namespace rdata { -namespace generic { - -namespace detail { -template <class Type, uint16_t typeCode> class DSLikeImpl; -} - -/// \brief \c rdata::generic::DS class represents the DS RDATA as defined in -/// RFC3658. -/// -/// This class implements the basic interfaces inherited from the abstract -/// \c rdata::Rdata class, and provides trivial accessors specific to the -/// DS RDATA. -class DS : public Rdata { -public: - // BEGIN_COMMON_MEMBERS - - explicit DS(const std::string& type_str); - DS(isc::util::InputBuffer& buffer, size_t rdata_len); - DS(const DS& other); - DS( - MasterLexer& lexer, const Name* name, - MasterLoader::Options options, MasterLoaderCallbacks& callbacks); - virtual std::string toText() const; - virtual void toWire(isc::util::OutputBuffer& buffer) const; - virtual void toWire(AbstractMessageRenderer& renderer) const; - virtual int compare(const Rdata& other) const; - - // END_COMMON_MEMBERS - - /// \brief Assignment operator. - /// - /// It internally allocates a resource, and if it fails a corresponding - /// standard exception will be thrown. - /// This operator never throws an exception otherwise. - /// - /// This operator provides the strong exception guarantee: When an - /// exception is thrown the content of the assignment target will be - /// intact. - DS& operator=(const DS& source); - - /// \brief The destructor. - ~DS(); - - /// \brief Return the value of the Tag field. - /// - /// This method never throws an exception. - uint16_t getTag() const; -private: - typedef detail::DSLikeImpl<DS, 43> DSImpl; - DSImpl* impl_; -}; - -} // end of namespace "generic" -} // end of namespace "rdata" -} // end of namespace "dns" -} // end of namespace "isc" -#endif // GENERIC_DS_43_H - -// Copyright (C) 2011-2021 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef GENERIC_HINFO_13_H -#define GENERIC_HINFO_13_H 1 -#include <stdint.h> - -#include <string> - -#include <boost/scoped_ptr.hpp> -#include <boost/noncopyable.hpp> - -#include <dns/name.h> -#include <dns/rdata.h> -#include <util/buffer.h> - -namespace isc { -namespace util { - -class InputBuffer; -class OutputBuffer; -} - -namespace dns { - -// BEGIN_COMMON_DECLARATIONS - -class AbstractMessageRenderer; - -// END_COMMON_DECLARATIONS - -namespace rdata { -namespace generic { - -class HINFOImpl; - -/// \brief \c HINFO class represents the HINFO rdata defined in -/// RFC1034, RFC1035 -/// -/// This class implements the basic interfaces inherited from the -/// \c rdata::Rdata class, and provides accessors specific to the -/// HINFO rdata. -class HINFO : public Rdata { -public: - // BEGIN_COMMON_MEMBERS - - explicit HINFO(const std::string& type_str); - HINFO(isc::util::InputBuffer& buffer, size_t rdata_len); - HINFO(const HINFO& other); - HINFO( - MasterLexer& lexer, const Name* name, - MasterLoader::Options options, MasterLoaderCallbacks& callbacks); - virtual std::string toText() const; - virtual void toWire(isc::util::OutputBuffer& buffer) const; - virtual void toWire(AbstractMessageRenderer& renderer) const; - virtual int compare(const Rdata& other) const; - - // END_COMMON_MEMBERS - - // HINFO specific methods - ~HINFO(); - - HINFO& operator=(const HINFO&); - - const std::string getCPU() const; - const std::string getOS() const; - -private: - /// Helper template function for toWire() - /// - /// \param outputer Where to write data in - template <typename T> - void toWireHelper(T& outputer) const; - - boost::scoped_ptr<HINFOImpl> impl_; -}; - - -} // end of namespace "generic" -} // end of namespace "rdata" -} // end of namespace "dns" -} // end of namespace "isc" -#endif // GENERIC_HINFO_13_H - -// Copyright (C) 2011-2021 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef GENERIC_MINFO_14_H -#define GENERIC_MINFO_14_H 1 - -#include <string> - -#include <dns/name.h> -#include <dns/rdata.h> - -namespace isc { -namespace util { - -class InputBuffer; -class OutputBuffer; -} - -namespace dns { - -// BEGIN_COMMON_DECLARATIONS - -class AbstractMessageRenderer; - -// END_COMMON_DECLARATIONS - -namespace rdata { -namespace generic { - -/// \brief \c rdata::generic::MINFO class represents the MINFO RDATA as -/// defined in RFC1035. -/// -/// This class implements the basic interfaces inherited from the abstract -/// \c rdata::Rdata class, and provides trivial accessors specific to the -/// MINFO RDATA. -class MINFO : public Rdata { -public: - // BEGIN_COMMON_MEMBERS - - explicit MINFO(const std::string& type_str); - MINFO(isc::util::InputBuffer& buffer, size_t rdata_len); - MINFO(const MINFO& other); - MINFO( - MasterLexer& lexer, const Name* name, - MasterLoader::Options options, MasterLoaderCallbacks& callbacks); - virtual std::string toText() const; - virtual void toWire(isc::util::OutputBuffer& buffer) const; - virtual void toWire(AbstractMessageRenderer& renderer) const; - virtual int compare(const Rdata& other) const; - - // END_COMMON_MEMBERS - - /// \brief Define the assignment operator. - /// - /// \exception std::bad_alloc Memory allocation fails in copying - /// internal member variables (this should be very rare). - MINFO& operator=(const MINFO& source); - - /// \brief Return the value of the rmailbox field. - /// - /// \throw std::bad_alloc If resource allocation for the returned - /// \c Name fails. - /// - /// \note - /// Unlike the case of some other RDATA classes (such as - /// \c NS::getNSName()), this method constructs a new \c Name object - /// and returns it, instead of returning a reference to a \c Name object - /// internally maintained in the class (which is a private member). - /// This is based on the observation that this method will be rarely - /// used and even when it's used it will not be in a performance context - /// (for example, a recursive resolver won't need this field in its - /// resolution process). By returning a new object we have flexibility - /// of changing the internal representation without the risk of changing - /// the interface or method property. - /// The same note applies to the \c getEmailbox() method. - Name getRmailbox() const { return (rmailbox_); } - - /// \brief Return the value of the emailbox field. - /// - /// \throw std::bad_alloc If resource allocation for the returned - /// \c Name fails. - Name getEmailbox() const { return (emailbox_); } - -private: - Name rmailbox_; - Name emailbox_; -}; - -} // end of namespace "generic" -} // end of namespace "rdata" -} // end of namespace "dns" -} // end of namespace "isc" -#endif // GENERIC_MINFO_14_H - -// Copyright (C) 2010-2021 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef GENERIC_MX_15_H -#define GENERIC_MX_15_H 1 - -#include <stdint.h> - -#include <string> - -#include <dns/name.h> -#include <dns/rdata.h> - -namespace isc { -namespace util { - -class InputBuffer; -class OutputBuffer; -} - -namespace dns { - -// BEGIN_COMMON_DECLARATIONS - -class AbstractMessageRenderer; - -// END_COMMON_DECLARATIONS - -namespace rdata { -namespace generic { - -class MX : public Rdata { -public: - // BEGIN_COMMON_MEMBERS - - explicit MX(const std::string& type_str); - MX(isc::util::InputBuffer& buffer, size_t rdata_len); - MX(const MX& other); - MX( - MasterLexer& lexer, const Name* name, - MasterLoader::Options options, MasterLoaderCallbacks& callbacks); - virtual std::string toText() const; - virtual void toWire(isc::util::OutputBuffer& buffer) const; - virtual void toWire(AbstractMessageRenderer& renderer) const; - virtual int compare(const Rdata& other) const; - - // END_COMMON_MEMBERS - - MX(uint16_t preference, const Name& mxname); - - /// - /// Specialized methods - /// - const Name& getMXName() const; - uint16_t getMXPref() const; - -private: - void constructFromLexer(isc::dns::MasterLexer& lexer, - const isc::dns::Name* origin); - - /// Note: this is a prototype version; we may reconsider - /// this representation later. - uint16_t preference_; - Name mxname_; -}; - -} // end of namespace "generic" -} // end of namespace "rdata" -} // end of namespace "dns" -} // end of namespace "isc" -#endif // GENERIC_MX_15_H - -// Copyright (C) 2011-2021 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef GENERIC_NAPTR_35_H -#define GENERIC_NAPTR_35_H 1 - -#include <string> - -#include <boost/scoped_ptr.hpp> - -#include <dns/name.h> -#include <dns/rdata.h> -#include <util/buffer.h> - -namespace isc { -namespace util { - -class InputBuffer; -class OutputBuffer; -} - -namespace dns { - -// BEGIN_COMMON_DECLARATIONS - -class AbstractMessageRenderer; - -// END_COMMON_DECLARATIONS - -namespace rdata { -namespace generic { - -class NAPTRImpl; - -/// \brief \c NAPTR class represents the NAPTR rdata defined in -/// RFC2915, RFC2168 and RFC3403 -/// -/// This class implements the basic interfaces inherited from the -/// \c rdata::Rdata class, and provides accessors specific to the -/// NAPTR rdata. -class NAPTR : public Rdata { -public: - // BEGIN_COMMON_MEMBERS - - explicit NAPTR(const std::string& type_str); - NAPTR(isc::util::InputBuffer& buffer, size_t rdata_len); - NAPTR(const NAPTR& other); - NAPTR( - MasterLexer& lexer, const Name* name, - MasterLoader::Options options, MasterLoaderCallbacks& callbacks); - virtual std::string toText() const; - virtual void toWire(isc::util::OutputBuffer& buffer) const; - virtual void toWire(AbstractMessageRenderer& renderer) const; - virtual int compare(const Rdata& other) const; - - // END_COMMON_MEMBERS - - // NAPTR specific methods - ~NAPTR(); - - NAPTR& operator=(const NAPTR& source); - - uint16_t getOrder() const; - uint16_t getPreference() const; - const std::string getFlags() const; - const std::string getServices() const; - const std::string getRegexp() const; - const Name& getReplacement() const; -private: - /// Helper template function for toWire() - /// - /// \param outputer Where to write data in - template <typename T> - void toWireHelper(T& outputer) const; - - boost::scoped_ptr<NAPTRImpl> impl_; -}; - -} // end of namespace "generic" -} // end of namespace "rdata" -} // end of namespace "dns" -} // end of namespace "isc" -#endif // GENERIC_NAPTR_35_H - -// Copyright (C) 2010-2021 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef GENERIC_NS_2_H -#define GENERIC_NS_2_H 1 - -#include <string> - -#include <dns/name.h> -#include <dns/rdata.h> - -namespace isc { -namespace util { - -class InputBuffer; -class OutputBuffer; -} - -namespace dns { - -// BEGIN_COMMON_DECLARATIONS - -class AbstractMessageRenderer; - -// END_COMMON_DECLARATIONS - -namespace rdata { -namespace generic { - -class NS : public Rdata { -public: - // BEGIN_COMMON_MEMBERS - - explicit NS(const std::string& type_str); - NS(isc::util::InputBuffer& buffer, size_t rdata_len); - NS(const NS& other); - NS( - MasterLexer& lexer, const Name* name, - MasterLoader::Options options, MasterLoaderCallbacks& callbacks); - virtual std::string toText() const; - virtual void toWire(isc::util::OutputBuffer& buffer) const; - virtual void toWire(AbstractMessageRenderer& renderer) const; - virtual int compare(const Rdata& other) const; - - // END_COMMON_MEMBERS - /// - /// Specialized constructor - /// - explicit NS(const Name& nsname) : nsname_(nsname) {} - /// - /// Specialized methods - /// - const Name& getNSName() const; -private: - Name nsname_; -}; - -} // end of namespace "generic" -} // end of namespace "rdata" -} // end of namespace "dns" -} // end of namespace "isc" -#endif // GENERIC_NS_2_H - -// Copyright (C) 2010-2021 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#include <stdint.h> - -#include <string> -#include <vector> - -#include <dns/name.h> -#include <dns/rrtype.h> -#include <dns/rrttl.h> -#include <dns/rdata.h> -#include <dns/master_lexer.h> - -#ifndef GENERIC_NSEC3_50_H -#define GENERIC_NSEC3_50_H 1 - -namespace isc { -namespace util { - -class InputBuffer; -class OutputBuffer; -} - -namespace dns { - -// BEGIN_COMMON_DECLARATIONS - -class AbstractMessageRenderer; - -// END_COMMON_DECLARATIONS - -namespace rdata { -namespace generic { - -struct NSEC3Impl; - -class NSEC3 : public Rdata { -public: - // BEGIN_COMMON_MEMBERS - - explicit NSEC3(const std::string& type_str); - NSEC3(isc::util::InputBuffer& buffer, size_t rdata_len); - NSEC3(const NSEC3& other); - NSEC3( - MasterLexer& lexer, const Name* name, - MasterLoader::Options options, MasterLoaderCallbacks& callbacks); - virtual std::string toText() const; - virtual void toWire(isc::util::OutputBuffer& buffer) const; - virtual void toWire(AbstractMessageRenderer& renderer) const; - virtual int compare(const Rdata& other) const; - - // END_COMMON_MEMBERS - NSEC3& operator=(const NSEC3& source); - ~NSEC3(); - - uint8_t getHashalg() const; - uint8_t getFlags() const; - uint16_t getIterations() const; - const std::vector<uint8_t>& getSalt() const; - const std::vector<uint8_t>& getNext() const; - -private: - NSEC3Impl* constructFromLexer(isc::dns::MasterLexer& lexer); - - NSEC3Impl* impl_; -}; - -} // end of namespace "generic" -} // end of namespace "rdata" -} // end of namespace "dns" -} // end of namespace "isc" -#endif // GENERIC_NSEC3_50_H - -// Copyright (C) 2010-2021 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#include <stdint.h> - -#include <string> -#include <vector> - -#include <dns/name.h> -#include <dns/rrtype.h> -#include <dns/rrttl.h> -#include <dns/rdata.h> -#include <dns/master_lexer.h> - -#ifndef GENERIC_NSEC3PARAM_51_H -#define GENERIC_NSEC3PARAM_51_H 1 - -namespace isc { -namespace util { - -class InputBuffer; -class OutputBuffer; -} - -namespace dns { - -// BEGIN_COMMON_DECLARATIONS - -class AbstractMessageRenderer; - -// END_COMMON_DECLARATIONS - -namespace rdata { -namespace generic { - -struct NSEC3PARAMImpl; - -class NSEC3PARAM : public Rdata { -public: - // BEGIN_COMMON_MEMBERS - - explicit NSEC3PARAM(const std::string& type_str); - NSEC3PARAM(isc::util::InputBuffer& buffer, size_t rdata_len); - NSEC3PARAM(const NSEC3PARAM& other); - NSEC3PARAM( - MasterLexer& lexer, const Name* name, - MasterLoader::Options options, MasterLoaderCallbacks& callbacks); - virtual std::string toText() const; - virtual void toWire(isc::util::OutputBuffer& buffer) const; - virtual void toWire(AbstractMessageRenderer& renderer) const; - virtual int compare(const Rdata& other) const; - - // END_COMMON_MEMBERS - NSEC3PARAM& operator=(const NSEC3PARAM& source); - ~NSEC3PARAM(); - - /// - /// Specialized methods - /// - uint8_t getHashalg() const; - uint8_t getFlags() const; - uint16_t getIterations() const; - const std::vector<uint8_t>& getSalt() const; - -private: - NSEC3PARAMImpl* constructFromLexer(isc::dns::MasterLexer& lexer); - - NSEC3PARAMImpl* impl_; -}; - -} // end of namespace "generic" -} // end of namespace "rdata" -} // end of namespace "dns" -} // end of namespace "isc" -#endif // GENERIC_NSEC3PARAM_51_H - -// Copyright (C) 2010-2021 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#include <stdint.h> - -#include <string> - -#include <dns/name.h> -#include <dns/rrtype.h> -#include <dns/rrttl.h> -#include <dns/rdata.h> - -#ifndef GENERIC_NSEC_47_H -#define GENERIC_NSEC_47_H 1 - -namespace isc { -namespace util { - -class InputBuffer; -class OutputBuffer; -} - -namespace dns { - -// BEGIN_COMMON_DECLARATIONS - -class AbstractMessageRenderer; - -// END_COMMON_DECLARATIONS - -namespace rdata { -namespace generic { - -struct NSECImpl; - -class NSEC : public Rdata { -public: - // BEGIN_COMMON_MEMBERS - - explicit NSEC(const std::string& type_str); - NSEC(isc::util::InputBuffer& buffer, size_t rdata_len); - NSEC(const NSEC& other); - NSEC( - MasterLexer& lexer, const Name* name, - MasterLoader::Options options, MasterLoaderCallbacks& callbacks); - virtual std::string toText() const; - virtual void toWire(isc::util::OutputBuffer& buffer) const; - virtual void toWire(AbstractMessageRenderer& renderer) const; - virtual int compare(const Rdata& other) const; - - // END_COMMON_MEMBERS - NSEC& operator=(const NSEC& source); - ~NSEC(); - - // specialized methods - - /// Return the next domain name. - /// - /// \exception std::bad_alloc Resource allocation failure in name copy. - /// - /// \return The next domain name field in the form of \c Name object. - const Name& getNextName() const; - -private: - NSECImpl* impl_; -}; - -} // end of namespace "generic" -} // end of namespace "rdata" -} // end of namespace "dns" -} // end of namespace "isc" -#endif // GENERIC_NSEC_47_H - -// Copyright (C) 2010-2021 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - #ifndef GENERIC_OPT_41_H -#define GENERIC_OPT_41_H 1 +#define GENERIC_OPT_41_H #include <string> +#include <util/buffer.h> #include <dns/rdata.h> #include <boost/shared_ptr.hpp> @@ -1475,12 +203,6 @@ private: #include <vector> namespace isc { -namespace util { - -class InputBuffer; -class OutputBuffer; -} - namespace dns { // BEGIN_COMMON_DECLARATIONS @@ -1561,7 +283,7 @@ public: const std::vector<PseudoRR>& getPseudoRRs() const; private: - OPTImpl* impl_; + boost::shared_ptr<OPTImpl> impl_; }; } // end of namespace "generic" @@ -1577,20 +299,15 @@ private: // file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef GENERIC_PTR_12_H -#define GENERIC_PTR_12_H 1 +#define GENERIC_PTR_12_H #include <string> +#include <util/buffer.h> #include <dns/name.h> #include <dns/rdata.h> namespace isc { -namespace util { - -class InputBuffer; -class OutputBuffer; -} - namespace dns { // BEGIN_COMMON_DECLARATIONS @@ -1622,7 +339,8 @@ public: /// /// Specialized constructor /// - explicit PTR(const Name& ptr_name) : ptr_name_(ptr_name) {} + explicit PTR(const Name& ptr_name) : ptr_name_(ptr_name) { + } /// /// Specialized methods /// @@ -1637,107 +355,6 @@ private: } // end of namespace "isc" #endif // GENERIC_PTR_12_H -// Copyright (C) 2011-2021 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef GENERIC_RP_17_H -#define GENERIC_RP_17_H 1 - -#include <string> - -#include <dns/name.h> -#include <dns/rdata.h> - -namespace isc { -namespace util { - -class InputBuffer; -class OutputBuffer; -} - -namespace dns { - -// BEGIN_COMMON_DECLARATIONS - -class AbstractMessageRenderer; - -// END_COMMON_DECLARATIONS - -namespace rdata { -namespace generic { - -/// \brief \c rdata::generic::RP class represents the RP RDATA as defined in -/// RFC1183. -/// -/// This class implements the basic interfaces inherited from the abstract -/// \c rdata::Rdata class, and provides trivial accessors specific to the -/// RP RDATA. -class RP : public Rdata { -public: - // BEGIN_COMMON_MEMBERS - - explicit RP(const std::string& type_str); - RP(isc::util::InputBuffer& buffer, size_t rdata_len); - RP(const RP& other); - RP( - MasterLexer& lexer, const Name* name, - MasterLoader::Options options, MasterLoaderCallbacks& callbacks); - virtual std::string toText() const; - virtual void toWire(isc::util::OutputBuffer& buffer) const; - virtual void toWire(AbstractMessageRenderer& renderer) const; - virtual int compare(const Rdata& other) const; - - // END_COMMON_MEMBERS - - /// We use the default copy constructor and assignment operator. - - /// \brief Constructor from RDATA field parameters. - /// - /// The parameters are a straightforward mapping of %RP RDATA - /// fields as defined in RFC1183. - RP(const Name& mailbox, const Name& text) : - mailbox_(mailbox), text_(text) - {} - - /// \brief Return the value of the mailbox field. - /// - /// \throw std::bad_alloc If resource allocation for the returned - /// \c Name fails. - /// - /// \note - /// Unlike the case of some other RDATA classes (such as - /// \c NS::getNSName()), this method constructs a new \c Name object - /// and returns it, instead of returning a reference to a \c Name object - /// internally maintained in the class (which is a private member). - /// This is based on the observation that this method will be rarely used - /// and even when it's used it will not be in a performance context - /// (for example, a recursive resolver won't need this field in its - /// resolution process). By returning a new object we have flexibility of - /// changing the internal representation without the risk of changing - /// the interface or method property. - /// The same note applies to the \c getText() method. - Name getMailbox() const { return (mailbox_); } - - /// \brief Return the value of the text field. - /// - /// \throw std::bad_alloc If resource allocation for the returned - /// \c Name fails. - Name getText() const { return (text_); } - -private: - Name mailbox_; - Name text_; -}; - -} // end of namespace "generic" -} // end of namespace "rdata" -} // end of namespace "dns" -} // end of namespace "isc" -#endif // GENERIC_RP_17_H - // Copyright (C) 2010-2021 Internet Systems Consortium, Inc. ("ISC") // // This Source Code Form is subject to the terms of the Mozilla Public @@ -1751,17 +368,12 @@ private: #include <dns/name.h> #include <dns/rrtype.h> #include <dns/rdata.h> +#include <boost/shared_ptr.hpp> #ifndef GENERIC_RRSIG_46_H -#define GENERIC_RRSIG_46_H 1 +#define GENERIC_RRSIG_46_H namespace isc { -namespace util { - -class InputBuffer; -class OutputBuffer; -} - namespace dns { // BEGIN_COMMON_DECLARATIONS @@ -1804,9 +416,9 @@ public: const RRType& typeCovered() const; private: // helper function for string and lexer constructors - RRSIGImpl* constructFromLexer(MasterLexer& lexer, const Name* origin); + boost::shared_ptr<RRSIGImpl> constructFromLexer(MasterLexer& lexer, const Name* origin); - RRSIGImpl* impl_; + boost::shared_ptr<RRSIGImpl> impl_; }; } // end of namespace "generic" @@ -1822,21 +434,17 @@ private: // file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef GENERIC_SOA_6_H -#define GENERIC_SOA_6_H 1 +#define GENERIC_SOA_6_H #include <string> #include <dns/name.h> #include <dns/rdata.h> +#include <dns/rrttl.h> #include <dns/serial.h> +#include <util/buffer.h> namespace isc { -namespace util { - -class InputBuffer; -class OutputBuffer; -} - namespace dns { // BEGIN_COMMON_DECLARATIONS @@ -1888,180 +496,7 @@ private: } // end of namespace "dns" } // end of namespace "isc" #endif // GENERIC_SOA_6_H - -// Copyright (C) 2010-2021 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef GENERIC_SPF_99_H -#define GENERIC_SPF_99_H 1 - -#include <stdint.h> - -#include <string> -#include <vector> - -#include <dns/rdata.h> - -namespace isc { -namespace util { - -class InputBuffer; -class OutputBuffer; -} - -namespace dns { - -// BEGIN_COMMON_DECLARATIONS - -class AbstractMessageRenderer; - -// END_COMMON_DECLARATIONS - -namespace rdata { -namespace generic { - -namespace detail { -template<class Type, uint16_t typeCode> class TXTLikeImpl; -} - -/// \brief \c rdata::SPF class represents the SPF RDATA as defined %in -/// RFC4408. -/// -/// This class implements the basic interfaces inherited from the abstract -/// \c rdata::Rdata class. The semantics of the class is provided by -/// a copy of instantiated TXTLikeImpl class common to both TXT and SPF. -class SPF : public Rdata { -public: - // BEGIN_COMMON_MEMBERS - - explicit SPF(const std::string& type_str); - SPF(isc::util::InputBuffer& buffer, size_t rdata_len); - SPF(const SPF& other); - SPF( - MasterLexer& lexer, const Name* name, - MasterLoader::Options options, MasterLoaderCallbacks& callbacks); - virtual std::string toText() const; - virtual void toWire(isc::util::OutputBuffer& buffer) const; - virtual void toWire(AbstractMessageRenderer& renderer) const; - virtual int compare(const Rdata& other) const; - - // END_COMMON_MEMBERS - - /// \brief Assignment operator. - /// - /// It internally allocates a resource, and if it fails a corresponding - /// standard exception will be thrown. - /// This operator never throws an exception otherwise. - /// - /// This operator provides the strong exception guarantee: When an - /// exception is thrown the content of the assignment target will be - /// intact. - SPF& operator=(const SPF& source); - - /// \brief The destructor. - ~SPF(); - - /// - /// Specialized methods - /// - - /// \brief Return a reference to the data strings - /// - /// This method never throws an exception. - const std::vector<std::vector<uint8_t> >& getString() const; - -private: - typedef isc::dns::rdata::generic::detail::TXTLikeImpl<SPF, 99> SPFImpl; - SPFImpl* impl_; -}; - -} // end of namespace "generic" -} // end of namespace "rdata" -} // end of namespace "dns" -} // end of namespace "isc" -#endif // GENERIC_SPF_99_H - -// Copyright (C) 2012-2021 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef GENERIC_SSHFP_44_H -#define GENERIC_SSHFP_44_H 1 - -#include <stdint.h> - -#include <string> -#include <vector> - -#include <dns/name.h> -#include <dns/rdata.h> - -namespace isc { -namespace util { - -class InputBuffer; -class OutputBuffer; -} - -namespace dns { - -// BEGIN_COMMON_DECLARATIONS - -class AbstractMessageRenderer; - -// END_COMMON_DECLARATIONS - -namespace rdata { -namespace generic { - -struct SSHFPImpl; - -class SSHFP : public Rdata { -public: - // BEGIN_COMMON_MEMBERS - - explicit SSHFP(const std::string& type_str); - SSHFP(isc::util::InputBuffer& buffer, size_t rdata_len); - SSHFP(const SSHFP& other); - SSHFP( - MasterLexer& lexer, const Name* name, - MasterLoader::Options options, MasterLoaderCallbacks& callbacks); - virtual std::string toText() const; - virtual void toWire(isc::util::OutputBuffer& buffer) const; - virtual void toWire(AbstractMessageRenderer& renderer) const; - virtual int compare(const Rdata& other) const; - - // END_COMMON_MEMBERS - - SSHFP(uint8_t algorithm, uint8_t fingerprint_type, - const std::string& fingerprint); - SSHFP& operator=(const SSHFP& source); - ~SSHFP(); - - /// - /// Specialized methods - /// - uint8_t getAlgorithmNumber() const; - uint8_t getFingerprintType() const; - const std::vector<uint8_t>& getFingerprint() const; - size_t getFingerprintLength() const; - -private: - SSHFPImpl* constructFromLexer(MasterLexer& lexer); - - SSHFPImpl* impl_; -}; - -} // end of namespace "generic" -} // end of namespace "rdata" -} // end of namespace "dns" -} // end of namespace "isc" -#endif // GENERIC_SSHFP_44_H +#endif // DNS_RDATACLASS_H // Copyright (C) 2021 Internet Systems Consortium, Inc. ("ISC") // @@ -2070,22 +505,18 @@ private: // file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef GENERIC_TKEY_249_H -#define GENERIC_TKEY_249_H 1 +#define GENERIC_TKEY_249_H #include <stdint.h> #include <string> +#include <util/buffer.h> #include <dns/name.h> #include <dns/rdata.h> +#include <boost/shared_ptr.hpp> namespace isc { -namespace util { - -class InputBuffer; -class OutputBuffer; -} - namespace dns { // BEGIN_COMMON_DECLARATIONS @@ -2217,9 +648,9 @@ public: static const uint16_t GSS_API_MODE; private: - TKEYImpl* constructFromLexer(MasterLexer& lexer, const Name* origin); + boost::shared_ptr<TKEYImpl> constructFromLexer(MasterLexer& lexer, const Name* origin); - TKEYImpl* impl_; + boost::shared_ptr<TKEYImpl> impl_; }; } // end of namespace "generic" @@ -2228,210 +659,6 @@ private: } // end of namespace "isc" #endif // GENERIC_TKEY_249_H -// Copyright (C) 2014-2021 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef GENERIC_TLSA_52_H -#define GENERIC_TLSA_52_H 1 - -#include <stdint.h> - -#include <dns/name.h> -#include <dns/rdata.h> - -#include <string> -#include <vector> - -namespace isc { -namespace util { - -class InputBuffer; -class OutputBuffer; -} - -namespace dns { - -// BEGIN_COMMON_DECLARATIONS - -class AbstractMessageRenderer; - -// END_COMMON_DECLARATIONS - -namespace rdata { -namespace generic { - -struct TLSAImpl; - -class TLSA : public Rdata { -public: - // BEGIN_COMMON_MEMBERS - - explicit TLSA(const std::string& type_str); - TLSA(isc::util::InputBuffer& buffer, size_t rdata_len); - TLSA(const TLSA& other); - TLSA( - MasterLexer& lexer, const Name* name, - MasterLoader::Options options, MasterLoaderCallbacks& callbacks); - virtual std::string toText() const; - virtual void toWire(isc::util::OutputBuffer& buffer) const; - virtual void toWire(AbstractMessageRenderer& renderer) const; - virtual int compare(const Rdata& other) const; - - // END_COMMON_MEMBERS - - TLSA(uint8_t certificate_usage, uint8_t selector, - uint8_t matching_type, const std::string& certificate_assoc_data); - TLSA& operator=(const TLSA& source); - ~TLSA(); - - /// - /// Specialized methods - /// - uint8_t getCertificateUsage() const; - uint8_t getSelector() const; - uint8_t getMatchingType() const; - const std::vector<uint8_t>& getData() const; - size_t getDataLength() const; - -private: - TLSAImpl* constructFromLexer(MasterLexer& lexer); - - TLSAImpl* impl_; -}; - -} // end of namespace "generic" -} // end of namespace "rdata" -} // end of namespace "dns" -} // end of namespace "isc" -#endif // GENERIC_TLSA_52_H - -// Copyright (C) 2010-2021 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef GENERIC_TXT_16_H -#define GENERIC_TXT_16_H 1 - -#include <stdint.h> - -#include <string> -#include <vector> - -#include <dns/rdata.h> - -namespace isc { -namespace util { - -class InputBuffer; -class OutputBuffer; -} - -namespace dns { - -// BEGIN_COMMON_DECLARATIONS - -class AbstractMessageRenderer; - -// END_COMMON_DECLARATIONS - -namespace rdata { -namespace generic { - -namespace detail { -template<class Type, uint16_t typeCode> class TXTLikeImpl; -} - -class TXT : public Rdata { -public: - // BEGIN_COMMON_MEMBERS - - explicit TXT(const std::string& type_str); - TXT(isc::util::InputBuffer& buffer, size_t rdata_len); - TXT(const TXT& other); - TXT( - MasterLexer& lexer, const Name* name, - MasterLoader::Options options, MasterLoaderCallbacks& callbacks); - virtual std::string toText() const; - virtual void toWire(isc::util::OutputBuffer& buffer) const; - virtual void toWire(AbstractMessageRenderer& renderer) const; - virtual int compare(const Rdata& other) const; - - // END_COMMON_MEMBERS - - TXT& operator=(const TXT& source); - ~TXT(); - -private: - typedef isc::dns::rdata::generic::detail::TXTLikeImpl<TXT, 16> TXTImpl; - TXTImpl* impl_; -}; - -} // end of namespace "generic" -} // end of namespace "rdata" -} // end of namespace "dns" -} // end of namespace "isc" -#endif // GENERIC_TXT_16_H - -// Copyright (C) 2010-2021 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef HS_A_1_H -#define HS_A_1_H 1 - -#include <string> - -#include <dns/rdata.h> - -namespace isc { -namespace util { - -class InputBuffer; -class OutputBuffer; -} - -namespace dns { - -// BEGIN_COMMON_DECLARATIONS - -class AbstractMessageRenderer; - -// END_COMMON_DECLARATIONS - -namespace rdata { -namespace hs { - -class A : public Rdata { -public: - // BEGIN_COMMON_MEMBERS - - explicit A(const std::string& type_str); - A(isc::util::InputBuffer& buffer, size_t rdata_len); - A(const A& other); - A( - MasterLexer& lexer, const Name* name, - MasterLoader::Options options, MasterLoaderCallbacks& callbacks); - virtual std::string toText() const; - virtual void toWire(isc::util::OutputBuffer& buffer) const; - virtual void toWire(AbstractMessageRenderer& renderer) const; - virtual int compare(const Rdata& other) const; - - // END_COMMON_MEMBERS -}; - -} // end of namespace "hs" -} // end of namespace "rdata" -} // end of namespace "dns" -} // end of namespace "isc" -#endif // HS_A_1_H - // Copyright (C) 2010-2021 Internet Systems Consortium, Inc. ("ISC") // // This Source Code Form is subject to the terms of the Mozilla Public @@ -2439,19 +666,14 @@ public: // file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef IN_A_1_H -#define IN_A_1_H 1 +#define IN_A_1_H #include <string> +#include <util/buffer.h> #include <dns/rdata.h> namespace isc { -namespace util { - -class InputBuffer; -class OutputBuffer; -} - namespace dns { // BEGIN_COMMON_DECLARATIONS @@ -2500,21 +722,16 @@ private: // file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef IN_AAAA_28_H -#define IN_AAAA_28_H 1 +#define IN_AAAA_28_H #include <stdint.h> #include <string> +#include <util/buffer.h> #include <dns/rdata.h> namespace isc { -namespace util { - -class InputBuffer; -class OutputBuffer; -} - namespace dns { // BEGIN_COMMON_DECLARATIONS @@ -2561,20 +778,15 @@ private: // file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef IN_DHCID_49_H -#define IN_DHCID_49_H 1 +#define IN_DHCID_49_H #include <string> #include <vector> +#include <util/buffer.h> #include <dns/rdata.h> namespace isc { -namespace util { - -class InputBuffer; -class OutputBuffer; -} - namespace dns { // BEGIN_COMMON_DECLARATIONS @@ -2629,118 +841,3 @@ private: } // end of namespace "dns" } // end of namespace "isc" #endif // IN_DHCID_49_H - -// Copyright (C) 2011-2021 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef IN_SRV_33_H -#define IN_SRV_33_H 1 - -#include <stdint.h> - -#include <dns/name.h> -#include <dns/rdata.h> - -namespace isc { -namespace util { - -class InputBuffer; -class OutputBuffer; -} - -namespace dns { - -// BEGIN_COMMON_DECLARATIONS - -class AbstractMessageRenderer; - -// END_COMMON_DECLARATIONS - -namespace rdata { -namespace in { - -struct SRVImpl; - -/// \brief \c rdata::SRV class represents the SRV RDATA as defined %in -/// RFC2782. -/// -/// This class implements the basic interfaces inherited from the abstract -/// \c rdata::Rdata class, and provides trivial accessors specific to the -/// SRV RDATA. -class SRV : public Rdata { -public: - // BEGIN_COMMON_MEMBERS - - explicit SRV(const std::string& type_str); - SRV(isc::util::InputBuffer& buffer, size_t rdata_len); - SRV(const SRV& other); - SRV( - MasterLexer& lexer, const Name* name, - MasterLoader::Options options, MasterLoaderCallbacks& callbacks); - virtual std::string toText() const; - virtual void toWire(isc::util::OutputBuffer& buffer) const; - virtual void toWire(AbstractMessageRenderer& renderer) const; - virtual int compare(const Rdata& other) const; - - // END_COMMON_MEMBERS - - /// \brief Assignment operator. - /// - /// It internally allocates a resource, and if it fails a corresponding - /// standard exception will be thrown. - /// This operator never throws an exception otherwise. - /// - /// This operator provides the strong exception guarantee: When an - /// exception is thrown the content of the assignment target will be - /// intact. - SRV& operator=(const SRV& source); - - /// \brief The destructor. - ~SRV(); - - /// - /// Specialized methods - /// - - /// \brief Return the value of the priority field. - /// - /// This method never throws an exception. - uint16_t getPriority() const; - - /// \brief Return the value of the weight field. - /// - /// This method never throws an exception. - uint16_t getWeight() const; - - /// \brief Return the value of the port field. - /// - /// This method never throws an exception. - uint16_t getPort() const; - - /// \brief Return the value of the target field. - /// - /// \return A reference to a \c Name class object corresponding to the - /// internal target name. - /// - /// This method never throws an exception. - const Name& getTarget() const; - -private: - SRVImpl* impl_; -}; - -} // end of namespace "in" -} // end of namespace "rdata" -} // end of namespace "dns" -} // end of namespace "isc" -#endif // IN_SRV_33_H - - -#endif // DNS_RDATACLASS_H - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/rdatafields.cc b/src/lib/dns/rdatafields.cc deleted file mode 100644 index e02ec8ff87..0000000000 --- a/src/lib/dns/rdatafields.cc +++ /dev/null @@ -1,216 +0,0 @@ -// Copyright (C) 2010-2015,2017 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#include <config.h> - -#include <stdint.h> - -#include <cassert> -#include <vector> - -#include <exceptions/exceptions.h> - -#include <util/buffer.h> -#include <dns/messagerenderer.h> -#include <dns/name.h> -#include <dns/rdata.h> -#include <dns/rdatafields.h> - -using namespace std; -using namespace isc::dns; -using namespace isc::dns::rdata; -using isc::util::OutputBuffer; -using isc::util::InputBuffer; - -namespace isc { -namespace dns { -namespace rdata { - -/// This is a helper class for \c RdataFields. -/// -/// It manages a local storage for the data when \c RdataFields is constructed -/// from an \c Rdata. -/// To minimize construction overhead in the other case, an instance of -/// this class is instantiated only when necessary - we don't need the vectors -/// when only rendering. -struct RdataFields::RdataFieldsDetail { - RdataFieldsDetail(const vector<FieldSpec>& fields, - const uint8_t* data, size_t data_length) : - allocated_fields_(fields), - allocated_data_(data, data + data_length) - {} - const vector<FieldSpec> allocated_fields_; - const vector<uint8_t> allocated_data_; -}; - -namespace { -// This class is used to divide the content of RDATA into \c RdataField -// fields via message rendering logic. -// The idea is to identify domain name fields in the writeName() method, -// and determine whether they are compressible using the "compress" -// parameter. -// Other types of data are simply copied into the internal buffer, and -// consecutive such fields are combined into a single \c RdataField field. -// -// Technically, this use of inheritance may be considered a violation of -// Liskov Substitution Principle in that it doesn't actually compress domain -// names, and some of the methods are not expected to be used. -// In fact, skip() or trim() may not be make much sense in this context. -// Nevertheless we keep this idea at the moment. Since the usage is limited -// (it's only used within this file, and only used with \c Rdata variants), -// it's hopefully an acceptable practice. -class RdataFieldComposer : public AbstractMessageRenderer { -public: - RdataFieldComposer() : - truncated_(false), length_limit_(65535), - mode_(CASE_INSENSITIVE), last_data_pos_(0) - {} - virtual ~RdataFieldComposer() {} - virtual bool isTruncated() const { return (truncated_); } - virtual size_t getLengthLimit() const { return (length_limit_); } - virtual CompressMode getCompressMode() const { return (mode_); } - virtual void setTruncated() { truncated_ = true; } - virtual void setLengthLimit(size_t len) { length_limit_ = len; } - virtual void setCompressMode(CompressMode mode) { mode_ = mode; } - virtual void writeName(const LabelSequence&, bool) {} - virtual void writeName(const Name& name, bool compress) { - extendData(); - const RdataFields::Type field_type = - compress ? RdataFields::COMPRESSIBLE_NAME : - RdataFields::INCOMPRESSIBLE_NAME; - // TODO: When we get rid of need for getBuffer, we can output the name - // to a buffer and then write the buffer inside - name.toWire(getBuffer()); - fields_.push_back(RdataFields::FieldSpec(field_type, - name.getLength())); - last_data_pos_ = getLength(); - } - - virtual void clear() { - isc_throw(Unexpected, "unexpected clear() for RdataFieldComposer"); - } - bool truncated_; - size_t length_limit_; - CompressMode mode_; - vector<RdataFields::FieldSpec> fields_; - vector<RdataFields::FieldSpec>& getFields() { - extendData(); - return (fields_); - } - // We use generic write* methods, with the exception of writeName. - // So new data can arrive without us knowing it, this considers all new - // data to be just data and extends the fields to take it into account. - size_t last_data_pos_; - void extendData() { - // No news, return to work - if (getLength() == last_data_pos_) { - return; - } - // The new bytes are just ordinary uninteresting data - if (fields_.empty() || fields_.back().type != RdataFields::DATA) { - fields_.push_back(RdataFields::FieldSpec(RdataFields::DATA, 0)); - } - // We added this much data from last time - fields_.back().len += getLength() - last_data_pos_; - last_data_pos_ = getLength(); - } -}; - -} - -RdataFields::RdataFields(const Rdata& rdata) { - RdataFieldComposer field_composer; - rdata.toWire(field_composer); - nfields_ = field_composer.getFields().size(); - data_length_ = field_composer.getLength(); - if (nfields_ > 0) { - assert(data_length_ > 0); - detail_ = new RdataFieldsDetail(field_composer.getFields(), - static_cast<const uint8_t*> - (field_composer.getData()), - field_composer.getLength()); - data_ = &detail_->allocated_data_[0]; - fields_ = &detail_->allocated_fields_[0]; - } else { - assert(data_length_ == 0); - detail_ = NULL; - data_ = NULL; - fields_ = NULL; - } -} - -RdataFields::RdataFields(const void* fields, const unsigned int fields_length, - const void* data, const size_t data_length) : - fields_(static_cast<const FieldSpec*>(fields)), - nfields_(fields_length / sizeof(*fields_)), - data_(static_cast<const uint8_t*>(data)), - data_length_(data_length), - detail_(NULL) -{ - if ((fields_ == NULL && nfields_ > 0) || - (fields_ != NULL && nfields_ == 0)) { - isc_throw(InvalidParameter, - "Inconsistent parameters for RdataFields: fields_length (" - << fields_length << ") and fields conflict each other"); - } - if ((data_ == NULL && data_length_ > 0) || - (data_ != NULL && data_length_ == 0)) { - isc_throw(InvalidParameter, - "Inconsistent parameters for RdataFields: data length (" - << data_length_ << ") and data conflict each other"); - } - - size_t total_length = 0; - for (unsigned int i = 0; i < nfields_; ++i) { - total_length += fields_[i].len; - } - if (total_length != data_length_) { - isc_throw(InvalidParameter, - "Inconsistent parameters for RdataFields: " - "fields len: " << total_length << - " data len: " << data_length_); - } -} - -RdataFields::~RdataFields() { - delete detail_; -} - -RdataFields::FieldSpec -RdataFields::getFieldSpec(const unsigned int field_id) const { - if (field_id >= nfields_) { - isc_throw(OutOfRange, "Rdata field ID is out of range: " << field_id); - } - return (fields_[field_id]); -} - -void -RdataFields::toWire(AbstractMessageRenderer& renderer) const { - size_t offset = 0; - - for (unsigned int i = 0; i < nfields_; ++i) { - if (fields_[i].type == DATA) { - renderer.writeData(data_ + offset, fields_[i].len); - } else { - // XXX: this is inefficient. Even if it's quite likely the - // data is a valid wire representation of a name we parse - // it to construct the Name object in the generic mode. - // This should be improved in a future version. - InputBuffer buffer(data_ + offset, fields_[i].len); - renderer.writeName(Name(buffer), - fields_[i].type == COMPRESSIBLE_NAME); - } - offset += fields_[i].len; - } -} - -void -RdataFields::toWire(OutputBuffer& buffer) const { - buffer.writeData(data_, data_length_); -} -} // end of namespace rdata -} // end of namespace dns -} // end of namespace isc diff --git a/src/lib/dns/rdatafields.h b/src/lib/dns/rdatafields.h deleted file mode 100644 index c4a64ad798..0000000000 --- a/src/lib/dns/rdatafields.h +++ /dev/null @@ -1,419 +0,0 @@ -// Copyright (C) 2010-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef RDATAFIELDS_H -#define RDATAFIELDS_H 1 - -#include <stdint.h> - -#include <cstddef> - -namespace isc { -namespace util { -class OutputBuffer; -} -namespace dns { -class AbstractMessageRenderer; - -namespace rdata { -class Rdata; - -/// A low-level, RR type-independent representation of DNS RDATA. -/// -/// <b>Purpose of the Class</b> -/// -/// This class intends to help "serialization" of the content of RDATA -/// in a space-efficient manner. Specific derived classes of \c Rdata -/// focus on the convenience of accessing RDATA fields for RR type-specific -/// protocol operations, and can be inefficient in terms of space. -/// For example, a DNS character string may be internally represented as a -/// \c std::string object with all of the overhead of the richer class. -/// If an application needs to maintain a very large number of RRs and it -/// does not have to perform RR specific operation so often, it may make more -/// sense to store the data in memory in a lower-level but space efficient -/// form. -/// -/// Another purpose of this class is to improve rendering performance for -/// RDATA. If the only requirement were space efficiency, it would be just -/// sufficient to convert the \c RDATA into a binary sequence in the wire -/// format. However, to render the data in a DNS message, we'd have to -/// re-construct a corresponding \c Rdata object in the case where name -/// compression is necessary. This is not desirable, and this class is -/// provided to avoid such unnecessary overhead. -/// -/// <b>Data Format</b> -/// -/// To meet these goals, this class helps convert an \c Rdata object into -/// two pieces of information: Wire-format representation of the \c Rdata -/// and associated meta information for efficient rendering. -/// -/// Specifically, it maintains the wire-format data as a sequence of typed -/// fields. The types are: -/// - Compressible name: a domain name as an RDATA field that can be compressed -/// - Incompressible name: a domain name as an RDATA field that cannot be -/// compressed -/// - Other data: any other fields of RDATA, which should be treated as opaque -/// -/// (See also the description of \c RdataFields::Type) -/// Whether a name can or cannot be compressed is determined according to -/// RFC3597. -/// -/// A "other data" field may not always correspond to a single RDATA field. -/// A \c RdataFields field (of other data) is just a contiguous region of the -/// wire-format data that does not involve name compression. -/// For example, the SOA RDATA begins with two "compressible" names followed -/// by 5 32-bit fields. -/// In \c RdataFields the last 5 fields would be considered a single 20-byte -/// field. -/// -/// Each \c RdataFields field is identified by the \c FieldSpec structure, -/// which provides the type and length of the field. -/// An \c RdataFields object internally maintains a sequence of \c FieldSpec -/// objects in a form of plain C-style array, which can be referenced via -/// a pointer returned by the \c getFieldSpecData() method. -/// The \c \c FieldSpec for a specific field can also be retrieved by the -/// \c getFieldSpec() method. -/// -/// The following diagram shows the internal memory representation of -/// an SOA RDATA in the form of \c RdataFields object and how an application -/// can get access to the memory region. -/** \verbatim -accessible via |0 getDataLength() bytes -getData()----------> <MNAME><RNAME><Rest of the data> - <---------- 3 * sizeof(FieldSpec) bytes -------------> -getFieldSpecData()-> { compressible name { compressible name { other data - len: MNAME-len } len: RNAME-len } len: 20 } -\endverbatim - */ -/// where MNAME and RNAME are wire format representations of the MNAME and -/// RNAME fields of the SOA RDATA, respectively, and "Rest of the data" -/// encodes the remaining 20 bytes of the RDATA in network byte order. -/// -/// <b>Usage of the Class</b> -/// -/// One major and common use case of the \c RdataFields class is to convert -/// a \c Rdata object (possibly given from a DNS message or some configuration -/// source such as a zone file) in the serialized format and store a copy of -/// the data somewhere in memory. The following code sample implements this -/// scenario: -/// \code // assume "rdata" is a reference type to Rdata -/// const RdataFields fields(rdata); -/// const unsigned int fields_size = fields.getFieldDataSize(); -/// memcpy(some_place, fields.getFieldSpecData(), fields_size); -/// const size_t data_length = fields.getDataLength(); -/// memcpy(other_place, fields.getData(), data_length); -/// // (fields_size and data_length should be stored somewhere, too) -/// \endcode -/// -/// Another typical usage is to render the stored data in the wire format -/// as efficiently as possible. The following code is an example of such -/// usage: -/// \code // assume "renderer" is of type MessageRenderer -/// // retrieve data_length and fields_size from the storage -/// RdataFields(some_place, fields_size, other_place, -/// data_length).toWire(renderer); -/// \endcode -/// -/// <b>Notes to Users</b> -/// -/// The main purposes of this class is to help efficient operation -/// for some (limited classes of) performance sensitive application. -/// For this reason the interface and implementation rely on relatively -/// lower-level, riskier primitives such as passing around bare pointers. -/// -/// It is therefore discouraged to use this class for general purpose -/// applications that do not need to maximize performance in terms of either -/// memory footprint or rendering speed. -/// All functionality provided by this class can be achieved via higher level -/// interfaces such as the \c Rdata class variants. -/// Normal applications should use those interfaces. -/// -/// The data format is public information so that an application can examine -/// and use selected parts of data. For example, an application may want to -/// encode domain names in RDATA in a different way while storing the other -/// data in a separate place. -/// However, at this moment the format is still in flux, and it may not -/// be compatible with future versions (see below). -/// -/// <b>Development Notes</b> -/// -/// We should conduct benchmark tests to measure rendering performance. -/// -/// The current implementation needs to re-construct name objects from -/// compressible and incompressible name fields as wire-format data. -/// This is not efficient, and we'll probably want to improve this in a -/// future version. One possibility is to store offset information as well -/// as the name data (at the cost of increasing memory footprint), and -/// to use the pair of data for faster rendering. -class RdataFields { -public: - /// Types of \c RdataFields fields. - /// - /// \c COMPRESSIBLE_NAME and \c INCOMPRESSIBLE_NAME represent a domain - /// name used as a field of an RDATA that can and cannot be compressed - /// per RFC3597. - /// \c DATA means all other types of fields. - enum Type { - DATA, ///< Plain data. - COMPRESSIBLE_NAME, ///< A domain name subject to name compression. - INCOMPRESSIBLE_NAME ///< A domain name that shouldn't be compressed. - }; - - /// Structure that specifies a single \c RdataFields field. - /// - /// This is a straightforward pair of the type and length of a single - /// \c RdataFields field. - /// - /// In some cases an application may want to do deeper inspection of - /// some \c RdataFields field(s). For example, an application may want - /// to construct a \c Name object for each domain name field of an RDATA - /// and use it for some special purpose. - /// The \c FieldSpec structure provides necessary parameters to get access - /// to a specific \c RdataFields field. - /// - /// The following code snippet implements the above example scenario: - /// \code // assume "fields" is of type RdataFields - /// size_t offset = 0; - /// for (int i = 0; i < fields.getFieldCount(); ++i) { - /// const FieldSpec spec = fields.getFieldSpec(i); - /// if (spec.type == RdataFields::COMPRESSIBLE_NAME || - /// spec.type == RdataFields::INCOMPRESSIBLE_NAME) { - /// InputBuffer ibuffer(fields.getData() + offset, spec.len); - /// Name name(ibuffer); - /// // do something with name - /// } - /// offset += spec.len; - /// } \endcode - /// - /// Note that the offset is not included in \c FieldSpec. - /// This is because such deeper inspection would be a relatively rare - /// operation while it is desirable to keep this structure as small as - /// possible for the purpose of space efficiency. - /// Also, if and when an application wants to look into a specific field, - /// it would be quite likely that the application iterates over all fields - /// and does something special for selected fields like the above example. - /// In that case the application can easily and efficiently identify the - /// necessary offset, again, as shown in the above code example. - /// - /// \todo We might find that 16bits per field is generally too much and - /// squeeze the two bit type into it as well, having 14bit length - /// (in the rare case of having too long field, it could be split into - /// multiple ones). That would save 2 bytes per item (one for the type, - /// one for padding). - struct FieldSpec { - FieldSpec(Type type_param, uint16_t len_param) : - type(type_param), len(len_param) - {} - Type type; ///< The type of the field. - uint16_t len; ///< The length of the field in bytes. - }; - - /// - /// \name Constructors and Destructor. - /// - /// \b Note: - /// The copy constructor and the assignment operator are intentionally - /// defined as private, making this class non copyable. - //@{ -private: - RdataFields(const RdataFields& source); - RdataFields& operator=(const RdataFields& source); - -public: - /// Constructor from Rdata. - /// - /// This constructor converts the data of a given \c Rdata object into - /// an \c RdataFields object so that the resulting data can be stored - /// in memory in a space-efficient way. - /// - /// It makes a local copy of the original data and dynamically allocates - /// necessary memory, so is not very efficient. - /// The basic idea is to perform the expensive conversion once and keep - /// using the result as long as possible to improve overall performance - /// in a longer term. - /// - /// If the internal resource allocation fails, a corresponding standard - /// exception will be thrown. - /// The current implementation of this constructor internally calls - /// the <code>Rdata::toWire(AbstractMessageRenderer&) const</code> method - /// for the conversion. - /// If that method throws an exception it will be propagated to the caller - /// of this constructor. - /// - /// \param rdata The RDATA for which the \c RdataFields to be constructed. - RdataFields(const Rdata& rdata); - - /// Constructor from field parameters. - /// - /// The intended usage of this version of constructor is to form a - /// structured representation of \c RDATA encoded by the other - /// constructor so that the resulting object can be used for subsequent - /// operations such as rendering in the wire format. - /// This version is intended to be efficient by not making any copy - /// of variable length data or expensive data inspection. - /// - /// This constructor is basically exception free, except against bogus - /// input parameters. - /// Specifically, the parameters must meet the following conditions; - /// otherwise an exception of class \c InvalidParameter will be thrown. - /// - \c fields can be \c NULL if and only if \c nfields is 0 - /// - \c data can be \c NULL if and only if \c data_length is 0 - /// - the sum of the lengths of \c fields entries must be equal to - /// \c data_length - /// - /// This constructor assumes that the memory region pointed by \c data (if - /// non \c NULL) is encoded as a sequence of valid \c RdataFields fields, - /// and does not perform deep inspection on each field. - /// In particular, for fields of type \c COMPRESSIBLE_NAME or - /// \c INCOMPRESSIBLE_NAME, this constructor assumes the corresponding - /// memory region is a valid representation of domain name. - /// Otherwise, a subsequent method call such as - /// <code>toWire(AbstractMessageRenderer&) const</code> - /// may trigger an unexpected exception. It also expects the fields reside - /// on address that is valid for them (eg. it has valid alignment), see - /// getFieldSpecData() for details. - /// - /// It is the caller's responsibility to ensure this assumption. - /// In general, this constructor is expected to be used for serialized data - /// generated by the other constructor from a valid \c Rdata. - /// The result is not guaranteed if the data is generated in any other - /// ways. - /// - /// The resulting \c RdataFields object does not maintain a copy of - /// \c fields or \c data. It is the caller's responsibility to ensure - /// the memory regions pointed to by these parameters are valid and intact - /// as long as the \c RdataFields object is used. - /// - /// \param fields An array of \c FieldSpec entries. This can be \c NULL. - /// \param fields_length The total length of the \c fields. - /// \param data A pointer to memory region for the entire RDATA. This can - /// be NULL. - /// \param data_length The length of \c data in bytes. - RdataFields(const void* fields, const unsigned int fields_length, - const void* data, const size_t data_length); - - /// The destructor. - ~RdataFields(); - //@} - - /// - /// \name Getter Methods - /// - //@{ - /// \brief Return the length of the entire RDATA encoded in the - /// \c RdataFields in bytes. - /// - /// This method never throws an exception. - unsigned int getDataLength() const { return (data_length_); } - - /// \brief Return a pointer to the RDATA encoded in the \c RdataFields. - /// - /// The RdataFields holds ownership of the data. - /// - /// This method never throws an exception. - const void* getData() const { return (data_); } - - /// \brief Return the number of bytes the buffer returned by - /// getFieldSpecData() will occupy. - /// - /// This method never throws an exception. - unsigned int getFieldSpecDataSize() const { return (nfields_ * - sizeof (*fields_)); } - - /// \brief Return the number of specs fields. - /// - /// It specifies the range of parameter for getFieldSpec(). - /// - /// This method never throws. - unsigned int getFieldCount() const { return (nfields_); } - - /// \brief Return a pointer to a sequence of \c FieldSpec for the - /// \c RdataFields. - /// - /// This should be treated as an opaque internal representation you can - /// just store off somewhere and use it to construct a new RdataFields. - /// from it. If you are really interested, you can typecast it to - /// FieldSpec * (which is what it really is internally). - /// - /// The RdataFields holds ownership of the data. - /// - /// \note You should, however, be aware of alignment issues. The pointer - /// you pass to the constructor must be an address where the FieldSpec - /// can live. If you store it at a wrong address (eg. even one with - /// current implementation on most architectures), it might lead bad - /// things from slow access to SIGBUS. The easiest way is not to - /// interleave the fields with data from getData(). It is OK to place - /// all the fields first (even from multiple RdataFields) and then - /// place all the data after them. - /// - /// This method never throws an exception. - const void* getFieldSpecData() const { - return (fields_); - } - - /// \brief Return the specification of the field identified by the given - /// index. - /// - /// \c field_id is the field index, which must be in the range of - /// <code>[0, getFieldCount())</code>. 0 means the first field, and - /// <code>getFieldCount()-1</code> means the last. - /// - /// If the given index is not in the valid range, an exception of class - /// \c OutOfRange will be thrown. - /// This method never throws an exception otherwise. - /// - /// \param field_id The index of an \c RdataFields field to be returned. - /// \return A \c FieldSpec structure that contains the information of - /// the \c field_id-th field. - FieldSpec getFieldSpec(const unsigned int field_id) const; - //@} - - /// - /// \name Converter Methods - /// - //@{ - /// \brief Render the RdataFields in the wire format with name compression. - /// - /// This method may require resource allocation in \c renderer. - /// If it fails, a corresponding standard exception will be thrown. - /// It should not throw any other exception as long as the \c RdataFields - /// object was constructed from valid parameters (see the description of - /// constructors). The result is not guaranteed if it's constructed in - /// any other ways. - /// - /// \param renderer DNS message rendering context that encapsulates the - /// output buffer and name compression information. - void toWire(AbstractMessageRenderer& renderer) const; - - /// \brief Render the RdataFields in the wire format without name - /// compression. - /// - /// This method may require resource allocation in \c buffer. - /// If it fails, a corresponding standard exception will be thrown. - /// - /// \param buffer An output buffer to store the wire data. - void toWire(isc::util::OutputBuffer& buffer) const; - //@} - -private: - const FieldSpec* fields_; - unsigned int nfields_; - const uint8_t* data_; - size_t data_length_; - - // hide further details within the implementation and don't create vectors - // every time we don't need them. - struct RdataFieldsDetail; - RdataFieldsDetail* detail_; -}; -} -} -} -#endif // RDATAFIELDS_H - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/rrclass-placeholder.h b/src/lib/dns/rrclass-placeholder.h index 9804c579f8..a9c4ebda0b 100644 --- a/src/lib/dns/rrclass-placeholder.h +++ b/src/lib/dns/rrclass-placeholder.h @@ -5,7 +5,9 @@ // file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef RRCLASS_H -#define RRCLASS_H 1 +#define RRCLASS_H + +#include <util/buffer.h> #include <stdint.h> @@ -24,10 +26,6 @@ #endif namespace isc { -namespace util { -class InputBuffer; -class OutputBuffer; -} namespace dns { @@ -228,7 +226,9 @@ public: /// This method never throws an exception. /// /// \return An 16-bit integer code corresponding to the RRClass. - uint16_t getCode() const { return (classcode_); } + uint16_t getCode() const { + return (classcode_); + } //@} /// @@ -243,10 +243,13 @@ public: /// /// \param other the \c RRClass object to compare against. /// \return true if the two RRClasses are equal; otherwise false. - bool equals(const RRClass& other) const - { return (classcode_ == other.classcode_); } + bool equals(const RRClass& other) const { + return (classcode_ == other.classcode_); + } /// \brief Same as \c equals(). - bool operator==(const RRClass& other) const { return (equals(other)); } + bool operator==(const RRClass& other) const { + return (equals(other)); + } /// \brief Return true iff two RRClasses are not equal. /// @@ -254,10 +257,13 @@ public: /// /// \param other the \c RRClass object to compare against. /// \return true if the two RRClasses are not equal; otherwise false. - bool nequals(const RRClass& other) const - { return (classcode_ != other.classcode_); } + bool nequals(const RRClass& other) const { + return (classcode_ != other.classcode_); + } /// \brief Same as \c nequals(). - bool operator!=(const RRClass& other) const { return (nequals(other)); } + bool operator!=(const RRClass& other) const { + return (nequals(other)); + } /// \brief Less-than comparison for RRClass against \c other /// @@ -274,8 +280,9 @@ public: /// \param other the \c RRClass object to compare against. /// \return true if \c this RRClass is less than the \c other; otherwise /// false. - bool operator<(const RRClass& other) const - { return (classcode_ < other.classcode_); } + bool operator<(const RRClass& other) const { + return (classcode_ < other.classcode_); + } // BEGIN_WELL_KNOWN_CLASS_DECLARATIONS // END_WELL_KNOWN_CLASS_DECLARATIONS @@ -306,7 +313,3 @@ operator<<(std::ostream& os, const RRClass& rrclass); } } #endif // RRCLASS_H - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/rrclass.h b/src/lib/dns/rrclass.h index 745efa6ad7..b730971454 100644 --- a/src/lib/dns/rrclass.h +++ b/src/lib/dns/rrclass.h @@ -12,7 +12,9 @@ // file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef RRCLASS_H -#define RRCLASS_H 1 +#define RRCLASS_H + +#include <util/buffer.h> #include <stdint.h> @@ -31,10 +33,6 @@ #endif namespace isc { -namespace util { -class InputBuffer; -class OutputBuffer; -} namespace dns { @@ -235,7 +233,9 @@ public: /// This method never throws an exception. /// /// \return An 16-bit integer code corresponding to the RRClass. - uint16_t getCode() const { return (classcode_); } + uint16_t getCode() const { + return (classcode_); + } //@} /// @@ -250,10 +250,14 @@ public: /// /// \param other the \c RRClass object to compare against. /// \return true if the two RRClasses are equal; otherwise false. - bool equals(const RRClass& other) const - { return (classcode_ == other.classcode_); } + bool equals(const RRClass& other) const { + return (classcode_ == other.classcode_); + } + /// \brief Same as \c equals(). - bool operator==(const RRClass& other) const { return (equals(other)); } + bool operator==(const RRClass& other) const { + return (equals(other)); + } /// \brief Return true iff two RRClasses are not equal. /// @@ -261,10 +265,13 @@ public: /// /// \param other the \c RRClass object to compare against. /// \return true if the two RRClasses are not equal; otherwise false. - bool nequals(const RRClass& other) const - { return (classcode_ != other.classcode_); } + bool nequals(const RRClass& other) const { + return (classcode_ != other.classcode_); + } /// \brief Same as \c nequals(). - bool operator!=(const RRClass& other) const { return (nequals(other)); } + bool operator!=(const RRClass& other) const { + return (nequals(other)); + } /// \brief Less-than comparison for RRClass against \c other /// @@ -281,13 +288,12 @@ public: /// \param other the \c RRClass object to compare against. /// \return true if \c this RRClass is less than the \c other; otherwise /// false. - bool operator<(const RRClass& other) const - { return (classcode_ < other.classcode_); } + bool operator<(const RRClass& other) const { + return (classcode_ < other.classcode_); + } // BEGIN_WELL_KNOWN_CLASS_DECLARATIONS static const RRClass& ANY(); - static const RRClass& CH(); - static const RRClass& HS(); static const RRClass& IN(); static const RRClass& NONE(); // END_WELL_KNOWN_CLASS_DECLARATIONS @@ -304,18 +310,6 @@ RRClass::ANY() { } inline const RRClass& -RRClass::CH() { - static RRClass rrclass(3); - return (rrclass); -} - -inline const RRClass& -RRClass::HS() { - static RRClass rrclass(4); - return (rrclass); -} - -inline const RRClass& RRClass::IN() { static RRClass rrclass(1); return (rrclass); @@ -348,7 +342,3 @@ operator<<(std::ostream& os, const RRClass& rrclass); } } #endif // RRCLASS_H - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/rrcollator.cc b/src/lib/dns/rrcollator.cc deleted file mode 100644 index 8378021675..0000000000 --- a/src/lib/dns/rrcollator.cc +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright (C) 2012-2020 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#include <config.h> - -#include <exceptions/exceptions.h> - -// include this first to check the header is self-contained. -#include <dns/rrcollator.h> - -#include <dns/name.h> -#include <dns/rdataclass.h> -#include <dns/rrclass.h> -#include <dns/rrtype.h> -#include <dns/rrttl.h> -#include <dns/rdata.h> -#include <dns/rrset.h> - -#include <algorithm> -#include <functional> - -using namespace isc::dns::rdata; -namespace ph = std::placeholders; - -namespace isc { -namespace dns { - -class RRCollator::Impl { -public: - Impl(const AddRRsetCallback& callback) : callback_(callback) {} - - void addRR(const Name& name, const RRClass& rrclass, - const RRType& rrtype, const RRTTL& rrttl, - const RdataPtr& rdata); - - RRsetPtr current_rrset_; - const AddRRsetCallback callback_; -}; - -namespace { -inline bool -isSameType(RRType type1, const ConstRdataPtr& rdata1, - const ConstRRsetPtr& rrset) -{ - if (type1 != rrset->getType()) { - return (false); - } - if (type1 == RRType::RRSIG()) { - RdataIteratorPtr rit = rrset->getRdataIterator(); - return (dynamic_cast<const generic::RRSIG&>(*rdata1).typeCovered() - == dynamic_cast<const generic::RRSIG&>( - rit->getCurrent()).typeCovered()); - } - return (true); -} -} - -void -RRCollator::Impl::addRR(const Name& name, const RRClass& rrclass, - const RRType& rrtype, const RRTTL& rrttl, - const RdataPtr& rdata) -{ - if (current_rrset_ && (!isSameType(rrtype, rdata, current_rrset_) || - current_rrset_->getClass() != rrclass || - current_rrset_->getName() != name)) { - callback_(current_rrset_); - current_rrset_.reset(); - } - - if (!current_rrset_) { - current_rrset_ = RRsetPtr(new RRset(name, rrclass, rrtype, rrttl)); - } else if (current_rrset_->getTTL() != rrttl) { - // RRs with different TTLs are given. Smaller TTL should win. - current_rrset_->setTTL(std::min(current_rrset_->getTTL(), rrttl)); - } - current_rrset_->addRdata(rdata); -} - -RRCollator::RRCollator(const AddRRsetCallback& callback) : - impl_(new Impl(callback)) -{} - -RRCollator::~RRCollator() { - delete impl_; -} - -AddRRCallback -RRCollator::getCallback() { - return (std::bind(&RRCollator::Impl::addRR, this->impl_, - ph::_1, ph::_2, ph::_3, ph::_4, ph::_5)); -} - -void -RRCollator::flush() { - if (impl_->current_rrset_) { - impl_->callback_(impl_->current_rrset_); - impl_->current_rrset_.reset(); - } -} - -} // end namespace dns -} // end namespace isc diff --git a/src/lib/dns/rrcollator.h b/src/lib/dns/rrcollator.h deleted file mode 100644 index 9442fd3970..0000000000 --- a/src/lib/dns/rrcollator.h +++ /dev/null @@ -1,125 +0,0 @@ -// Copyright (C) 2012-2020 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef RRCOLLATOR_H -#define RRCOLLATOR_H 1 - -#include <dns/master_loader_callbacks.h> -#include <dns/rrset.h> - -#include <boost/noncopyable.hpp> -#include <functional> - -namespace isc { -namespace dns { - -/// \brief A converter from a stream of RRs to a stream of collated RRsets -/// -/// This class is mainly intended to be a helper used as an adapter for -/// user applications of the \c MasterLoader class; it works as a callback -/// for \c MasterLoader, buffers given RRs from the loader, collating -/// consecutive RRs that belong to the same RRset (ones having the same -/// owner name, RR type and class), and produces a stream of RRsets through -/// its own callback. RRSIGs are also separated if their type covered fields -/// have different values even if the owner name and RR class are the same. -/// -/// It also "normalizes" TTLs of the RR; if collated RRs have different TTLs, -/// this class guarantees that the TTL of the resulting RRsets has the -/// smallest TTL among them. -/// -/// The conversion will be useful for applications of \c MasterLoader because -/// many of this library have interfaces that take an RRset object (or -/// a pointer to it). Note, however, that this class doesn't guarantee that -/// all RRs that would belong to the same RRset are collated into the same -/// single RRset. In fact, it can only collate RRs that are consecutive -/// in the original stream; once it encounters an RR of a different RRset, -/// any subsequent RRs of the previous RRset will form a separate RRset object. -/// -/// This class is non-copyable; it's partially for the convenience of internal -/// implementation details, but it actually doesn't make sense to copy -/// an object of this class, if not harmful, for the intended usage of -/// the class. -class RRCollator : boost::noncopyable { -public: - /// \brief Callback functor type for \c RRCollator. - /// - /// This type of callback is given to an \c RRCollator object on its - /// construction, and will be called for each collated RRset built in - /// the \c RRCollator. - /// - /// \param rrset The collated RRset. - typedef std::function<void(const RRsetPtr& rrset)> AddRRsetCallback; - - /// \brief Constructor. - /// - /// \throw std::bad_alloc Internal memory allocation fails. This should - /// be very rare. - /// - /// \param callback The callback functor to be called for each collated - /// RRset. - RRCollator(const AddRRsetCallback& callback); - - /// \brief Destructor. - /// - /// It only performs trivial internal cleanup. In particular, even if - /// it still has a buffered RRset it will be simply discarded. This is - /// because the given callback could throw an exception, and it's - /// impossible to predict how this class is used (to see if it's a very - /// rare case where propagating an exception from a destructor is - /// justified). Instead, the application needs to make sure that - /// \c flush() is called before the object of this class is destroyed. - /// - /// \throw None - ~RRCollator(); - - /// \brief Call the callback on the remaining RRset, if any. - /// - /// This method is expected to be called that it's supposed all RRs have - /// been passed to this class object. Since there is no explicit - /// indicator of the end of the stream, the user of this class needs to - /// explicitly call this method to call the callback for the last buffered - /// RRset (see also the destructor's description). - /// - /// If there is no buffered RRset, this method does nothing. It can happen - /// if it's called without receiving any RRs, or called more than once. - /// - /// It propagates any exception thrown from the callback; otherwise it - /// doesn't throw anything. - void flush(); - - /// \brief Return \c MasterLoader compatible callback. - /// - /// This method returns a functor in the form of \c AddRRCallback - /// that works as an adapter between \c MasterLoader and an application - /// that needs to get a stream of RRsets. When the returned callback - /// is called, this \c RRCollator object accepts the corresponding RR, - /// and collates it with other RRs of the same RRset if necessary. - /// Every time the \c RRCollator object encounters an RR of a different - /// RRset, it calls the callback passed to the constructor with the RRset - /// built so far. - /// - /// Like \c flush(), this \c AddRRCallback functor propagates any exception - /// thrown from the callback. - /// - /// This method is expected to be called only once for a given - /// \c RRCollator object. It doesn't prohibit duplicate calls, but - /// returned functor objects internally refer to the same \c RRCollator - /// object, and calling the both callbacks randomly will just cause - /// confusion. - AddRRCallback getCallback(); - -private: - class Impl; - Impl* impl_; -}; - -} // namespace dns -} // namespace isc -#endif // RRCOLLATOR_H - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/rrparamregistry-placeholder.cc b/src/lib/dns/rrparamregistry-placeholder.cc index 40214604c5..da46d12b70 100644 --- a/src/lib/dns/rrparamregistry-placeholder.cc +++ b/src/lib/dns/rrparamregistry-placeholder.cc @@ -155,25 +155,21 @@ typedef map<RRType, RdataFactoryPtr> GenericRdataFactoryMap; template <typename T> class RdataFactory : public AbstractRdataFactory { public: - virtual RdataPtr create(const string& rdata_str) const - { + virtual RdataPtr create(const string& rdata_str) const { return (RdataPtr(new T(rdata_str))); } - virtual RdataPtr create(InputBuffer& buffer, size_t rdata_len) const - { + virtual RdataPtr create(InputBuffer& buffer, size_t rdata_len) const { return (RdataPtr(new T(buffer, rdata_len))); } - virtual RdataPtr create(const Rdata& source) const - { + virtual RdataPtr create(const Rdata& source) const { return (RdataPtr(new T(dynamic_cast<const T&>(source)))); } virtual RdataPtr create(MasterLexer& lexer, const Name* origin, MasterLoader::Options options, - MasterLoaderCallbacks& callbacks) const - { + MasterLoaderCallbacks& callbacks) const { return (RdataPtr(new T(lexer, origin, options, callbacks))); } }; @@ -198,21 +194,16 @@ struct RRParamRegistryImpl { GenericRdataFactoryMap genericrdata_factories; }; -RRParamRegistry::RRParamRegistry() { - impl_ = new RRParamRegistryImpl; - - // set up parameters for well-known RRs +RRParamRegistry::RRParamRegistry() : impl_(new RRParamRegistryImpl()) { // set up parameters for well-known RRs try { // BEGIN_WELL_KNOWN_PARAMS // END_WELL_KNOWN_PARAMS } catch (...) { - delete impl_; throw; } } RRParamRegistry::~RRParamRegistry() { - delete impl_; } RRParamRegistry& @@ -274,8 +265,7 @@ RRParamRegistry::add(const std::string& typecode_string, uint16_t typecode, bool RRParamRegistry::removeRdataFactory(const RRType& rrtype, - const RRClass& rrclass) -{ + const RRClass& rrclass) { RdataFactoryMap::iterator found = impl_->rdata_factories.find(RRTypeClass(rrtype, rrclass)); if (found != impl_->rdata_factories.end()) { @@ -330,8 +320,7 @@ caseStringEqual(const string& s1, const string& s2, size_t n) { /// InvalidRRClass template <typename PT, typename MC, typename MS, typename ET> inline bool -addParam(const string& code_string, uint16_t code, MC& codemap, MS& stringmap) -{ +addParam(const string& code_string, uint16_t code, MC& codemap, MS& stringmap) { // Duplicate type check typename MC::const_iterator found = codemap.find(code); if (found != codemap.end()) { @@ -436,8 +425,7 @@ RRParamRegistry::removeType(uint16_t code) { bool RRParamRegistry::textToTypeCode(const string& type_string, - uint16_t& type_code) const -{ + uint16_t& type_code) const { return (textToCode<RRTypeParam, StrRRTypeMap> (type_string, impl_->str2typemap, type_code)); } @@ -462,8 +450,7 @@ RRParamRegistry::removeClass(uint16_t code) { bool RRParamRegistry::textToClassCode(const string& class_string, - uint16_t& class_code) const -{ + uint16_t& class_code) const { return (textToCode<RRClassParam, StrRRClassMap> (class_string, impl_->str2classmap, class_code)); } @@ -477,8 +464,7 @@ RRParamRegistry::codeToClassText(uint16_t code) const { namespace { inline const AbstractRdataFactory* findRdataFactory(RRParamRegistryImpl* reg_impl, - const RRType& rrtype, const RRClass& rrclass) -{ + const RRType& rrtype, const RRClass& rrclass) { RdataFactoryMap::const_iterator found; found = reg_impl->rdata_factories.find(RRTypeClass(rrtype, rrclass)); if (found != reg_impl->rdata_factories.end()) { @@ -497,8 +483,7 @@ findRdataFactory(RRParamRegistryImpl* reg_impl, RdataPtr RRParamRegistry::createRdata(const RRType& rrtype, const RRClass& rrclass, - const std::string& rdata_string) -{ + const std::string& rdata_string) { // If the text indicates that it's rdata of an "unknown" type (beginning // with '\# n'), parse it that way. (TBD) @@ -513,8 +498,7 @@ RRParamRegistry::createRdata(const RRType& rrtype, const RRClass& rrclass, RdataPtr RRParamRegistry::createRdata(const RRType& rrtype, const RRClass& rrclass, - InputBuffer& buffer, size_t rdata_len) -{ + InputBuffer& buffer, size_t rdata_len) { const AbstractRdataFactory* factory = findRdataFactory(impl_, rrtype, rrclass); if (factory != NULL) { @@ -526,8 +510,7 @@ RRParamRegistry::createRdata(const RRType& rrtype, const RRClass& rrclass, RdataPtr RRParamRegistry::createRdata(const RRType& rrtype, const RRClass& rrclass, - const Rdata& source) -{ + const Rdata& source) { const AbstractRdataFactory* factory = findRdataFactory(impl_, rrtype, rrclass); if (factory != NULL) { @@ -542,8 +525,7 @@ RdataPtr RRParamRegistry::createRdata(const RRType& rrtype, const RRClass& rrclass, MasterLexer& lexer, const Name* name, MasterLoader::Options options, - MasterLoaderCallbacks& callbacks) -{ + MasterLoaderCallbacks& callbacks) { const AbstractRdataFactory* factory = findRdataFactory(impl_, rrtype, rrclass); if (factory != NULL) { diff --git a/src/lib/dns/rrparamregistry.cc b/src/lib/dns/rrparamregistry.cc index 23c63829b3..91a0e5420c 100644 --- a/src/lib/dns/rrparamregistry.cc +++ b/src/lib/dns/rrparamregistry.cc @@ -57,8 +57,7 @@ CICharLess(char c1, char c2) { } struct CIStringLess { - bool operator()(const string& s1, const string& s2) const - { + bool operator()(const string& s1, const string& s2) const { return (lexicographical_compare(s1.begin(), s1.end(), s2.begin(), s2.end(), CICharLess)); } @@ -164,25 +163,21 @@ typedef map<RRType, RdataFactoryPtr> GenericRdataFactoryMap; template <typename T> class RdataFactory : public AbstractRdataFactory { public: - virtual RdataPtr create(const string& rdata_str) const - { + virtual RdataPtr create(const string& rdata_str) const { return (RdataPtr(new T(rdata_str))); } - virtual RdataPtr create(InputBuffer& buffer, size_t rdata_len) const - { + virtual RdataPtr create(InputBuffer& buffer, size_t rdata_len) const { return (RdataPtr(new T(buffer, rdata_len))); } - virtual RdataPtr create(const Rdata& source) const - { + virtual RdataPtr create(const Rdata& source) const { return (RdataPtr(new T(dynamic_cast<const T&>(source)))); } virtual RdataPtr create(MasterLexer& lexer, const Name* origin, MasterLoader::Options options, - MasterLoaderCallbacks& callbacks) const - { + MasterLoaderCallbacks& callbacks) const { return (RdataPtr(new T(lexer, origin, options, callbacks))); } }; @@ -207,116 +202,35 @@ struct RRParamRegistryImpl { GenericRdataFactoryMap genericrdata_factories; }; -RRParamRegistry::RRParamRegistry() { - impl_ = new RRParamRegistryImpl; +RRParamRegistry::RRParamRegistry() : impl_(new RRParamRegistryImpl()) { // set up parameters for well-known RRs try { // BEGIN_WELL_KNOWN_PARAMS add("A", 1, "IN", 1, RdataFactoryPtr(new RdataFactory<in::A>())); - add("NS", 2, "IN", 1, RdataFactoryPtr(new RdataFactory<generic::NS>())); - add("CNAME", 5, "IN", 1, RdataFactoryPtr(new RdataFactory<generic::CNAME>())); add("SOA", 6, "IN", 1, RdataFactoryPtr(new RdataFactory<generic::SOA>())); add("PTR", 12, "IN", 1, RdataFactoryPtr(new RdataFactory<generic::PTR>())); - add("HINFO", 13, "IN", 1, RdataFactoryPtr(new RdataFactory<generic::HINFO>())); - add("MINFO", 14, "IN", 1, RdataFactoryPtr(new RdataFactory<generic::MINFO>())); - add("MX", 15, "IN", 1, RdataFactoryPtr(new RdataFactory<generic::MX>())); - add("TXT", 16, "IN", 1, RdataFactoryPtr(new RdataFactory<generic::TXT>())); - add("RP", 17, "IN", 1, RdataFactoryPtr(new RdataFactory<generic::RP>())); - add("AFSDB", 18, "IN", 1, RdataFactoryPtr(new RdataFactory<generic::AFSDB>())); add("AAAA", 28, "IN", 1, RdataFactoryPtr(new RdataFactory<in::AAAA>())); - add("SRV", 33, "IN", 1, RdataFactoryPtr(new RdataFactory<in::SRV>())); - add("NAPTR", 35, "IN", 1, RdataFactoryPtr(new RdataFactory<generic::NAPTR>())); - add("DNAME", 39, "IN", 1, RdataFactoryPtr(new RdataFactory<generic::DNAME>())); add("OPT", 41, "IN", 1, RdataFactoryPtr(new RdataFactory<generic::OPT>())); - add("DS", 43, "IN", 1, RdataFactoryPtr(new RdataFactory<generic::DS>())); - add("SSHFP", 44, "IN", 1, RdataFactoryPtr(new RdataFactory<generic::SSHFP>())); add("RRSIG", 46, "IN", 1, RdataFactoryPtr(new RdataFactory<generic::RRSIG>())); - add("NSEC", 47, "IN", 1, RdataFactoryPtr(new RdataFactory<generic::NSEC>())); - add("DNSKEY", 48, "IN", 1, RdataFactoryPtr(new RdataFactory<generic::DNSKEY>())); add("DHCID", 49, "IN", 1, RdataFactoryPtr(new RdataFactory<in::DHCID>())); - add("NSEC3", 50, "IN", 1, RdataFactoryPtr(new RdataFactory<generic::NSEC3>())); - add("NSEC3PARAM", 51, "IN", 1, RdataFactoryPtr(new RdataFactory<generic::NSEC3PARAM>())); - add("TLSA", 52, "IN", 1, RdataFactoryPtr(new RdataFactory<generic::TLSA>())); - add("SPF", 99, "IN", 1, RdataFactoryPtr(new RdataFactory<generic::SPF>())); add("TKEY", 249, "IN", 1, RdataFactoryPtr(new RdataFactory<generic::TKEY>())); - add("CAA", 257, "IN", 1, RdataFactoryPtr(new RdataFactory<generic::CAA>())); - add("DLV", 32769, "IN", 1, RdataFactoryPtr(new RdataFactory<generic::DLV>())); - add("A", 1, "CH", 3, RdataFactoryPtr(new RdataFactory<ch::A>())); - add("A", 1, "HS", 4, RdataFactoryPtr(new RdataFactory<hs::A>())); add("TSIG", 250, "ANY", 255, RdataFactoryPtr(new RdataFactory<any::TSIG>())); - add("NS", 2, RdataFactoryPtr(new RdataFactory<generic::NS>())); - add("CNAME", 5, RdataFactoryPtr(new RdataFactory<generic::CNAME>())); add("SOA", 6, RdataFactoryPtr(new RdataFactory<generic::SOA>())); add("PTR", 12, RdataFactoryPtr(new RdataFactory<generic::PTR>())); - add("HINFO", 13, RdataFactoryPtr(new RdataFactory<generic::HINFO>())); - add("MINFO", 14, RdataFactoryPtr(new RdataFactory<generic::MINFO>())); - add("MX", 15, RdataFactoryPtr(new RdataFactory<generic::MX>())); - add("TXT", 16, RdataFactoryPtr(new RdataFactory<generic::TXT>())); - add("RP", 17, RdataFactoryPtr(new RdataFactory<generic::RP>())); - add("AFSDB", 18, RdataFactoryPtr(new RdataFactory<generic::AFSDB>())); - add("NAPTR", 35, RdataFactoryPtr(new RdataFactory<generic::NAPTR>())); - add("DNAME", 39, RdataFactoryPtr(new RdataFactory<generic::DNAME>())); add("OPT", 41, RdataFactoryPtr(new RdataFactory<generic::OPT>())); - add("DS", 43, RdataFactoryPtr(new RdataFactory<generic::DS>())); - add("SSHFP", 44, RdataFactoryPtr(new RdataFactory<generic::SSHFP>())); add("RRSIG", 46, RdataFactoryPtr(new RdataFactory<generic::RRSIG>())); - add("NSEC", 47, RdataFactoryPtr(new RdataFactory<generic::NSEC>())); - add("DNSKEY", 48, RdataFactoryPtr(new RdataFactory<generic::DNSKEY>())); - add("NSEC3", 50, RdataFactoryPtr(new RdataFactory<generic::NSEC3>())); - add("NSEC3PARAM", 51, RdataFactoryPtr(new RdataFactory<generic::NSEC3PARAM>())); - add("TLSA", 52, RdataFactoryPtr(new RdataFactory<generic::TLSA>())); - add("SPF", 99, RdataFactoryPtr(new RdataFactory<generic::SPF>())); add("TKEY", 249, RdataFactoryPtr(new RdataFactory<generic::TKEY>())); - add("CAA", 257, RdataFactoryPtr(new RdataFactory<generic::CAA>())); - add("DLV", 32769, RdataFactoryPtr(new RdataFactory<generic::DLV>())); - // Meta and non-implemented RR types - addType("IXFR", 251); - addType("AXFR", 252); addType("ANY", 255); - addType("MD", 3); - addType("MF", 4); - addType("MB", 7); - addType("MG", 8); - addType("MR", 9); - addType("NXT", 30); - addType("A6", 38); - addType("MAILA", 254); - addType("NULL", 10); - addType("WKS", 11); - addType("X25", 19); - addType("RT", 21); - addType("NSAP", 22); - addType("NSAP-PTR", 23); - addType("SIG", 24); - addType("ISDN", 20); - addType("KEY", 25); - addType("PX", 26); - addType("GPOS", 27); - addType("LOC", 29); - addType("KX", 36); - addType("CERT", 37); - addType("APL", 42); - addType("IPSECKEY", 45); - addType("HIP", 55); - addType("UNSPEC", 103); - addType("NID", 104); - addType("L32", 105); - addType("L64", 106); - addType("LP", 107); - addType("MAILB", 253); - addType("URI", 256); // Meta classes addClass("NONE", 254); // END_WELL_KNOWN_PARAMS } catch (...) { - delete impl_; throw; } } RRParamRegistry::~RRParamRegistry() { - delete impl_; } RRParamRegistry& @@ -328,8 +242,7 @@ RRParamRegistry::getRegistry() { void RRParamRegistry::add(const std::string& typecode_string, uint16_t typecode, - RdataFactoryPtr rdata_factory) -{ + RdataFactoryPtr rdata_factory) { bool type_added = false; try { type_added = addType(typecode_string, typecode); @@ -347,8 +260,7 @@ RRParamRegistry::add(const std::string& typecode_string, uint16_t typecode, void RRParamRegistry::add(const std::string& typecode_string, uint16_t typecode, const std::string& classcode_string, uint16_t classcode, - RdataFactoryPtr rdata_factory) -{ + RdataFactoryPtr rdata_factory) { // Rollback logic on failure is complicated. If adding the new type or // class fails, we should revert to the original state, cleaning up // intermediate state. But we need to make sure that we don't remove @@ -378,8 +290,7 @@ RRParamRegistry::add(const std::string& typecode_string, uint16_t typecode, bool RRParamRegistry::removeRdataFactory(const RRType& rrtype, - const RRClass& rrclass) -{ + const RRClass& rrclass) { RdataFactoryMap::iterator found = impl_->rdata_factories.find(RRTypeClass(rrtype, rrclass)); if (found != impl_->rdata_factories.end()) { @@ -434,8 +345,7 @@ caseStringEqual(const string& s1, const string& s2, size_t n) { /// InvalidRRClass template <typename PT, typename MC, typename MS, typename ET> inline bool -addParam(const string& code_string, uint16_t code, MC& codemap, MS& stringmap) -{ +addParam(const string& code_string, uint16_t code, MC& codemap, MS& stringmap) { // Duplicate type check typename MC::const_iterator found = codemap.find(code); if (found != codemap.end()) { @@ -540,8 +450,7 @@ RRParamRegistry::removeType(uint16_t code) { bool RRParamRegistry::textToTypeCode(const string& type_string, - uint16_t& type_code) const -{ + uint16_t& type_code) const { return (textToCode<RRTypeParam, StrRRTypeMap> (type_string, impl_->str2typemap, type_code)); } @@ -566,8 +475,7 @@ RRParamRegistry::removeClass(uint16_t code) { bool RRParamRegistry::textToClassCode(const string& class_string, - uint16_t& class_code) const -{ + uint16_t& class_code) const { return (textToCode<RRClassParam, StrRRClassMap> (class_string, impl_->str2classmap, class_code)); } @@ -581,8 +489,7 @@ RRParamRegistry::codeToClassText(uint16_t code) const { namespace { inline const AbstractRdataFactory* findRdataFactory(RRParamRegistryImpl* reg_impl, - const RRType& rrtype, const RRClass& rrclass) -{ + const RRType& rrtype, const RRClass& rrclass) { RdataFactoryMap::const_iterator found; found = reg_impl->rdata_factories.find(RRTypeClass(rrtype, rrclass)); if (found != reg_impl->rdata_factories.end()) { @@ -601,13 +508,12 @@ findRdataFactory(RRParamRegistryImpl* reg_impl, RdataPtr RRParamRegistry::createRdata(const RRType& rrtype, const RRClass& rrclass, - const std::string& rdata_string) -{ + const std::string& rdata_string) { // If the text indicates that it's rdata of an "unknown" type (beginning // with '\# n'), parse it that way. (TBD) const AbstractRdataFactory* factory = - findRdataFactory(impl_, rrtype, rrclass); + findRdataFactory(impl_.get(), rrtype, rrclass); if (factory != NULL) { return (factory->create(rdata_string)); } @@ -617,10 +523,9 @@ RRParamRegistry::createRdata(const RRType& rrtype, const RRClass& rrclass, RdataPtr RRParamRegistry::createRdata(const RRType& rrtype, const RRClass& rrclass, - InputBuffer& buffer, size_t rdata_len) -{ + InputBuffer& buffer, size_t rdata_len) { const AbstractRdataFactory* factory = - findRdataFactory(impl_, rrtype, rrclass); + findRdataFactory(impl_.get(), rrtype, rrclass); if (factory != NULL) { return (factory->create(buffer, rdata_len)); } @@ -630,10 +535,9 @@ RRParamRegistry::createRdata(const RRType& rrtype, const RRClass& rrclass, RdataPtr RRParamRegistry::createRdata(const RRType& rrtype, const RRClass& rrclass, - const Rdata& source) -{ + const Rdata& source) { const AbstractRdataFactory* factory = - findRdataFactory(impl_, rrtype, rrclass); + findRdataFactory(impl_.get(), rrtype, rrclass); if (factory != NULL) { return (factory->create(source)); } @@ -646,10 +550,9 @@ RdataPtr RRParamRegistry::createRdata(const RRType& rrtype, const RRClass& rrclass, MasterLexer& lexer, const Name* name, MasterLoader::Options options, - MasterLoaderCallbacks& callbacks) -{ + MasterLoaderCallbacks& callbacks) { const AbstractRdataFactory* factory = - findRdataFactory(impl_, rrtype, rrclass); + findRdataFactory(impl_.get(), rrtype, rrclass); if (factory != NULL) { return (factory->create(lexer, name, options, callbacks)); } diff --git a/src/lib/dns/rrparamregistry.h b/src/lib/dns/rrparamregistry.h index 27e8a4fc2d..36aa1e6b45 100644 --- a/src/lib/dns/rrparamregistry.h +++ b/src/lib/dns/rrparamregistry.h @@ -533,13 +533,9 @@ public: //@} private: - RRParamRegistryImpl* impl_; + boost::shared_ptr<RRParamRegistryImpl> impl_; }; } } #endif // RRPARAMREGISTRY_H - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/rrset.cc b/src/lib/dns/rrset.cc index 92bc7ce8bf..5458279197 100644 --- a/src/lib/dns/rrset.cc +++ b/src/lib/dns/rrset.cc @@ -228,13 +228,11 @@ BasicRRsetImpl::toWire(AbstractMessageRenderer& renderer, size_t limit) const { } BasicRRset::BasicRRset(const Name& name, const RRClass& rrclass, - const RRType& rrtype, const RRTTL& ttl) -{ - impl_ = new BasicRRsetImpl(name, rrclass, rrtype, ttl); + const RRType& rrtype, const RRTTL& ttl) { + impl_.reset(new BasicRRsetImpl(name, rrclass, rrtype, ttl)); } BasicRRset::~BasicRRset() { - delete impl_; } void @@ -348,12 +346,11 @@ BasicRRset::toWire(AbstractMessageRenderer& renderer) const { RRset::RRset(const Name& name, const RRClass& rrclass, const RRType& rrtype, const RRTTL& ttl) : - BasicRRset(name, rrclass, rrtype, ttl) -{ - rrsig_ = RRsetPtr(); + BasicRRset(name, rrclass, rrtype, ttl) { } -RRset::~RRset() {} +RRset::~RRset() { +} unsigned int RRset::getRRsigDataCount() const { @@ -417,10 +414,12 @@ class BasicRdataIterator : public RdataIterator { public: /// @brief Constructor. BasicRdataIterator(const std::vector<rdata::ConstRdataPtr>& datavector) : - datavector_(&datavector), it_(datavector_->begin()) {} + datavector_(&datavector), it_(datavector_->begin()) { + } /// @brief Destructor. - ~BasicRdataIterator() {} + ~BasicRdataIterator() { + } /// @brief Set iterator at first position. virtual void first() { diff --git a/src/lib/dns/rrset.h b/src/lib/dns/rrset.h index d17846aa97..ece89697ad 100644 --- a/src/lib/dns/rrset.h +++ b/src/lib/dns/rrset.h @@ -5,7 +5,7 @@ // file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef RRSET_H -#define RRSET_H 1 +#define RRSET_H #include <iostream> #include <string> @@ -836,7 +836,7 @@ public: } //@} private: - BasicRRsetImpl* impl_; + boost::shared_ptr<BasicRRsetImpl> impl_; }; /// \brief The \c RRset class is a concrete derived class of @@ -953,6 +953,3 @@ std::ostream& operator<<(std::ostream& os, const AbstractRRset& rrset); } // end of namespace isc #endif // RRSET_H -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/rrset_collection.cc b/src/lib/dns/rrset_collection.cc deleted file mode 100644 index a98ed16ae7..0000000000 --- a/src/lib/dns/rrset_collection.cc +++ /dev/null @@ -1,123 +0,0 @@ -// Copyright (C) 2012-2020 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#include <config.h> - -#include <dns/rrset_collection.h> -#include <dns/master_loader_callbacks.h> -#include <dns/master_loader.h> -#include <dns/rrcollator.h> - -#include <exceptions/exceptions.h> - -#include <functional> - -using namespace isc; -namespace ph = std::placeholders; - -namespace isc { -namespace dns { - -void -RRsetCollection::loaderCallback(const std::string&, size_t, const std::string&) -{ - // We just ignore callbacks for errors and warnings. -} - -void -RRsetCollection::addRRset(RRsetPtr rrset) { - const CollectionKey key(rrset->getClass(), rrset->getType(), - rrset->getName()); - CollectionMap::const_iterator it = rrsets_.find(key); - if (it != rrsets_.end()) { - isc_throw(InvalidParameter, - "RRset for " << rrset->getName() << "/" << rrset->getClass() - << " with type " << rrset->getType() << " already exists"); - } - - rrsets_.insert(std::pair<CollectionKey, RRsetPtr>(key, rrset)); -} - -template<typename T> -void -RRsetCollection::constructHelper(T source, const isc::dns::Name& origin, - const isc::dns::RRClass& rrclass) -{ - RRCollator collator(std::bind(&RRsetCollection::addRRset, this, ph::_1)); - MasterLoaderCallbacks callbacks - (std::bind(&RRsetCollection::loaderCallback, this, ph::_1, ph::_2, ph::_3), - std::bind(&RRsetCollection::loaderCallback, this, ph::_1, ph::_2, ph::_3)); - MasterLoader loader(source, origin, rrclass, callbacks, - collator.getCallback(), - MasterLoader::DEFAULT); - loader.load(); - collator.flush(); -} - -RRsetCollection::RRsetCollection(const char* filename, const Name& origin, - const RRClass& rrclass) -{ - constructHelper(filename, origin, rrclass); -} - -RRsetCollection::RRsetCollection(std::istream& input_stream, const Name& origin, - const RRClass& rrclass) -{ - constructHelper<std::istream&>(input_stream, origin, rrclass); -} - -RRsetPtr -RRsetCollection::find(const Name& name, const RRClass& rrclass, - const RRType& rrtype) { - const CollectionKey key(rrclass, rrtype, name); - CollectionMap::iterator it = rrsets_.find(key); - if (it != rrsets_.end()) { - return (it->second); - } - return (RRsetPtr()); -} - -ConstRRsetPtr -RRsetCollection::find(const Name& name, const RRClass& rrclass, - const RRType& rrtype) const -{ - const CollectionKey key(rrclass, rrtype, name); - CollectionMap::const_iterator it = rrsets_.find(key); - if (it != rrsets_.end()) { - return (it->second); - } - return (ConstRRsetPtr()); -} - -bool -RRsetCollection::removeRRset(const Name& name, const RRClass& rrclass, - const RRType& rrtype) -{ - const CollectionKey key(rrclass, rrtype, name); - - CollectionMap::iterator it = rrsets_.find(key); - if (it == rrsets_.end()) { - return (false); - } - - rrsets_.erase(it); - return (true); -} - -RRsetCollectionBase::IterPtr -RRsetCollection::getBeginning() { - CollectionMap::iterator it = rrsets_.begin(); - return (RRsetCollectionBase::IterPtr(new DnsIter(it))); -} - -RRsetCollectionBase::IterPtr -RRsetCollection::getEnd() { - CollectionMap::iterator it = rrsets_.end(); - return (RRsetCollectionBase::IterPtr(new DnsIter(it))); -} - -} // end of namespace dns -} // end of namespace isc diff --git a/src/lib/dns/rrset_collection.h b/src/lib/dns/rrset_collection.h deleted file mode 100644 index 7fb1e9c78b..0000000000 --- a/src/lib/dns/rrset_collection.h +++ /dev/null @@ -1,164 +0,0 @@ -// Copyright (C) 2012-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef RRSET_COLLECTION_H -#define RRSET_COLLECTION_H 1 - -#include <dns/rrset_collection_base.h> -#include <dns/rrclass.h> - -#include <boost/tuple/tuple.hpp> -#include <boost/tuple/tuple_comparison.hpp> - -#include <map> - -namespace isc { -namespace dns { - -/// \brief libdns++ implementation of RRsetCollectionBase using an STL -/// container. -class RRsetCollection : public RRsetCollectionBase { -public: - /// \brief Constructor. - /// - /// This constructor creates an empty collection without any data in - /// it. RRsets can be added to the collection with the \c addRRset() - /// method. - RRsetCollection() {} - - /// \brief Constructor. - /// - /// The \c origin and \c rrclass arguments are required for the zone - /// loading, but \c RRsetCollection itself does not do any - /// validation, and the collection of RRsets does not have to form a - /// valid zone. - /// - /// \throws MasterLoaderError if there is an error during loading. - /// \param filename Name of a file containing a collection of RRs in - /// the master file format (which may or may not form a valid zone). - /// \param origin The zone origin. - /// \param rrclass The zone class. - RRsetCollection(const char* filename, const isc::dns::Name& origin, - const isc::dns::RRClass& rrclass); - - /// \brief Constructor. - /// - /// This constructor is similar to the previous one, but instead of - /// taking a filename to load a zone from, it takes an input - /// stream. - /// - /// \throws MasterLoaderError if there is an error during loading. - /// \param input_stream The input stream to load from. - /// \param origin The zone origin. - /// \param rrclass The zone class. - RRsetCollection(std::istream& input_stream, const isc::dns::Name& origin, - const isc::dns::RRClass& rrclass); - - /// \brief Destructor - virtual ~RRsetCollection() {} - - /// \brief Add an RRset to the collection. - /// - /// Does not do any validation whether \c rrset belongs to a - /// particular zone or not. A reference to \c rrset is taken in an - /// internally managed \c shared_ptr, so even if the caller's - /// \c RRsetPtr is destroyed, the RRset it wrapped is still alive - /// and managed by the \c RRsetCollection. It throws an - /// \c isc::InvalidParameter exception if an rrset with the same - /// class, type and name already exists. - /// - /// Callers must not modify the RRset after adding it to the - /// collection, as the rrset is indexed internally by the - /// collection. - void addRRset(isc::dns::RRsetPtr rrset); - - /// \brief Remove an RRset from the collection. - /// - /// RRset(s) matching the \c name, \c rrclass and \c rrtype are - /// removed from the collection. - /// - /// \return \c true if a matching RRset was deleted, \c false if no - /// such RRset exists. - bool removeRRset(const isc::dns::Name& name, - const isc::dns::RRClass& rrclass, - const isc::dns::RRType& rrtype); - - /// \brief Find a matching RRset in the collection. - /// - /// Returns the RRset in the collection that exactly matches the - /// given \c name, \c rrclass and \c rrtype. If no matching RRset - /// is found, \c NULL is returned. - /// - /// \param name The name of the RRset to search for. - /// \param rrclass The class of the RRset to search for. - /// \param rrtype The type of the RRset to search for. - /// \return The RRset if found, \c NULL otherwise. - virtual isc::dns::ConstRRsetPtr find(const isc::dns::Name& name, - const isc::dns::RRClass& rrclass, - const isc::dns::RRType& rrtype) const; - - /// \brief Find a matching RRset in the collection (non-const - /// variant). - /// - /// See above for a description of the method and arguments. - isc::dns::RRsetPtr find(const isc::dns::Name& name, - const isc::dns::RRClass& rrclass, - const isc::dns::RRType& rrtype); - -private: - template<typename T> - void constructHelper(T source, const isc::dns::Name& origin, - const isc::dns::RRClass& rrclass); - void loaderCallback(const std::string&, size_t, const std::string&); - - typedef boost::tuple<isc::dns::RRClass, isc::dns::RRType, isc::dns::Name> - CollectionKey; - typedef std::map<CollectionKey, isc::dns::RRsetPtr> CollectionMap; - - CollectionMap rrsets_; - -protected: - class DnsIter : public RRsetCollectionBase::Iter { - public: - DnsIter(CollectionMap::iterator& iter) : - iter_(iter) - {} - - virtual const isc::dns::AbstractRRset& getValue() { - isc::dns::RRsetPtr& rrset = iter_->second; - return (*rrset); - } - - virtual IterPtr getNext() { - CollectionMap::iterator it = iter_; - ++it; - return (RRsetCollectionBase::IterPtr(new DnsIter(it))); - } - - virtual bool equals(Iter& other) { - const DnsIter* other_real = dynamic_cast<DnsIter*>(&other); - if (other_real == NULL) { - return (false); - } - return (iter_ == other_real->iter_); - } - - private: - CollectionMap::iterator iter_; - }; - - virtual RRsetCollectionBase::IterPtr getBeginning(); - virtual RRsetCollectionBase::IterPtr getEnd(); -}; - -} // end of namespace dns -} // end of namespace isc - -#endif // RRSET_COLLECTION_H - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/rrset_collection_base.h b/src/lib/dns/rrset_collection_base.h deleted file mode 100644 index a8ca2551c6..0000000000 --- a/src/lib/dns/rrset_collection_base.h +++ /dev/null @@ -1,214 +0,0 @@ -// Copyright (C) 2012-2022 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef RRSET_COLLECTION_BASE_H -#define RRSET_COLLECTION_BASE_H 1 - -#include <dns/rrset.h> -#include <dns/name.h> - -#include <boost/shared_ptr.hpp> - -#include <iterator> - -namespace isc { -namespace dns { - -/// \brief Error during RRsetCollectionBase find() operation -/// -/// This exception is thrown when calling an implementation of -/// \c RRsetCollectionBase::find() results in an error which is not due -/// to unmatched data, but because of some other underlying error -/// condition. -class RRsetCollectionError : public Exception { -public: - RRsetCollectionError(const char* file, size_t line, const char* what) : - Exception(file, line, what) - {} -}; - -/// \brief Generic class to represent a set of RRsets. -/// -/// This is a generic container and the stored set of RRsets does not -/// necessarily form a valid zone (e.g. there doesn't necessarily have -/// to be an SOA at the "origin"). Instead, it will be used to represent -/// a single zone for the purpose of zone loading/checking. It provides -/// a simple find() method to find an RRset for the given name and type -/// (and maybe class) and a way to iterate over all RRsets. -/// -/// See \c RRsetCollection for a simple libdns++ implementation using an -/// STL container. libdatasrc will have another implementation. -class RRsetCollectionBase { -public: - /// \brief Find a matching RRset in the collection. - /// - /// Returns the RRset in the collection that exactly matches the - /// given \c name, \c rrclass and \c rrtype. If no matching RRset - /// is found, \c NULL is returned. - /// - /// This method's implementations currently are not specified to - /// handle \c RRTypes such as RRSIG and NSEC3. This interface may be - /// refined to clarify this point in the future, and perhaps, provide - /// additional API for these RRType. - /// - /// As for RRSIG, there are some fundamental open questions. For - /// example, it's not clear whether we want to return all RRSIGs of - /// the given name covering any RR types (in which case, we need to - /// figure out how), or we need to extend the interface so we can - /// specify the covered type. A specific derived implementation may - /// return something if type RRSIG is specified, but this is not - /// specified here at the base class level. So, for RRSIGs the - /// behavior should be assumed as undefined. - /// - /// As for NSEC3, it's not clear whether owner names (which included - /// hashed labels) are the best choice of search key, because in many - /// cases, what the application wants to find is an NSEC3 that has the - /// hash of some particular "normal" domain names. Also, if the underlying - /// implementation encapsulates a single zone, NSEC3 records conceptually - /// belong to a separate name space, which may cause implementation - /// difficulty. - /// - /// Behavior with meta types such as ANY and AXFR are also - /// undefined. A specific implementation may return something for - /// these. But, unlike the case of RRSIGs, these types of RRsets - /// are not expected to be added to any implementation of - /// collection in the first place (by the definition of "meta - /// types"), so querying for such types is basically an invalid - /// operation. The API doesn't require implementations to check - /// this condition and reject it, so the behavior is - /// undefined. This interface will not be refined in future - /// versions for these meta types. - /// - /// \throw RRsetCollectionError if find() results in some - /// implementation-specific error. - /// \param name The name of the RRset to search for. - /// \param rrtype The type of the RRset to search for. - /// \param rrclass The class of the RRset to search for. - /// \return The RRset if found, \c NULL otherwise. - virtual isc::dns::ConstRRsetPtr find - (const isc::dns::Name& name, const isc::dns::RRClass& rrclass, - const isc::dns::RRType& rrtype) - const = 0; - - /// \brief Destructor - virtual ~RRsetCollectionBase() {} - -protected: - class Iter; // forward declaration - - /// \brief Wraps Iter with a reference count. - typedef boost::shared_ptr<Iter> IterPtr; - - /// \brief A helper iterator interface for \c RRsetCollectionBase. - /// - /// This is a protected iterator class that is a helper interface - /// used by the public iterator. Derived classes of - /// \c RRsetCollectionBase are supposed to implement this class and - /// the \c getBeginning() and \c getEnd() methods, so that the - /// public iterator interface can be provided. This is a forward - /// iterator only. - class Iter { - public: - virtual ~Iter() {}; - - /// \brief Returns the \c AbstractRRset currently pointed to by - /// the iterator. - virtual const isc::dns::AbstractRRset& getValue() = 0; - - /// \brief Returns an \c IterPtr wrapping an Iter pointing to - /// the next \c AbstractRRset in sequence in the collection. - virtual IterPtr getNext() = 0; - - /// \brief Check if another iterator is equal to this one. - /// - /// Returns \c true if this iterator is equal to \c other, - /// \c false otherwise. Note that if \c other is not the same - /// type as \c this, or cannot be compared meaningfully, the - /// method must return \c false. - /// - /// \param other The other iterator to compare against. - /// \return \c true if equal, \c false otherwise. - virtual bool equals(Iter& other) = 0; - }; - - /// \brief Returns an \c IterPtr wrapping an Iter pointing to the - /// beginning of the collection. - /// - /// \throw isc::dns::RRsetCollectionError if using the iterator - /// results in some underlying datasrc error. - virtual IterPtr getBeginning() = 0; - - /// \brief Returns an \c IterPtr wrapping an Iter pointing past the - /// end of the collection. - /// - /// \throw isc::dns::RRsetCollectionError if using the iterator - /// results in some underlying datasrc error. - virtual IterPtr getEnd() = 0; - -public: - /// \brief A forward \c std::iterator for \c RRsetCollectionBase. - /// - /// It behaves like a \c std::iterator forward iterator, so please - /// see its documentation for usage. - class Iterator { - public: - // Aliases used to enable iterator behavior on this class - using iterator_category = std::forward_iterator_tag; - using value_type = isc::dns::AbstractRRset const; - using difference_type = std::ptrdiff_t; - using pointer = isc::dns::AbstractRRset const*; - using reference = isc::dns::AbstractRRset const&; - - explicit Iterator(IterPtr iter) : - iter_(iter) - {} - - reference operator*() { - return (iter_->getValue()); - } - - Iterator& operator++() { - iter_ = iter_->getNext(); - return (*this); - } - - Iterator operator++(int) { - Iterator tmp(iter_); - ++*this; - return (tmp); - } - - bool operator==(const Iterator& other) const { - return (iter_->equals(*other.iter_)); - } - - bool operator!=(const Iterator& other) const { - return (!iter_->equals(*other.iter_)); - } - - private: - IterPtr iter_; - }; - - /// \brief Returns an iterator pointing to the beginning of the - /// collection. - Iterator begin() { - return Iterator(getBeginning()); - } - - /// \brief Returns an iterator pointing past the end of the - /// collection. - Iterator end() { - return Iterator(getEnd()); - } -}; - -typedef boost::shared_ptr<RRsetCollectionBase> RRsetCollectionPtr; - -} // end of namespace dns -} // end of namespace isc - -#endif // RRSET_COLLECTION_BASE_H diff --git a/src/lib/dns/rrttl.h b/src/lib/dns/rrttl.h index abda3e5c31..d6675ec702 100644 --- a/src/lib/dns/rrttl.h +++ b/src/lib/dns/rrttl.h @@ -5,20 +5,16 @@ // file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef RRTTL_H -#define RRTTL_H 1 +#define RRTTL_H #include <dns/exceptions.h> +#include <util/buffer.h> #include <boost/optional.hpp> #include <stdint.h> namespace isc { -namespace util { -class InputBuffer; -class OutputBuffer; -} - namespace dns { // forward declarations @@ -65,7 +61,8 @@ public: /// This constructor never throws an exception. /// /// \param ttlval An 32-bit integer of the RRTTL. - explicit RRTTL(uint32_t ttlval) : ttlval_(ttlval) {} + explicit RRTTL(uint32_t ttlval) : ttlval_(ttlval) { + } /// Constructor from a string. /// @@ -173,7 +170,9 @@ public: /// This method never throws an exception. /// /// \return An 32-bit integer corresponding to the RRTTL. - uint32_t getValue() const { return (ttlval_); } + uint32_t getValue() const { + return (ttlval_); + } //@} /// @@ -189,21 +188,25 @@ public: /// This method never throws an exception. /// /// \param other the \c RRTTL object to compare against. - bool equals(const RRTTL& other) const - { return (ttlval_ == other.ttlval_); } + bool equals(const RRTTL& other) const { + return (ttlval_ == other.ttlval_); + } /// \brief Same as \c equals(). - bool operator==(const RRTTL& other) const - { return (ttlval_ == other.ttlval_); } + bool operator==(const RRTTL& other) const { + return (ttlval_ == other.ttlval_); + } /// \brief Return true iff two RRTTLs are not equal. /// /// This method never throws an exception. /// /// \param other the \c RRTTL object to compare against. - bool nequals(const RRTTL& other) const - { return (ttlval_ != other.ttlval_); } + bool nequals(const RRTTL& other) const { + return (ttlval_ != other.ttlval_); + } /// \brief Same as \c nequals(). - bool operator!=(const RRTTL& other) const - { return (ttlval_ != other.ttlval_); } + bool operator!=(const RRTTL& other) const { + return (ttlval_ != other.ttlval_); + } /// \brief Less-than or equal comparison for RRTTL against \c other. /// /// This method never throws an exception. @@ -211,12 +214,14 @@ public: /// \param other the \c RRTTL object to compare against. /// \return true if \c this RRTTL is less than or equal to the \c other; /// otherwise false. - bool leq(const RRTTL& other) const - { return (ttlval_ <= other.ttlval_); } + bool leq(const RRTTL& other) const { + return (ttlval_ <= other.ttlval_); + } /// Same as \c leq() - bool operator<=(const RRTTL& other) const - { return (ttlval_ <= other.ttlval_); } + bool operator<=(const RRTTL& other) const { + return (ttlval_ <= other.ttlval_); + } /// \brief Greater-than or equal comparison for RRTTL against \c other. /// @@ -225,12 +230,14 @@ public: /// \param other the \c RRTTL object to compare against. /// \return true if \c this RRTTL is greater than or equal to the \c other; /// otherwise false. - bool geq(const RRTTL& other) const - { return (ttlval_ >= other.ttlval_); } + bool geq(const RRTTL& other) const { + return (ttlval_ >= other.ttlval_); + } /// Same as \c geq() - bool operator>=(const RRTTL& other) const - { return (ttlval_ >= other.ttlval_); } + bool operator>=(const RRTTL& other) const { + return (ttlval_ >= other.ttlval_); + } /// \brief Less-than comparison for RRTTL against \c other. /// @@ -239,12 +246,14 @@ public: /// \param other the \c RRTTL object to compare against. /// \return true if \c this RRTTL is less than the \c other; /// otherwise false. - bool lthan(const RRTTL& other) const - { return (ttlval_ < other.ttlval_); } + bool lthan(const RRTTL& other) const { + return (ttlval_ < other.ttlval_); + } /// Same as \c lthan() - bool operator<(const RRTTL& other) const - { return (ttlval_ < other.ttlval_); } + bool operator<(const RRTTL& other) const { + return (ttlval_ < other.ttlval_); + } /// \brief Greater-than comparison for RRTTL against \c other. /// @@ -253,12 +262,14 @@ public: /// \param other the \c RRTTL object to compare against. /// \return true if \c this RRTTL is greater than the \c other; /// otherwise false. - bool gthan(const RRTTL& other) const - { return (ttlval_ > other.ttlval_); } + bool gthan(const RRTTL& other) const { + return (ttlval_ > other.ttlval_); + } /// Same as \c gthan() - bool operator>(const RRTTL& other) const - { return (ttlval_ > other.ttlval_); } + bool operator>(const RRTTL& other) const { + return (ttlval_ > other.ttlval_); + } //@} /// @@ -300,7 +311,3 @@ operator<<(std::ostream& os, const RRTTL& rrttl); } } #endif // RRTTL_H - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/rrtype-placeholder.h b/src/lib/dns/rrtype-placeholder.h index e86e2f66ec..4e9c99acce 100644 --- a/src/lib/dns/rrtype-placeholder.h +++ b/src/lib/dns/rrtype-placeholder.h @@ -5,14 +5,15 @@ // file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef RRTYPE_H -#define RRTYPE_H 1 +#define RRTYPE_H #include <stdint.h> #include <string> #include <ostream> -#include <dns/exceptions.h> +#include <dns/exceptions.h>' +#include <util/buffer.h> // Solaris x86 defines DS in <sys/regset.h>, which gets pulled in by Boost #if defined(__sun) && defined(DS) @@ -20,36 +21,10 @@ #endif namespace isc { -namespace util { -class InputBuffer; -class OutputBuffer; -} - namespace dns { // forward declarations 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 DNSTextError { -public: - InvalidRRType(const char* file, size_t line, const char* what) : - DNSTextError(file, line, what) {} -}; - -/// -/// \brief A standard DNS module exception that is thrown if an RRType object -/// is being constructed from a incomplete (too short) wire-format data. -/// -class IncompleteRRType : public isc::dns::Exception { -public: - IncompleteRRType(const char* file, size_t line, const char* what) : - isc::dns::Exception(file, line, what) {} -}; - /// /// The \c RRType class encapsulates DNS resource record types. /// @@ -151,47 +126,6 @@ public: //@} /// We use the default copy assignment operator intentionally. /// - - /// - /// \name Converter methods - /// - //@{ - /// \brief Convert the \c RRType to a string. - /// - /// If a "well known" textual representation for the type code is registered - /// in the RR parameter registry (see the class description), that will be - /// used as the return value of this method. Otherwise, this method creates - /// a new string for an "unknown" RR type in the format defined in RFC3597, - /// i.e., "TYPEnnnn", and returns it. - /// - /// If resource allocation for the string fails, a corresponding standard - /// exception will be thrown. - /// - /// \return A string representation of the \c RRType. - const std::string toText() const; - /// \brief Render the \c RRType in the wire format. - /// - /// This method renders the type code in network byte order via \c renderer, - /// which encapsulates output buffer and other rendering contexts. - /// - /// If resource allocation in rendering process fails, a corresponding - /// standard exception will be thrown. - /// - /// \param renderer DNS message rendering context that encapsulates the - /// output buffer in which the RRType is to be stored. - void toWire(AbstractMessageRenderer& renderer) const; - /// \brief Render the \c RRType in the wire format. - /// - /// This method renders the type code in network byte order into the - /// \c buffer. - /// - /// If resource allocation in rendering process fails, a corresponding - /// standard exception will be thrown. - /// - /// \param buffer An output buffer to store the wire data. - void toWire(isc::util::OutputBuffer& buffer) const; - //@} - /// /// \name Getter Methods /// @@ -201,56 +135,10 @@ public: /// This method never throws an exception. /// /// \return An 16-bit integer code corresponding to the RRType. - uint16_t getCode() const { return (typecode_); } - //@} - - /// - /// \name Comparison methods - /// - //@{ - /// \brief Return true iff two RRTypes are equal. - /// - /// Two RRTypes are equal iff their type codes are equal. - /// - /// This method never throws an exception. - /// - /// \param other the \c RRType object to compare against. - /// \return true if the two RRTypes are equal; otherwise false. - bool equals(const RRType& other) const - { return (typecode_ == other.typecode_); } - /// \brief Same as \c equals(). - bool operator==(const RRType& other) const { return (equals(other)); } - - /// \brief Return true iff two RRTypes are not equal. - /// - /// This method never throws an exception. - /// - /// \param other the \c RRType object to compare against. - /// \return true if the two RRTypes are not equal; otherwise false. - bool nequals(const RRType& other) const - { return (typecode_ != other.typecode_); } - /// \brief Same as \c nequals(). - bool operator!=(const RRType& other) const { return (nequals(other)); } - - /// \brief Less-than comparison for RRType against \c other - /// - /// We define the less-than relationship based on their type codes; - /// one RRType is less than the other iff the code of the former is less - /// than that of the other as unsigned integers. - /// The relationship is meaningless in terms of DNS protocol; the only - /// reason we define this method is that RRType objects can be stored in - /// STL containers without requiring user-defined less-than relationship. - /// We therefore don't define other comparison operators. - /// - /// This method never throws an exception. - /// - /// \param other the \c RRType object to compare against. - /// \return true if \c this RRType is less than the \c other; otherwise - /// false. - bool operator<(const RRType& other) const - { return (typecode_ < other.typecode_); } + uint16_t getCode() const { + return (typecode_); + } //@} - // BEGIN_WELL_KNOWN_TYPE_DECLARATIONS // END_WELL_KNOWN_TYPE_DECLARATIONS @@ -260,27 +148,6 @@ private: // BEGIN_WELL_KNOWN_TYPE_DEFINITIONS // END_WELL_KNOWN_TYPE_DEFINITIONS - -/// -/// \brief Insert the \c RRType as a string into stream. -/// -/// This method convert the \c rrtype into a string and inserts it into the -/// output stream \c os. -/// -/// This function overloads the global operator<< to behave as described in -/// ostream::operator<< but applied to \c RRType objects. -/// -/// \param os A \c std::ostream object on which the insertion operation is -/// performed. -/// \param rrtype The \c RRType object output by the operation. -/// \return A reference to the same \c std::ostream object referenced by -/// parameter \c os after the insertion operation. -std::ostream& -operator<<(std::ostream& os, const RRType& rrtype); } } #endif // RRTYPE_H - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/rrtype.h b/src/lib/dns/rrtype.h index e75225304a..6f2c583323 100644 --- a/src/lib/dns/rrtype.h +++ b/src/lib/dns/rrtype.h @@ -12,7 +12,7 @@ // file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef RRTYPE_H -#define RRTYPE_H 1 +#define RRTYPE_H #include <stdint.h> @@ -20,6 +20,7 @@ #include <ostream> #include <dns/exceptions.h> +#include <util/buffer.h> // Solaris x86 defines DS in <sys/regset.h>, which gets pulled in by Boost #if defined(__sun) && defined(DS) @@ -27,10 +28,6 @@ #endif namespace isc { -namespace util { -class InputBuffer; -class OutputBuffer; -} namespace dns { @@ -208,7 +205,9 @@ public: /// This method never throws an exception. /// /// \return An 16-bit integer code corresponding to the RRType. - uint16_t getCode() const { return (typecode_); } + uint16_t getCode() const { + return (typecode_); + } //@} /// @@ -223,10 +222,13 @@ public: /// /// \param other the \c RRType object to compare against. /// \return true if the two RRTypes are equal; otherwise false. - bool equals(const RRType& other) const - { return (typecode_ == other.typecode_); } + bool equals(const RRType& other) const { + return (typecode_ == other.typecode_); + } /// \brief Same as \c equals(). - bool operator==(const RRType& other) const { return (equals(other)); } + bool operator==(const RRType& other) const { + return (equals(other)); + } /// \brief Return true iff two RRTypes are not equal. /// @@ -234,10 +236,13 @@ public: /// /// \param other the \c RRType object to compare against. /// \return true if the two RRTypes are not equal; otherwise false. - bool nequals(const RRType& other) const - { return (typecode_ != other.typecode_); } + bool nequals(const RRType& other) const { + return (typecode_ != other.typecode_); + } /// \brief Same as \c nequals(). - bool operator!=(const RRType& other) const { return (nequals(other)); } + bool operator!=(const RRType& other) const { + return (nequals(other)); + } /// \brief Less-than comparison for RRType against \c other /// @@ -254,76 +259,22 @@ public: /// \param other the \c RRType object to compare against. /// \return true if \c this RRType is less than the \c other; otherwise /// false. - bool operator<(const RRType& other) const - { return (typecode_ < other.typecode_); } + bool operator<(const RRType& other) const { + return (typecode_ < other.typecode_); + } //@} // BEGIN_WELL_KNOWN_TYPE_DECLARATIONS static const RRType& TSIG(); - static const RRType& A(); - static const RRType& AFSDB(); - static const RRType& CAA(); - static const RRType& CNAME(); - static const RRType& DLV(); - static const RRType& DNAME(); - static const RRType& DNSKEY(); - static const RRType& DS(); - static const RRType& HINFO(); - static const RRType& MINFO(); - static const RRType& MX(); - static const RRType& NAPTR(); - static const RRType& NS(); - static const RRType& NSEC3(); - static const RRType& NSEC3PARAM(); - static const RRType& NSEC(); static const RRType& OPT(); static const RRType& PTR(); - static const RRType& RP(); static const RRType& RRSIG(); static const RRType& SOA(); - static const RRType& SPF(); - static const RRType& SSHFP(); static const RRType& TKEY(); - static const RRType& TLSA(); - static const RRType& TXT(); + static const RRType& A(); static const RRType& AAAA(); static const RRType& DHCID(); - static const RRType& SRV(); - static const RRType& IXFR(); - static const RRType& AXFR(); static const RRType& ANY(); - static const RRType& MD(); - static const RRType& MF(); - static const RRType& MB(); - static const RRType& MG(); - static const RRType& MR(); - static const RRType& NXT(); - static const RRType& A6(); - static const RRType& MAILA(); - static const RRType& Null(); - static const RRType& WKS(); - static const RRType& X25(); - static const RRType& RT(); - static const RRType& NSAP(); - static const RRType& NSAP_PTR(); - static const RRType& SIG(); - static const RRType& ISDN(); - static const RRType& KEY(); - static const RRType& PX(); - static const RRType& GPOS(); - static const RRType& LOC(); - static const RRType& KX(); - static const RRType& CERT(); - static const RRType& APL(); - static const RRType& IPSECKEY(); - static const RRType& HIP(); - static const RRType& UNSPEC(); - static const RRType& NID(); - static const RRType& L32(); - static const RRType& L64(); - static const RRType& LP(); - static const RRType& MAILB(); - static const RRType& URI(); // END_WELL_KNOWN_TYPE_DECLARATIONS private: @@ -331,6 +282,7 @@ private: }; // BEGIN_WELL_KNOWN_TYPE_DEFINITIONS + inline const RRType& RRType::TSIG() { static RRType rrtype(250); @@ -344,96 +296,6 @@ RRType::A() { } inline const RRType& -RRType::AFSDB() { - static RRType rrtype(18); - return (rrtype); -} - -inline const RRType& -RRType::CAA() { - static RRType rrtype(257); - return (rrtype); -} - -inline const RRType& -RRType::CNAME() { - static RRType rrtype(5); - return (rrtype); -} - -inline const RRType& -RRType::DLV() { - static RRType rrtype(32769); - return (rrtype); -} - -inline const RRType& -RRType::DNAME() { - static RRType rrtype(39); - return (rrtype); -} - -inline const RRType& -RRType::DNSKEY() { - static RRType rrtype(48); - return (rrtype); -} - -inline const RRType& -RRType::DS() { - static RRType rrtype(43); - return (rrtype); -} - -inline const RRType& -RRType::HINFO() { - static RRType rrtype(13); - return (rrtype); -} - -inline const RRType& -RRType::MINFO() { - static RRType rrtype(14); - return (rrtype); -} - -inline const RRType& -RRType::MX() { - static RRType rrtype(15); - return (rrtype); -} - -inline const RRType& -RRType::NAPTR() { - static RRType rrtype(35); - return (rrtype); -} - -inline const RRType& -RRType::NS() { - static RRType rrtype(2); - return (rrtype); -} - -inline const RRType& -RRType::NSEC3() { - static RRType rrtype(50); - return (rrtype); -} - -inline const RRType& -RRType::NSEC3PARAM() { - static RRType rrtype(51); - return (rrtype); -} - -inline const RRType& -RRType::NSEC() { - static RRType rrtype(47); - return (rrtype); -} - -inline const RRType& RRType::OPT() { static RRType rrtype(41); return (rrtype); @@ -446,12 +308,6 @@ RRType::PTR() { } inline const RRType& -RRType::RP() { - static RRType rrtype(17); - return (rrtype); -} - -inline const RRType& RRType::RRSIG() { static RRType rrtype(46); return (rrtype); @@ -464,36 +320,12 @@ RRType::SOA() { } inline const RRType& -RRType::SPF() { - static RRType rrtype(99); - return (rrtype); -} - -inline const RRType& -RRType::SSHFP() { - static RRType rrtype(44); - return (rrtype); -} - -inline const RRType& RRType::TKEY() { static RRType rrtype(249); return (rrtype); } inline const RRType& -RRType::TLSA() { - static RRType rrtype(52); - return (rrtype); -} - -inline const RRType& -RRType::TXT() { - static RRType rrtype(16); - return (rrtype); -} - -inline const RRType& RRType::AAAA() { static RRType rrtype(28); return (rrtype); @@ -506,221 +338,11 @@ RRType::DHCID() { } inline const RRType& -RRType::SRV() { - static RRType rrtype(33); - return (rrtype); -} - -inline const RRType& -RRType::IXFR() { - static RRType rrtype(251); - return (rrtype); -} - -inline const RRType& -RRType::AXFR() { - static RRType rrtype(252); - return (rrtype); -} - -inline const RRType& RRType::ANY() { static RRType rrtype(255); return (rrtype); } -inline const RRType& -RRType::MD() { - static RRType rrtype(3); - return (rrtype); -} - -inline const RRType& -RRType::MF() { - static RRType rrtype(4); - return (rrtype); -} - -inline const RRType& -RRType::MB() { - static RRType rrtype(7); - return (rrtype); -} - -inline const RRType& -RRType::MG() { - static RRType rrtype(8); - return (rrtype); -} - -inline const RRType& -RRType::MR() { - static RRType rrtype(9); - return (rrtype); -} - -inline const RRType& -RRType::NXT() { - static RRType rrtype(30); - return (rrtype); -} - -inline const RRType& -RRType::A6() { - static RRType rrtype(38); - return (rrtype); -} - -inline const RRType& -RRType::MAILA() { - static RRType rrtype(254); - return (rrtype); -} - -inline const RRType& -RRType::Null() { - static RRType rrtype(10); - return (rrtype); -} - -inline const RRType& -RRType::WKS() { - static RRType rrtype(11); - return (rrtype); -} - -inline const RRType& -RRType::X25() { - static RRType rrtype(19); - return (rrtype); -} - -inline const RRType& -RRType::RT() { - static RRType rrtype(21); - return (rrtype); -} - -inline const RRType& -RRType::NSAP() { - static RRType rrtype(22); - return (rrtype); -} - -inline const RRType& -RRType::NSAP_PTR() { - static RRType rrtype(23); - return (rrtype); -} - -inline const RRType& -RRType::SIG() { - static RRType rrtype(24); - return (rrtype); -} - -inline const RRType& -RRType::ISDN() { - static RRType rrtype(20); - return (rrtype); -} - -inline const RRType& -RRType::KEY() { - static RRType rrtype(25); - return (rrtype); -} - -inline const RRType& -RRType::PX() { - static RRType rrtype(26); - return (rrtype); -} - -inline const RRType& -RRType::GPOS() { - static RRType rrtype(27); - return (rrtype); -} - -inline const RRType& -RRType::LOC() { - static RRType rrtype(29); - return (rrtype); -} - -inline const RRType& -RRType::KX() { - static RRType rrtype(36); - return (rrtype); -} - -inline const RRType& -RRType::CERT() { - static RRType rrtype(37); - return (rrtype); -} - -inline const RRType& -RRType::APL() { - static RRType rrtype(42); - return (rrtype); -} - -inline const RRType& -RRType::IPSECKEY() { - static RRType rrtype(45); - return (rrtype); -} - -inline const RRType& -RRType::HIP() { - static RRType rrtype(55); - return (rrtype); -} - -inline const RRType& -RRType::UNSPEC() { - static RRType rrtype(103); - return (rrtype); -} - -inline const RRType& -RRType::NID() { - static RRType rrtype(104); - return (rrtype); -} - -inline const RRType& -RRType::L32() { - static RRType rrtype(105); - return (rrtype); -} - -inline const RRType& -RRType::L64() { - static RRType rrtype(106); - return (rrtype); -} - -inline const RRType& -RRType::LP() { - static RRType rrtype(107); - return (rrtype); -} - -inline const RRType& -RRType::MAILB() { - static RRType rrtype(253); - return (rrtype); -} - -inline const RRType& -RRType::URI() { - static RRType rrtype(256); - return (rrtype); -} - // END_WELL_KNOWN_TYPE_DEFINITIONS /// @@ -742,7 +364,3 @@ operator<<(std::ostream& os, const RRType& rrtype); } } #endif // RRTYPE_H - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/tests/dns_exceptions_unittest.cc b/src/lib/dns/tests/dns_exceptions_unittest.cc index a8d25907c7..8b13789179 100644 --- a/src/lib/dns/tests/dns_exceptions_unittest.cc +++ b/src/lib/dns/tests/dns_exceptions_unittest.cc @@ -1,65 +1 @@ -// Copyright (C) 2014-2015,2017 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. -#include <config.h> - -#include <dns/exceptions.h> - -#include <gtest/gtest.h> - -namespace { // begin unnamed namespace - -TEST(DNSExceptionsTest, checkExceptionsHierarchy) { - EXPECT_NO_THROW({ - const isc::dns::Exception exception("", 0, ""); - const isc::Exception& exception_cast = - dynamic_cast<const isc::Exception&>(exception); - // to avoid compiler warning - exception_cast.what(); - }); - - EXPECT_NO_THROW({ - const isc::dns::DNSTextError exception("", 0, ""); - const isc::dns::Exception& exception_cast = - dynamic_cast<const isc::dns::Exception&>(exception); - // to avoid compiler warning - exception_cast.what(); - }); - - EXPECT_NO_THROW({ - const isc::dns::NameParserException exception("", 0, ""); - const isc::dns::DNSTextError& exception_cast = - dynamic_cast<const isc::dns::DNSTextError&>(exception); - // to avoid compiler warning - exception_cast.what(); - }); - - EXPECT_NO_THROW({ - const isc::dns::DNSMessageFORMERR exception("", 0, ""); - const isc::dns::DNSProtocolError& exception_cast = - dynamic_cast<const isc::dns::DNSProtocolError&>(exception); - const isc::dns::Exception& exception_cast2 = - dynamic_cast<const isc::dns::Exception&>(exception); - // to avoid compiler warning - exception_cast.getRcode(); - exception_cast.what(); - exception_cast2.what(); - }); - - EXPECT_NO_THROW({ - const isc::dns::DNSMessageBADVERS exception("", 0, ""); - const isc::dns::DNSProtocolError& exception_cast = - dynamic_cast<const isc::dns::DNSProtocolError&>(exception); - const isc::dns::Exception& exception_cast2 = - dynamic_cast<const isc::dns::Exception&>(exception); - // to avoid compiler warning - exception_cast.getRcode(); - exception_cast.what(); - exception_cast2.what(); - }); -} - -} // end unnamed namespace diff --git a/src/lib/dns/tests/edns_unittest.cc b/src/lib/dns/tests/edns_unittest.cc index dfc68cc67e..8b13789179 100644 --- a/src/lib/dns/tests/edns_unittest.cc +++ b/src/lib/dns/tests/edns_unittest.cc @@ -1,258 +1 @@ -// Copyright (C) 2010-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. -#include <config.h> - -#include <sstream> - -#include <exceptions/exceptions.h> - -#include <util/buffer.h> -#include <dns/edns.h> -#include <dns/exceptions.h> -#include <dns/message.h> -#include <dns/messagerenderer.h> -#include <dns/name.h> -#include <dns/rcode.h> -#include <dns/rdataclass.h> -#include <dns/rrclass.h> -#include <dns/rrttl.h> -#include <dns/rrtype.h> - -#include <gtest/gtest.h> - -#include <dns/tests/unittest_util.h> -#include <util/unittests/wiredata.h> - -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; - -namespace { -class EDNSTest : public ::testing::Test { -protected: - EDNSTest() : rrtype(RRType::OPT()), buffer(NULL, 0), obuffer(0), rcode(0) { - opt_rdata = ConstRdataPtr(new generic::OPT()); - edns_base.setUDPSize(4096); - } - RRType rrtype; - EDNS edns_base; - ConstEDNSPtr edns; - InputBuffer buffer; - OutputBuffer obuffer; - MessageRenderer renderer; - ConstRdataPtr opt_rdata; - Rcode rcode; - vector<unsigned char> wiredata; -}; - -// RRClass of EDNS OPT means UDP buffer size -const RRClass rrclass(4096); -// RRTTL of EDNS OPT encodes extended-rcode, version, and DO bit -const RRTTL rrttl_do_on(0x00008000); // DO=on -const RRTTL rrttl_do_off(0); // DO=off -const RRTTL rrttl_badver(0x00018000); // version=1, DO=on - -TEST_F(EDNSTest, badVerConstruct) { - EXPECT_THROW(EDNS(1), isc::InvalidParameter); -} - -TEST_F(EDNSTest, DNSSECDOBit) { - // tests for EDNS from RR - - // DO bit is on, so DNSSEC should be considered to be supported. - EXPECT_TRUE(EDNS(Name::ROOT_NAME(), rrclass, rrtype, - rrttl_do_on, *opt_rdata).getDNSSECAwareness()); - - // DO bit is off. DNSSEC should be considered to be unsupported. - EXPECT_FALSE(EDNS(Name::ROOT_NAME(), rrclass, rrtype, - rrttl_do_off, *opt_rdata).getDNSSECAwareness()); - - // tests for EDNS constructed by hand - EXPECT_FALSE(edns_base.getDNSSECAwareness()); // false by default - edns_base.setDNSSECAwareness(true); // enable by hand - EXPECT_TRUE(edns_base.getDNSSECAwareness()); - edns_base.setDNSSECAwareness(false); // disable by hand - EXPECT_FALSE(edns_base.getDNSSECAwareness()); -} - -TEST_F(EDNSTest, UDPSize) { - EXPECT_EQ(4096, EDNS(Name::ROOT_NAME(), rrclass, rrtype, rrttl_do_on, - *opt_rdata).getUDPSize()); - - // EDNS UDP size smaller than the traditional max, 512. Unusual, but - // not prohibited. - edns_base.setUDPSize(511); - EXPECT_EQ(511, edns_base.getUDPSize()); - - // Even 0 is okay. - edns_base.setUDPSize(0); - EXPECT_EQ(0, edns_base.getUDPSize()); - - // Possible max value is also okay, although the higher layer app may - // adjust it to a reasonably lower value - edns_base.setUDPSize(65535); - EXPECT_EQ(65535, edns_base.getUDPSize()); -} - -TEST_F(EDNSTest, getVersion) { - // Constructed by hand - EXPECT_EQ(EDNS::SUPPORTED_VERSION, EDNS().getVersion()); - - // From RR - EXPECT_EQ(EDNS::SUPPORTED_VERSION, - EDNS(Name::ROOT_NAME(), rrclass, rrtype, rrttl_do_on, - *opt_rdata).getVersion()); -} - -TEST_F(EDNSTest, BadWireData) { - // Incompatible RR type - EXPECT_THROW(EDNS(Name::ROOT_NAME(), rrclass, RRType::A(), - rrttl_do_on, *opt_rdata), isc::InvalidParameter); - - // OPT RR of a non root name - EXPECT_THROW(EDNS(Name("example.com"), rrclass, rrtype, - rrttl_do_on, *opt_rdata), DNSMessageFORMERR); - - // Unsupported Version - EXPECT_THROW(EDNS(Name::ROOT_NAME(), rrclass, rrtype, - rrttl_badver, *opt_rdata), DNSMessageBADVERS); -} - -TEST_F(EDNSTest, toText) { - // Typical case, disabling DNSSEC - EXPECT_EQ("; EDNS: version: 0, flags:; udp: 4096\n", - EDNS(Name::ROOT_NAME(), rrclass, rrtype, rrttl_do_off, - *opt_rdata).toText()); - - // Typical case, enabling DNSSEC - EXPECT_EQ("; EDNS: version: 0, flags: do; udp: 4096\n", - EDNS(Name::ROOT_NAME(), rrclass, rrtype, rrttl_do_on, - *opt_rdata).toText()); - - // Non-0 extended Rcode: ignored in the toText() output. - EXPECT_EQ("; EDNS: version: 0, flags: do; udp: 4096\n", - EDNS(Name::ROOT_NAME(), rrclass, rrtype, - RRTTL(0x01008000), *opt_rdata).toText()); - - // Unknown flag: ignored in the toText() output. - EXPECT_EQ("; EDNS: version: 0, flags: do; udp: 4096\n", - EDNS(Name::ROOT_NAME(), rrclass, rrtype, - RRTTL(0x00008001), *opt_rdata).toText()); -} - -TEST_F(EDNSTest, toWireRenderer) { - // Typical case, (explicitly) disabling DNSSEC - edns_base.setDNSSECAwareness(false); - EXPECT_EQ(1, edns_base.toWire(renderer, - Rcode::NOERROR().getExtendedCode())); - UnitTestUtil::readWireData("edns_toWire1.wire", wiredata); - matchWireData(&wiredata[0], wiredata.size(), - renderer.getData(), renderer.getLength()); - - // Typical case, enabling DNSSEC - renderer.clear(); - wiredata.clear(); - edns_base.setDNSSECAwareness(true); - EXPECT_EQ(1, edns_base.toWire(renderer, - Rcode::NOERROR().getExtendedCode())); - UnitTestUtil::readWireData("edns_toWire2.wire", wiredata); - matchWireData(&wiredata[0], wiredata.size(), - renderer.getData(), renderer.getLength()); - - // Non-0 extended Rcode - renderer.clear(); - wiredata.clear(); - edns_base.setDNSSECAwareness(true); - EXPECT_EQ(1, edns_base.toWire(renderer, - Rcode::BADVERS().getExtendedCode())); - UnitTestUtil::readWireData("edns_toWire3.wire", wiredata); - matchWireData(&wiredata[0], wiredata.size(), - renderer.getData(), renderer.getLength()); - - // Uncommon UDP buffer size - renderer.clear(); - wiredata.clear(); - edns_base.setDNSSECAwareness(true); - edns_base.setUDPSize(511); - EXPECT_EQ(1, edns_base.toWire(renderer, - Rcode::NOERROR().getExtendedCode())); - UnitTestUtil::readWireData("edns_toWire4.wire", wiredata); - matchWireData(&wiredata[0], wiredata.size(), - renderer.getData(), renderer.getLength()); - - // From RR with unknown flag. If used for toWire(), the unknown flag - // should disappear. - renderer.clear(); - wiredata.clear(); - EXPECT_EQ(1, EDNS(Name::ROOT_NAME(), rrclass, rrtype, RRTTL(0x00008001), - *opt_rdata).toWire(renderer, - Rcode::NOERROR().getExtendedCode())); - UnitTestUtil::readWireData("edns_toWire2.wire", wiredata); - 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. - renderer.clear(); - renderer.setLengthLimit(10); // 10 = minimum length of OPT RR - 1 - edns_base.setDNSSECAwareness(true); - edns_base.setUDPSize(4096); - EXPECT_EQ(0, edns_base.toWire(renderer, - Rcode::NOERROR().getExtendedCode())); - // renderer should be intact - EXPECT_EQ(0, renderer.getLength()); -} - -TEST_F(EDNSTest, toWireBuffer) { - // "to renderer" and "to buffer" should generally produce the same result. - // for simplicity we only check one typical case to confirm that. - EXPECT_EQ(1, edns_base.toWire(obuffer, - Rcode::NOERROR().getExtendedCode())); - UnitTestUtil::readWireData("edns_toWire1.wire", wiredata); - matchWireData(&wiredata[0], wiredata.size(), - obuffer.getData(), obuffer.getLength()); -} - -TEST_F(EDNSTest, createFromRR) { - uint8_t extended_rcode; - - // normal case - edns = ConstEDNSPtr(createEDNSFromRR(Name::ROOT_NAME(), rrclass, rrtype, - rrttl_do_on, *opt_rdata, - extended_rcode)); - EXPECT_EQ(EDNS::SUPPORTED_VERSION, edns->getVersion()); - EXPECT_TRUE(edns->getDNSSECAwareness()); - EXPECT_EQ(4096, edns->getUDPSize()); - EXPECT_EQ(0, static_cast<int>(extended_rcode)); - - // non-0 extended rcode - extended_rcode = 0; - ConstEDNSPtr(createEDNSFromRR(Name::ROOT_NAME(), rrclass, rrtype, - RRTTL(0x01008000), *opt_rdata, - extended_rcode)); - EXPECT_EQ(1, static_cast<int>(extended_rcode)); - - // creation triggers an exception. extended_rcode must be intact. - extended_rcode = 0; - EXPECT_THROW(createEDNSFromRR(Name::ROOT_NAME(), rrclass, rrtype, - rrttl_badver, *opt_rdata, extended_rcode), - DNSMessageBADVERS); - EXPECT_EQ(0, static_cast<int>(extended_rcode)); -} - -// test operator<<. We simply confirm it appends the result of toText(). -TEST_F(EDNSTest, LeftShiftOperator) { - ostringstream oss; - oss << edns_base; - EXPECT_EQ(edns_base.toText(), oss.str()); -} -} diff --git a/src/lib/dns/tests/labelsequence_unittest.cc b/src/lib/dns/tests/labelsequence_unittest.cc index 15650fac07..8b13789179 100644 --- a/src/lib/dns/tests/labelsequence_unittest.cc +++ b/src/lib/dns/tests/labelsequence_unittest.cc @@ -1,1243 +1 @@ -// Copyright (C) 2012-2020 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. -#include <config.h> - -#include <util/buffer.h> - -#include <dns/labelsequence.h> -#include <dns/name.h> -#include <exceptions/exceptions.h> - -#include <gtest/gtest.h> - -#include <boost/functional/hash.hpp> - -#include <string> -#include <vector> -#include <utility> -#include <set> - -using namespace isc::dns; -using namespace std; - -// XXX: this is defined as class static constants, but some compilers -// seemingly cannot find the symbols when used in the EXPECT_xxx macros. -const size_t LabelSequence::MAX_SERIALIZED_LENGTH; - -namespace { - -// Common check that two labelsequences are equal -void check_equal(const LabelSequence& ls1, const LabelSequence& ls2) { - NameComparisonResult result = ls1.compare(ls2); - EXPECT_EQ(isc::dns::NameComparisonResult::EQUAL, - result.getRelation()) << ls1.toText() << " != " << ls2.toText(); - EXPECT_EQ(0, result.getOrder()) << ls1.toText() << " != " << ls2.toText(); - EXPECT_EQ(ls1.getLabelCount(), result.getCommonLabels()); -} - -// Common check for general comparison of two labelsequences -void check_compare(const LabelSequence& ls1, const LabelSequence& ls2, - isc::dns::NameComparisonResult::NameRelation relation, - size_t common_labels, bool check_order, int order=0) { - NameComparisonResult result = ls1.compare(ls2); - EXPECT_EQ(relation, result.getRelation()); - EXPECT_EQ(common_labels, result.getCommonLabels()); - if (check_order) { - EXPECT_EQ(order, result.getOrder()); - } -} - -class LabelSequenceTest : public ::testing::Test { -public: - LabelSequenceTest() : n1("example.org"), n2("example.com"), - n3("example.org"), n4("foo.bar.test.example"), - n5("example.ORG"), n6("ExAmPlE.org"), - n7("."), n8("foo.example.org.bar"), - n9("\\000xample.org"), - n10("\\000xample.org"), - n11("\\000xample.com"), - n12("\\000xamplE.com"), - n_maxlabel("0.1.2.3.4.5.6.7.8.9.0.1.2.3.4.5.6.7.8.9." - "0.1.2.3.4.5.6.7.8.9.0.1.2.3.4.5.6.7.8.9." - "0.1.2.3.4.5.6.7.8.9.0.1.2.3.4.5.6.7.8.9." - "0.1.2.3.4.5.6.7.8.9.0.1.2.3.4.5.6.7.8.9." - "0.1.2.3.4.5.6.7.8.9.0.1.2.3.4.5.6.7.8.9." - "0.1.2.3.4.5.6.7.8.9.0.1.2.3.4.5.6.7.8.9." - "0.1.2.3.4.5.6"), - ls1(n1), ls2(n2), ls3(n3), ls4(n4), ls5(n5), - ls6(n6), ls7(n7), ls8(n8), - ls9(n9), ls10(n10), ls11(n11), ls12(n12) - {}; - // Need to keep names in scope for at least the lifetime of - // the labelsequences - Name n1, n2, n3, n4, n5, n6, n7, n8; - Name n9, n10, n11, n12; - const Name n_maxlabel; - - LabelSequence ls1, ls2, ls3, ls4, ls5, ls6, ls7, ls8; - LabelSequence ls9, ls10, ls11, ls12; -}; - -// Check the assignment operator. -TEST_F(LabelSequenceTest, assign) { - // Create the label sequence with example.org (n1 name). - LabelSequence ls(n1); - EXPECT_TRUE(ls == ls1); - - // Assign the label sequence to example.com (n2 name). - ls = ls2; - EXPECT_FALSE(ls == ls1); - EXPECT_TRUE(ls == ls2); -} - -// Basic equality tests -TEST_F(LabelSequenceTest, equals_sensitive) { - EXPECT_TRUE(ls1.equals(ls1, true)); - EXPECT_FALSE(ls1.equals(ls2, true)); - EXPECT_TRUE(ls1.equals(ls3, true)); - EXPECT_FALSE(ls1.equals(ls4, true)); - EXPECT_FALSE(ls1.equals(ls5, true)); - EXPECT_FALSE(ls1.equals(ls6, true)); - EXPECT_FALSE(ls1.equals(ls7, true)); - EXPECT_FALSE(ls1.equals(ls8, true)); - - EXPECT_FALSE(ls2.equals(ls1, true)); - EXPECT_TRUE(ls2.equals(ls2, true)); - EXPECT_FALSE(ls2.equals(ls3, true)); - EXPECT_FALSE(ls2.equals(ls4, true)); - EXPECT_FALSE(ls2.equals(ls5, true)); - EXPECT_FALSE(ls2.equals(ls6, true)); - EXPECT_FALSE(ls2.equals(ls7, true)); - EXPECT_FALSE(ls2.equals(ls8, true)); - - EXPECT_FALSE(ls4.equals(ls1, true)); - EXPECT_FALSE(ls4.equals(ls2, true)); - EXPECT_FALSE(ls4.equals(ls3, true)); - EXPECT_TRUE(ls4.equals(ls4, true)); - EXPECT_FALSE(ls4.equals(ls5, true)); - EXPECT_FALSE(ls4.equals(ls6, true)); - EXPECT_FALSE(ls4.equals(ls7, true)); - EXPECT_FALSE(ls4.equals(ls8, true)); - - EXPECT_FALSE(ls5.equals(ls1, true)); - EXPECT_FALSE(ls5.equals(ls2, true)); - EXPECT_FALSE(ls5.equals(ls3, true)); - EXPECT_FALSE(ls5.equals(ls4, true)); - EXPECT_TRUE(ls5.equals(ls5, true)); - EXPECT_FALSE(ls5.equals(ls6, true)); - EXPECT_FALSE(ls5.equals(ls7, true)); - EXPECT_FALSE(ls5.equals(ls8, true)); - - EXPECT_TRUE(ls9.equals(ls10, true)); - EXPECT_FALSE(ls9.equals(ls11, true)); - EXPECT_FALSE(ls9.equals(ls12, true)); - EXPECT_FALSE(ls11.equals(ls12, true)); -} - -TEST_F(LabelSequenceTest, equals_insensitive) { - EXPECT_TRUE(ls1.equals(ls1)); - EXPECT_FALSE(ls1.equals(ls2)); - EXPECT_TRUE(ls1.equals(ls3)); - EXPECT_FALSE(ls1.equals(ls4)); - EXPECT_TRUE(ls1.equals(ls5)); - EXPECT_TRUE(ls1.equals(ls6)); - EXPECT_FALSE(ls1.equals(ls7)); - - EXPECT_FALSE(ls2.equals(ls1)); - EXPECT_TRUE(ls2.equals(ls2)); - EXPECT_FALSE(ls2.equals(ls3)); - EXPECT_FALSE(ls2.equals(ls4)); - EXPECT_FALSE(ls2.equals(ls5)); - EXPECT_FALSE(ls2.equals(ls6)); - EXPECT_FALSE(ls2.equals(ls7)); - - EXPECT_TRUE(ls3.equals(ls1)); - EXPECT_FALSE(ls3.equals(ls2)); - EXPECT_TRUE(ls3.equals(ls3)); - EXPECT_FALSE(ls3.equals(ls4)); - EXPECT_TRUE(ls3.equals(ls5)); - EXPECT_TRUE(ls3.equals(ls6)); - EXPECT_FALSE(ls3.equals(ls7)); - - EXPECT_FALSE(ls4.equals(ls1)); - EXPECT_FALSE(ls4.equals(ls2)); - EXPECT_FALSE(ls4.equals(ls3)); - EXPECT_TRUE(ls4.equals(ls4)); - EXPECT_FALSE(ls4.equals(ls5)); - EXPECT_FALSE(ls4.equals(ls6)); - EXPECT_FALSE(ls4.equals(ls7)); - - EXPECT_TRUE(ls5.equals(ls1)); - EXPECT_FALSE(ls5.equals(ls2)); - EXPECT_TRUE(ls5.equals(ls3)); - EXPECT_FALSE(ls5.equals(ls4)); - EXPECT_TRUE(ls5.equals(ls5)); - EXPECT_TRUE(ls5.equals(ls6)); - EXPECT_FALSE(ls5.equals(ls7)); - - EXPECT_TRUE(ls9.equals(ls10)); - EXPECT_FALSE(ls9.equals(ls11)); - EXPECT_FALSE(ls9.equals(ls12)); - EXPECT_TRUE(ls11.equals(ls12)); -} - -// operator==(). This is mostly trivial wrapper, so it should suffice to -// check some basic cases. -TEST_F(LabelSequenceTest, operatorEqual) { - // cppcheck-suppress duplicateExpression - EXPECT_TRUE(ls1 == ls1); // self equivalence - EXPECT_TRUE(ls1 == LabelSequence(n1)); // equivalent two different objects - EXPECT_FALSE(ls1 == ls2); // non equivalent objects - EXPECT_TRUE(ls1 == ls5); // it's always case insensitive -} - -// Compare tests -TEST_F(LabelSequenceTest, compare) { - // "example.org." and "example.org.", case sensitive - NameComparisonResult result = ls1.compare(ls3, true); - EXPECT_EQ(isc::dns::NameComparisonResult::EQUAL, - result.getRelation()); - EXPECT_EQ(0, result.getOrder()); - EXPECT_EQ(3, result.getCommonLabels()); - - // "example.org." and "example.ORG.", case sensitive - result = ls3.compare(ls5, true); - EXPECT_EQ(isc::dns::NameComparisonResult::COMMONANCESTOR, - result.getRelation()); - EXPECT_LT(0, result.getOrder()); - EXPECT_EQ(1, result.getCommonLabels()); - - // "example.org." and "example.ORG.", case in-sensitive - result = ls3.compare(ls5); - EXPECT_EQ(isc::dns::NameComparisonResult::EQUAL, - result.getRelation()); - EXPECT_EQ(0, result.getOrder()); - EXPECT_EQ(3, result.getCommonLabels()); - - Name na("a.example.org"); - Name nb("b.example.org"); - LabelSequence lsa(na); - LabelSequence lsb(nb); - - // "a.example.org." and "b.example.org.", case in-sensitive - result = lsa.compare(lsb); - EXPECT_EQ(isc::dns::NameComparisonResult::COMMONANCESTOR, - result.getRelation()); - EXPECT_GT(0, result.getOrder()); - EXPECT_EQ(3, result.getCommonLabels()); - - // "example.org." and "b.example.org.", case in-sensitive - lsa.stripLeft(1); - result = lsa.compare(lsb); - EXPECT_EQ(isc::dns::NameComparisonResult::SUPERDOMAIN, - result.getRelation()); - EXPECT_GT(0, result.getOrder()); - EXPECT_EQ(3, result.getCommonLabels()); - - Name nc("g.f.e.d.c.example.org"); - LabelSequence lsc(nc); - - // "g.f.e.d.c.example.org." and "b.example.org" (not absolute), case - // in-sensitive; the absolute one is always smaller. - lsb.stripRight(1); - result = lsc.compare(lsb); - EXPECT_EQ(isc::dns::NameComparisonResult::NONE, result.getRelation()); - EXPECT_GT(0, result.getOrder()); - EXPECT_EQ(0, result.getCommonLabels()); - - // "g.f.e.d.c.example.org." and "example.org.", case in-sensitive - result = lsc.compare(ls1); - EXPECT_EQ(isc::dns::NameComparisonResult::SUBDOMAIN, - result.getRelation()); - EXPECT_LT(0, result.getOrder()); - EXPECT_EQ(3, result.getCommonLabels()); - - // "e.d.c.example.org." and "example.org.", case in-sensitive - lsc.stripLeft(2); - result = lsc.compare(ls1); - EXPECT_EQ(isc::dns::NameComparisonResult::SUBDOMAIN, - result.getRelation()); - EXPECT_LT(0, result.getOrder()); - EXPECT_EQ(3, result.getCommonLabels()); - - // "example.org." and "example.org.", case in-sensitive - lsc.stripLeft(3); - result = lsc.compare(ls1); - EXPECT_EQ(isc::dns::NameComparisonResult::EQUAL, - result.getRelation()); - EXPECT_EQ(0, result.getOrder()); - EXPECT_EQ(3, result.getCommonLabels()); - - // "." and "example.org.", case in-sensitive - lsc.stripLeft(2); - result = lsc.compare(ls1); - EXPECT_EQ(isc::dns::NameComparisonResult::SUPERDOMAIN, - result.getRelation()); - EXPECT_GT(0, result.getOrder()); - EXPECT_EQ(1, result.getCommonLabels()); - - Name nd("a.b.c.isc.example.org"); - LabelSequence lsd(nd); - Name ne("w.x.y.isc.EXAMPLE.org"); - LabelSequence lse(ne); - - // "a.b.c.isc.example.org." and "w.x.y.isc.EXAMPLE.org.", - // case sensitive - result = lsd.compare(lse, true); - EXPECT_EQ(isc::dns::NameComparisonResult::COMMONANCESTOR, - result.getRelation()); - EXPECT_LT(0, result.getOrder()); - EXPECT_EQ(2, result.getCommonLabels()); - - // "a.b.c.isc.example.org." and "w.x.y.isc.EXAMPLE.org.", - // case in-sensitive - result = lsd.compare(lse); - EXPECT_EQ(isc::dns::NameComparisonResult::COMMONANCESTOR, - result.getRelation()); - EXPECT_GT(0, result.getOrder()); - EXPECT_EQ(4, result.getCommonLabels()); - - // "isc.example.org." and "isc.EXAMPLE.org.", case sensitive - lsd.stripLeft(3); - lse.stripLeft(3); - result = lsd.compare(lse, true); - EXPECT_EQ(isc::dns::NameComparisonResult::COMMONANCESTOR, - result.getRelation()); - EXPECT_LT(0, result.getOrder()); - EXPECT_EQ(2, result.getCommonLabels()); - - // "isc.example.org." and "isc.EXAMPLE.org.", case in-sensitive - result = lsd.compare(lse); - EXPECT_EQ(isc::dns::NameComparisonResult::EQUAL, - result.getRelation()); - EXPECT_EQ(0, result.getOrder()); - EXPECT_EQ(4, result.getCommonLabels()); - - Name nf("a.b.c.isc.example.org"); - LabelSequence lsf(nf); - Name ng("w.x.y.isc.EXAMPLE.org"); - LabelSequence lsg(ng); - - // lsf: "a.b.c.isc.example.org." - // lsg: "w.x.y.isc.EXAMPLE.org" (not absolute), case in-sensitive. - // the absolute one is always smaller. - lsg.stripRight(1); - result = lsg.compare(lsf); // lsg > lsf - EXPECT_EQ(isc::dns::NameComparisonResult::NONE, result.getRelation()); - EXPECT_LT(0, result.getOrder()); - EXPECT_EQ(0, result.getCommonLabels()); - - // "a.b.c.isc.example.org" (not absolute) and - // "w.x.y.isc.EXAMPLE.org" (not absolute), case in-sensitive - lsf.stripRight(1); - result = lsg.compare(lsf); - EXPECT_EQ(isc::dns::NameComparisonResult::COMMONANCESTOR, - result.getRelation()); - EXPECT_LT(0, result.getOrder()); - EXPECT_EQ(3, result.getCommonLabels()); - - // "a.b.c.isc.example" (not absolute) and - // "w.x.y.isc.EXAMPLE" (not absolute), case in-sensitive - lsf.stripRight(1); - lsg.stripRight(1); - result = lsg.compare(lsf); - EXPECT_EQ(isc::dns::NameComparisonResult::COMMONANCESTOR, - result.getRelation()); - EXPECT_LT(0, result.getOrder()); - EXPECT_EQ(2, result.getCommonLabels()); - - // lsf: "a.b.c" (not absolute) and - // lsg: "w.x.y" (not absolute), case in-sensitive; a.b.c < w.x.y; - // no common labels. - lsf.stripRight(2); - lsg.stripRight(2); - result = lsf.compare(lsg); - EXPECT_EQ(isc::dns::NameComparisonResult::NONE, result.getRelation()); - EXPECT_GT(0, result.getOrder()); - EXPECT_EQ(0, result.getCommonLabels()); - - // lsf2: a.b.cc (not absolute); a.b.c < a.b.cc, no common labels. - const Name nf2("a.b.cc"); - LabelSequence lsf2(nf2); - lsf2.stripRight(1); - result = lsf.compare(lsf2); - EXPECT_EQ(isc::dns::NameComparisonResult::NONE, result.getRelation()); - EXPECT_GT(0, result.getOrder()); - EXPECT_EQ(0, result.getCommonLabels()); - - Name nh("aexample.org"); - LabelSequence lsh(nh); - Name ni("bexample.org"); - LabelSequence lsi(ni); - - // "aexample.org" (not absolute) and - // "bexample.org" (not absolute), case in-sensitive - lsh.stripRight(1); - lsi.stripRight(1); - result = lsh.compare(lsi); - EXPECT_EQ(isc::dns::NameComparisonResult::COMMONANCESTOR, - result.getRelation()); - EXPECT_GT(0, result.getOrder()); - EXPECT_EQ(1, result.getCommonLabels()); - - // "aexample" (not absolute) and - // "bexample" (not absolute), case in-sensitive; - // aexample < bexample; no common labels. - lsh.stripRight(1); - lsi.stripRight(1); - result = lsh.compare(lsi); - EXPECT_EQ(isc::dns::NameComparisonResult::NONE, result.getRelation()); - EXPECT_GT(0, result.getOrder()); - EXPECT_EQ(0, result.getCommonLabels()); - - Name nj("example.org"); - LabelSequence lsj(nj); - Name nk("example.org"); - LabelSequence lsk(nk); - - // "example.org" (not absolute) and - // "example.org" (not absolute), case in-sensitive - lsj.stripRight(1); - lsk.stripRight(1); - result = lsj.compare(lsk); - EXPECT_EQ(isc::dns::NameComparisonResult::EQUAL, - result.getRelation()); - EXPECT_EQ(0, result.getOrder()); - EXPECT_EQ(2, result.getCommonLabels()); - - // "example" (not absolute) and - // "example" (not absolute), case in-sensitive - lsj.stripRight(1); - lsk.stripRight(1); - result = lsj.compare(lsk); - EXPECT_EQ(isc::dns::NameComparisonResult::EQUAL, - result.getRelation()); - EXPECT_EQ(0, result.getOrder()); - EXPECT_EQ(1, result.getCommonLabels()); -} - -void -getDataCheck(const uint8_t* expected_data, size_t expected_len, - const LabelSequence& ls) -{ - size_t len; - const uint8_t* data = ls.getData(&len); - ASSERT_EQ(expected_len, len) << "Expected data: " << expected_data << - ", label sequence: " << ls; - EXPECT_EQ(expected_len, ls.getDataLength()) << - "Expected data: " << expected_data << - ", label sequence: " << ls; - for (size_t i = 0; i < len; ++i) { - EXPECT_EQ(expected_data[i], data[i]) << - "Difference at pos " << i << ": Expected data: " << expected_data << - ", label sequence: " << ls; - } -} - -// Convenient data converter for expected data. Label data must be of -// uint8_t*, while it's convenient if we can specify some test data in -// plain string (which is of char*). This wrapper converts the latter to -// the former in a safer way. -void -getDataCheck(const char* expected_char_data, size_t expected_len, - const LabelSequence& ls) -{ - const vector<uint8_t> expected_data(expected_char_data, - expected_char_data + expected_len); - getDataCheck(&expected_data[0], expected_len, ls); -} - -TEST_F(LabelSequenceTest, getData) { - getDataCheck("\007example\003org\000", 13, ls1); - getDataCheck("\007example\003com\000", 13, ls2); - getDataCheck("\007example\003org\000", 13, ls3); - getDataCheck("\003foo\003bar\004test\007example\000", 22, ls4); - getDataCheck("\007example\003ORG\000", 13, ls5); - getDataCheck("\007ExAmPlE\003org\000", 13, ls6); - getDataCheck("\000", 1, ls7); -}; - -TEST_F(LabelSequenceTest, stripLeft) { - EXPECT_TRUE(ls1.equals(ls3)); - ls1.stripLeft(0); - getDataCheck("\007example\003org\000", 13, ls1); - EXPECT_TRUE(ls1.equals(ls3)); - ls1.stripLeft(1); - getDataCheck("\003org\000", 5, ls1); - EXPECT_FALSE(ls1.equals(ls3)); - ls1.stripLeft(1); - getDataCheck("\000", 1, ls1); - EXPECT_TRUE(ls1.equals(ls7)); - - ls2.stripLeft(2); - getDataCheck("\000", 1, ls2); - EXPECT_TRUE(ls2.equals(ls7)); -} - -TEST_F(LabelSequenceTest, stripRight) { - EXPECT_TRUE(ls1.equals(ls3)); - ls1.stripRight(1); - getDataCheck("\007example\003org", 12, ls1); - EXPECT_FALSE(ls1.equals(ls3)); - ls1.stripRight(1); - getDataCheck("\007example", 8, ls1); - EXPECT_FALSE(ls1.equals(ls3)); - - ASSERT_FALSE(ls1.equals(ls2)); - ls2.stripRight(2); - getDataCheck("\007example", 8, ls2); - EXPECT_TRUE(ls1.equals(ls2)); -} - -TEST_F(LabelSequenceTest, stripOutOfRange) { - EXPECT_THROW(ls1.stripLeft(100), isc::OutOfRange); - EXPECT_THROW(ls1.stripLeft(5), isc::OutOfRange); - EXPECT_THROW(ls1.stripLeft(4), isc::OutOfRange); - EXPECT_THROW(ls1.stripLeft(3), isc::OutOfRange); - getDataCheck("\007example\003org\000", 13, ls1); - - EXPECT_THROW(ls1.stripRight(100), isc::OutOfRange); - EXPECT_THROW(ls1.stripRight(5), isc::OutOfRange); - EXPECT_THROW(ls1.stripRight(4), isc::OutOfRange); - EXPECT_THROW(ls1.stripRight(3), isc::OutOfRange); - getDataCheck("\007example\003org\000", 13, ls1); -} - -TEST_F(LabelSequenceTest, getLabelCount) { - EXPECT_EQ(3, ls1.getLabelCount()); - ls1.stripLeft(0); - EXPECT_EQ(3, ls1.getLabelCount()); - ls1.stripLeft(1); - EXPECT_EQ(2, ls1.getLabelCount()); - ls1.stripLeft(1); - EXPECT_EQ(1, ls1.getLabelCount()); - - EXPECT_EQ(3, ls2.getLabelCount()); - ls2.stripRight(1); - EXPECT_EQ(2, ls2.getLabelCount()); - ls2.stripRight(1); - EXPECT_EQ(1, ls2.getLabelCount()); - - EXPECT_EQ(3, ls3.getLabelCount()); - ls3.stripRight(2); - EXPECT_EQ(1, ls3.getLabelCount()); - - EXPECT_EQ(5, ls4.getLabelCount()); - ls4.stripRight(3); - EXPECT_EQ(2, ls4.getLabelCount()); - - EXPECT_EQ(3, ls5.getLabelCount()); - ls5.stripLeft(2); - EXPECT_EQ(1, ls5.getLabelCount()); -} - -TEST_F(LabelSequenceTest, comparePart) { - EXPECT_FALSE(ls1.equals(ls8)); - - // strip root label from example.org. - ls1.stripRight(1); - // strip foo from foo.example.org.bar. - ls8.stripLeft(1); - // strip bar. (i.e. bar and root) too - ls8.stripRight(2); - - EXPECT_TRUE(ls1.equals(ls8)); - - // Data comparison - size_t len; - const uint8_t* data = ls1.getData(&len); - getDataCheck(data, len, ls8); -} - -TEST_F(LabelSequenceTest, isAbsolute) { - ASSERT_TRUE(ls1.isAbsolute()); - - ls1.stripLeft(1); - ASSERT_TRUE(ls1.isAbsolute()); - ls1.stripRight(1); - ASSERT_FALSE(ls1.isAbsolute()); - - ASSERT_TRUE(ls2.isAbsolute()); - ls2.stripRight(1); - ASSERT_FALSE(ls2.isAbsolute()); - - ASSERT_TRUE(ls3.isAbsolute()); - ls3.stripLeft(2); - ASSERT_TRUE(ls3.isAbsolute()); -} - -TEST_F(LabelSequenceTest, toText) { - EXPECT_EQ(".", ls7.toText()); - - EXPECT_EQ("example.org.", ls1.toText()); - ls1.stripLeft(1); - EXPECT_EQ("org.", ls1.toText()); - ls1.stripLeft(1); - EXPECT_EQ(".", ls1.toText()); - - EXPECT_EQ("example.com.", ls2.toText()); - ls2.stripRight(1); - EXPECT_EQ("example.com", ls2.toText()); - ls2.stripRight(1); - EXPECT_EQ("example", ls2.toText()); - - EXPECT_EQ("foo.example.org.bar.", ls8.toText()); - ls8.stripRight(2); - EXPECT_EQ("foo.example.org", ls8.toText()); - - EXPECT_EQ(".", ls7.toText()); - EXPECT_THROW(ls7.stripLeft(1), isc::OutOfRange); - - Name n_long1("012345678901234567890123456789" - "012345678901234567890123456789012." - "012345678901234567890123456789" - "012345678901234567890123456789012." - "012345678901234567890123456789" - "012345678901234567890123456789012." - "012345678901234567890123456789" - "0123456789012345678901234567890"); - LabelSequence ls_long1(n_long1); - - EXPECT_EQ("012345678901234567890123456789" - "012345678901234567890123456789012." - "012345678901234567890123456789" - "012345678901234567890123456789012." - "012345678901234567890123456789" - "012345678901234567890123456789012." - "012345678901234567890123456789" - "0123456789012345678901234567890.", ls_long1.toText()); - ls_long1.stripRight(1); - EXPECT_EQ("012345678901234567890123456789" - "012345678901234567890123456789012." - "012345678901234567890123456789" - "012345678901234567890123456789012." - "012345678901234567890123456789" - "012345678901234567890123456789012." - "012345678901234567890123456789" - "0123456789012345678901234567890", ls_long1.toText()); - - LabelSequence ls_long2(n_maxlabel); - - EXPECT_EQ("0.1.2.3.4.5.6.7.8.9.0.1.2.3.4.5.6.7.8.9." - "0.1.2.3.4.5.6.7.8.9.0.1.2.3.4.5.6.7.8.9." - "0.1.2.3.4.5.6.7.8.9.0.1.2.3.4.5.6.7.8.9." - "0.1.2.3.4.5.6.7.8.9.0.1.2.3.4.5.6.7.8.9." - "0.1.2.3.4.5.6.7.8.9.0.1.2.3.4.5.6.7.8.9." - "0.1.2.3.4.5.6.7.8.9.0.1.2.3.4.5.6.7.8.9." - "0.1.2.3.4.5.6.", ls_long2.toText()); - ls_long2.stripRight(1); - EXPECT_EQ("0.1.2.3.4.5.6.7.8.9.0.1.2.3.4.5.6.7.8.9." - "0.1.2.3.4.5.6.7.8.9.0.1.2.3.4.5.6.7.8.9." - "0.1.2.3.4.5.6.7.8.9.0.1.2.3.4.5.6.7.8.9." - "0.1.2.3.4.5.6.7.8.9.0.1.2.3.4.5.6.7.8.9." - "0.1.2.3.4.5.6.7.8.9.0.1.2.3.4.5.6.7.8.9." - "0.1.2.3.4.5.6.7.8.9.0.1.2.3.4.5.6.7.8.9." - "0.1.2.3.4.5.6", ls_long2.toText()); - ls_long2.stripRight(125); - EXPECT_EQ("0.1", ls_long2.toText()); -} - -// The following verifies that toRawText() returns a string -// actual characters in place of escape sequences. We do not -// bother with an exhaustive set of tests here as this is -// not a primary use case. -TEST_F(LabelSequenceTest, toRawText) { - Name n("a bc.$exa(m)ple.@org"); - LabelSequence l(n); - EXPECT_EQ("a bc.$exa(m)ple.@org", l.toRawText(true)); - EXPECT_EQ("a bc.$exa(m)ple.@org.", l.toRawText(false)); - - // toRawText is not supposed to do any sanity checks. - // Let's try with a very weird name. - Name n2("xtra\tchars\n.in.name"); - LabelSequence l2(n2); - EXPECT_EQ("xtra\tchars\n.in.name.", l2.toRawText(false)); -} - -// The following are test data used in the getHash test below. Normally -// we use example/documentation domain names for testing, but in this case -// we'd specifically like to use more realistic data, and are intentionally -// using real-world samples: They are the NS names of root and some top level -// domains as of this test. -const char* const root_servers[] = { - "a.root-servers.net", "b.root-servers.net", "c.root-servers.net", - "d.root-servers.net", "e.root-servers.net", "f.root-servers.net", - "g.root-servers.net", "h.root-servers.net", "i.root-servers.net", - "j.root-servers.net", "k.root-servers.net", "l.root-servers.net", - "m.root-servers.net", NULL -}; - -const char* const jp_servers[] = { - "a.dns.jp", "b.dns.jp", "c.dns.jp", "d.dns.jp", "e.dns.jp", - "f.dns.jp", "g.dns.jp", NULL -}; -const char* const cn_servers[] = { - "a.dns.cn", "b.dns.cn", "c.dns.cn", "d.dns.cn", "e.dns.cn", - "ns.cernet.net", NULL -}; -const char* const ca_servers[] = { - "k.ca-servers.ca", "e.ca-servers.ca", "a.ca-servers.ca", "z.ca-servers.ca", - "tld.isc-sns.net", "c.ca-servers.ca", "j.ca-servers.ca", "l.ca-servers.ca", - "sns-pb.isc.org", "f.ca-servers.ca", NULL -}; - -// A helper function used in the getHash test below. -void -hashDistributionCheck(const char* const* servers) { - const size_t BUCKETS = 64; // constant used in the MessageRenderer - set<Name> names; - vector<size_t> hash_counts(BUCKETS); - - // Store all test names and their super domain names (excluding the - // "root" label) in the set, calculates their hash values, and increments - // the counter for the corresponding hash "bucket". - for (size_t i = 0; servers[i] != NULL; ++i) { - const Name name(servers[i]); - for (size_t l = 0; l < name.getLabelCount() - 1; ++l) { - pair<set<Name>::const_iterator, bool> ret = - names.insert(name.split(l)); - if (ret.second) { - hash_counts[LabelSequence((*ret.first)).getHash(false) % - BUCKETS]++; - } - } - } - - // See how many conflicts we have in the buckets. For the testing purpose - // we expect there's at most 2 conflicts in each set, which is an - // arbitrary choice (it should happen to succeed with the hash function - // and data we are using; if it's not the case, maybe with an update to - // the hash implementation, we should revise the test). - for (size_t i = 0; i < BUCKETS; ++i) { - EXPECT_GE(3, hash_counts[i]); - } -} - -TEST_F(LabelSequenceTest, getHash) { - // Trivial case. The same sequence should have the same hash. - EXPECT_EQ(ls1.getHash(true), ls1.getHash(true)); - - // Check the case-insensitive mode behavior. - EXPECT_EQ(ls1.getHash(false), ls5.getHash(false)); - - // Check that the distribution of hash values is "not too bad" (such as - // everything has the same hash value due to a stupid bug). It's - // difficult to check such things reliably. We do some ad hoc tests here. - hashDistributionCheck(root_servers); - hashDistributionCheck(jp_servers); - hashDistributionCheck(cn_servers); - hashDistributionCheck(ca_servers); -} - -// test operator<<. We simply confirm it appends the result of toText(). -TEST_F(LabelSequenceTest, LeftShiftOperator) { - ostringstream oss; - oss << ls1; - EXPECT_EQ(ls1.toText(), oss.str()); -} - -TEST_F(LabelSequenceTest, serialize) { - // placeholder for serialized data. We use a sufficiently large space - // for testing the overwrapping cases below. - uint8_t labels_buf[LabelSequence::MAX_SERIALIZED_LENGTH * 3]; - - // vector to store expected and actual data - vector<LabelSequence> actual_labelseqs; - typedef pair<size_t, const uint8_t*> DataPair; - vector<DataPair> expected; - - // An absolute sequence directly constructed from a valid name. - // labels = 3, offset sequence = 0, 8, 12, data = "example.com." - actual_labelseqs.push_back(ls1); - const uint8_t expected_data1[] = { - 3, 0, 8, 12, 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', - 3, 'o', 'r', 'g', 0 }; - expected.push_back(DataPair(sizeof(expected_data1), expected_data1)); - - // Strip the original one from right. - // labels = 2, offset sequence = 0, 8, data = "example.com" (non absolute) - LabelSequence ls_rstripped = ls1; - ls_rstripped.stripRight(1); - actual_labelseqs.push_back(ls_rstripped); - const uint8_t expected_data2[] = { - 2, 0, 8, 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', - 3, 'o', 'r', 'g'}; - expected.push_back(DataPair(sizeof(expected_data2), expected_data2)); - - // Strip the original one from left. - // labels = 2, offset sequence = 0, 4, data = "com." - // Note that offsets are adjusted so that they begin with 0. - LabelSequence ls_lstripped = ls1; - ls_lstripped.stripLeft(1); - actual_labelseqs.push_back(ls_lstripped); - const uint8_t expected_data3[] = { 2, 0, 4, 3, 'o', 'r', 'g', 0 }; - expected.push_back(DataPair(sizeof(expected_data3), expected_data3)); - - // Root label. - LabelSequence ls_root(Name::ROOT_NAME()); - actual_labelseqs.push_back(ls_root); - const uint8_t expected_data4[] = { 1, 0, 0 }; - expected.push_back(DataPair(sizeof(expected_data4), expected_data4)); - - // Non absolute single-label. - LabelSequence ls_single = ls_rstripped; - ls_single.stripRight(1); - actual_labelseqs.push_back(ls_single); - const uint8_t expected_data5[] = { - 1, 0, 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e' }; - expected.push_back(DataPair(sizeof(expected_data5), expected_data5)); - - // Labels containing a longest possible label - const Name name_longlabel(std::string(63, 'x')); // 63 'x's - LabelSequence ls_longlabel(name_longlabel); - actual_labelseqs.push_back(ls_longlabel); - vector<uint8_t> expected_data6; - expected_data6.push_back(2); // 2 labels - expected_data6.push_back(0); // 1st offset - expected_data6.push_back(64); // 2nd offset - expected_data6.push_back(63); // 1st label length - expected_data6.insert(expected_data6.end(), 63, 'x'); // 1st label: 63 'x's - expected_data6.push_back(0); // 2nd label: trailing 0 - expected.push_back(DataPair(expected_data6.size(), &expected_data6[0])); - - // Max number of labels and longest possible name - EXPECT_EQ(Name::MAX_WIRE, n_maxlabel.getLength()); - LabelSequence ls_maxlabel(n_maxlabel); - actual_labelseqs.push_back(ls_maxlabel); - vector<uint8_t> expected_data7; - expected_data7.push_back(Name::MAX_LABELS); // number of labels - for (size_t i = 0; i < Name::MAX_LABELS; ++i) { - expected_data7.push_back(i * 2); // each label has length and 1 byte - } - // Copy wire data of the name - isc::util::OutputBuffer ob(0); - n_maxlabel.toWire(ob); - expected_data7.insert(expected_data7.end(), - static_cast<const uint8_t*>(ob.getData()), - static_cast<const uint8_t*>(ob.getData()) + - ob.getLength()); - expected.push_back(DataPair(expected_data7.size(), &expected_data7[0])); - - // For each data set, serialize the labels and compare the data to the - // expected one. - vector<DataPair>::const_iterator it = expected.begin(); - vector<LabelSequence>::const_iterator itl = actual_labelseqs.begin(); - for (; it != expected.end(); ++it, ++itl) { - SCOPED_TRACE(itl->toText()); - - const size_t serialized_len = itl->getSerializedLength(); - - ASSERT_GE(LabelSequence::MAX_SERIALIZED_LENGTH, serialized_len); - itl->serialize(labels_buf, serialized_len); - EXPECT_EQ(it->first, serialized_len); - EXPECT_EQ(0, memcmp(it->second, labels_buf, serialized_len)); - - EXPECT_EQ(NameComparisonResult::EQUAL, - LabelSequence(labels_buf).compare(*itl).getRelation()); - - // Shift the data to the middle of the buffer for overwrap check - uint8_t* const bp = labels_buf; - std::memcpy(bp + serialized_len, bp, serialized_len); - // Memory layout is now as follows: - // <- ser_len -> <- ser_len ------> - // bp bp+ser_len bp+(ser_len*2) - // olen,odata,ndata - - // end of buffer would be the first byte of offsets: invalid. - EXPECT_THROW(LabelSequence(bp + serialized_len). - serialize(bp + 2, serialized_len), - isc::BadValue); - // begin of buffer would be the last byte of ndata: invalid. - EXPECT_THROW(LabelSequence(bp + serialized_len). - serialize(bp + (2 * serialized_len) - 1, serialized_len), - isc::BadValue); - // A boundary safe case: buffer is placed after the sequence data. - // should cause no disruption. - LabelSequence(bp + serialized_len). - serialize(bp + 2 * serialized_len, serialized_len); - // A boundary safe case: buffer is placed before the sequence data - // should cause no disruption. (but the original serialized data will - // be overridden, so it can't be used any more) - LabelSequence(bp + serialized_len). - serialize(bp + 1, serialized_len); - } - - EXPECT_THROW(ls1.serialize(labels_buf, ls1.getSerializedLength() - 1), - 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 }; - EXPECT_THROW(LabelSequence ls(zero_offsets), isc::BadValue); - const uint8_t toomany_offsets[] = { Name::MAX_LABELS + 1 }; - EXPECT_THROW(LabelSequence ls(toomany_offsets), isc::BadValue); - - // (second) offset does not match actual label length - const uint8_t offsets_wrongoffset[] = { 2, 0, 64, 1 }; - EXPECT_THROW(LabelSequence ls(offsets_wrongoffset), isc::BadValue); - - // offset matches, but exceeds MAX_LABEL_LEN - const uint8_t offsets_toolonglabel[] = { 2, 0, 64, 64 }; - EXPECT_THROW(LabelSequence ls(offsets_toolonglabel), isc::BadValue); - - // Inconsistent data: an offset is lower than the previous offset - const uint8_t offsets_lower[] = { 3, // # of offsets - 0, 2, 1, // offsets - 1, 'a', 1, 'b', 0}; - EXPECT_THROW(LabelSequence ls(offsets_lower), isc::BadValue); - - // Inconsistent data: an offset is equal to the previous offset - const uint8_t offsets_noincrease[] = { 2, 0, 0, 0, 0 }; - EXPECT_THROW(LabelSequence ls(offsets_noincrease), isc::BadValue); -} - -#endif - -namespace { - -// Helper function; repeatedly calls -// - Initially, all three labelsequences should be the same -// - repeatedly performs: -// - checks all three are equal -// - stripLeft on ls1 -// - checks ls1 and ls2 are different, and ls2 and ls3 are equal -// - stripLeft on ls2 -// - checks ls1 and ls2 are equal, and ls2 and ls3 are different -// - stripLeft on ls3 -// -// (this test makes sure the stripLeft of one has no effect on the other -// two, and that the strip properties hold regardless of how they were -// constructed) -// -void stripLeftCheck(LabelSequence ls1, LabelSequence ls2, LabelSequence ls3) { - ASSERT_LT(1, ls1.getLabelCount()); - while (ls1.getLabelCount() > 1) { - check_equal(ls1, ls2); - check_equal(ls2, ls3); - - ls1.stripLeft(1); - check_compare(ls1, ls2, isc::dns::NameComparisonResult::SUPERDOMAIN, - ls1.getLabelCount(), true, -1); - check_equal(ls2, ls3); - - ls2.stripLeft(1); - check_equal(ls1, ls2); - check_compare(ls2, ls3, isc::dns::NameComparisonResult::SUPERDOMAIN, - ls1.getLabelCount(), true, -1); - - ls3.stripLeft(1); - } -} - -// Similar to stripLeftCheck, but using stripRight() -void stripRightCheck(LabelSequence ls1, LabelSequence ls2, LabelSequence ls3) { - ASSERT_LT(1, ls1.getLabelCount()); - while (ls1.getLabelCount() > 1) { - check_equal(ls1, ls2); - check_equal(ls2, ls3); - - ls1.stripRight(1); - check_compare(ls1, ls2, isc::dns::NameComparisonResult::NONE, 0, - false); - check_equal(ls2, ls3); - - ls2.stripRight(1); - check_equal(ls1, ls2); - check_compare(ls2, ls3, isc::dns::NameComparisonResult::NONE, 0, - false); - - ls3.stripRight(1); - } -} - -} // end anonymous namespace - -class ExtendableLabelSequenceTest : public ::testing::Test { -public: - ExtendableLabelSequenceTest() : bar("bar."), - example_org("example.org"), - foo("foo."), - foo_bar("foo.bar."), - foo_bar_example_org("foo.bar.example.org."), - foo_bar_foo_bar("foo.bar.foo.bar."), - foo_example("foo.example."), - org("org") - { - // explicitly set to non-zero data, to make sure - // we don't try to use data we don't set - memset(buf, 0xff, LabelSequence::MAX_SERIALIZED_LENGTH); - } - - Name bar; - Name example_org; - Name foo; - Name foo_bar; - Name foo_bar_example_org; - Name foo_bar_foo_bar; - Name foo_example; - Name org; - - uint8_t buf[LabelSequence::MAX_SERIALIZED_LENGTH]; -}; - -// Test that 'extendable' labelsequences behave correctly when using -// stripLeft() and stripRight() -TEST_F(ExtendableLabelSequenceTest, extendableLabelSequence) { - LabelSequence ls1(example_org); - LabelSequence ls2(example_org); - - LabelSequence els(ls1, buf); - // ls1 is absolute, so els should be too - EXPECT_TRUE(els.isAbsolute()); - check_equal(ls1, els); - - ASSERT_EQ(ls1.getDataLength(), els.getDataLength()); - stripLeftCheck(ls1, els, ls2); - stripRightCheck(ls1, els, ls2); - - // Creating an extendable labelsequence from a non-absolute - // label sequence should result in a non-absolute label sequence - ls1.stripRight(1); - els = LabelSequence(ls1, buf); - EXPECT_FALSE(els.isAbsolute()); - check_equal(ls1, els); - - // and extending with the root label should make it absolute again - els.extend(LabelSequence(Name(".")), buf); - EXPECT_TRUE(els.isAbsolute()); - check_equal(ls2, els); -} - -// Test that 'extendable' LabelSequences behave correctly when initialized -// with a stripped source LabelSequence -TEST_F(ExtendableLabelSequenceTest, extendableLabelSequenceLeftStrippedSource) { - LabelSequence ls1(foo_bar_example_org); - LabelSequence ls2(foo_bar_example_org); - - while (ls1.getLabelCount() > 2) { - ls1.stripLeft(1); - ls2.stripLeft(1); - - LabelSequence els(ls1, buf); - - ASSERT_EQ(ls1.getDataLength(), els.getDataLength()); - stripLeftCheck(ls1, els, ls2); - stripRightCheck(ls1, els, ls2); - } -} - -TEST_F(ExtendableLabelSequenceTest, extendableLabelSequenceRightStrippedSource) { - LabelSequence ls1(foo_bar_example_org); - LabelSequence ls2(foo_bar_example_org); - - while (ls1.getLabelCount() > 2) { - ls1.stripRight(1); - ls2.stripRight(1); - - LabelSequence els(ls1, buf); - - ASSERT_EQ(ls1.getDataLength(), els.getDataLength()); - stripLeftCheck(ls1, els, ls2); - stripRightCheck(ls1, els, ls2); - } -} - -// Check some basic 'extend' functionality -TEST_F(ExtendableLabelSequenceTest, extend) { - LabelSequence ls1(foo_bar); - LabelSequence ls2(foo); - LabelSequence ls3(bar); - LabelSequence ls4(foo_bar); - - LabelSequence els(ls2, buf); - - check_compare(ls1, els, isc::dns::NameComparisonResult::COMMONANCESTOR, 1, - true, -4); - els.extend(ls3, buf); - EXPECT_TRUE(els.isAbsolute()); - - check_equal(ls1, els); - stripLeftCheck(ls1, els, ls4); - stripRightCheck(ls1, els, ls4); - - // strip, then extend again - els.stripRight(2); // (2, 1 for root label, 1 for last label) - els.extend(ls3, buf); - EXPECT_TRUE(els.isAbsolute()); - check_equal(ls1, els); - - // Extending again should make it different - els.extend(ls3, buf); - EXPECT_TRUE(els.isAbsolute()); - check_compare(ls1, els, isc::dns::NameComparisonResult::COMMONANCESTOR, 2, - true, 4); - - // Extending with a non-absolute name should make it non-absolute as well - ls3.stripRight(1); - els.extend(ls3, buf); - EXPECT_FALSE(els.isAbsolute()); - - Name check_name("foo.bar.bar.bar"); - LabelSequence check_ls(check_name); - check_ls.stripRight(1); - check_equal(check_ls, els); - - // And try extending when both are not absolute - els.stripRight(3); - ls1.stripRight(1); - EXPECT_FALSE(els.isAbsolute()); - els.extend(ls3, buf); - EXPECT_FALSE(els.isAbsolute()); - check_equal(ls1, els); - - // Extending non-absolute with absolute should make it absolute again - EXPECT_FALSE(els.isAbsolute()); - els.extend(LabelSequence(Name("absolute.")), buf); - EXPECT_TRUE(els.isAbsolute()); - check_equal(LabelSequence(Name("foo.bar.absolute")), els); -} - -TEST_F(ExtendableLabelSequenceTest, extendLeftStripped) { - LabelSequence ls1(foo_example); - LabelSequence ls2(example_org); - LabelSequence ls3(org); - - LabelSequence els(ls1, buf); - - els.stripLeft(1); - els.extend(ls3, buf); - EXPECT_TRUE(els.isAbsolute()); - check_equal(ls2, els); -} - -// Check that when extending with itself, it does not cause horrible failures -TEST_F(ExtendableLabelSequenceTest, extendWithItself) { - LabelSequence ls1(foo_bar); - LabelSequence ls2(foo_bar_foo_bar); - - LabelSequence els(ls1, buf); - - els.extend(els, buf); - EXPECT_TRUE(els.isAbsolute()); - check_equal(ls2, els); - - // Also try for non-absolute names - ls2.stripRight(1); - els = LabelSequence(ls1, buf); - els.stripRight(1); - els.extend(els, buf); - EXPECT_FALSE(els.isAbsolute()); - check_equal(ls2, els); - - // Once more, now start out with non-absolute labelsequence - ls1.stripRight(1); - els = LabelSequence(ls1, buf); - els.extend(els, buf); - EXPECT_FALSE(els.isAbsolute()); - check_equal(ls2, els); -} - -// Test that 'extending' with just a root label is a no-op, iff the original -// was already absolute -TEST_F(ExtendableLabelSequenceTest, extendWithRoot) { - LabelSequence ls1(example_org); - - LabelSequence els(LabelSequence(ls1, buf)); - check_equal(ls1, els); - els.extend(LabelSequence(Name(".")), buf); - EXPECT_TRUE(els.isAbsolute()); - check_equal(ls1, els); - - // but not if the original was not absolute (it will be equal to - // the original labelsequence used above, but not the one it was based - // on). - LabelSequence ls2(example_org); - ls2.stripRight(1); - els = LabelSequence(ls2, buf); - EXPECT_FALSE(els.isAbsolute()); - els.extend(LabelSequence(Name(".")), buf); - EXPECT_TRUE(els.isAbsolute()); - check_equal(ls1, els); - check_compare(ls2, els, isc::dns::NameComparisonResult::NONE, 0, true, 3); -} - -// Check possible failure modes of extend() -TEST_F(ExtendableLabelSequenceTest, extendBadData) { - LabelSequence ls1(example_org); - - LabelSequence els(ls1, buf); - - // try use with unrelated labelsequence - EXPECT_THROW(ls1.extend(ls1, buf), isc::BadValue); - - // Create a long name, but so that we can still extend once - Name longlabel("1234567890123456789012345678901234567890" - "12345678901234567890"); - LabelSequence long_ls(longlabel); - els = LabelSequence(long_ls, buf); - els.extend(els, buf); - els.extend(long_ls, buf); - els.extend(long_ls, buf); - ASSERT_EQ(245, els.getDataLength()); - // Extending once more with 10 bytes should still work - els.extend(LabelSequence(Name("123456789")), buf); - EXPECT_TRUE(els.isAbsolute()); - - // Extended label sequence should now look like - const Name full_name( - "123456789012345678901234567890123456789012345678901234567890." - "123456789012345678901234567890123456789012345678901234567890." - "123456789012345678901234567890123456789012345678901234567890." - "123456789012345678901234567890123456789012345678901234567890." - "123456789."); - const LabelSequence full_ls(full_name); - check_equal(full_ls, els); - - // But now, even the shortest extension should fail - EXPECT_THROW(els.extend(LabelSequence(Name("1")), buf), isc::BadValue); - - // Check it hasn't been changed - EXPECT_TRUE(els.isAbsolute()); - check_equal(full_ls, els); - - // Also check that extending past MAX_LABELS is not possible - Name shortname("1."); - LabelSequence short_ls(shortname); - els = LabelSequence(short_ls, buf); - for (size_t i=0; i < 126; ++i) { - els.extend(short_ls, buf); - } - - // Should now look like this - const Name full_name2( - "1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1." - "1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1." - "1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1." - "1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1." - "1.1.1.1.1.1.1."); - const LabelSequence full_ls2(full_name2); - EXPECT_TRUE(els.isAbsolute()); - check_equal(full_ls2, els); - - EXPECT_THROW(els.extend(short_ls, buf), isc::BadValue); - - EXPECT_TRUE(els.isAbsolute()); - check_equal(full_ls2, els); -} - -// Check the static fixed 'wildcard' LabelSequence -TEST(WildCardLabelSequence, wildcard) { - ASSERT_FALSE(LabelSequence::WILDCARD().isAbsolute()); - ASSERT_EQ("*", LabelSequence::WILDCARD().toText()); -} - -} diff --git a/src/lib/dns/tests/master_lexer_inputsource_unittest.cc b/src/lib/dns/tests/master_lexer_inputsource_unittest.cc index c5f618af06..8b13789179 100644 --- a/src/lib/dns/tests/master_lexer_inputsource_unittest.cc +++ b/src/lib/dns/tests/master_lexer_inputsource_unittest.cc @@ -1,368 +1 @@ -// Copyright (C) 2012-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. -#include <config.h> - -#include <dns/master_lexer_inputsource.h> -#include <dns/master_lexer.h> -#include <exceptions/exceptions.h> - -#include <gtest/gtest.h> - -#include <iostream> -#include <sstream> -#include <string> - -#include <string.h> - -using namespace std; -using namespace isc::dns; -using namespace isc::dns::master_lexer_internal; - -namespace { - -const char* const test_input = - "Line1 to scan.\nLine2 to scan.\nLine3 to scan.\n"; - -class InputSourceTest : public ::testing::Test { -protected: - InputSourceTest() : - str_(test_input), - str_length_(strlen(str_)), - iss_(str_), - source_(iss_) - {} - - const char* str_; - const size_t str_length_; - stringstream iss_; - InputSource source_; -}; - -// Test the default return values set during InputSource construction. -TEST_F(InputSourceTest, defaults) { - EXPECT_EQ(1, source_.getCurrentLine()); - EXPECT_FALSE(source_.atEOF()); -} - -// getName() on file and stream sources -TEST_F(InputSourceTest, getName) { - EXPECT_EQ(0, source_.getName().find("stream-")); - - // Use some file; doesn't really matter what. - InputSource source2(TEST_DATA_SRCDIR "/masterload.txt"); - EXPECT_EQ(TEST_DATA_SRCDIR "/masterload.txt", source2.getName()); -} - -TEST_F(InputSourceTest, nonExistentFile) { - EXPECT_THROW({ - InputSource source(TEST_DATA_SRCDIR "/does-not-exist"); - }, InputSource::OpenError); -} - -// getChar() should return characters from the input stream in -// sequence. ungetChar() should skip backwards. -void -checkGetAndUngetChar(InputSource& source, - const char* str, const size_t str_length) -{ - for (size_t i = 0; i < str_length; ++i) { - EXPECT_EQ(str[i], source.getChar()); - EXPECT_EQ(i + 1, source.getPosition()); - EXPECT_FALSE(source.atEOF()); - } - - // At this point, we still have not reached EOF. - EXPECT_FALSE(source.atEOF()); - - // This should cause EOF to be set. - EXPECT_EQ(InputSource::END_OF_STREAM, source.getChar()); - - // Now, EOF should be set. - EXPECT_TRUE(source.atEOF()); - - // It doesn't increase the position count. - EXPECT_EQ(str_length, source.getPosition()); - EXPECT_EQ(str_length, source.getSize()); // this should be == getSize(). - - // Now, let's go backwards. This should cause the EOF to be set to - // false. - source.ungetChar(); - - // Now, EOF should be false. - EXPECT_FALSE(source.atEOF()); - - // But the position shouldn't change. - EXPECT_EQ(str_length, source.getPosition()); - - // This should cause EOF to be set again. - EXPECT_EQ(InputSource::END_OF_STREAM, source.getChar()); - - // Now, EOF should be set. - EXPECT_TRUE(source.atEOF()); - - // Now, let's go backwards in a loop. Start by skipping the EOF. - source.ungetChar(); - - for (size_t i = 0; i < str_length; ++i) { - const size_t index = str_length - 1 - i; - // Skip one character. - source.ungetChar(); - EXPECT_EQ(str[index], source.getChar()); - EXPECT_EQ(index + 1, source.getPosition()); - // Skip the character we received again. - source.ungetChar(); - } - - // Skipping past the start of buffer should throw. - EXPECT_THROW(source.ungetChar(), InputSource::UngetBeforeBeginning); -} - -TEST_F(InputSourceTest, stream) { - checkGetAndUngetChar(source_, str_, str_length_); -} - -TEST_F(InputSourceTest, file) { - std::ifstream fs(TEST_DATA_SRCDIR "/masterload.txt"); - const std::string str((std::istreambuf_iterator<char>(fs)), - std::istreambuf_iterator<char>()); - fs.close(); - - InputSource source(TEST_DATA_SRCDIR "/masterload.txt"); - checkGetAndUngetChar(source, str.c_str(), str.size()); -} - -// ungetAll() should skip back to the place where the InputSource -// started at construction, or the last saved start of line. -TEST_F(InputSourceTest, ungetAll) { - while (!source_.atEOF()) { - source_.getChar(); - } - - // Now, we are at EOF. - EXPECT_TRUE(source_.atEOF()); - EXPECT_EQ(4, source_.getCurrentLine()); - - source_.ungetAll(); - - // Now we are back to where we started. - EXPECT_EQ(1, source_.getCurrentLine()); - EXPECT_FALSE(source_.atEOF()); - EXPECT_EQ(0, source_.getPosition()); -} - -TEST_F(InputSourceTest, compact) { - // Compact at the start - source_.compact(); - - // Ungetting here must throw. - EXPECT_THROW(source_.ungetChar(), InputSource::UngetBeforeBeginning); - - for (size_t i = 0; i < str_length_; ++i) { - EXPECT_EQ(str_[i], source_.getChar()); - EXPECT_FALSE(source_.atEOF()); - } - - // At this point, we still have not reached EOF. - EXPECT_FALSE(source_.atEOF()); - - // This should cause EOF to be set. - EXPECT_EQ(InputSource::END_OF_STREAM, source_.getChar()); - - // Now, EOF should be set. - EXPECT_TRUE(source_.atEOF()); - EXPECT_EQ(4, source_.getCurrentLine()); - - // Compact again - source_.compact(); - - // We are still at EOF. - EXPECT_TRUE(source_.atEOF()); - EXPECT_EQ(4, source_.getCurrentLine()); - - // compact shouldn't change the position count. - EXPECT_EQ(source_.getSize(), source_.getPosition()); - - // Skip the EOF. - source_.ungetChar(); - - // Ungetting here must throw. - EXPECT_THROW(source_.ungetChar(), InputSource::UngetBeforeBeginning); - - EXPECT_EQ(InputSource::END_OF_STREAM, source_.getChar()); - EXPECT_TRUE(source_.atEOF()); -} - -TEST_F(InputSourceTest, markDuring) { - // First, skip to line 2. - while (!source_.atEOF() && - (source_.getCurrentLine() != 2)) { - source_.getChar(); - } - EXPECT_FALSE(source_.atEOF()); - EXPECT_EQ(2, source_.getCurrentLine()); - - // Now, unget a couple of characters. This should cause the - // buffer_pos_ to be not equal to the size of the buffer. - source_.ungetChar(); - source_.ungetChar(); - - // Now "mark" the source, meaning that we save line number and also - // compact the internal buffer at this stage. - source_.mark(); - - // Ungetting here must throw. - EXPECT_THROW(source_.ungetChar(), InputSource::UngetBeforeBeginning); - - for (size_t i = 13; i < str_length_; ++i) { - EXPECT_EQ(str_[i], source_.getChar()); - EXPECT_FALSE(source_.atEOF()); - } - - // At this point, we still have not reached EOF. - EXPECT_FALSE(source_.atEOF()); - - // This should cause EOF to be set. - EXPECT_EQ(InputSource::END_OF_STREAM, source_.getChar()); - - // Now, EOF should be set. - EXPECT_TRUE(source_.atEOF()); - - // Now, ungetAll() and check where it goes back. - source_.ungetAll(); - - // Ungetting here must throw. - EXPECT_THROW(source_.ungetChar(), InputSource::UngetBeforeBeginning); - - for (size_t i = 13; i < str_length_; ++i) { - EXPECT_EQ(str_[i], source_.getChar()); - EXPECT_FALSE(source_.atEOF()); - } - - // At this point, we still have not reached EOF. - EXPECT_FALSE(source_.atEOF()); - - // This should cause EOF to be set. - EXPECT_EQ(InputSource::END_OF_STREAM, source_.getChar()); - - // Now, EOF should be set. - EXPECT_TRUE(source_.atEOF()); -} - -// Test line counters. -TEST_F(InputSourceTest, lines) { - size_t line = 1; - while (!source_.atEOF()) { - if (source_.getChar() == '\n') { - ++line; - } - EXPECT_EQ(line, source_.getCurrentLine()); - } - - // Now, we are at EOF. - EXPECT_TRUE(source_.atEOF()); - EXPECT_EQ(4, source_.getCurrentLine()); - - // Go backwards 2 characters, skipping the last EOF and '\n'. - source_.ungetChar(); - source_.ungetChar(); - - EXPECT_FALSE(source_.atEOF()); - EXPECT_EQ(3, source_.getCurrentLine()); - - source_.ungetAll(); - - // Now we are back to where we started. - EXPECT_EQ(1, source_.getCurrentLine()); - EXPECT_FALSE(source_.atEOF()); - - // Now check that line numbers are decremented properly (as much as - // possible using the available API). - while (!source_.atEOF()) { - source_.getChar(); - } - line = source_.getCurrentLine(); - - // Now, we are at EOF. - EXPECT_TRUE(source_.atEOF()); - EXPECT_EQ(4, line); - - EXPECT_THROW({ - while (true) { - source_.ungetChar(); - EXPECT_TRUE(((line == source_.getCurrentLine()) || - ((line - 1) == source_.getCurrentLine()))); - line = source_.getCurrentLine(); - } - }, InputSource::UngetBeforeBeginning); - - // Now we are back to where we started. - EXPECT_EQ(1, source_.getCurrentLine()); -} - -// ungetAll() after saveLine() should skip back to the last-saved place. -TEST_F(InputSourceTest, saveLine) { - // First, skip to line 2. - while (!source_.atEOF() && - (source_.getCurrentLine() != 2)) { - source_.getChar(); - } - EXPECT_FALSE(source_.atEOF()); - EXPECT_EQ(2, source_.getCurrentLine()); - - // Now, save the line. - source_.saveLine(); - - // Now, go to EOF - while (!source_.atEOF()) { - source_.getChar(); - } - - // Now, we are at EOF. - EXPECT_TRUE(source_.atEOF()); - EXPECT_EQ(4, source_.getCurrentLine()); - - // Now, ungetAll() and check where it goes back. - source_.ungetAll(); - - // Now we are back to where we last-saved. - EXPECT_EQ(2, source_.getCurrentLine()); - EXPECT_FALSE(source_.atEOF()); -} - -TEST_F(InputSourceTest, getSize) { - // A simple case using string stream - EXPECT_EQ(strlen(test_input), source_.getSize()); - - // Check it works with an empty input - istringstream iss(""); - EXPECT_EQ(0, InputSource(iss).getSize()); - - // Pretend there's an error in seeking in the stream. It will be - // considered a seek specific error, and getSize() returns "unknown". - iss.setstate(std::ios_base::failbit); - EXPECT_EQ(MasterLexer::SOURCE_SIZE_UNKNOWN, InputSource(iss).getSize()); - // The fail bit should have been cleared. - EXPECT_FALSE(iss.fail()); - - // Pretend there's a *critical* error in the stream. The constructor will - // throw in the attempt of getting the input size. - iss.setstate(std::ios_base::badbit); - EXPECT_THROW(InputSource isrc(iss), InputSource::OpenError); - - // Check with input source from file name. We hardcode the file size - // for simplicity. It won't change too often. - EXPECT_EQ(143, InputSource(TEST_DATA_SRCDIR "/masterload.txt").getSize()); -} - -TEST_F(InputSourceTest, getPosition) { - // Initially the position is set to 0. Other cases are tested in tests - // for get and unget. - EXPECT_EQ(0, source_.getPosition()); - EXPECT_EQ(0, InputSource(TEST_DATA_SRCDIR "/masterload.txt").getPosition()); -} - -} // end namespace diff --git a/src/lib/dns/tests/master_lexer_state_unittest.cc b/src/lib/dns/tests/master_lexer_state_unittest.cc index e810136068..8b13789179 100644 --- a/src/lib/dns/tests/master_lexer_state_unittest.cc +++ b/src/lib/dns/tests/master_lexer_state_unittest.cc @@ -1,607 +1 @@ -// Copyright (C) 2012-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#include <config.h> - -#include <dns/master_lexer.h> -#include <dns/master_lexer_inputsource.h> -#include <dns/master_lexer_state.h> - -#include <gtest/gtest.h> - -#include <sstream> - -using namespace isc::dns; -using namespace master_lexer_internal; - -namespace { -typedef MasterToken Token; // shortcut - -class MasterLexerStateTest : public ::testing::Test { -protected: - MasterLexerStateTest() : common_options(MasterLexer::INITIAL_WS), - s_null(NULL), - s_crlf(State::getInstance(State::CRLF)), - s_string(State::getInstance(State::String)), - s_qstring(State::getInstance(State::QString)), - s_number(State::getInstance(State::Number)), - options(MasterLexer::NONE), - orig_options(options) - {} - - // Specify INITIAL_WS as common initial options. - const MasterLexer::Options common_options; - MasterLexer lexer; - const State* const s_null; - const State& s_crlf; - const State& s_string; - const State& s_qstring; - const State& s_number; - std::stringstream ss; - MasterLexer::Options options, orig_options; -}; - -// Common check for the end-of-file condition. -// Token is set to END_OF_FILE, and the lexer was NOT last eol state. -// Passed state can be any valid one; they are stateless, just providing the -// interface for inspection. -void -eofCheck(const State& state, MasterLexer& lexer) { - EXPECT_EQ(Token::END_OF_FILE, state.getToken(lexer).getType()); - EXPECT_FALSE(state.wasLastEOL(lexer)); -} - -TEST_F(MasterLexerStateTest, startAndEnd) { - // A simple case: the input is empty, so we begin with start and - // are immediately done. - lexer.pushSource(ss); - EXPECT_EQ(s_null, State::start(lexer, common_options)); - eofCheck(s_crlf, lexer); -} - -TEST_F(MasterLexerStateTest, startToEOL) { - ss << "\n"; - lexer.pushSource(ss); - - EXPECT_EQ(s_null, State::start(lexer, common_options)); - EXPECT_TRUE(s_crlf.wasLastEOL(lexer)); - EXPECT_EQ(Token::END_OF_LINE, s_crlf.getToken(lexer).getType()); - - // The next lexer session will reach EOF. Same eof check should pass. - EXPECT_EQ(s_null, State::start(lexer, common_options)); - eofCheck(s_crlf, lexer); -} - -TEST_F(MasterLexerStateTest, space) { - // repeat '\t\n' twice (see below), then space after EOL - ss << " \t\n\t\n "; - lexer.pushSource(ss); - - // by default space characters and tabs will be ignored. We check this - // twice; at the second iteration, it's a white space at the beginning - // of line, but since we don't specify INITIAL_WS option, it's treated as - // normal space and ignored. - for (size_t i = 0; i < 2; ++i) { - EXPECT_EQ(s_null, State::start(lexer, MasterLexer::NONE)); - EXPECT_TRUE(s_crlf.wasLastEOL(lexer)); - EXPECT_EQ(Token::END_OF_LINE, s_crlf.getToken(lexer).getType()); - } - - // Now we specify the INITIAL_WS option. It will be recognized and the - // corresponding token will be returned. - EXPECT_EQ(s_null, State::start(lexer, MasterLexer::INITIAL_WS)); - EXPECT_FALSE(s_crlf.wasLastEOL(lexer)); - EXPECT_EQ(Token::INITIAL_WS, s_crlf.getToken(lexer).getType()); -} - -TEST_F(MasterLexerStateTest, parentheses) { - ss << "\n(\na\n )\n "; // 1st \n is to check if 'was EOL' is set to false - lexer.pushSource(ss); - - EXPECT_EQ(s_null, State::start(lexer, common_options)); // handle \n - - // Now handle '('. It skips \n and recognize 'a' as string - EXPECT_EQ(0, s_crlf.getParenCount(lexer)); // check pre condition - EXPECT_EQ(&s_string, State::start(lexer, common_options)); - EXPECT_EQ(1, s_crlf.getParenCount(lexer)); // check post condition - EXPECT_FALSE(s_crlf.wasLastEOL(lexer)); - - // skip 'a' - s_string.handle(lexer); - - // Then handle ')'. '\n' before ')' isn't recognized because - // it's canceled due to the '('. Likewise, the space after the '\n' - // shouldn't be recognized but should be just ignored. - EXPECT_EQ(s_null, State::start(lexer, common_options)); - EXPECT_EQ(0, s_crlf.getParenCount(lexer)); - - // Now, temporarily disabled options are restored: Both EOL and the - // initial WS are recognized - EXPECT_EQ(Token::END_OF_LINE, s_crlf.getToken(lexer).getType()); - EXPECT_EQ(s_null, State::start(lexer, common_options)); - EXPECT_EQ(Token::INITIAL_WS, s_crlf.getToken(lexer).getType()); -} - -TEST_F(MasterLexerStateTest, nestedParentheses) { - // This is an unusual, but allowed (in this implementation) case. - ss << "(a(b)\n c)\n "; - lexer.pushSource(ss); - - EXPECT_EQ(&s_string, State::start(lexer, common_options)); // consume '(' - s_string.handle(lexer); // consume 'a' - EXPECT_EQ(&s_string, State::start(lexer, common_options)); // consume '(' - s_string.handle(lexer); // consume 'b' - EXPECT_EQ(2, s_crlf.getParenCount(lexer)); // now the count is 2 - - // Close the inner most parentheses. count will be decreased, but option - // shouldn't be restored yet, so the intermediate EOL or initial WS won't - // be recognized. - EXPECT_EQ(&s_string, State::start(lexer, common_options)); // consume ')' - s_string.handle(lexer); // consume 'c' - EXPECT_EQ(1, s_crlf.getParenCount(lexer)); - - // Close the outermost parentheses. count will be reset to 0, and original - // options are restored. - EXPECT_EQ(s_null, State::start(lexer, common_options)); - - // Now, temporarily disabled options are restored: Both EOL and the - // initial WS are recognized - EXPECT_EQ(Token::END_OF_LINE, s_crlf.getToken(lexer).getType()); - EXPECT_EQ(s_null, State::start(lexer, common_options)); - EXPECT_EQ(Token::INITIAL_WS, s_crlf.getToken(lexer).getType()); -} - -TEST_F(MasterLexerStateTest, unbalancedParentheses) { - // Only closing paren is provided. We prepend a \n to check if it's - // correctly canceled after detecting the error. - ss << "\n)"; - ss << "(a"; - lexer.pushSource(ss); - - EXPECT_EQ(s_null, State::start(lexer, common_options)); // consume '\n' - EXPECT_TRUE(s_crlf.wasLastEOL(lexer)); // this \n was remembered - - // Now checking ')'. The result should be error, count shouldn't be - // changed. "last EOL" should be canceled. - EXPECT_EQ(0, s_crlf.getParenCount(lexer)); - EXPECT_EQ(s_null, State::start(lexer, common_options)); - EXPECT_EQ(0, s_crlf.getParenCount(lexer)); - ASSERT_EQ(Token::ERROR, s_crlf.getToken(lexer).getType()); - EXPECT_EQ(Token::UNBALANCED_PAREN, s_crlf.getToken(lexer).getErrorCode()); - EXPECT_FALSE(s_crlf.wasLastEOL(lexer)); - - // Reach EOF with a dangling open parenthesis. - EXPECT_EQ(&s_string, State::start(lexer, common_options)); // consume '(' - s_string.handle(lexer); // consume 'a' - EXPECT_EQ(1, s_crlf.getParenCount(lexer)); - EXPECT_EQ(s_null, State::start(lexer, common_options)); // reach EOF - ASSERT_EQ(Token::ERROR, s_crlf.getToken(lexer).getType()); - EXPECT_EQ(Token::UNBALANCED_PAREN, s_crlf.getToken(lexer).getErrorCode()); - EXPECT_EQ(0, s_crlf.getParenCount(lexer)); // should be reset to 0 -} - -TEST_F(MasterLexerStateTest, startToComment) { - // Begin with 'start', detect space, then encounter a comment. Skip - // the rest of the line, and recognize the new line. Note that the - // second ';' is simply ignored. - ss << " ;a;\n"; - ss << ";a;"; // Likewise, but the comment ends with EOF. - lexer.pushSource(ss); - - // Initial whitespace (asked for in common_options) - EXPECT_EQ(s_null, State::start(lexer, common_options)); - EXPECT_EQ(Token::INITIAL_WS, s_crlf.getToken(lexer).getType()); - // Comment ending with EOL - EXPECT_EQ(s_null, State::start(lexer, common_options)); - EXPECT_EQ(Token::END_OF_LINE, s_crlf.getToken(lexer).getType()); - - // Comment ending with EOF - EXPECT_EQ(s_null, State::start(lexer, common_options)); - EXPECT_EQ(Token::END_OF_FILE, s_crlf.getToken(lexer).getType()); -} - -TEST_F(MasterLexerStateTest, commentAfterParen) { - // comment after an opening parenthesis. The code that is tested by - // other tests should also ensure that it works correctly, but we - // check it explicitly. - ss << "( ;this is a comment\na)\n"; - lexer.pushSource(ss); - - // consume '(', skip comments, consume 'a', then consume ')' - EXPECT_EQ(&s_string, State::start(lexer, common_options)); - s_string.handle(lexer); - EXPECT_EQ(s_null, State::start(lexer, common_options)); - EXPECT_EQ(Token::END_OF_LINE, s_crlf.getToken(lexer).getType()); -} - -TEST_F(MasterLexerStateTest, crlf) { - ss << "\r\n"; // case 1 - ss << "\r "; // case 2 - ss << "\r;comment\na"; // case 3 - ss << "\r"; // case 4 - lexer.pushSource(ss); - - // 1. A sequence of \r, \n is recognized as a single 'end-of-line' - EXPECT_EQ(&s_crlf, State::start(lexer, common_options)); // recognize '\r' - s_crlf.handle(lexer); // recognize '\n' - EXPECT_EQ(Token::END_OF_LINE, s_crlf.getToken(lexer).getType()); - EXPECT_TRUE(s_crlf.wasLastEOL(lexer)); - - // 2. Single '\r' (not followed by \n) is recognized as a single - // 'end-of-line'. then there will be "initial WS" - EXPECT_EQ(&s_crlf, State::start(lexer, common_options)); // recognize '\r' - // see ' ', "unget" it - s_crlf.handle(lexer); - EXPECT_EQ(s_null, State::start(lexer, common_options)); // recognize ' ' - EXPECT_EQ(Token::INITIAL_WS, s_crlf.getToken(lexer).getType()); - - // 3. comment between \r and \n - EXPECT_EQ(&s_crlf, State::start(lexer, common_options)); // recognize '\r' - // skip comments, recognize '\n' - s_crlf.handle(lexer); - EXPECT_EQ(Token::END_OF_LINE, s_crlf.getToken(lexer).getType()); - EXPECT_EQ(&s_string, State::start(lexer, common_options)); - s_string.handle(lexer); // skip 'a' - - // 4. \r then EOF - EXPECT_EQ(&s_crlf, State::start(lexer, common_options)); // recognize '\r' - // see EOF, then "unget" it - s_crlf.handle(lexer); - EXPECT_EQ(s_null, State::start(lexer, common_options)); // recognize EOF - EXPECT_EQ(Token::END_OF_FILE, s_crlf.getToken(lexer).getType()); -} - -// Commonly used check for string related test cases, checking if the given -// token has expected values. -void -stringTokenCheck(const std::string& expected, const MasterToken& token, - bool quoted = false) -{ - EXPECT_EQ(quoted ? Token::QSTRING : Token::STRING, token.getType()); - EXPECT_EQ(expected, token.getString()); - const std::string actual(token.getStringRegion().beg, - token.getStringRegion().beg + - token.getStringRegion().len); - EXPECT_EQ(expected, actual); - - // There should be "hidden" nul-terminator after the string data. - ASSERT_NE(static_cast<const char*>(NULL), token.getStringRegion().beg); - EXPECT_EQ(0, *(token.getStringRegion().beg + token.getStringRegion().len)); -} - -TEST_F(MasterLexerStateTest, string) { - // Check with simple strings followed by separate characters - ss << "followed-by-EOL\n"; - ss << "followed-by-CR\r"; - ss << "followed-by-space "; - ss << "followed-by-tab\t"; - ss << "followed-by-comment;this is comment and ignored\n"; - ss << "followed-by-paren(closing)"; - ss << "followed-by-EOF"; - lexer.pushSource(ss); - - EXPECT_EQ(&s_string, State::start(lexer, common_options)); - s_string.handle(lexer); // recognize str, see \n - EXPECT_FALSE(s_string.wasLastEOL(lexer)); - stringTokenCheck("followed-by-EOL", s_string.getToken(lexer)); - EXPECT_EQ(s_null, State::start(lexer, common_options)); // skip \n - - EXPECT_EQ(&s_string, State::start(lexer, common_options)); - s_string.handle(lexer); // recognize str, see \r - stringTokenCheck("followed-by-CR", s_string.getToken(lexer)); - EXPECT_EQ(&s_crlf, State::start(lexer, common_options)); // handle \r... - s_crlf.handle(lexer); // ...and skip it - - EXPECT_EQ(&s_string, State::start(lexer, common_options)); - s_string.handle(lexer); // recognize str, see ' ' - stringTokenCheck("followed-by-space", s_string.getToken(lexer)); - - // skip ' ', then recognize the next string - EXPECT_EQ(&s_string, State::start(lexer, common_options)); - s_string.handle(lexer); // recognize str, see \t - stringTokenCheck("followed-by-tab", s_string.getToken(lexer)); - - // skip \t, then recognize the next string - EXPECT_EQ(&s_string, State::start(lexer, common_options)); - s_string.handle(lexer); // recognize str, see comment - stringTokenCheck("followed-by-comment", s_string.getToken(lexer)); - EXPECT_EQ(s_null, State::start(lexer, common_options)); // skip \n after it - - EXPECT_EQ(&s_string, State::start(lexer, common_options)); - s_string.handle(lexer); // recognize str, see '(' - stringTokenCheck("followed-by-paren", s_string.getToken(lexer)); - EXPECT_EQ(&s_string, State::start(lexer, common_options)); // str in () - s_string.handle(lexer); // recognize the str, see ')' - stringTokenCheck("closing", s_string.getToken(lexer)); - - EXPECT_EQ(&s_string, State::start(lexer, common_options)); - s_string.handle(lexer); // recognize str, see EOF - stringTokenCheck("followed-by-EOF", s_string.getToken(lexer)); -} - -TEST_F(MasterLexerStateTest, stringEscape) { - // some of the separate characters should be considered part of the - // string if escaped. - ss << "escaped\\ space "; - ss << "escaped\\\ttab "; - ss << "escaped\\(paren "; - ss << "escaped\\)close "; - ss << "escaped\\;comment "; - ss << "escaped\\\\ backslash "; // second '\' shouldn't escape ' ' - lexer.pushSource(ss); - - EXPECT_EQ(&s_string, State::start(lexer, common_options)); - s_string.handle(lexer); // recognize str, see ' ' at end - stringTokenCheck("escaped\\ space", s_string.getToken(lexer)); - - EXPECT_EQ(&s_string, State::start(lexer, common_options)); - s_string.handle(lexer); // recognize str, see ' ' at end - stringTokenCheck("escaped\\\ttab", s_string.getToken(lexer)); - - EXPECT_EQ(&s_string, State::start(lexer, common_options)); - s_string.handle(lexer); // recognize str, see ' ' at end - stringTokenCheck("escaped\\(paren", s_string.getToken(lexer)); - - EXPECT_EQ(&s_string, State::start(lexer, common_options)); - s_string.handle(lexer); // recognize str, see ' ' at end - stringTokenCheck("escaped\\)close", s_string.getToken(lexer)); - - EXPECT_EQ(&s_string, State::start(lexer, common_options)); - s_string.handle(lexer); // recognize str, see ' ' at end - stringTokenCheck("escaped\\;comment", s_string.getToken(lexer)); - - EXPECT_EQ(&s_string, State::start(lexer, common_options)); - s_string.handle(lexer); // recognize str, see ' ' in mid - stringTokenCheck("escaped\\\\", s_string.getToken(lexer)); - - // Confirm the word that follows the escaped '\' is correctly recognized. - EXPECT_EQ(&s_string, State::start(lexer, common_options)); - s_string.handle(lexer); // recognize str, see ' ' at end - stringTokenCheck("backslash", s_string.getToken(lexer)); -} - -TEST_F(MasterLexerStateTest, quotedString) { - ss << "\"ignore-quotes\"\n"; - ss << "\"quoted string\" "; // space is part of the qstring - ss << "\"\" "; // empty quoted string - // also check other separator characters. note that \r doesn't cause - // UNBALANCED_QUOTES. Not sure if it's intentional, but that's how the - // BIND 9 version works, so we follow it (it should be too minor to matter - // in practice anyway) - ss << "\"quoted()\t\rstring\" "; - ss << "\"escape\\ in quote\" "; - ss << "\"escaped\\\"\" "; - ss << "\"escaped backslash\\\\\" "; - ss << "\"no;comment\""; - lexer.pushSource(ss); - - // by default, '"' is unexpected (when QSTRING is not specified), - // and it returns MasterToken::UNEXPECTED_QUOTES. - EXPECT_EQ(s_null, State::start(lexer, common_options)); - EXPECT_EQ(Token::UNEXPECTED_QUOTES, s_string.getToken(lexer).getErrorCode()); - // Read it as a QSTRING. - s_qstring.handle(lexer); // recognize quoted str, see \n - stringTokenCheck("ignore-quotes", s_qstring.getToken(lexer), true); - EXPECT_EQ(s_null, State::start(lexer, common_options)); // skip \n after it - EXPECT_TRUE(s_string.wasLastEOL(lexer)); - - // If QSTRING is specified in option, '"' is regarded as a beginning of - // a quoted string. - const MasterLexer::Options options = common_options | MasterLexer::QSTRING; - EXPECT_EQ(&s_qstring, State::start(lexer, options)); - EXPECT_FALSE(s_string.wasLastEOL(lexer)); // EOL is canceled due to '"' - s_qstring.handle(lexer); - stringTokenCheck("quoted string", s_string.getToken(lexer), true); - - // Empty string is okay as qstring - EXPECT_EQ(&s_qstring, State::start(lexer, options)); - s_qstring.handle(lexer); - stringTokenCheck("", s_string.getToken(lexer), true); - - // Also checks other separator characters within a qstring - EXPECT_EQ(&s_qstring, State::start(lexer, options)); - s_qstring.handle(lexer); - stringTokenCheck("quoted()\t\rstring", s_string.getToken(lexer), true); - - // escape character mostly doesn't have any effect in the qstring - // processing - EXPECT_EQ(&s_qstring, State::start(lexer, options)); - s_qstring.handle(lexer); - stringTokenCheck("escape\\ in quote", s_string.getToken(lexer), true); - - // The only exception is the quotation mark itself. Note that the escape - // only works on the quotation mark immediately after it. - EXPECT_EQ(&s_qstring, State::start(lexer, options)); - s_qstring.handle(lexer); - stringTokenCheck("escaped\"", s_string.getToken(lexer), true); - - // quoted '\' then '"'. Unlike the previous case '"' shouldn't be - // escaped. - EXPECT_EQ(&s_qstring, State::start(lexer, options)); - s_qstring.handle(lexer); - stringTokenCheck("escaped backslash\\\\", s_string.getToken(lexer), true); - - // ';' has no meaning in a quoted string (not indicating a comment) - EXPECT_EQ(&s_qstring, State::start(lexer, options)); - s_qstring.handle(lexer); - stringTokenCheck("no;comment", s_string.getToken(lexer), true); -} - -TEST_F(MasterLexerStateTest, brokenQuotedString) { - ss << "\"unbalanced-quote\n"; - ss << "\"quoted\\\n\" "; - ss << "\"unclosed quote and EOF"; - lexer.pushSource(ss); - - // EOL is encountered without closing the quote - const MasterLexer::Options options = common_options | MasterLexer::QSTRING; - EXPECT_EQ(&s_qstring, State::start(lexer, options)); - s_qstring.handle(lexer); - ASSERT_EQ(Token::ERROR, s_qstring.getToken(lexer).getType()); - EXPECT_EQ(Token::UNBALANCED_QUOTES, - s_qstring.getToken(lexer).getErrorCode()); - // We can resume after the error from the '\n' - EXPECT_EQ(s_null, State::start(lexer, options)); - EXPECT_EQ(Token::END_OF_LINE, s_crlf.getToken(lexer).getType()); - - // \n is okay in a quoted string if escaped - EXPECT_EQ(&s_qstring, State::start(lexer, options)); - s_qstring.handle(lexer); - stringTokenCheck("quoted\\\n", s_string.getToken(lexer), true); - - // EOF is encountered without closing the quote - EXPECT_EQ(&s_qstring, State::start(lexer, options)); - s_qstring.handle(lexer); - ASSERT_EQ(Token::ERROR, s_qstring.getToken(lexer).getType()); - EXPECT_EQ(Token::UNEXPECTED_END, s_qstring.getToken(lexer).getErrorCode()); - // If we continue we'll simply see the EOF - EXPECT_EQ(s_null, State::start(lexer, options)); - EXPECT_EQ(Token::END_OF_FILE, s_crlf.getToken(lexer).getType()); -} - -TEST_F(MasterLexerStateTest, basicNumbers) { - ss << "0 "; - ss << "1 "; - ss << "12345 "; - ss << "4294967295 "; // 2^32-1 - ss << "4294967296 "; // Out of range - ss << "340282366920938463463374607431768211456 "; - // Very much out of range (2^128) - ss << "005 "; // Leading zeroes are ignored - ss << "42;asdf\n"; // Number with comment - ss << "37"; // Simple number again, here to make - // sure none of the above messed up - // the tokenizer - lexer.pushSource(ss); - - // Ask the lexer to recognize numbers as well - const MasterLexer::Options options = common_options | MasterLexer::NUMBER; - - EXPECT_EQ(&s_number, State::start(lexer, options)); - s_number.handle(lexer); - EXPECT_EQ(0, s_number.getToken(lexer).getNumber()); - - EXPECT_EQ(&s_number, State::start(lexer, options)); - s_number.handle(lexer); - EXPECT_EQ(1, s_number.getToken(lexer).getNumber()); - - EXPECT_EQ(&s_number, State::start(lexer, options)); - s_number.handle(lexer); - EXPECT_EQ(12345, s_number.getToken(lexer).getNumber()); - - EXPECT_EQ(&s_number, State::start(lexer, options)); - s_number.handle(lexer); - EXPECT_EQ(4294967295u, s_number.getToken(lexer).getNumber()); - - EXPECT_EQ(&s_number, State::start(lexer, options)); - s_number.handle(lexer); - EXPECT_EQ(Token::NUMBER_OUT_OF_RANGE, - s_number.getToken(lexer).getErrorCode()); - - EXPECT_EQ(&s_number, State::start(lexer, options)); - s_number.handle(lexer); - EXPECT_EQ(Token::NUMBER_OUT_OF_RANGE, - s_number.getToken(lexer).getErrorCode()); - - EXPECT_EQ(&s_number, State::start(lexer, options)); - s_number.handle(lexer); - EXPECT_EQ(5, s_number.getToken(lexer).getNumber()); - - EXPECT_EQ(&s_number, State::start(lexer, options)); - s_number.handle(lexer); - EXPECT_EQ(42, s_number.getToken(lexer).getNumber()); - - EXPECT_EQ(s_null, State::start(lexer, options)); - EXPECT_TRUE(s_crlf.wasLastEOL(lexer)); - EXPECT_EQ(Token::END_OF_LINE, s_crlf.getToken(lexer).getType()); - - EXPECT_EQ(&s_number, State::start(lexer, options)); - s_number.handle(lexer); - EXPECT_EQ(37, s_number.getToken(lexer).getNumber()); - - // If we continue we'll simply see the EOF - EXPECT_EQ(s_null, State::start(lexer, options)); - EXPECT_EQ(Token::END_OF_FILE, s_crlf.getToken(lexer).getType()); -} - -// Test tokens that look like (or start out as) numbers, -// but turn out to be strings. Tests include escaped characters. -TEST_F(MasterLexerStateTest, stringNumbers) { - ss << "123 "; // Should be read as a string if the - // NUMBER option is not given - ss << "-1 "; // Negative numbers are interpreted - // as strings (unsigned integers only) - ss << "123abc456 "; // 'Numbers' containing non-digits should - // be interpreted as strings - ss << "123\\456 "; // Numbers containing escaped digits are - // interpreted as strings - ss << "3scaped\\ space "; - ss << "3scaped\\\ttab "; - ss << "3scaped\\(paren "; - ss << "3scaped\\)close "; - ss << "3scaped\\;comment "; - ss << "3scaped\\\\ 8ackslash "; // second '\' shouldn't escape ' ' - - lexer.pushSource(ss); - - // Note that common_options does not include MasterLexer::NUMBER, - // so the token should be recognized as a string - EXPECT_EQ(&s_string, State::start(lexer, common_options)); - s_string.handle(lexer); - stringTokenCheck("123", s_string.getToken(lexer), false); - - // Ask the lexer to recognize numbers as well - const MasterLexer::Options options = common_options | MasterLexer::NUMBER; - - EXPECT_EQ(&s_string, State::start(lexer, options)); - s_string.handle(lexer); - stringTokenCheck("-1", s_string.getToken(lexer), false); - - // Starts out as a number, but ends up being a string - EXPECT_EQ(&s_number, State::start(lexer, options)); - s_number.handle(lexer); - stringTokenCheck("123abc456", s_number.getToken(lexer), false); - - EXPECT_EQ(&s_number, State::start(lexer, options)); - s_number.handle(lexer); - stringTokenCheck("123\\456", s_number.getToken(lexer), false); - - EXPECT_EQ(&s_number, State::start(lexer, options)); - s_number.handle(lexer); // recognize str, see ' ' at end - stringTokenCheck("3scaped\\ space", s_number.getToken(lexer)); - - EXPECT_EQ(&s_number, State::start(lexer, options)); - s_number.handle(lexer); // recognize str, see ' ' at end - stringTokenCheck("3scaped\\\ttab", s_number.getToken(lexer)); - - EXPECT_EQ(&s_number, State::start(lexer, options)); - s_number.handle(lexer); // recognize str, see ' ' at end - stringTokenCheck("3scaped\\(paren", s_number.getToken(lexer)); - - EXPECT_EQ(&s_number, State::start(lexer, options)); - s_number.handle(lexer); // recognize str, see ' ' at end - stringTokenCheck("3scaped\\)close", s_number.getToken(lexer)); - - EXPECT_EQ(&s_number, State::start(lexer, options)); - s_number.handle(lexer); // recognize str, see ' ' at end - stringTokenCheck("3scaped\\;comment", s_number.getToken(lexer)); - - EXPECT_EQ(&s_number, State::start(lexer, options)); - s_number.handle(lexer); // recognize str, see ' ' in mid - stringTokenCheck("3scaped\\\\", s_number.getToken(lexer)); - - // Confirm the word that follows the escaped '\' is correctly recognized. - EXPECT_EQ(&s_number, State::start(lexer, options)); - s_number.handle(lexer); // recognize str, see ' ' at end - stringTokenCheck("8ackslash", s_number.getToken(lexer)); - - // If we continue we'll simply see the EOF - EXPECT_EQ(s_null, State::start(lexer, options)); - EXPECT_EQ(Token::END_OF_FILE, s_crlf.getToken(lexer).getType()); -} - -} // end anonymous namespace diff --git a/src/lib/dns/tests/master_lexer_token_unittest.cc b/src/lib/dns/tests/master_lexer_token_unittest.cc index 2167a9f5e6..8b13789179 100644 --- a/src/lib/dns/tests/master_lexer_token_unittest.cc +++ b/src/lib/dns/tests/master_lexer_token_unittest.cc @@ -1,162 +1 @@ -// Copyright (C) 2012-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. -#include <config.h> - -#include <exceptions/exceptions.h> - -#include <dns/master_lexer.h> - -#include <gtest/gtest.h> - -#include <string> - -using namespace isc::dns; - -namespace { - -const char TEST_STRING[] = "string token"; -// This excludes the ending \0 character -const size_t TEST_STRING_LEN = sizeof(TEST_STRING) - 1; - -class MasterLexerTokenTest : public ::testing::Test { -protected: - MasterLexerTokenTest() : - token_eof(MasterToken::END_OF_FILE), - token_str(TEST_STRING, TEST_STRING_LEN), - token_num(42), - token_err(MasterToken::UNEXPECTED_END) - {} - - const MasterToken token_eof; // an example of non-value type token - const MasterToken token_str; - const MasterToken token_num; - const MasterToken token_err; -}; - - -TEST_F(MasterLexerTokenTest, strings) { - // basic construction and getter checks - EXPECT_EQ(MasterToken::STRING, token_str.getType()); - EXPECT_EQ(std::string("string token"), token_str.getString()); - std::string strval = "dummy"; // this should be replaced - token_str.getString(strval); - EXPECT_EQ(std::string("string token"), strval); - const MasterToken::StringRegion str_region = - token_str.getStringRegion(); - EXPECT_EQ(TEST_STRING, str_region.beg); - EXPECT_EQ(TEST_STRING_LEN, str_region.len); - - // Even if the stored string contains a nul character (in this case, - // it happens to be at the end of the string, but could be in the middle), - // getString() should return a string object containing the nul. - std::string expected_str("string token"); - expected_str.push_back('\0'); - EXPECT_EQ(expected_str, - MasterToken(TEST_STRING, TEST_STRING_LEN + 1).getString()); - MasterToken(TEST_STRING, TEST_STRING_LEN + 1).getString(strval); - EXPECT_EQ(expected_str, strval); - - // Construct type of qstring - EXPECT_EQ(MasterToken::QSTRING, - MasterToken(TEST_STRING, sizeof(TEST_STRING), true). - getType()); - // if we explicitly set 'quoted' to false, it should be normal string - EXPECT_EQ(MasterToken::STRING, - MasterToken(TEST_STRING, sizeof(TEST_STRING), false). - getType()); - - // getString/StringRegion() aren't allowed for non string(-variant) types - EXPECT_THROW(token_eof.getString(), isc::InvalidOperation); - EXPECT_THROW(token_eof.getString(strval), isc::InvalidOperation); - EXPECT_THROW(token_num.getString(), isc::InvalidOperation); - EXPECT_THROW(token_num.getString(strval), isc::InvalidOperation); - EXPECT_THROW(token_eof.getStringRegion(), isc::InvalidOperation); - EXPECT_THROW(token_num.getStringRegion(), isc::InvalidOperation); -} - -TEST_F(MasterLexerTokenTest, numbers) { - EXPECT_EQ(42, token_num.getNumber()); - EXPECT_EQ(MasterToken::NUMBER, token_num.getType()); - - // It's copyable and assignable. - MasterToken token(token_num); - EXPECT_EQ(42, token.getNumber()); - EXPECT_EQ(MasterToken::NUMBER, token.getType()); - - token = token_num; - EXPECT_EQ(42, token.getNumber()); - EXPECT_EQ(MasterToken::NUMBER, token.getType()); - - // it's okay to replace it with a different type of token - token = token_eof; - EXPECT_EQ(MasterToken::END_OF_FILE, token.getType()); - - // Possible max value - token = MasterToken(0xffffffff); - EXPECT_EQ(4294967295u, token.getNumber()); - - // getNumber() isn't allowed for non number types - EXPECT_THROW(token_eof.getNumber(), isc::InvalidOperation); - EXPECT_THROW(token_str.getNumber(), isc::InvalidOperation); -} - -TEST_F(MasterLexerTokenTest, novalues) { - // Just checking we can construct them and getType() returns correct value. - EXPECT_EQ(MasterToken::END_OF_FILE, token_eof.getType()); - EXPECT_EQ(MasterToken::END_OF_LINE, - MasterToken(MasterToken::END_OF_LINE).getType()); - EXPECT_EQ(MasterToken::INITIAL_WS, - MasterToken(MasterToken::INITIAL_WS).getType()); - - // Special types of tokens cannot have value-based types - EXPECT_THROW(MasterToken t(MasterToken::STRING), isc::InvalidParameter); - EXPECT_THROW(MasterToken t(MasterToken::QSTRING), isc::InvalidParameter); - EXPECT_THROW(MasterToken t(MasterToken::NUMBER), isc::InvalidParameter); - EXPECT_THROW(MasterToken t(MasterToken::ERROR), isc::InvalidParameter); -} - -TEST_F(MasterLexerTokenTest, errors) { - EXPECT_EQ(MasterToken::ERROR, token_err.getType()); - EXPECT_EQ(MasterToken::UNEXPECTED_END, token_err.getErrorCode()); - EXPECT_EQ("unexpected end of input", token_err.getErrorText()); - EXPECT_EQ("lexer not started", MasterToken(MasterToken::NOT_STARTED). - getErrorText()); - EXPECT_EQ("unbalanced parentheses", - MasterToken(MasterToken::UNBALANCED_PAREN). - getErrorText()); - EXPECT_EQ("unbalanced quotes", MasterToken(MasterToken::UNBALANCED_QUOTES). - getErrorText()); - EXPECT_EQ("no token produced", MasterToken(MasterToken::NO_TOKEN_PRODUCED). - getErrorText()); - EXPECT_EQ("number out of range", - MasterToken(MasterToken::NUMBER_OUT_OF_RANGE). - getErrorText()); - EXPECT_EQ("not a valid number", - MasterToken(MasterToken::BAD_NUMBER).getErrorText()); - EXPECT_EQ("unexpected quotes", - MasterToken(MasterToken::UNEXPECTED_QUOTES).getErrorText()); - - // getErrorCode/Text() isn't allowed for non number types - EXPECT_THROW(token_num.getErrorCode(), isc::InvalidOperation); - EXPECT_THROW(token_num.getErrorText(), isc::InvalidOperation); - - // Only the pre-defined error code is accepted. Hardcoding '8' (max code - // + 1) is intentional; it'd be actually better if we notice it when we - // update the enum list (which shouldn't happen too often). - // - // Note: if you fix this testcase, you probably want to update the - // getErrorText() tests above too. - EXPECT_THROW(MasterToken(MasterToken::ErrorCode(8)), - isc::InvalidParameter); - - // Check the coexistence of "from number" and "from error-code" - // constructors won't cause confusion. - EXPECT_EQ(MasterToken::NUMBER, - MasterToken(static_cast<uint32_t>(MasterToken::NOT_STARTED)). - getType()); -} -} diff --git a/src/lib/dns/tests/master_lexer_unittest.cc b/src/lib/dns/tests/master_lexer_unittest.cc index 7bebb48bbe..8b13789179 100644 --- a/src/lib/dns/tests/master_lexer_unittest.cc +++ b/src/lib/dns/tests/master_lexer_unittest.cc @@ -1,521 +1 @@ -// Copyright (C) 2012-2020 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. -#include <config.h> - -#include <exceptions/exceptions.h> - -#include <dns/master_lexer.h> -#include <dns/master_lexer_state.h> - -#include <gtest/gtest.h> - -#include <boost/lexical_cast.hpp> -#include <boost/scoped_ptr.hpp> - -#include <string> -#include <sstream> - -using namespace isc::dns; -using std::string; -using std::stringstream; -using boost::lexical_cast; -using boost::scoped_ptr; -using master_lexer_internal::State; - -namespace { - -class MasterLexerTest : public ::testing::Test { -protected: - MasterLexerTest() : - expected_stream_name("stream-" + lexical_cast<string>(&ss)) - {} - - MasterLexer lexer; - stringstream ss; - const string expected_stream_name; -}; - -// Commonly used check case where the input sources stack is empty. -void -checkEmptySource(const MasterLexer& lexer) { - EXPECT_TRUE(lexer.getSourceName().empty()); - EXPECT_EQ(0, lexer.getSourceLine()); - EXPECT_EQ(0, lexer.getPosition()); -} - -TEST_F(MasterLexerTest, preOpen) { - // Initially sources stack is empty. - checkEmptySource(lexer); -} - -TEST_F(MasterLexerTest, pushStream) { - EXPECT_EQ(0, lexer.getSourceCount()); - ss << "test"; - lexer.pushSource(ss); - EXPECT_EQ(expected_stream_name, lexer.getSourceName()); - EXPECT_EQ(1, lexer.getSourceCount()); - EXPECT_EQ(4, lexer.getTotalSourceSize()); // 4 = len("test") - - // From the point of view of this test, we only have to check (though - // indirectly) getSourceLine calls InputSource::getCurrentLine. It should - // return 1 initially. - EXPECT_EQ(1, lexer.getSourceLine()); - - // By popping it the stack will be empty again. - lexer.popSource(); - EXPECT_EQ(0, lexer.getSourceCount()); - checkEmptySource(lexer); - EXPECT_EQ(4, lexer.getTotalSourceSize()); // this shouldn't change -} - -TEST_F(MasterLexerTest, pushStreamFail) { - // Pretend a "bad" thing happened in the stream. This will make the - // initialization throw an exception. - ss << "test"; - ss.setstate(std::ios_base::badbit); - - EXPECT_THROW(lexer.pushSource(ss), isc::Unexpected); -} - -TEST_F(MasterLexerTest, pushFile) { - // We use zone file (-like) data, but in this test that actually doesn't - // matter. - EXPECT_EQ(0, lexer.getSourceCount()); - EXPECT_TRUE(lexer.pushSource(TEST_DATA_SRCDIR "/masterload.txt")); - EXPECT_EQ(1, lexer.getSourceCount()); - EXPECT_EQ(TEST_DATA_SRCDIR "/masterload.txt", lexer.getSourceName()); - EXPECT_EQ(1, lexer.getSourceLine()); - - // 143 = size of the test zone file. hardcode it assuming it won't change - // too often. - EXPECT_EQ(143, lexer.getTotalSourceSize()); - - lexer.popSource(); - checkEmptySource(lexer); - EXPECT_EQ(0, lexer.getSourceCount()); - EXPECT_EQ(143, lexer.getTotalSourceSize()); // this shouldn't change - - // If we give a non NULL string pointer, its content will be intact - // if pushSource succeeds. - std::string error_txt = "dummy"; - EXPECT_TRUE(lexer.pushSource(TEST_DATA_SRCDIR "/masterload.txt", - &error_txt)); - EXPECT_EQ("dummy", error_txt); -} - -TEST_F(MasterLexerTest, pushBadFileName) { - EXPECT_THROW(lexer.pushSource(NULL), isc::InvalidParameter); -} - -TEST_F(MasterLexerTest, pushFileFail) { - // The file to be pushed doesn't exist. pushSource() fails and - // some non empty error string should be set. - std::string error_txt; - EXPECT_TRUE(error_txt.empty()); - EXPECT_FALSE(lexer.pushSource("no-such-file", &error_txt)); - EXPECT_FALSE(error_txt.empty()); - - // It's safe to pass NULL error_txt (either explicitly or implicitly as - // the default) - EXPECT_FALSE(lexer.pushSource("no-such-file", NULL)); - EXPECT_FALSE(lexer.pushSource("no-such-file")); -} - -TEST_F(MasterLexerTest, nestedPush) { - const string test_txt = "test"; - ss << test_txt; - lexer.pushSource(ss); - - EXPECT_EQ(test_txt.size(), lexer.getTotalSourceSize()); - EXPECT_EQ(0, lexer.getPosition()); - - EXPECT_EQ(expected_stream_name, lexer.getSourceName()); - - // Read the string; getPosition() should reflect that. - EXPECT_EQ(MasterToken::STRING, lexer.getNextToken().getType()); - EXPECT_EQ(test_txt.size(), lexer.getPosition()); - - // We can push another source without popping the previous one. - lexer.pushSource(TEST_DATA_SRCDIR "/masterload.txt"); - EXPECT_EQ(TEST_DATA_SRCDIR "/masterload.txt", lexer.getSourceName()); - EXPECT_EQ(143 + test_txt.size(), - lexer.getTotalSourceSize()); // see above for magic nums - - // the next token should be the EOL (skipping a comment line), its - // position in the file is 35 (hardcoded). - EXPECT_EQ(MasterToken::END_OF_LINE, lexer.getNextToken().getType()); - EXPECT_EQ(test_txt.size() + 35, lexer.getPosition()); - - // popSource() works on the "topmost" (last-pushed) source - lexer.popSource(); - EXPECT_EQ(expected_stream_name, lexer.getSourceName()); - - // pop shouldn't change the total size and the current position - EXPECT_EQ(143 + test_txt.size(), lexer.getTotalSourceSize()); - EXPECT_EQ(test_txt.size() + 35, lexer.getPosition()); - - lexer.popSource(); - EXPECT_TRUE(lexer.getSourceName().empty()); - - // size and position still shouldn't change - EXPECT_EQ(143 + test_txt.size(), lexer.getTotalSourceSize()); - EXPECT_EQ(test_txt.size() + 35, lexer.getPosition()); -} - -TEST_F(MasterLexerTest, unknownSourceSize) { - // Similar to the previous case, but the size of the second source - // will be considered "unknown" (by emulating an error). - ss << "test"; - lexer.pushSource(ss); - EXPECT_EQ(4, lexer.getTotalSourceSize()); - - stringstream ss2; - ss2.setstate(std::ios_base::failbit); // this will make the size unknown - lexer.pushSource(ss2); - // Then the total size is also unknown. - EXPECT_EQ(MasterLexer::SOURCE_SIZE_UNKNOWN, lexer.getTotalSourceSize()); - - // Even if we pop that source, the size is still unknown. - lexer.popSource(); - EXPECT_EQ(MasterLexer::SOURCE_SIZE_UNKNOWN, lexer.getTotalSourceSize()); -} - -TEST_F(MasterLexerTest, invalidPop) { - // popSource() cannot be called if the sources stack is empty. - EXPECT_THROW(lexer.popSource(), isc::InvalidOperation); -} - -// Test it is not possible to get token when no source is available. -TEST_F(MasterLexerTest, noSource) { - EXPECT_THROW(lexer.getNextToken(), isc::InvalidOperation); -} - -// Test getting some tokens. It also check basic behavior of getPosition(). -TEST_F(MasterLexerTest, getNextToken) { - ss << "\n \n\"STRING\"\n"; - lexer.pushSource(ss); - - // First, the newline should get out. - EXPECT_EQ(MasterToken::END_OF_LINE, lexer.getNextToken().getType()); - EXPECT_EQ(1, lexer.getPosition()); - // Then the whitespace, if we specify the option. - EXPECT_EQ(MasterToken::INITIAL_WS, - lexer.getNextToken(MasterLexer::INITIAL_WS).getType()); - EXPECT_EQ(2, lexer.getPosition()); - // The newline - EXPECT_EQ(MasterToken::END_OF_LINE, lexer.getNextToken().getType()); - EXPECT_EQ(5, lexer.getPosition()); // 1st \n + 3 spaces, then 2nd \n - // The (quoted) string - EXPECT_EQ(MasterToken::QSTRING, - lexer.getNextToken(MasterLexer::QSTRING).getType()); - EXPECT_EQ(5 + 8, lexer.getPosition()); // 8 = len("STRING') + quotes - - // And the end of line and file - EXPECT_EQ(MasterToken::END_OF_LINE, lexer.getNextToken().getType()); - EXPECT_EQ(5 + 8 + 1, lexer.getPosition()); // previous + 3rd \n - EXPECT_EQ(MasterToken::END_OF_FILE, lexer.getNextToken().getType()); - EXPECT_EQ(5 + 8 + 1, lexer.getPosition()); // position doesn't change -} - -// Test we correctly find end of file. -TEST_F(MasterLexerTest, eof) { - // Let the ss empty. - lexer.pushSource(ss); - - // The first one is found to be EOF - EXPECT_EQ(MasterToken::END_OF_FILE, lexer.getNextToken().getType()); - // And it stays on EOF for any following attempts - EXPECT_EQ(MasterToken::END_OF_FILE, lexer.getNextToken().getType()); - // And we can step back one token, but that is the EOF too. - lexer.ungetToken(); - EXPECT_EQ(MasterToken::END_OF_FILE, lexer.getNextToken().getType()); -} - -// Check we properly return error when there's an opened parentheses and no -// closing one -TEST_F(MasterLexerTest, getUnbalancedParen) { - ss << "(string"; - lexer.pushSource(ss); - - // The string gets out first - EXPECT_EQ(MasterToken::STRING, lexer.getNextToken().getType()); - // Then an unbalanced parenthesis - EXPECT_EQ(MasterToken::UNBALANCED_PAREN, - lexer.getNextToken().getErrorCode()); - // And then EOF - EXPECT_EQ(MasterToken::END_OF_FILE, lexer.getNextToken().getType()); -} - -// Check we properly return error when there's an opened quoted string and no -// closing one -TEST_F(MasterLexerTest, getUnbalancedString) { - ss << "\"string"; - lexer.pushSource(ss); - - // Then an unbalanced qstring (reported as an unexpected end) - EXPECT_EQ(MasterToken::UNEXPECTED_END, - lexer.getNextToken(MasterLexer::QSTRING).getErrorCode()); - // And then EOF - EXPECT_EQ(MasterToken::END_OF_FILE, lexer.getNextToken().getType()); -} - -// Test ungetting tokens works. Also check getPosition() is adjusted -TEST_F(MasterLexerTest, ungetToken) { - ss << "\n (\"string\"\n) more"; - lexer.pushSource(ss); - - // Try getting the newline - EXPECT_EQ(MasterToken::END_OF_LINE, lexer.getNextToken().getType()); - EXPECT_EQ(1, lexer.getPosition()); - // Return it and get again - lexer.ungetToken(); - EXPECT_EQ(0, lexer.getPosition()); - EXPECT_EQ(MasterToken::END_OF_LINE, lexer.getNextToken().getType()); - EXPECT_EQ(1, lexer.getPosition()); - // Get the string and return it back - EXPECT_EQ(MasterToken::QSTRING, - lexer.getNextToken(MasterLexer::QSTRING).getType()); - EXPECT_EQ(string("\n (\"string\"").size(), lexer.getPosition()); - lexer.ungetToken(); - EXPECT_EQ(1, lexer.getPosition()); // back to just after 1st \n - // But if we change the options, it honors them - EXPECT_EQ(MasterToken::INITIAL_WS, - lexer.getNextToken(MasterLexer::QSTRING | - MasterLexer::INITIAL_WS).getType()); - // Get to the "more" string - EXPECT_EQ(MasterToken::QSTRING, - lexer.getNextToken(MasterLexer::QSTRING).getType()); - EXPECT_EQ(MasterToken::STRING, - lexer.getNextToken(MasterLexer::QSTRING).getType()); - // Return it back. It should get inside the parentheses. - // Upon next attempt to get it again, the newline inside the parentheses - // should be still ignored. - lexer.ungetToken(); - EXPECT_EQ(MasterToken::STRING, - lexer.getNextToken(MasterLexer::QSTRING).getType()); -} - -// Check ungetting token without overriding the start method. We also -// check it works well with changing options between the calls. -TEST_F(MasterLexerTest, ungetRealOptions) { - ss << " \n"; - lexer.pushSource(ss); - - // If we call it the usual way, it skips up to the newline and returns - // it - EXPECT_EQ(MasterToken::END_OF_LINE, lexer.getNextToken().getType()); - - // Now we return it. If we call it again, but with different options, - // we get the initial whitespace. - lexer.ungetToken(); - EXPECT_EQ(MasterToken::INITIAL_WS, - lexer.getNextToken(MasterLexer::INITIAL_WS).getType()); -} - -// Check the initial whitespace is found even in the first line of included -// file. It also confirms getPosition() works for multiple sources, each -// of which is partially parsed. -TEST_F(MasterLexerTest, includeAndInitialWS) { - ss << " \n"; - lexer.pushSource(ss); - - stringstream ss2; - ss2 << " \n"; - - EXPECT_EQ(MasterToken::INITIAL_WS, - lexer.getNextToken(MasterLexer::INITIAL_WS).getType()); - EXPECT_EQ(1, lexer.getPosition()); - lexer.pushSource(ss2); - EXPECT_EQ(MasterToken::INITIAL_WS, - lexer.getNextToken(MasterLexer::INITIAL_WS).getType()); - EXPECT_EQ(2, lexer.getPosition()); // should be sum of pushed positions. -} - -// Test only one token can be ungotten -TEST_F(MasterLexerTest, ungetTwice) { - ss << "\n"; - lexer.pushSource(ss); - - EXPECT_EQ(MasterToken::END_OF_LINE, lexer.getNextToken().getType()); - // Unget the token. It can be done once - lexer.ungetToken(); - // But not twice - EXPECT_THROW(lexer.ungetToken(), isc::InvalidOperation); -} - -// Test we can't unget a token before we get one -TEST_F(MasterLexerTest, ungetBeforeGet) { - lexer.pushSource(ss); // Just to eliminate the missing source problem - EXPECT_THROW(lexer.ungetToken(), isc::InvalidOperation); -} - -// Test we can't unget a token after a source switch, even when we got -// something before. -TEST_F(MasterLexerTest, ungetAfterSwitch) { - ss << "\n\n"; - lexer.pushSource(ss); - EXPECT_EQ(MasterToken::END_OF_LINE, lexer.getNextToken().getType()); - // Switch the source - std::stringstream ss2; - ss2 << "\n\n"; - lexer.pushSource(ss2); - EXPECT_THROW(lexer.ungetToken(), isc::InvalidOperation); - // We can get from the new source - EXPECT_EQ(MasterToken::END_OF_LINE, lexer.getNextToken().getType()); - // And when we drop the current source, we can't unget again - lexer.popSource(); - EXPECT_THROW(lexer.ungetToken(), isc::InvalidOperation); -} - -// Common checks for the case when getNextToken() should result in LexerError -void -lexerErrorCheck(MasterLexer& lexer, MasterToken::Type expect, - MasterToken::ErrorCode expected_error) -{ - bool thrown = false; - try { - lexer.getNextToken(expect); - } catch (const MasterLexer::LexerError& error) { - EXPECT_EQ(expected_error, error.token_.getErrorCode()); - thrown = true; - } - EXPECT_TRUE(thrown); -} - -// Common checks regarding expected/unexpected end-of-line -// -// The 'lexer' should be at a position before two consecutive '\n's. -// The first one will be recognized, and the second one will be considered an -// unexpected token. Then this helper consumes the second '\n', so the caller -// can continue the test after these '\n's. -void -eolCheck(MasterLexer& lexer, MasterToken::Type expect) { - // If EOL is found and eol_ok is true, we get it. - EXPECT_EQ(MasterToken::END_OF_LINE, - lexer.getNextToken(expect, true).getType()); - // We'll see the second '\n'; by default it will fail. - EXPECT_THROW(lexer.getNextToken(expect), MasterLexer::LexerError); - // Same if eol_ok is explicitly set to false. This also checks the - // offending '\n' was "ungotten". - EXPECT_THROW(lexer.getNextToken(expect, false), MasterLexer::LexerError); - - // And also check the error token set in the exception object. - lexerErrorCheck(lexer, expect, MasterToken::UNEXPECTED_END); - - // Then skip the 2nd '\n' - EXPECT_EQ(MasterToken::END_OF_LINE, lexer.getNextToken().getType()); -} - -// Common checks regarding expected/unexpected end-of-file -// -// The 'lexer' should be at a position just before an end-of-file. -void -eofCheck(MasterLexer& lexer, MasterToken::Type expect) { - EXPECT_EQ(MasterToken::END_OF_FILE, - lexer.getNextToken(expect, true).getType()); - EXPECT_THROW(lexer.getNextToken(expect), MasterLexer::LexerError); - EXPECT_THROW(lexer.getNextToken(expect, false), MasterLexer::LexerError); -} - -TEST_F(MasterLexerTest, getNextTokenString) { - ss << "normal-string\n"; - ss << "\n"; - ss << "another-string"; - lexer.pushSource(ss); - - // Normal successful case: Expecting a string and get one. - EXPECT_EQ("normal-string", - lexer.getNextToken(MasterToken::STRING).getString()); - eolCheck(lexer, MasterToken::STRING); - - // Same set of tests but for end-of-file - EXPECT_EQ("another-string", - lexer.getNextToken(MasterToken::STRING, true).getString()); - eofCheck(lexer, MasterToken::STRING); -} - -TEST_F(MasterLexerTest, getNextTokenQString) { - ss << "\"quoted-string\"\n"; - ss << "\n"; - ss << "normal-string"; - lexer.pushSource(ss); - - // Expecting a quoted string and get one. - EXPECT_EQ("quoted-string", - lexer.getNextToken(MasterToken::QSTRING).getString()); - eolCheck(lexer, MasterToken::QSTRING); - - // Expecting a quoted string but see a normal string. It's okay. - EXPECT_EQ("normal-string", - lexer.getNextToken(MasterToken::QSTRING).getString()); - eofCheck(lexer, MasterToken::QSTRING); -} - -TEST_F(MasterLexerTest, getNextTokenNumber) { - ss << "3600\n"; - ss << "\n"; - ss << "4294967296 "; // =2^32, out of range - ss << "not-a-number "; - ss << "123abc "; // starting with digits, but resulting in a string - ss << "86400"; - lexer.pushSource(ss); - - // Expecting a number string and get one. - EXPECT_EQ(3600, - lexer.getNextToken(MasterToken::NUMBER).getNumber()); - eolCheck(lexer, MasterToken::NUMBER); - - // Expecting a number, but it's too big for uint32. - lexerErrorCheck(lexer, MasterToken::NUMBER, - MasterToken::NUMBER_OUT_OF_RANGE); - // The token should have been "ungotten". Re-read and skip it. - EXPECT_EQ(MasterToken::STRING, lexer.getNextToken().getType()); - - // Expecting a number, but see a string. - lexerErrorCheck(lexer, MasterToken::NUMBER, MasterToken::BAD_NUMBER); - // The unexpected string should have been "ungotten". Re-read and skip it. - EXPECT_EQ(MasterToken::STRING, lexer.getNextToken().getType()); - - // Expecting a number, but see a string. - lexerErrorCheck(lexer, MasterToken::NUMBER, MasterToken::BAD_NUMBER); - // The unexpected string should have been "ungotten". Re-read and skip it. - EXPECT_EQ(MasterToken::STRING, lexer.getNextToken().getType()); - - // Unless we specify NUMBER, decimal number string should be recognized - // as a string. - EXPECT_EQ("86400", - lexer.getNextToken(MasterToken::STRING).getString()); - eofCheck(lexer, MasterToken::NUMBER); -} - -TEST_F(MasterLexerTest, getNextTokenErrors) { - // Check miscellaneous error cases - - ss << ") "; // unbalanced parenthesis - ss << "string-after-error "; - lexer.pushSource(ss); - - // Only string/qstring/number can be "expected". - EXPECT_THROW(lexer.getNextToken(MasterToken::END_OF_LINE), - isc::InvalidParameter); - EXPECT_THROW(lexer.getNextToken(MasterToken::END_OF_FILE), - isc::InvalidParameter); - EXPECT_THROW(lexer.getNextToken(MasterToken::INITIAL_WS), - isc::InvalidParameter); - EXPECT_THROW(lexer.getNextToken(MasterToken::ERROR), - isc::InvalidParameter); - - // If it encounters a syntax error, it results in LexerError exception. - lexerErrorCheck(lexer, MasterToken::STRING, MasterToken::UNBALANCED_PAREN); - - // Unlike the NUMBER_OUT_OF_RANGE case, the error part has been skipped - // within getNextToken(). We should be able to get the next token. - EXPECT_EQ("string-after-error", - lexer.getNextToken(MasterToken::STRING).getString()); -} - -} diff --git a/src/lib/dns/tests/master_loader_callbacks_test.cc b/src/lib/dns/tests/master_loader_callbacks_test.cc index 9d238023dd..8b13789179 100644 --- a/src/lib/dns/tests/master_loader_callbacks_test.cc +++ b/src/lib/dns/tests/master_loader_callbacks_test.cc @@ -1,79 +1 @@ -// Copyright (C) 2012-2020 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. -#include <config.h> - -#include <dns/master_loader_callbacks.h> -#include <dns/rrset.h> -#include <dns/name.h> -#include <dns/rrttl.h> -#include <dns/rrclass.h> - -#include <exceptions/exceptions.h> - -#include <gtest/gtest.h> -#include <functional> - -namespace { - -using std::string; -using namespace isc::dns; -namespace ph = std::placeholders; - -class MasterLoaderCallbacksTest : public ::testing::Test { -protected: - MasterLoaderCallbacksTest() : - last_was_error_(false), // Not needed, but then cppcheck complains - issue_called_(false), - rrset_(new RRset(Name("example.org"), RRClass::IN(), RRType::A(), - RRTTL(3600))), - error_(std::bind(&MasterLoaderCallbacksTest::checkCallback, this, - true, ph::_1, ph::_2, ph::_3)), - warning_(std::bind(&MasterLoaderCallbacksTest::checkCallback, this, - false, ph::_1, ph::_2, ph::_3)), - callbacks_(error_, warning_) - {} - - void checkCallback(bool error, const string& source, size_t line, - const string& reason) - { - issue_called_ = true; - last_was_error_ = error; - EXPECT_EQ("source", source); - EXPECT_EQ(1, line); - EXPECT_EQ("reason", reason); - } - bool last_was_error_; - bool issue_called_; - const RRsetPtr rrset_; - const MasterLoaderCallbacks::IssueCallback error_, warning_; - MasterLoaderCallbacks callbacks_; -}; - -// Check the constructor rejects empty callbacks, but accepts non-empty ones -TEST_F(MasterLoaderCallbacksTest, constructor) { - EXPECT_THROW(MasterLoaderCallbacks(MasterLoaderCallbacks::IssueCallback(), - warning_), isc::InvalidParameter); - EXPECT_THROW(MasterLoaderCallbacks(error_, - MasterLoaderCallbacks::IssueCallback()), - isc::InvalidParameter); - EXPECT_NO_THROW(MasterLoaderCallbacks(error_, warning_)); -} - -// Call the issue callbacks -TEST_F(MasterLoaderCallbacksTest, issueCall) { - callbacks_.error("source", 1, "reason"); - EXPECT_TRUE(last_was_error_); - EXPECT_TRUE(issue_called_); - - issue_called_ = false; - - callbacks_.warning("source", 1, "reason"); - EXPECT_FALSE(last_was_error_); - EXPECT_TRUE(issue_called_); -} - -} diff --git a/src/lib/dns/tests/master_loader_unittest.cc b/src/lib/dns/tests/master_loader_unittest.cc index 74300d3171..8b13789179 100644 --- a/src/lib/dns/tests/master_loader_unittest.cc +++ b/src/lib/dns/tests/master_loader_unittest.cc @@ -1,1445 +1 @@ -// Copyright (C) 2012-2021 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. -#include <config.h> - -#include <dns/master_loader_callbacks.h> -#include <dns/master_loader.h> -#include <dns/rrtype.h> -#include <dns/rrset.h> -#include <dns/rrclass.h> -#include <dns/rrttl.h> -#include <dns/name.h> -#include <dns/rdata.h> - -#include <gtest/gtest.h> - -#include <boost/lexical_cast.hpp> -#include <boost/scoped_ptr.hpp> - -#include <functional> -#include <string> -#include <vector> -#include <list> -#include <sstream> - -using namespace isc::dns; -using std::vector; -using std::string; -using std::list; -using std::stringstream; -using std::endl; -using boost::lexical_cast; -namespace ph = std::placeholders; - -namespace { -class MasterLoaderTest : public ::testing::Test { -public: - MasterLoaderTest() : - callbacks_(std::bind(&MasterLoaderTest::callback, this, - &errors_, ph::_1, ph::_2, ph::_3), - std::bind(&MasterLoaderTest::callback, this, - &warnings_, ph::_1, ph::_2, ph::_3)) - {} - - void TearDown() { - // Check there are no more RRs we didn't expect - EXPECT_TRUE(rrsets_.empty()); - } - - /// Concatenate file, line, and reason, and add it to either errors - /// or warnings - void callback(vector<string>* target, const std::string& file, size_t line, - const std::string& reason) - { - std::stringstream ss; - ss << reason << " [" << file << ":" << line << "]"; - target->push_back(ss.str()); - } - - void addRRset(const Name& name, const RRClass& rrclass, - const RRType& rrtype, const RRTTL& rrttl, - const rdata::RdataPtr& data) { - const RRsetPtr rrset(new BasicRRset(name, rrclass, rrtype, rrttl)); - rrset->addRdata(data); - rrsets_.push_back(rrset); - } - - void setLoader(const char* file, const Name& origin, - const RRClass& rrclass, const MasterLoader::Options options) - { - loader_.reset(new MasterLoader(file, origin, rrclass, callbacks_, - std::bind(&MasterLoaderTest::addRRset, - this, ph::_1, ph::_2, ph::_3, - ph::_4, ph::_5), - options)); - } - - void setLoader(std::istream& stream, const Name& origin, - const RRClass& rrclass, const MasterLoader::Options options) - { - loader_.reset(new MasterLoader(stream, origin, rrclass, callbacks_, - std::bind(&MasterLoaderTest::addRRset, - this, ph::_1, ph::_2, ph::_3, - ph::_4, ph::_5), - options)); - } - - static string prepareZone(const string& line, bool include_last) { - string result; - result += "example.org. 3600 IN SOA ns1.example.org. " - "admin.example.org. 1234 3600 1800 2419200 7200\n"; - result += line; - if (include_last) { - result += "\n"; - result += "correct 3600 IN A 192.0.2.2\n"; - } - return (result); - } - - void clear() { - warnings_.clear(); - errors_.clear(); - rrsets_.clear(); - } - - // Check the next RR in the ones produced by the loader - // Other than passed arguments are checked to be the default for the tests - void checkRR(const string& name, const RRType& type, const string& data, - const RRTTL& rrttl = RRTTL(3600)) { - ASSERT_FALSE(rrsets_.empty()); - RRsetPtr current = rrsets_.front(); - rrsets_.pop_front(); - - EXPECT_EQ(Name(name), current->getName()); - EXPECT_EQ(type, current->getType()); - EXPECT_EQ(RRClass::IN(), current->getClass()); - 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())) - << data << " vs. " - << current->getRdataIterator()->getCurrent().toText(); - } - - void checkBasicRRs() { - checkRR("example.org", RRType::SOA(), - "ns1.example.org. admin.example.org. " - "1234 3600 1800 2419200 7200"); - checkRR("example.org", RRType::NS(), "ns1.example.org."); - checkRR("www.example.org", RRType::A(), "192.0.2.1"); - checkRR("www.example.org", RRType::AAAA(), "2001:db8::1"); - } - - void checkARR(const string& name) { - checkRR(name, RRType::A(), "192.0.2.1"); - } - - MasterLoaderCallbacks callbacks_; - boost::scoped_ptr<MasterLoader> loader_; - vector<string> errors_; - vector<string> warnings_; - list<RRsetPtr> rrsets_; -}; - -// Test simple loading. The zone file contains no tricky things, and nothing is -// omitted. No RRset contains more than one RR Also no errors or warnings. -TEST_F(MasterLoaderTest, basicLoad) { - setLoader(TEST_DATA_SRCDIR "/example.org", Name("example.org."), - RRClass::IN(), MasterLoader::MANY_ERRORS); - - EXPECT_FALSE(loader_->loadedSuccessfully()); - - // The following three should be set to 0 initially in case the loader - // is constructed from a file name. - EXPECT_EQ(0, loader_->getSize()); - EXPECT_EQ(0, loader_->getPosition()); - - loader_->load(); - EXPECT_TRUE(loader_->loadedSuccessfully()); - - EXPECT_TRUE(errors_.empty()); - EXPECT_TRUE(warnings_.empty()); - - // Hardcode expected values taken from the test data file, assuming it - // won't change too often. - EXPECT_EQ(550, loader_->getSize()); - EXPECT_EQ(550, loader_->getPosition()); - - checkBasicRRs(); -} - -// Test the $INCLUDE directive -TEST_F(MasterLoaderTest, include) { - // Test various cases of include - const char* includes[] = { - "$include", - "$INCLUDE", - "$Include", - "$InCluDe", - "\"$INCLUDE\"", - NULL - }; - for (const char** include = includes; *include != NULL; ++include) { - SCOPED_TRACE(*include); - - clear(); - // Prepare input source that has the include and some more data - // below (to see it returns back to the original source). - const string include_str = string(*include) + " " + - TEST_DATA_SRCDIR + "/example.org\nwww 3600 IN AAAA 2001:db8::1\n"; - stringstream ss(include_str); - setLoader(ss, Name("example.org."), RRClass::IN(), - MasterLoader::MANY_ERRORS); - - loader_->load(); - EXPECT_TRUE(loader_->loadedSuccessfully()); - EXPECT_TRUE(errors_.empty()); - EXPECT_TRUE(warnings_.empty()); - - checkBasicRRs(); - checkRR("www.example.org", RRType::AAAA(), "2001:db8::1"); - } -} - -TEST_F(MasterLoaderTest, includeAndIncremental) { - // Check getSize() and getPosition() are adjusted before and after - // $INCLUDE. - const string first_rr = "before.example.org. 0 A 192.0.2.1\n"; - const string include_str = "$INCLUDE " TEST_DATA_SRCDIR "/example.org"; - const string zone_data = first_rr + include_str + "\n" + - "www 3600 IN AAAA 2001:db8::1\n"; - stringstream ss(zone_data); - setLoader(ss, Name("example.org."), RRClass::IN(), MasterLoader::DEFAULT); - - // On construction, getSize() returns the size of the data (exclude the - // the file to be included); position is set to 0. - EXPECT_EQ(zone_data.size(), loader_->getSize()); - EXPECT_EQ(0, loader_->getPosition()); - - // Read the first RR. getSize() doesn't change; position should be - // at the end of the first line. - loader_->loadIncremental(1); - EXPECT_EQ(zone_data.size(), loader_->getSize()); - EXPECT_EQ(first_rr.size(), loader_->getPosition()); - - // Read next 4. It includes $INCLUDE processing. Magic number of 550 - // is the size of the test zone file (see above); 507 is the position in - // the file at the end of 4th RR (due to extra comments it's smaller than - // the file size). - loader_->loadIncremental(4); - EXPECT_EQ(zone_data.size() + 550, loader_->getSize()); - EXPECT_EQ(first_rr.size() + include_str.size() + 507, - loader_->getPosition()); - - // Read the last one. At this point getSize and getPosition return - // the same value, indicating progress of 100%. - loader_->loadIncremental(1); - EXPECT_EQ(zone_data.size() + 550, loader_->getSize()); - EXPECT_EQ(zone_data.size() + 550, loader_->getPosition()); - - // we were not interested in checking RRs in this test. clear them to - // not confuse TearDown(). - rrsets_.clear(); -} - -// A commonly used helper to check callback message. -void -checkCallbackMessage(const string& actual_msg, const string& expected_msg, - size_t expected_line) { - // The actual message should begin with the expected message. - EXPECT_EQ(0, actual_msg.find(expected_msg)) << "actual message: " << - actual_msg << " expected: " << - expected_msg; - - // and it should end with "...:<line_num>]" - const string line_desc = ":" + lexical_cast<string>(expected_line) + "]"; - EXPECT_EQ(actual_msg.size() - line_desc.size(), - actual_msg.find(line_desc)) << "Expected on line " << - expected_line; -} - -TEST_F(MasterLoaderTest, origin) { - // Various forms of the directive - const char* origins[] = { - "$origin", - "$ORIGIN", - "$Origin", - "$OrigiN", - "\"$ORIGIN\"", - NULL - }; - for (const char** origin = origins; *origin != NULL; ++origin) { - SCOPED_TRACE(*origin); - - clear(); - const string directive = *origin; - const string input = - "@ 1H IN A 192.0.2.1\n" + - directive + " sub.example.org.\n" - "\"www\" 1H IN A 192.0.2.1\n" + - // Relative name in the origin - directive + " relative\n" - "@ 1H IN A 192.0.2.1\n" - // Origin is _not_ used here (absolute name) - "noorigin.example.org. 60M 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_->loadedSuccessfully()); - EXPECT_TRUE(errors_.empty()); - // There's a relative origin in it, we warn about that. - EXPECT_EQ(1, warnings_.size()); - checkCallbackMessage(warnings_.at(0), - "The new origin is relative, did you really mean " - "relative.sub.example.org.?", 4); - - checkARR("example.org"); - checkARR("www.sub.example.org"); - checkARR("relative.sub.example.org"); - checkARR("noorigin.example.org"); - } -} - -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_->loadedSuccessfully()); - EXPECT_TRUE(errors_.empty()); - - // The "before" and "after" scaffolding below checks that no - // extra records are added by $GENERATE outside the requested - // range. - checkRR("before.example.org", RRType::A(), "192.0.2.0"); - checkRR("host3.example.org", RRType::A(), "192.0.2.3"); - checkRR("host4.example.org", RRType::A(), "192.0.2.4"); - checkRR("host5.example.org", RRType::A(), "192.0.2.5"); - checkRR("after.example.org", RRType::A(), "192.0.2.255"); - } -} - -TEST_F(MasterLoaderTest, generateRelativeLHS) { - const string input = - "$ORIGIN example.org.\n" - "$GENERATE 1-2 @ 3600 NS ns$.example.org.\n"; - stringstream ss(input); - setLoader(ss, Name("example.org."), RRClass::IN(), - MasterLoader::MANY_ERRORS); - - loader_->load(); - EXPECT_TRUE(loader_->loadedSuccessfully()); - 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_->loadedSuccessfully()); - 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_->loadedSuccessfully()); - EXPECT_TRUE(errors_.empty()); - - checkRR("num9-host.example.org", RRType::TXT(), "This is 9 pomegranate"); - checkRR("num10-host.example.org", RRType::TXT(), "This is 10 pomegranate"); -} - -TEST_F(MasterLoaderTest, generateAtEnd) { - // $ is at the end - const string input = - "$ORIGIN example.org.\n" - "$GENERATE 9-10 num$-host 3600 TXT Pomegranate$\n"; - stringstream ss(input); - setLoader(ss, Name("example.org."), RRClass::IN(), - MasterLoader::MANY_ERRORS); - - loader_->load(); - EXPECT_TRUE(loader_->loadedSuccessfully()); - EXPECT_TRUE(errors_.empty()); - - checkRR("num9-host.example.org", RRType::TXT(), "Pomegranate9"); - checkRR("num10-host.example.org", RRType::TXT(), "Pomegranate10"); -} - -TEST_F(MasterLoaderTest, generateStripsQuotes) { - const string input = - "$ORIGIN example.org.\n" - "$GENERATE 1-2 @ 3600 MX \"$ mx$.example.org.\"\n"; - stringstream ss(input); - setLoader(ss, Name("example.org."), RRClass::IN(), - MasterLoader::MANY_ERRORS); - - loader_->load(); - EXPECT_TRUE(loader_->loadedSuccessfully()); - 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_->loadedSuccessfully()); - 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_->loadedSuccessfully()); - 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_->loadedSuccessfully()); - 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_->loadedSuccessfully()); - EXPECT_TRUE(errors_.empty()); - - checkRR("host2.example.org", RRType::A(), "192.0.2.2"); - checkRR("host4.example.org", RRType::A(), "192.0.2.4"); - checkRR("host6.example.org", RRType::A(), "192.0.2.6"); - checkRR("host8.example.org", RRType::A(), "192.0.2.8"); - - checkRR("host12.example.org", RRType::A(), "192.0.2.12"); - checkRR("host15.example.org", RRType::A(), "192.0.2.15"); - checkRR("host18.example.org", RRType::A(), "192.0.2.18"); - checkRR("host21.example.org", RRType::A(), "192.0.2.21"); - - checkRR("host30.example.org", RRType::A(), "192.0.2.30"); - checkRR("host31.example.org", RRType::A(), "192.0.2.31"); -} - -TEST_F(MasterLoaderTest, generateWithModifiers) { - const string input = - "$ORIGIN example.org.\n" - "$TTL 3600\n" - - // Use a positive delta of 1 in the LHS and a negative delta of - // -1 in the RHS - "$GENERATE 2-9/2 host${1} A 192.0.2.${-1}\n" - - "$GENERATE 10-12 host${0,4} A 192.0.2.$\n" - "$GENERATE 14-15 host${0,4,d} A 192.0.2.$\n" - - // Names are case-insensitive, so we use TXT's RDATA to check - // case with hex representation. - "$GENERATE 30-31 host$ TXT \"Value ${0,4,x}\"\n" - "$GENERATE 42-43 host$ TXT \"Value ${0,4,X}\"\n" - - // Octal does not use any alphabets - "$GENERATE 45-46 host${0,4,o} A 192.0.2.$\n" - - // Here, the LHS has a trailing dot (which would result in an - // out-of-zone name), but that should be handled as a relative - // name. - "$GENERATE 90-92 ${0,8,n} A 192.0.2.$\n" - - // Here, the LHS has no trailing dot, and results in the same - // number of labels as width=8 above. - "$GENERATE 94-96 ${0,7,n} A 192.0.2.$\n" - - // Names are case-insensitive, so we use TXT's RDATA to check - // case with nibble representation. - "$GENERATE 106-107 host$ TXT \"Value ${0,9,n}\"\n" - "$GENERATE 109-110 host$ TXT \"Value ${0,9,N}\"\n" - - // Junk type will not parse and 'd' is assumed. No error is - // generated (this is to match BIND 9 behavior). - "$GENERATE 200-201 host${0,4,j} A 192.0.2.$\n"; - stringstream ss(input); - setLoader(ss, Name("example.org."), RRClass::IN(), - MasterLoader::MANY_ERRORS); - - loader_->load(); - EXPECT_TRUE(loader_->loadedSuccessfully()); - EXPECT_TRUE(errors_.empty()); - - checkRR("host3.example.org", RRType::A(), "192.0.2.1"); - checkRR("host5.example.org", RRType::A(), "192.0.2.3"); - checkRR("host7.example.org", RRType::A(), "192.0.2.5"); - checkRR("host9.example.org", RRType::A(), "192.0.2.7"); - - checkRR("host0010.example.org", RRType::A(), "192.0.2.10"); - checkRR("host0011.example.org", RRType::A(), "192.0.2.11"); - checkRR("host0012.example.org", RRType::A(), "192.0.2.12"); - - checkRR("host0014.example.org", RRType::A(), "192.0.2.14"); - checkRR("host0015.example.org", RRType::A(), "192.0.2.15"); - - checkRR("host30.example.org", RRType::TXT(), "Value 001e"); - checkRR("host31.example.org", RRType::TXT(), "Value 001f"); - - checkRR("host42.example.org", RRType::TXT(), "Value 002A"); - checkRR("host43.example.org", RRType::TXT(), "Value 002B"); - - checkRR("host0055.example.org", RRType::A(), "192.0.2.45"); - checkRR("host0056.example.org", RRType::A(), "192.0.2.46"); - - checkRR("a.5.0.0.example.org", RRType::A(), "192.0.2.90"); - checkRR("b.5.0.0.example.org", RRType::A(), "192.0.2.91"); - checkRR("c.5.0.0.example.org", RRType::A(), "192.0.2.92"); - - checkRR("e.5.0.0.example.org", RRType::A(), "192.0.2.94"); - checkRR("f.5.0.0.example.org", RRType::A(), "192.0.2.95"); - checkRR("0.6.0.0.example.org", RRType::A(), "192.0.2.96"); - - checkRR("host106.example.org", RRType::TXT(), "Value a.6.0.0.0"); - checkRR("host107.example.org", RRType::TXT(), "Value b.6.0.0.0"); - checkRR("host109.example.org", RRType::TXT(), "Value D.6.0.0.0"); - checkRR("host110.example.org", RRType::TXT(), "Value E.6.0.0.0"); - - checkRR("host0200.example.org", RRType::A(), "192.0.2.200"); - checkRR("host0201.example.org", RRType::A(), "192.0.2.201"); -} - -TEST_F(MasterLoaderTest, generateWithNoModifiers) { - const string input = - "$ORIGIN example.org.\n" - "$TTL 3600\n" - "$GENERATE 10-12 host${} A 192.0.2.$\n"; - stringstream ss(input); - setLoader(ss, Name("example.org."), RRClass::IN(), - MasterLoader::MANY_ERRORS); - - loader_->load(); - EXPECT_FALSE(loader_->loadedSuccessfully()); - 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_->loadedSuccessfully()); - ASSERT_EQ(2, errors_.size()); // For the broken GENERATE - EXPECT_TRUE(warnings_.empty()); - - checkCallbackMessage(errors_.at(0), - "Invalid $GENERATE format modifiers", 3); - checkCallbackMessage(errors_.at(1), - "$GENERATE error", 3); -} - -TEST_F(MasterLoaderTest, generateMissingRange) { - const string input = - "$ORIGIN example.org.\n" - "$GENERATE\n"; - stringstream ss(input); - setLoader(ss, Name("example.org."), RRClass::IN(), - MasterLoader::MANY_ERRORS); - - loader_->load(); - EXPECT_FALSE(loader_->loadedSuccessfully()); - 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_->loadedSuccessfully()); - 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_->loadedSuccessfully()); - 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_->loadedSuccessfully()); - 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_->loadedSuccessfully()); - 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_->loadedSuccessfully()); - 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_->loadedSuccessfully()); - 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_->loadedSuccessfully()); - 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 - "/broken.zone\nwww 3600 IN AAAA 2001:db8::1\n"; - stringstream ss(include_str); - // We perform the test with MANY_ERRORS, we want to see what happens - // after the error. - setLoader(ss, Name("example.org."), RRClass::IN(), - MasterLoader::MANY_ERRORS); - - loader_->load(); - EXPECT_FALSE(loader_->loadedSuccessfully()); - EXPECT_EQ(1, errors_.size()); // For the broken RR - EXPECT_EQ(1, warnings_.size()); // For missing EOLN - - // The included file doesn't contain anything usable, but the - // line after the include should be there. - checkRR("www.example.org", RRType::AAAA(), "2001:db8::1"); -} - -// Check it works the same when created based on a stream, not filename -TEST_F(MasterLoaderTest, streamConstructor) { - const string zone_data(prepareZone("", true)); - stringstream zone_stream(zone_data); - setLoader(zone_stream, Name("example.org."), RRClass::IN(), - MasterLoader::MANY_ERRORS); - - EXPECT_FALSE(loader_->loadedSuccessfully()); - - // Unlike the basicLoad test, if we construct the loader from a stream - // getSize() returns the data size in the stream immediately after the - // construction. - EXPECT_EQ(zone_data.size(), loader_->getSize()); - EXPECT_EQ(0, loader_->getPosition()); - - loader_->load(); - EXPECT_TRUE(loader_->loadedSuccessfully()); - - EXPECT_TRUE(errors_.empty()); - EXPECT_TRUE(warnings_.empty()); - checkRR("example.org", RRType::SOA(), "ns1.example.org. " - "admin.example.org. 1234 3600 1800 2419200 7200"); - checkRR("correct.example.org", RRType::A(), "192.0.2.2"); - - // On completion of the load, both getSize() and getPosition() return the - // size of the data. - EXPECT_EQ(zone_data.size(), loader_->getSize()); - EXPECT_EQ(zone_data.size(), loader_->getPosition()); -} - -// Try loading data incrementally. -TEST_F(MasterLoaderTest, incrementalLoad) { - setLoader(TEST_DATA_SRCDIR "/example.org", Name("example.org."), - RRClass::IN(), MasterLoader::MANY_ERRORS); - - EXPECT_FALSE(loader_->loadedSuccessfully()); - EXPECT_FALSE(loader_->loadIncremental(2)); - EXPECT_FALSE(loader_->loadedSuccessfully()); - - EXPECT_TRUE(errors_.empty()); - EXPECT_TRUE(warnings_.empty()); - - checkRR("example.org", RRType::SOA(), - "ns1.example.org. admin.example.org. " - "1234 3600 1800 2419200 7200"); - checkRR("example.org", RRType::NS(), "ns1.example.org."); - - // The third one is not loaded yet - EXPECT_TRUE(rrsets_.empty()); - - // Load the rest. - EXPECT_TRUE(loader_->loadIncremental(20)); - EXPECT_TRUE(loader_->loadedSuccessfully()); - - EXPECT_TRUE(errors_.empty()); - EXPECT_TRUE(warnings_.empty()); - - checkRR("www.example.org", RRType::A(), "192.0.2.1"); - checkRR("www.example.org", RRType::AAAA(), "2001:db8::1"); -} - -// Try loading from file that doesn't exist. There should be single error -// saying so. -TEST_F(MasterLoaderTest, invalidFile) { - setLoader("This file doesn't exist at all", - Name("example.org."), RRClass::IN(), MasterLoader::MANY_ERRORS); - - // Nothing yet. The loader is dormant until invoked. - // Is it really what we want? - EXPECT_TRUE(errors_.empty()); - - loader_->load(); - - EXPECT_TRUE(warnings_.empty()); - EXPECT_TRUE(rrsets_.empty()); - ASSERT_EQ(1, errors_.size()); - EXPECT_EQ(0, errors_[0].find("Error opening the input source file: ")) << - "Different error: " << errors_[0]; -} - -struct ErrorCase { - const char* const line; // The broken line in master file - const char* const reason; // If non NULL, the reason string - const char* const problem; // Description of the problem for SCOPED_TRACE -} const error_cases[] = { - { "www... 3600 IN A 192.0.2.1", NULL, "Invalid name" }, - { "www FORTNIGHT IN A 192.0.2.1", NULL, "Invalid TTL" }, - { "www 3600 XX A 192.0.2.1", NULL, "Invalid class" }, - { "www 3600 IN A bad_ip", NULL, "Invalid Rdata" }, - - // Parameter ordering errors - { "www IN A 3600 192.168.2.7", - "createRdata from text failed: Bad IN/A RDATA text: '3600'", - "Incorrect order of class, TTL and type" }, - { "www A IN 3600 192.168.2.8", - "createRdata from text failed: Bad IN/A RDATA text: 'IN'", - "Incorrect order of class, TTL and type" }, - { "www 3600 A IN 192.168.2.7", - "createRdata from text failed: Bad IN/A RDATA text: 'IN'", - "Incorrect order of class, TTL and type" }, - { "www A 3600 IN 192.168.2.8", - "createRdata from text failed: Bad IN/A RDATA text: '3600'", - "Incorrect order of class, TTL and type" }, - - // Missing type and Rdata - { "www", "unexpected end of input", "Missing type and Rdata" }, - { "www 3600", "unexpected end of input", "Missing type and Rdata" }, - { "www IN", "unexpected end of input", "Missing type and Rdata" }, - { "www 3600 IN", "unexpected end of input", "Missing type and Rdata" }, - { "www IN 3600", "unexpected end of input", "Missing type and Rdata" }, - - // Missing Rdata - { "www A", - "createRdata from text failed: unexpected end of input", - "Missing Rdata" }, - { "www 3600 A", - "createRdata from text failed: unexpected end of input", - "Missing Rdata" }, - { "www IN A", - "createRdata from text failed: unexpected end of input", - "Missing Rdata" }, - { "www 3600 IN A", - "createRdata from text failed: unexpected end of input", - "Missing Rdata" }, - { "www IN 3600 A", - "createRdata from text failed: unexpected end of input", - "Missing Rdata" }, - - { "www 3600 IN", NULL, "Unexpected EOLN" }, - { "www 3600 CH TXT nothing", "Class mismatch: CH vs. IN", - "Class mismatch" }, - { "www \"3600\" IN A 192.0.2.1", NULL, "Quoted TTL" }, - { "www 3600 \"IN\" A 192.0.2.1", NULL, "Quoted class" }, - { "www 3600 IN \"A\" 192.0.2.1", NULL, "Quoted type" }, - { "unbalanced)paren 3600 IN A 192.0.2.1", NULL, "Token error 1" }, - { "www 3600 unbalanced)paren A 192.0.2.1", NULL, - "Token error 2" }, - // Check the unknown directive. The rest looks like ordinary RR, - // so we see the $ is actually special. - { "$UNKNOWN 3600 IN A 192.0.2.1", NULL, "Unknown $ directive" }, - { "$INCLUD " TEST_DATA_SRCDIR "/example.org", "Unknown directive 'INCLUD'", - "Include too short" }, - { "$INCLUDES " TEST_DATA_SRCDIR "/example.org", - "Unknown directive 'INCLUDES'", "Include too long" }, - { "$INCLUDE", "unexpected end of input", "Missing include path" }, - // The following two error messages are system dependent, omitting - { "$INCLUDE /file/not/found", NULL, "Include file not found" }, - { "$INCLUDE /file/not/found example.org. and here goes bunch of garbage", - NULL, "Include file not found and garbage at the end of line" }, - { "$ORIGIN", "unexpected end of input", "Missing origin name" }, - { "$ORIGIN invalid...name", "duplicate period in invalid...name", - "Invalid name for origin" }, - { "$ORIGIN )brokentoken", "unbalanced parentheses", - "Broken token in origin" }, - { "$ORIGIN example.org. garbage", "Extra tokens at the end of line", - "Garbage after origin" }, - { "$ORIGI name.", "Unknown directive 'ORIGI'", "$ORIGIN too short" }, - { "$ORIGINAL name.", "Unknown directive 'ORIGINAL'", "$ORIGIN too long" }, - { "$TTL 100 extra-garbage", "Extra tokens at the end of line", - "$TTL with extra token" }, - { "$TTL", "unexpected end of input", "missing TTL" }, - { "$TTL No-ttl", "Unknown unit used: N in: No-ttl", "bad TTL" }, - { "$TTL \"100\"", "unexpected quotes", "bad TTL, quoted" }, - { "$TT 100", "Unknown directive 'TT'", "bad directive, too short" }, - { "$TTLLIKE 100", "Unknown directive 'TTLLIKE'", "bad directive, extra" }, - { NULL, NULL, NULL } -}; - -// Test a broken zone is handled properly. We test several problems, -// both in strict and lenient mode. -TEST_F(MasterLoaderTest, brokenZone) { - for (const ErrorCase* ec = error_cases; ec->line != NULL; ++ec) { - SCOPED_TRACE(ec->problem); - const string zone(prepareZone(ec->line, true)); - - { - SCOPED_TRACE("Strict mode"); - clear(); - stringstream zone_stream(zone); - setLoader(zone_stream, Name("example.org."), RRClass::IN(), - MasterLoader::DEFAULT); - EXPECT_FALSE(loader_->loadedSuccessfully()); - EXPECT_THROW(loader_->load(), MasterLoaderError); - EXPECT_FALSE(loader_->loadedSuccessfully()); - EXPECT_EQ(1, errors_.size()); - if (ec->reason != NULL) { - checkCallbackMessage(errors_.at(0), ec->reason, 2); - } - EXPECT_TRUE(warnings_.empty()); - - checkRR("example.org", RRType::SOA(), "ns1.example.org. " - "admin.example.org. 1234 3600 1800 2419200 7200"); - // In the strict mode, it is aborted. The last RR is not - // even attempted. - EXPECT_TRUE(rrsets_.empty()); - } - - { - SCOPED_TRACE("Lenient mode"); - clear(); - stringstream zone_stream(zone); - setLoader(zone_stream, Name("example.org."), RRClass::IN(), - MasterLoader::MANY_ERRORS); - EXPECT_FALSE(loader_->loadedSuccessfully()); - EXPECT_NO_THROW(loader_->load()); - EXPECT_FALSE(loader_->loadedSuccessfully()); - EXPECT_EQ(1, errors_.size()); - EXPECT_TRUE(warnings_.empty()); - checkRR("example.org", RRType::SOA(), "ns1.example.org. " - "admin.example.org. 1234 3600 1800 2419200 7200"); - // This one is below the error one. - checkRR("correct.example.org", RRType::A(), "192.0.2.2"); - EXPECT_TRUE(rrsets_.empty()); - } - - { - SCOPED_TRACE("Error at EOF"); - // This case is interesting only in the lenient mode. - clear(); - const string zoneEOF(prepareZone(ec->line, false)); - stringstream zone_stream(zoneEOF); - setLoader(zone_stream, Name("example.org."), RRClass::IN(), - MasterLoader::MANY_ERRORS); - EXPECT_FALSE(loader_->loadedSuccessfully()); - EXPECT_NO_THROW(loader_->load()); - EXPECT_FALSE(loader_->loadedSuccessfully()); - EXPECT_EQ(1, errors_.size()) << errors_[0] << "\n" << errors_[1]; - // The unexpected EOF warning - EXPECT_EQ(1, warnings_.size()); - checkRR("example.org", RRType::SOA(), "ns1.example.org. " - "admin.example.org. 1234 3600 1800 2419200 7200"); - EXPECT_TRUE(rrsets_.empty()); - } - } -} - -// Check that a garbage after the include generates an error, but not fatal -// one (in lenient mode) and we can recover. -TEST_F(MasterLoaderTest, includeWithGarbage) { - // Include an origin (example.org) because we expect it to be handled - // soon and we don't want it to break here. - const string include_str("$INCLUDE " TEST_DATA_SRCDIR - "/example.org example.org. bunch of other stuff\n" - "www 3600 IN AAAA 2001:db8::1\n"); - stringstream zone_stream(include_str); - setLoader(zone_stream, Name("example.org."), RRClass::IN(), - MasterLoader::MANY_ERRORS); - - EXPECT_NO_THROW(loader_->load()); - EXPECT_FALSE(loader_->loadedSuccessfully()); - ASSERT_EQ(1, errors_.size()); - checkCallbackMessage(errors_.at(0), "Extra tokens at the end of line", 1); - // It says something about extra tokens at the end - EXPECT_NE(string::npos, errors_[0].find("Extra")); - EXPECT_TRUE(warnings_.empty()); - checkBasicRRs(); - checkRR("www.example.org", RRType::AAAA(), "2001:db8::1"); -} - -// Check we error about garbage at the end of $ORIGIN line (but the line -// works). -TEST_F(MasterLoaderTest, originWithGarbage) { - const string origin_str = "$ORIGIN www.example.org. More garbage here\n" - "@ 1H IN A 192.0.2.1\n"; - stringstream ss(origin_str); - setLoader(ss, Name("example.org."), RRClass::IN(), - MasterLoader::MANY_ERRORS); - EXPECT_NO_THROW(loader_->load()); - EXPECT_FALSE(loader_->loadedSuccessfully()); - ASSERT_EQ(1, errors_.size()); - checkCallbackMessage(errors_.at(0), "Extra tokens at the end of line", 1); - EXPECT_TRUE(warnings_.empty()); - checkARR("www.example.org"); -} - -// Test we can pass both file to include and the origin to switch -TEST_F(MasterLoaderTest, includeAndOrigin) { - // First, switch origin to something else, so we can check it is - // switched back. - const string include_string = "$ORIGIN www.example.org.\n" - "@ 1H IN A 192.0.2.1\n" - // Then include the file with data and switch origin back - "$INCLUDE " TEST_DATA_SRCDIR "/example.org example.org.\n" - // Another RR to see we fall back to the previous origin. - "www 1H IN A 192.0.2.1\n"; - stringstream ss(include_string); - setLoader(ss, Name("example.org"), RRClass::IN(), - MasterLoader::MANY_ERRORS); - // Successfully load the data - loader_->load(); - EXPECT_TRUE(loader_->loadedSuccessfully()); - EXPECT_TRUE(errors_.empty()); - EXPECT_TRUE(warnings_.empty()); - // And check it's the correct data - checkARR("www.example.org"); - checkBasicRRs(); - checkARR("www.www.example.org"); -} - -// Like above, but the origin after include is bogus. The whole line should -// be rejected. -TEST_F(MasterLoaderTest, includeAndBadOrigin) { - const string include_string = - "$INCLUDE " TEST_DATA_SRCDIR "/example.org example..org.\n" - // Another RR to see the switch survives after we exit include - "www 1H IN A 192.0.2.1\n"; - stringstream ss(include_string); - setLoader(ss, Name("example.org"), RRClass::IN(), - MasterLoader::MANY_ERRORS); - loader_->load(); - EXPECT_FALSE(loader_->loadedSuccessfully()); - EXPECT_EQ(1, errors_.size()); - checkCallbackMessage(errors_.at(0), "duplicate period in example..org.", - 1); - EXPECT_TRUE(warnings_.empty()); - // And check it's the correct data - checkARR("www.example.org"); -} - -// Check the origin doesn't get outside of the included file. -TEST_F(MasterLoaderTest, includeOriginRestore) { - const string include_string = - "$INCLUDE " TEST_DATA_SRCDIR "/origincheck.txt\n" - "@ 1H IN A 192.0.2.1\n"; - stringstream ss(include_string); - setLoader(ss, Name("example.org"), RRClass::IN(), - MasterLoader::MANY_ERRORS); - // Successfully load the data - loader_->load(); - EXPECT_TRUE(loader_->loadedSuccessfully()); - EXPECT_TRUE(errors_.empty()); - EXPECT_TRUE(warnings_.empty()); - // And check it's the correct data - checkARR("www.example.org"); - checkARR("example.org"); -} - -// Check we restore the last name for initial whitespace when returning from -// include. But we do produce a warning if there's one just ofter the include. -TEST_F(MasterLoaderTest, includeAndInitialWS) { - const string include_string = "xyz 1H IN A 192.0.2.1\n" - "$INCLUDE " TEST_DATA_SRCDIR "/example.org\n" - " 1H IN A 192.0.2.1\n"; - stringstream ss(include_string); - setLoader(ss, Name("example.org"), RRClass::IN(), - MasterLoader::MANY_ERRORS); - // Successfully load the data - loader_->load(); - EXPECT_TRUE(loader_->loadedSuccessfully()); - EXPECT_TRUE(errors_.empty()); - EXPECT_EQ(1, warnings_.size()); - checkCallbackMessage(warnings_.at(0), - "Owner name omitted around $INCLUDE, the result might " - "not be as expected", 3); - checkARR("xyz.example.org"); - checkBasicRRs(); - checkARR("xyz.example.org"); -} - -// Test for "$TTL" -TEST_F(MasterLoaderTest, ttlDirective) { - stringstream zone_stream; - - // Set the default TTL with $TTL followed by an RR omitting the TTL - zone_stream << "$TTL 1800\nexample.org. IN A 192.0.2.1\n"; - // $TTL can be quoted. Also testing the case of $TTL being changed. - zone_stream << "\"$TTL\" 100\na.example.org. IN A 192.0.2.2\n"; - // Extended TTL form is accepted. - zone_stream << "$TTL 1H\nb.example.org. IN A 192.0.2.3\n"; - // Matching is case insensitive. - zone_stream << "$tTl 360\nc.example.org. IN A 192.0.2.4\n"; - // Maximum allowable TTL - zone_stream << "$TTL 2147483647\nd.example.org. IN A 192.0.2.5\n"; - - setLoader(zone_stream, Name("example.org."), RRClass::IN(), - MasterLoader::DEFAULT); - loader_->load(); - EXPECT_TRUE(loader_->loadedSuccessfully()); - checkRR("example.org", RRType::A(), "192.0.2.1", RRTTL(1800)); - checkRR("a.example.org", RRType::A(), "192.0.2.2", RRTTL(100)); - checkRR("b.example.org", RRType::A(), "192.0.2.3", RRTTL(3600)); - checkRR("c.example.org", RRType::A(), "192.0.2.4", RRTTL(360)); - checkRR("d.example.org", RRType::A(), "192.0.2.5", RRTTL(2147483647)); -} - -TEST_F(MasterLoaderTest, ttlFromSOA) { - // No $TTL, and the SOA doesn't have an explicit TTL field. Its minimum - // TTL field will be used as the RR's TTL, and it'll be used as the - // default TTL for others. - stringstream zone_stream("example.org. IN SOA . . 0 0 0 0 1800\n" - "a.example.org. IN A 192.0.2.1\n"); - setLoader(zone_stream, Name("example.org."), RRClass::IN(), - MasterLoader::DEFAULT); - loader_->load(); - EXPECT_TRUE(loader_->loadedSuccessfully()); - checkRR("example.org", RRType::SOA(), ". . 0 0 0 0 1800", RRTTL(1800)); - checkRR("a.example.org", RRType::A(), "192.0.2.1", RRTTL(1800)); - - // The use of SOA minimum TTL should have caused a warning. - EXPECT_EQ(1, warnings_.size()); - checkCallbackMessage(warnings_.at(0), - "no TTL specified; using SOA MINTTL instead", 1); -} - -TEST_F(MasterLoaderTest, ttlFromPrevious) { - // No available default TTL. 2nd and 3rd RR will use the TTL of the - // 1st RR. This will result in a warning, but only for the first time. - stringstream zone_stream("a.example.org. 1800 IN A 192.0.2.1\n" - "b.example.org. IN A 192.0.2.2\n" - "c.example.org. IN A 192.0.2.3\n"); - setLoader(zone_stream, Name("example.org."), RRClass::IN(), - MasterLoader::DEFAULT); - loader_->load(); - EXPECT_TRUE(loader_->loadedSuccessfully()); - checkRR("a.example.org", RRType::A(), "192.0.2.1", RRTTL(1800)); - checkRR("b.example.org", RRType::A(), "192.0.2.2", RRTTL(1800)); - checkRR("c.example.org", RRType::A(), "192.0.2.3", RRTTL(1800)); - - EXPECT_EQ(1, warnings_.size()); - checkCallbackMessage(warnings_.at(0), "using RFC1035 TTL semantics", 2); -} - -TEST_F(MasterLoaderTest, RRParamsOrdering) { - // We test the order and existence of TTL, class and type. See - // MasterLoader::MasterLoaderImpl::parseRRParams() for ordering. - - stringstream zone_stream; - // <TTL> <class> <type> <RDATA> - zone_stream << "a.example.org. 1800 IN A 192.0.2.1\n"; - // <type> <RDATA> - zone_stream << "b.example.org. A 192.0.2.2\n"; - // <class> <TTL> <type> <RDATA> - zone_stream << "c.example.org. IN 3600 A 192.0.2.3\n"; - // <TTL> <type> <RDATA> - zone_stream << "d.example.org. 7200 A 192.0.2.4\n"; - // <class> <type> <RDATA> - zone_stream << "e.example.org. IN A 192.0.2.5\n"; - - setLoader(zone_stream, Name("example.org."), RRClass::IN(), - MasterLoader::DEFAULT); - loader_->load(); - EXPECT_TRUE(loader_->loadedSuccessfully()); - checkRR("a.example.org", RRType::A(), "192.0.2.1", RRTTL(1800)); - checkRR("b.example.org", RRType::A(), "192.0.2.2", RRTTL(1800)); - checkRR("c.example.org", RRType::A(), "192.0.2.3", RRTTL(3600)); - checkRR("d.example.org", RRType::A(), "192.0.2.4", RRTTL(7200)); - checkRR("e.example.org", RRType::A(), "192.0.2.5", RRTTL(7200)); - - EXPECT_EQ(1, warnings_.size()); - checkCallbackMessage(warnings_.at(0), "using RFC1035 TTL semantics", 2); -} - -TEST_F(MasterLoaderTest, ttlFromPreviousSOA) { - // Mixture of the previous two cases: SOA has explicit TTL, followed by - // an RR without an explicit TTL. In this case the minimum TTL won't be - // recognized as the "default TTL". - stringstream zone_stream("example.org. 100 IN SOA . . 0 0 0 0 1800\n" - "a.example.org. IN A 192.0.2.1\n"); - setLoader(zone_stream, Name("example.org."), RRClass::IN(), - MasterLoader::DEFAULT); - loader_->load(); - EXPECT_TRUE(loader_->loadedSuccessfully()); - - checkRR("example.org", RRType::SOA(), ". . 0 0 0 0 1800", RRTTL(100)); - checkRR("a.example.org", RRType::A(), "192.0.2.1", RRTTL(100)); - - EXPECT_EQ(1, warnings_.size()); - checkCallbackMessage(warnings_.at(0), "using RFC1035 TTL semantics", 2); -} - -TEST_F(MasterLoaderTest, ttlUnknown) { - // No available TTL is known for the first RR. - stringstream zone_stream("a.example.org. IN A 192.0.2.1\n"); - setLoader(zone_stream, Name("example.org."), RRClass::IN(), - MasterLoader::DEFAULT); - EXPECT_THROW(loader_->load(), MasterLoaderError); -} - -TEST_F(MasterLoaderTest, ttlUnknownAndContinue) { - stringstream zone_stream("a.example.org. IN A 192.0.2.1\n" - "b.example.org. 1800 IN A 192.0.2.2\n"); - setLoader(zone_stream, Name("example.org."), RRClass::IN(), - MasterLoader::MANY_ERRORS); - loader_->load(); - EXPECT_FALSE(loader_->loadedSuccessfully()); - checkRR("b.example.org", RRType::A(), "192.0.2.2", RRTTL(1800)); - - EXPECT_TRUE(warnings_.empty()); - EXPECT_EQ(1, errors_.size()); - checkCallbackMessage(errors_.at(0), "no TTL specified; load rejected", 1); -} - -TEST_F(MasterLoaderTest, ttlUnknownAndEOF) { - // Similar to the previous case, but the input will be abruptly terminated - // after the offending RR. This will cause an additional warning. - stringstream zone_stream("a.example.org. IN A 192.0.2.1"); - setLoader(zone_stream, Name("example.org."), RRClass::IN(), - MasterLoader::MANY_ERRORS); - loader_->load(); - EXPECT_FALSE(loader_->loadedSuccessfully()); - EXPECT_TRUE(rrsets_.empty()); - - EXPECT_EQ(1, errors_.size()); - checkCallbackMessage(errors_.at(0), "no TTL specified; load rejected", 1); - - // RDATA implementation can complain about it, too. To be independent of - // its details, we focus on the very last warning. - EXPECT_FALSE(warnings_.empty()); - checkCallbackMessage(*warnings_.rbegin(), "File does not end with newline", - 1); -} - -TEST_F(MasterLoaderTest, ttlOverflow) { - stringstream zone_stream; - zone_stream << "example.org. IN SOA . . 0 0 0 0 2147483648\n"; - zone_stream << "$TTL 3600\n"; // reset to an in-range value - zone_stream << "$TTL 2147483649\n"; - zone_stream << "a.example.org. IN A 192.0.2.1\n"; - zone_stream << "$TTL 3600\n"; // reset to an in-range value - zone_stream << "b.example.org. 2147483650 IN A 192.0.2.2\n"; - setLoader(zone_stream, Name("example.org."), RRClass::IN(), - MasterLoader::DEFAULT); - - loader_->load(); - EXPECT_TRUE(loader_->loadedSuccessfully()); - EXPECT_EQ(3, rrsets_.size()); - - checkRR("example.org", RRType::SOA(), ". . 0 0 0 0 2147483648", RRTTL(0)); - checkRR("a.example.org", RRType::A(), "192.0.2.1", RRTTL(0)); - checkRR("b.example.org", RRType::A(), "192.0.2.2", RRTTL(0)); - - EXPECT_EQ(4, warnings_.size()); - checkCallbackMessage(warnings_.at(1), - "TTL 2147483648 > MAXTTL, setting to 0 per RFC2181", - 1); - checkCallbackMessage(warnings_.at(2), - "TTL 2147483649 > MAXTTL, setting to 0 per RFC2181", - 3); - checkCallbackMessage(warnings_.at(3), - "TTL 2147483650 > MAXTTL, setting to 0 per RFC2181", - 6); -} - -// Test the constructor rejects empty add callback. -TEST_F(MasterLoaderTest, emptyCallback) { - EXPECT_THROW(MasterLoader(TEST_DATA_SRCDIR "/example.org", - Name("example.org"), RRClass::IN(), callbacks_, - AddRRCallback()), isc::InvalidParameter); - // And the same with the second constructor - stringstream ss(""); - EXPECT_THROW(MasterLoader(ss, Name("example.org"), RRClass::IN(), - callbacks_, AddRRCallback()), - isc::InvalidParameter); -} - -// Check it throws when we try to load after loading was complete. -TEST_F(MasterLoaderTest, loadTwice) { - setLoader(TEST_DATA_SRCDIR "/example.org", Name("example.org."), - RRClass::IN(), MasterLoader::MANY_ERRORS); - - loader_->load(); - EXPECT_THROW(loader_->load(), isc::InvalidOperation); - // Don't check them, they are not interesting, so suppress the error - // at TearDown - rrsets_.clear(); -} - -// Load 0 items should be rejected -TEST_F(MasterLoaderTest, loadZero) { - setLoader(TEST_DATA_SRCDIR "/example.org", Name("example.org."), - RRClass::IN(), MasterLoader::MANY_ERRORS); - EXPECT_THROW(loader_->loadIncremental(0), isc::InvalidParameter); -} - -// Test there's a warning when the file terminates without end of -// line. -TEST_F(MasterLoaderTest, noEOLN) { - // No \n at the end - const string input("example.org. 3600 IN SOA ns1.example.org. " - "admin.example.org. 1234 3600 1800 2419200 7200"); - stringstream ss(input); - setLoader(ss, Name("example.org."), RRClass::IN(), - MasterLoader::MANY_ERRORS); - - loader_->load(); - EXPECT_TRUE(loader_->loadedSuccessfully()); - EXPECT_TRUE(errors_.empty()); - // There should be one warning about the EOLN - EXPECT_EQ(1, warnings_.size()); - checkRR("example.org", RRType::SOA(), "ns1.example.org. " - "admin.example.org. 1234 3600 1800 2419200 7200"); -} - -// Test it rejects when we don't have the previous name to use in place of -// initial whitespace -TEST_F(MasterLoaderTest, noPreviousName) { - const string input(" 1H IN A 192.0.2.1\n"); - stringstream ss(input); - setLoader(ss, Name("example.org."), RRClass::IN(), - MasterLoader::MANY_ERRORS); - loader_->load(); - EXPECT_FALSE(loader_->loadedSuccessfully()); - EXPECT_EQ(1, errors_.size()); - checkCallbackMessage(errors_.at(0), "No previous name to use in place of " - "initial whitespace", 1); - EXPECT_TRUE(warnings_.empty()); -} - -// Check we warn if the first RR in an included file has omitted name -TEST_F(MasterLoaderTest, previousInInclude) { - const string input("www 1H IN A 192.0.2.1\n" - "$INCLUDE " TEST_DATA_SRCDIR "/omitcheck.txt\n"); - stringstream ss(input); - setLoader(ss, Name("example.org"), RRClass::IN(), - MasterLoader::MANY_ERRORS); - loader_->load(); - EXPECT_TRUE(loader_->loadedSuccessfully()); - EXPECT_TRUE(errors_.empty()); - // There should be one warning about the EOLN - EXPECT_EQ(1, warnings_.size()); - checkCallbackMessage(warnings_.at(0), "Owner name omitted around " - "$INCLUDE, the result might not be as expected", 1); - checkARR("www.example.org"); - 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_->loadedSuccessfully()); - EXPECT_TRUE(errors_.empty()); - EXPECT_TRUE(warnings_.empty()); - - checkRR("1.example.org", RRType::A(), "192.0.2.1"); -} - -} diff --git a/src/lib/dns/tests/masterload_unittest.cc b/src/lib/dns/tests/masterload_unittest.cc index e412de011a..8b13789179 100644 --- a/src/lib/dns/tests/masterload_unittest.cc +++ b/src/lib/dns/tests/masterload_unittest.cc @@ -1,397 +1 @@ -// Copyright (C) 2010-2022 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. -#include <config.h> - -#include <functional> -#include <ios> -#include <fstream> -#include <sstream> -#include <string> -#include <vector> - -#include <gtest/gtest.h> - -#include <dns/masterload.h> -#include <dns/name.h> -#include <dns/rdata.h> -#include <dns/rrclass.h> -#include <dns/rrset.h> - -using namespace std; -using namespace isc::dns; -namespace ph = std::placeholders; - -namespace { -// A callback functor for masterLoad() commonly used for the following tests. -class TestCallback { -public: - TestCallback(vector<ConstRRsetPtr>& rrsets) : rrsets_(rrsets) {} - void operator()(ConstRRsetPtr rrset) { - rrsets_.push_back(rrset); - } -private: - vector<ConstRRsetPtr>& rrsets_; -}; - -// A function version of TestCallback. -void -testCallback(ConstRRsetPtr rrset, vector<ConstRRsetPtr>* rrsets) { - rrsets->push_back(rrset); -} - -class MasterLoadTest : public ::testing::Test { -protected: - MasterLoadTest() : origin("example.com"), zclass(RRClass::IN()), - callback(results) {} -public: - void rrsetCallback(ConstRRsetPtr rrset) { - results.push_back(rrset); - } -protected: - Name origin; - RRClass zclass; - stringstream rr_stream; - vector<ConstRRsetPtr> results; - TestCallback callback; -}; - -// Commonly used test RRs -const char* const txt_rr = "example.com. 3600 IN TXT \"test data\"\n"; -const char* const a_rr1 = "www.example.com. 60 IN A 192.0.2.1\n"; -const char* const a_rr2 = "www.example.com. 60 IN A 192.0.2.2\n"; -const char* const a_rr3 = "ftp.example.com. 60 IN A 192.0.2.3\n"; -// multi-field RR case -const char* const soa_rr = "example.com. 7200 IN SOA . . 0 0 0 0 0\n"; -// A couple of RRSIGs, different type covered -const char* const rrsig_rr1 = - "www.example.com. 60 IN RRSIG A 5 3 3600 20000101000000 20000201000000 " - "12345 example.com. FAKEFAKEFAKE\n"; -const char* const rrsig_rr2 = - "www.example.com. 60 IN RRSIG AAAA 5 3 3600 20000101000000 20000201000000 " - "12345 example.com. FAKEFAKEFAKE\n"; - -// Commonly used for some tests to check the constructed RR content. -const char* const dnskey_rdata = - "256 3 7 AwEAAaetidLzsKWUt4swWR8yu0wPHPiUi8LUsAD0QPWU+wzt89epO6tH " - "zkMBVDkC7qphQO2hTY4hHn9npWFRw5BYubE=\n"; - -TEST_F(MasterLoadTest, loadRRs) { - // a simple case: loading 3 RRs, each consists of a single RRset. - rr_stream << txt_rr << a_rr1 << soa_rr; - masterLoad(rr_stream, origin, zclass, callback); - ASSERT_EQ(3, results.size()); - EXPECT_EQ(txt_rr, results[0]->toText()); - EXPECT_EQ(a_rr1, results[1]->toText()); - EXPECT_EQ(soa_rr, results[2]->toText()); -} - -TEST_F(MasterLoadTest, loadWithFunctionCallback) { - // The same test as loadRRs but using a normal function (not a functor - // object) - rr_stream << txt_rr << a_rr1 << soa_rr; - masterLoad(rr_stream, origin, zclass, - std::bind(&testCallback, ph::_1, &results)); - ASSERT_EQ(3, results.size()); - EXPECT_EQ(txt_rr, results[0]->toText()); - EXPECT_EQ(a_rr1, results[1]->toText()); - EXPECT_EQ(soa_rr, results[2]->toText()); -} - -TEST_F(MasterLoadTest, loadWithMemFunctionCallback) { - // The same test as loadRRs but using a class member function (with a - // help of std.bind) - rr_stream << txt_rr << a_rr1 << soa_rr; - masterLoad(rr_stream, origin, zclass, - std::bind(&MasterLoadTest::rrsetCallback, this, ph::_1)); - ASSERT_EQ(3, results.size()); - EXPECT_EQ(txt_rr, results[0]->toText()); - EXPECT_EQ(a_rr1, results[1]->toText()); - EXPECT_EQ(soa_rr, results[2]->toText()); -} - -TEST_F(MasterLoadTest, loadComments) { - rr_stream << ";; comment line, should be skipped\n" - << "\n" // blank line (should be skipped) - << txt_rr; - masterLoad(rr_stream, origin, zclass, callback); - ASSERT_EQ(1, results.size()); - EXPECT_EQ(txt_rr, results[0]->toText()); -} - -TEST_F(MasterLoadTest, loadRRset) { - // load an RRset containing two RRs - rr_stream << a_rr1 << a_rr2; - masterLoad(rr_stream, origin, zclass, callback); - ASSERT_EQ(1, results.size()); - EXPECT_EQ(string(a_rr1) + string(a_rr2), results[0]->toText()); -} - -TEST_F(MasterLoadTest, loadRRsetsOfSameType) { - // load two RRsets with the same RR type and different owner names. - // the loader must distinguish them as separate RRsets. - rr_stream << a_rr1 << a_rr3; - masterLoad(rr_stream, origin, zclass, callback); - ASSERT_EQ(2, results.size()); - EXPECT_EQ(a_rr1, results[0]->toText()); - EXPECT_EQ(a_rr3, results[1]->toText()); -} - -TEST_F(MasterLoadTest, loadRRsetsInterleaved) { - // two RRs that belongs to the same RRset (rr1 and rr2) are interleaved - // by another. This is an unexpected case for this loader, but it's - // not considered an error. The loader will simply treat them separate - // RRsets. - rr_stream << a_rr1 << a_rr3 << a_rr2; - masterLoad(rr_stream, origin, zclass, callback); - ASSERT_EQ(3, results.size()); - EXPECT_EQ(a_rr1, results[0]->toText()); - EXPECT_EQ(a_rr3, results[1]->toText()); - EXPECT_EQ(a_rr2, results[2]->toText()); -} - -TEST_F(MasterLoadTest, loadRRsigs) { - // RRSIGs of different types covered should be separated - rr_stream << rrsig_rr1 << rrsig_rr2; - masterLoad(rr_stream, origin, zclass, callback); - EXPECT_EQ(2, results.size()); -} - -// This test was disabled by #2387, because the test data has trailing -// comments and it (eventually) uses the string RDATA constructor which -// doesn't support them. This test should be fixed and re-enabled by -// #2381, or deleted. -TEST_F(MasterLoadTest, DISABLED_loadRRWithComment) { - // Comment at the end of line should be ignored and the RR should be - // accepted. - rr_stream << "example.com. 3600 IN DNSKEY\t256 3 7 " - "AwEAAaetidLzsKWUt4swWR8yu0wPHPiUi8LUsAD0QPWU+wzt89epO6tH " - "zkMBVDkC7qphQO2hTY4hHn9npWFRw5BYubE= ; key id = 40430\n"; - masterLoad(rr_stream, origin, zclass, callback); - ASSERT_EQ(1, results.size()); - EXPECT_EQ(0, results[0]->getRdataIterator()->getCurrent().compare( - *rdata::createRdata(RRType::DNSKEY(), zclass, - dnskey_rdata))); -} - -// This test was disabled by #2387, because the test data has trailing -// comments and it (eventually) uses the string RDATA constructor which -// doesn't support them. This test should be fixed and re-enabled by -// #2381, or deleted. -TEST_F(MasterLoadTest, DISABLED_loadRRWithCommentNoSpace) { - // Similar to the previous one, but there's no space before comments. - // It should still work. - rr_stream << "example.com. 3600 IN DNSKEY\t256 3 7 " - "AwEAAaetidLzsKWUt4swWR8yu0wPHPiUi8LUsAD0QPWU+wzt89epO6tH " - "zkMBVDkC7qphQO2hTY4hHn9npWFRw5BYubE=; key id = 40430\n"; - masterLoad(rr_stream, origin, zclass, callback); - ASSERT_EQ(1, results.size()); - EXPECT_EQ(0, results[0]->getRdataIterator()->getCurrent().compare( - *rdata::createRdata(RRType::DNSKEY(), zclass, - dnskey_rdata))); -} - -// This test was disabled by #2387, because the test data has trailing -// comments and it (eventually) uses the string RDATA constructor which -// doesn't support them. This test should be fixed and re-enabled by -// #2381, or deleted. -TEST_F(MasterLoadTest, DISABLED_loadRRWithCommentEmptyComment) { - // Similar to the previous one, but there's no data after the ; - // It should still work. - rr_stream << "example.com. 3600 IN DNSKEY\t256 3 7 " - "AwEAAaetidLzsKWUt4swWR8yu0wPHPiUi8LUsAD0QPWU+wzt89epO6tH " - "zkMBVDkC7qphQO2hTY4hHn9npWFRw5BYubE= ;\n"; - masterLoad(rr_stream, origin, zclass, callback); - ASSERT_EQ(1, results.size()); - EXPECT_EQ(0, results[0]->getRdataIterator()->getCurrent().compare( - *rdata::createRdata(RRType::DNSKEY(), zclass, - dnskey_rdata))); -} - -// This test was disabled by #2387, because the test data has trailing -// comments and it (eventually) uses the string RDATA constructor which -// doesn't support them. This test should be fixed and re-enabled by -// #2381, or deleted. -TEST_F(MasterLoadTest, DISABLED_loadRRWithCommentEmptyCommentNoSpace) { - // Similar to the previous one, but there's no space before or after ; - // It should still work. - rr_stream << "example.com. 3600 IN DNSKEY\t256 3 7 " - "AwEAAaetidLzsKWUt4swWR8yu0wPHPiUi8LUsAD0QPWU+wzt89epO6tH " - "zkMBVDkC7qphQO2hTY4hHn9npWFRw5BYubE=;\n"; - masterLoad(rr_stream, origin, zclass, callback); - ASSERT_EQ(1, results.size()); - EXPECT_EQ(0, results[0]->getRdataIterator()->getCurrent().compare( - *rdata::createRdata(RRType::DNSKEY(), zclass, - dnskey_rdata))); -} - -TEST_F(MasterLoadTest, loadRRWithEOLWhitespace) { - // Test with whitespace after rdata - // It should still work. - rr_stream << "example.com. 3600 IN NSEC3PARAM 1 0 1 beef \n"; - masterLoad(rr_stream, origin, zclass, callback); - ASSERT_EQ(1, results.size()); - EXPECT_EQ(0, results[0]->getRdataIterator()->getCurrent().compare( - *rdata::createRdata(RRType::NSEC3PARAM(), zclass, - "1 0 1 beef"))); -} - -TEST_F(MasterLoadTest, loadRRWithEOLWhitespaceTab) { - // Similar to the previous one, tab instead of space. - // It should still work. - rr_stream << "example.com. 3600 IN NSEC3PARAM 1 0 1 beef\t\n"; - masterLoad(rr_stream, origin, zclass, callback); - ASSERT_EQ(1, results.size()); - EXPECT_EQ(0, results[0]->getRdataIterator()->getCurrent().compare( - *rdata::createRdata(RRType::NSEC3PARAM(), zclass, - "1 0 1 beef"))); -} - -TEST_F(MasterLoadTest, loadRRNoComment) { - // A semicolon in a character-string shouldn't confuse the parser. - rr_stream << "example.com. 3600 IN TXT \"aaa;bbb\"\n"; - masterLoad(rr_stream, origin, zclass, callback); - EXPECT_EQ(1, results.size()); - EXPECT_EQ(0, results[0]->getRdataIterator()->getCurrent().compare( - *rdata::createRdata(RRType::TXT(), zclass, - "\"aaa;bbb\""))); -} - -TEST_F(MasterLoadTest, nonAbsoluteOwner) { - // If the owner name is not absolute, the zone origin is assumed to be - // its origin. - rr_stream << "example.com 3600 IN A 192.0.2.1"; - masterLoad(rr_stream, origin, zclass, callback); - EXPECT_EQ(1, results.size()); - EXPECT_EQ(results[0]->getName(), Name("example.com.example.com")); -} - -TEST_F(MasterLoadTest, loadRREmptyAndComment) { - // There's no RDATA (invalid in this case) but a comment. This position - // shouldn't cause any disruption and should be treated as a normal error. - rr_stream << "example.com. 3600 IN A ;\n"; - EXPECT_THROW(masterLoad(rr_stream, origin, zclass, callback), - MasterLoadError); -} - -TEST_F(MasterLoadTest, loadWithNoEOF) { - // the input stream doesn't end with a new line (and the following blank - // line). It should be accepted. - string rr_string(a_rr1); - rr_string.erase(rr_string.end() - 1); - rr_stream << rr_string; - masterLoad(rr_stream, origin, zclass, callback); - ASSERT_EQ(1, results.size()); - EXPECT_EQ(a_rr1, results[0]->toText()); -} - -TEST_F(MasterLoadTest, loadEmpty) { - // an unusual case: empty input. load must succeed with an empty result. - masterLoad(rr_stream, origin, zclass, callback); - EXPECT_EQ(0, results.size()); -} - -TEST_F(MasterLoadTest, loadWithBeginningSpace) { - rr_stream << " " << a_rr1; - EXPECT_THROW(masterLoad(rr_stream, origin, zclass, callback), - MasterLoadError); -} - -TEST_F(MasterLoadTest, loadWithBeginningTab) { - rr_stream << "\t" << a_rr1; - EXPECT_THROW(masterLoad(rr_stream, origin, zclass, callback), - MasterLoadError); -} - -TEST_F(MasterLoadTest, loadInvalidRRClass) { - rr_stream << "example.com. 3600 CH TXT \"test text\""; - EXPECT_THROW(masterLoad(rr_stream, origin, zclass, callback), - MasterLoadError); -} - -TEST_F(MasterLoadTest, loadOutOfZoneData) { - rr_stream << "example.org. 3600 IN A 192.0.2.255"; - EXPECT_THROW(masterLoad(rr_stream, origin, zclass, callback), - MasterLoadError); -} - -TEST_F(MasterLoadTest, loadNonAtopSOA) { - // SOA's owner name must be zone's origin. - rr_stream << "soa.example.com. 3600 IN SOA . . 0 0 0 0 0"; - EXPECT_THROW(masterLoad(rr_stream, origin, zclass, callback), - MasterLoadError); -} - -// Load TTL with units -TEST_F(MasterLoadTest, loadUnitTTL) { - stringstream rr_stream2("example.com. 1D IN A 192.0.2.1"); - masterLoad(rr_stream2, origin, zclass, callback); - EXPECT_EQ(1, results.size()); - EXPECT_EQ(0, results[0]->getRdataIterator()->getCurrent().compare( - *rdata::createRdata(RRType::A(), zclass, "192.0.2.1"))); -} - -TEST_F(MasterLoadTest, loadBadRRText) { - rr_stream << "example..com. 3600 IN A 192.0.2.1"; // bad owner name - EXPECT_THROW(masterLoad(rr_stream, origin, zclass, callback), - MasterLoadError); - - // bad RR class text - stringstream rr_stream3("example.com. 3600 BAD A 192.0.2.1"); - EXPECT_THROW(masterLoad(rr_stream3, origin, zclass, callback), - MasterLoadError); - - // bad RR type text - stringstream rr_stream4("example.com. 3600 IN BAD 192.0.2.1"); - EXPECT_THROW(masterLoad(rr_stream4, origin, zclass, callback), - MasterLoadError); - - // bad RDATA text - stringstream rr_stream5("example.com. 3600 IN A 2001:db8::1"); - EXPECT_THROW(masterLoad(rr_stream5, origin, zclass, callback), - MasterLoadError); - - // incomplete RR text - stringstream rr_stream6("example.com. 3600 IN A"); - EXPECT_THROW(masterLoad(rr_stream6, origin, zclass, callback), - MasterLoadError); -} - -// This is a helper callback to test the case the input stream becomes bad -// in the middle of processing. -class StreamInvalidator { -public: - StreamInvalidator(stringstream& ss) : ss_(ss) {} - void operator()(ConstRRsetPtr) { - ss_.setstate(ios::badbit); - } -private: - stringstream& ss_; -}; - -TEST_F(MasterLoadTest, loadBadStream) { - rr_stream << txt_rr << a_rr1; - StreamInvalidator invalidator(rr_stream); - EXPECT_THROW(masterLoad(rr_stream, origin, zclass, invalidator), - MasterLoadError); -} - -TEST_F(MasterLoadTest, loadFromFile) { - // The main parser is shared with the stream version, so we simply test - // file I/O specific parts. - masterLoad(TEST_DATA_SRCDIR "/masterload.txt", origin, zclass, callback); - ASSERT_EQ(2, results.size()); - EXPECT_EQ(txt_rr, results[0]->toText()); - EXPECT_EQ(string(a_rr1) + string(a_rr2), results[1]->toText()); - - // NULL file name. Should result in exception. - EXPECT_THROW(masterLoad(NULL, origin, zclass, callback), MasterLoadError); - - // Non existent file name. Ditto. - EXPECT_THROW(masterLoad(TEST_DATA_BUILDDIR "/nonexistent.txt", origin, - zclass, callback), MasterLoadError); -} -} // end namespace diff --git a/src/lib/dns/tests/message_unittest.cc b/src/lib/dns/tests/message_unittest.cc index cbf485d912..8b13789179 100644 --- a/src/lib/dns/tests/message_unittest.cc +++ b/src/lib/dns/tests/message_unittest.cc @@ -1,1160 +1 @@ -// Copyright (C) 2010-2024 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. -#include <config.h> - -#include <fstream> - -#include <boost/scoped_ptr.hpp> - -#include <exceptions/exceptions.h> - -#include <util/buffer.h> -#include <util/time_utilities.h> - -#include <util/unittests/testdata.h> -#include <util/unittests/textdata.h> - -#include <dns/edns.h> -#include <dns/exceptions.h> -#include <dns/message.h> -#include <dns/messagerenderer.h> -#include <dns/question.h> -#include <dns/opcode.h> -#include <dns/rcode.h> -#include <dns/rdataclass.h> -#include <dns/rrclass.h> -#include <dns/rrttl.h> -#include <dns/rrtype.h> -#include <dns/tsig.h> -#include <dns/tsigkey.h> - -#include <gtest/gtest.h> - -#include <dns/tests/unittest_util.h> -#include <util/unittests/wiredata.h> - -using namespace std; -using namespace isc; -using namespace isc::dns; -using namespace isc::util; -using namespace isc::dns::rdata; -using isc::UnitTestUtil; -using isc::util::unittests::matchWireData; - -// -// Note: we need more tests, including: -// parsing malformed headers -// more complete tests about parsing/rendering header flags, opcode, rcode, etc. -// tests for adding RRsets -// tests for RRset/Question iterators -// But, we'll ship with the current set of tests for now, partly because many -// of the above are covered as part of other tests, and partly due to time -// limitation. We also expect to revisit the fundamental design of the Message -// class, at which point we'll also revise the tests including more cases. -// - -const uint16_t Message::DEFAULT_MAX_UDPSIZE; - -namespace isc { -namespace util { -namespace detail { -extern int64_t (*gettimeFunction)(); -} -} -} - -// XXX: this is defined as class static constants, but some compilers -// seemingly cannot find the symbol when used in the EXPECT_xxx macros. -const uint16_t TSIGContext::DEFAULT_FUDGE; - -namespace { -class MessageTest : public ::testing::Test { -protected: - MessageTest() : test_name("test.example.com"), obuffer(0), - message_parse(Message::PARSE), - message_render(Message::RENDER), - bogus_section(static_cast<Message::Section>( - Message::SECTION_ADDITIONAL + 1)), - tsig_ctx(TSIGKey("www.example.com:" - "SFuWd/q99SzF8Yzd1QbB9g==")) - { - rrset_a = RRsetPtr(new RRset(test_name, RRClass::IN(), - RRType::A(), RRTTL(3600))); - rrset_a->addRdata(in::A("192.0.2.1")); - rrset_a->addRdata(in::A("192.0.2.2")); - - rrset_aaaa = RRsetPtr(new RRset(test_name, RRClass::IN(), - RRType::AAAA(), RRTTL(3600))); - rrset_aaaa->addRdata(in::AAAA("2001:db8::1234")); - - rrset_rrsig = RRsetPtr(new RRset(test_name, RRClass::IN(), - RRType::RRSIG(), RRTTL(3600))); - rrset_rrsig->addRdata(generic::RRSIG("AAAA 5 3 7200 20100322084538 " - "20100220084538 1 example.com. " - "FAKEFAKEFAKEFAKE")); - rrset_aaaa->addRRsig(rrset_rrsig); - } - - static Question factoryFromFile(const char* datafile); - const Name test_name; - OutputBuffer obuffer; - MessageRenderer renderer; - Message message_parse; - Message message_render; - const Message::Section bogus_section; - RRsetPtr rrset_a; // A RRset with two RDATAs - RRsetPtr rrset_aaaa; // AAAA RRset with one RDATA with RRSIG - RRsetPtr rrset_rrsig; // RRSIG for the AAAA RRset - TSIGContext tsig_ctx; - vector<unsigned char> received_data; - vector<unsigned char> expected_data; - - void factoryFromFile(Message& message, const char* datafile, - Message::ParseOptions options = - Message::PARSE_DEFAULT); -}; - -void -MessageTest::factoryFromFile(Message& message, const char* datafile, - Message::ParseOptions options) -{ - received_data.clear(); - UnitTestUtil::readWireData(datafile, received_data); - - InputBuffer buffer(&received_data[0], received_data.size()); - message.fromWire(buffer, options); -} - -TEST_F(MessageTest, headerFlag) { - // by default no flag is set - EXPECT_FALSE(message_render.getHeaderFlag(Message::HEADERFLAG_QR)); - EXPECT_FALSE(message_render.getHeaderFlag(Message::HEADERFLAG_AA)); - EXPECT_FALSE(message_render.getHeaderFlag(Message::HEADERFLAG_TC)); - EXPECT_FALSE(message_render.getHeaderFlag(Message::HEADERFLAG_RD)); - EXPECT_FALSE(message_render.getHeaderFlag(Message::HEADERFLAG_RA)); - EXPECT_FALSE(message_render.getHeaderFlag(Message::HEADERFLAG_AD)); - EXPECT_FALSE(message_render.getHeaderFlag(Message::HEADERFLAG_CD)); - - // set operation: by default it will be on - message_render.setHeaderFlag(Message::HEADERFLAG_QR); - EXPECT_TRUE(message_render.getHeaderFlag(Message::HEADERFLAG_QR)); - - // it can be set to on explicitly, too - message_render.setHeaderFlag(Message::HEADERFLAG_AA, true); - EXPECT_TRUE(message_render.getHeaderFlag(Message::HEADERFLAG_AA)); - - // the bit can also be cleared - message_render.setHeaderFlag(Message::HEADERFLAG_AA, false); - EXPECT_FALSE(message_render.getHeaderFlag(Message::HEADERFLAG_AA)); - - // Invalid flag values - EXPECT_THROW(message_render.setHeaderFlag( - static_cast<Message::HeaderFlag>(0)), InvalidParameter); - EXPECT_THROW(message_render.setHeaderFlag( - static_cast<Message::HeaderFlag>(0x7000)), - InvalidParameter); - EXPECT_THROW(message_render.setHeaderFlag( - static_cast<Message::HeaderFlag>(0x0800)), - InvalidParameter); - EXPECT_THROW(message_render.setHeaderFlag( - static_cast<Message::HeaderFlag>(0x0040)), - InvalidParameter); - EXPECT_THROW(message_render.setHeaderFlag( - static_cast<Message::HeaderFlag>(0x10000)), - InvalidParameter); - EXPECT_THROW(message_render.setHeaderFlag( - static_cast<Message::HeaderFlag>(0x80000000)), - InvalidParameter); - - // set operation isn't allowed in the parse mode. - EXPECT_THROW(message_parse.setHeaderFlag(Message::HEADERFLAG_QR), - InvalidMessageOperation); -} -TEST_F(MessageTest, getEDNS) { - EXPECT_FALSE(message_parse.getEDNS()); // by default EDNS isn't set - - factoryFromFile(message_parse, "message_fromWire10.wire"); - EXPECT_TRUE(message_parse.getEDNS()); - EXPECT_EQ(0, message_parse.getEDNS()->getVersion()); - EXPECT_EQ(4096, message_parse.getEDNS()->getUDPSize()); - EXPECT_TRUE(message_parse.getEDNS()->getDNSSECAwareness()); -} - -TEST_F(MessageTest, setEDNS) { - // setEDNS() isn't allowed in the parse mode - EXPECT_THROW(message_parse.setEDNS(EDNSPtr(new EDNS())), - InvalidMessageOperation); - - EDNSPtr edns = EDNSPtr(new EDNS()); - message_render.setEDNS(edns); - EXPECT_EQ(edns, message_render.getEDNS()); -} - -TEST_F(MessageTest, fromWireWithTSIG) { - // Initially there should be no TSIG - EXPECT_EQ(static_cast<void*>(NULL), message_parse.getTSIGRecord()); - - // getTSIGRecord() is only valid in the parse mode. - EXPECT_THROW(message_render.getTSIGRecord(), InvalidMessageOperation); - - factoryFromFile(message_parse, "message_toWire2.wire"); - const uint8_t expected_mac[] = { - 0x22, 0x70, 0x26, 0xad, 0x29, 0x7b, 0xee, 0xe7, - 0x21, 0xce, 0x6c, 0x6f, 0xff, 0x1e, 0x9e, 0xf3 - }; - const TSIGRecord* tsig_rr = message_parse.getTSIGRecord(); - ASSERT_NE(static_cast<void*>(NULL), tsig_rr); - EXPECT_EQ(Name("www.example.com"), tsig_rr->getName()); - EXPECT_EQ(85, tsig_rr->getLength()); // see TSIGRecordTest.getLength - 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()); - matchWireData(expected_mac, sizeof(expected_mac), - tsig_rr->getRdata().getMAC(), - tsig_rr->getRdata().getMACSize()); - EXPECT_EQ(0, tsig_rr->getRdata().getError()); - EXPECT_EQ(0, tsig_rr->getRdata().getOtherLen()); - EXPECT_EQ(static_cast<void*>(NULL), tsig_rr->getRdata().getOtherData()); - - // If we clear the message for reuse, the recorded TSIG will be cleared. - message_parse.clear(Message::PARSE); - EXPECT_EQ(static_cast<void*>(NULL), message_parse.getTSIGRecord()); -} - -TEST_F(MessageTest, fromWireWithTSIGCompressed) { - // Mostly same as fromWireWithTSIG, but the TSIG owner name is compressed. - factoryFromFile(message_parse, "message_fromWire12.wire"); - const TSIGRecord* tsig_rr = message_parse.getTSIGRecord(); - ASSERT_NE(static_cast<void*>(NULL), tsig_rr); - EXPECT_EQ(Name("www.example.com"), tsig_rr->getName()); - // len(www.example.com) = 17, but when fully compressed, the length is - // 2 bytes. So the length of the record should be 15 bytes shorter. - EXPECT_EQ(70, tsig_rr->getLength()); -} - -TEST_F(MessageTest, fromWireWithBadTSIG) { - // Multiple TSIG RRs - EXPECT_THROW(factoryFromFile(message_parse, "message_fromWire13.wire"), - DNSMessageFORMERR); - message_parse.clear(Message::PARSE); - - // TSIG in the answer section (must be in additional) - EXPECT_THROW(factoryFromFile(message_parse, "message_fromWire14.wire"), - DNSMessageFORMERR); - message_parse.clear(Message::PARSE); - - // TSIG is not the last record. - EXPECT_THROW(factoryFromFile(message_parse, "message_fromWire15.wire"), - DNSMessageFORMERR); - message_parse.clear(Message::PARSE); - - // Unexpected RR Class (this will fail in constructing TSIGRecord) - EXPECT_THROW(factoryFromFile(message_parse, "message_fromWire16.wire"), - DNSMessageFORMERR); -} - -TEST_F(MessageTest, getRRCount) { - // by default all counters should be 0 - EXPECT_EQ(0, message_render.getRRCount(Message::SECTION_QUESTION)); - EXPECT_EQ(0, message_render.getRRCount(Message::SECTION_ANSWER)); - EXPECT_EQ(0, message_render.getRRCount(Message::SECTION_AUTHORITY)); - EXPECT_EQ(0, message_render.getRRCount(Message::SECTION_ADDITIONAL)); - - message_render.addQuestion(Question(Name("test.example.com"), - RRClass::IN(), RRType::A())); - EXPECT_EQ(1, message_render.getRRCount(Message::SECTION_QUESTION)); - - // rrset_a contains two RRs - message_render.addRRset(Message::SECTION_ANSWER, rrset_a); - EXPECT_EQ(2, message_render.getRRCount(Message::SECTION_ANSWER)); - - // parse a message containing a Question and EDNS OPT RR. - // OPT shouldn't be counted as normal RR, so result of getRRCount - // shouldn't change. - factoryFromFile(message_parse, "message_fromWire11.wire"); - EXPECT_EQ(1, message_render.getRRCount(Message::SECTION_QUESTION)); - EXPECT_EQ(0, message_render.getRRCount(Message::SECTION_ADDITIONAL)); - - // out-of-band section ID - EXPECT_THROW(message_parse.getRRCount(bogus_section), OutOfRange); -} - -TEST_F(MessageTest, addRRset) { - // initially, we have 0 - EXPECT_EQ(0, message_render.getRRCount(Message::SECTION_ANSWER)); - - // add two A RRs (unsigned) - message_render.addRRset(Message::SECTION_ANSWER, rrset_a); - EXPECT_EQ(rrset_a, - *message_render.beginSection(Message::SECTION_ANSWER)); - EXPECT_EQ(2, message_render.getRRCount(Message::SECTION_ANSWER)); - - message_render.clear(Message::RENDER); - - // add one AAAA RR (signed) - message_render.addRRset(Message::SECTION_ANSWER, rrset_aaaa); - EXPECT_EQ(rrset_aaaa, - *message_render.beginSection(Message::SECTION_ANSWER)); - EXPECT_EQ(2, message_render.getRRCount(Message::SECTION_ANSWER)); -} - -TEST_F(MessageTest, badAddRRset) { - // addRRset() isn't allowed in the parse mode. - EXPECT_THROW(message_parse.addRRset(Message::SECTION_ANSWER, - rrset_a), InvalidMessageOperation); - // out-of-band section ID - EXPECT_THROW(message_render.addRRset(bogus_section, rrset_a), OutOfRange); - - // NULL RRset - EXPECT_THROW(message_render.addRRset(Message::SECTION_ANSWER, RRsetPtr()), - InvalidParameter); -} - -TEST_F(MessageTest, hasRRset) { - message_render.addRRset(Message::SECTION_ANSWER, rrset_a); - EXPECT_TRUE(message_render.hasRRset(Message::SECTION_ANSWER, test_name, - RRClass::IN(), RRType::A())); - // section doesn't match - EXPECT_FALSE(message_render.hasRRset(Message::SECTION_ADDITIONAL, test_name, - RRClass::IN(), RRType::A())); - // name doesn't match - EXPECT_FALSE(message_render.hasRRset(Message::SECTION_ANSWER, - Name("nomatch.example"), - RRClass::IN(), RRType::A())); - // RR class doesn't match - EXPECT_FALSE(message_render.hasRRset(Message::SECTION_ANSWER, test_name, - RRClass::CH(), RRType::A())); - // RR type doesn't match - EXPECT_FALSE(message_render.hasRRset(Message::SECTION_ANSWER, test_name, - RRClass::IN(), RRType::AAAA())); - - // out-of-band section ID - EXPECT_THROW(message_render.hasRRset(bogus_section, test_name, - RRClass::IN(), RRType::A()), - OutOfRange); - - // Repeat the checks having created an RRset of the appropriate type. - - RRsetPtr rrs1(new RRset(test_name, RRClass::IN(), RRType::A(), RRTTL(60))); - EXPECT_TRUE(message_render.hasRRset(Message::SECTION_ANSWER, rrs1)); - EXPECT_FALSE(message_render.hasRRset(Message::SECTION_ADDITIONAL, rrs1)); - - RRsetPtr rrs2(new RRset(Name("nomatch.example"), RRClass::IN(), RRType::A(), - RRTTL(5))); - EXPECT_FALSE(message_render.hasRRset(Message::SECTION_ANSWER, rrs2)); - - RRsetPtr rrs3(new RRset(test_name, RRClass::CH(), RRType::A(), RRTTL(60))); - EXPECT_FALSE(message_render.hasRRset(Message::SECTION_ANSWER, rrs3)); - - RRsetPtr rrs4(new RRset(test_name, RRClass::IN(), RRType::AAAA(), RRTTL(5))); - EXPECT_FALSE(message_render.hasRRset(Message::SECTION_ANSWER, rrs4)); - - RRsetPtr rrs5(new RRset(test_name, RRClass::IN(), RRType::AAAA(), RRTTL(5))); - EXPECT_FALSE(message_render.hasRRset(Message::SECTION_ANSWER, rrs4)); - - EXPECT_THROW(message_render.hasRRset(bogus_section, rrs1), OutOfRange); -} - -TEST_F(MessageTest, removeRRset) { - message_render.addRRset(Message::SECTION_ANSWER, rrset_a); - message_render.addRRset(Message::SECTION_ANSWER, rrset_aaaa); - EXPECT_TRUE(message_render.hasRRset(Message::SECTION_ANSWER, test_name, - RRClass::IN(), RRType::A())); - EXPECT_TRUE(message_render.hasRRset(Message::SECTION_ANSWER, test_name, - RRClass::IN(), RRType::AAAA())); - EXPECT_EQ(4, message_render.getRRCount(Message::SECTION_ANSWER)); - - // Locate the AAAA RRset and remove it and any associated RRSIGs - RRsetIterator i = message_render.beginSection(Message::SECTION_ANSWER); - if ((*i)->getType() == RRType::A()) { - ++i; - } - EXPECT_EQ(RRType::AAAA(), (*i)->getType()); - message_render.removeRRset(Message::SECTION_ANSWER, i); - - EXPECT_TRUE(message_render.hasRRset(Message::SECTION_ANSWER, test_name, - RRClass::IN(), RRType::A())); - EXPECT_FALSE(message_render.hasRRset(Message::SECTION_ANSWER, test_name, - RRClass::IN(), RRType::AAAA())); - EXPECT_EQ(2, message_render.getRRCount(Message::SECTION_ANSWER)); -} - -TEST_F(MessageTest, clearQuestionSection) { - QuestionPtr q(new Question(Name("www.example.com"), RRClass::IN(), - RRType::A())); - message_render.addQuestion(q); - ASSERT_EQ(1, message_render.getRRCount(Message::SECTION_QUESTION)); - - message_render.clearSection(Message::SECTION_QUESTION); - EXPECT_EQ(0, message_render.getRRCount(Message::SECTION_QUESTION)); - EXPECT_TRUE(message_render.beginQuestion() == - message_render.endQuestion()); -} - - -TEST_F(MessageTest, clearAnswerSection) { - // Add two RRsets, check they are present, clear the section, - // check if they are gone. - message_render.addRRset(Message::SECTION_ANSWER, rrset_a); - message_render.addRRset(Message::SECTION_ANSWER, rrset_aaaa); - ASSERT_TRUE(message_render.hasRRset(Message::SECTION_ANSWER, test_name, - RRClass::IN(), RRType::A())); - ASSERT_TRUE(message_render.hasRRset(Message::SECTION_ANSWER, test_name, - RRClass::IN(), RRType::AAAA())); - ASSERT_EQ(4, message_render.getRRCount(Message::SECTION_ANSWER)); - - message_render.clearSection(Message::SECTION_ANSWER); - EXPECT_FALSE(message_render.hasRRset(Message::SECTION_ANSWER, test_name, - RRClass::IN(), RRType::A())); - EXPECT_FALSE(message_render.hasRRset(Message::SECTION_ANSWER, test_name, - RRClass::IN(), RRType::AAAA())); - EXPECT_EQ(0, message_render.getRRCount(Message::SECTION_ANSWER)); -} - -TEST_F(MessageTest, clearAuthoritySection) { - // Add two RRsets, check they are present, clear the section, - // check if they are gone. - message_render.addRRset(Message::SECTION_AUTHORITY, rrset_a); - message_render.addRRset(Message::SECTION_AUTHORITY, rrset_aaaa); - ASSERT_TRUE(message_render.hasRRset(Message::SECTION_AUTHORITY, test_name, - RRClass::IN(), RRType::A())); - ASSERT_TRUE(message_render.hasRRset(Message::SECTION_AUTHORITY, test_name, - RRClass::IN(), RRType::AAAA())); - ASSERT_EQ(4, message_render.getRRCount(Message::SECTION_AUTHORITY)); - - message_render.clearSection(Message::SECTION_AUTHORITY); - EXPECT_FALSE(message_render.hasRRset(Message::SECTION_AUTHORITY, test_name, - RRClass::IN(), RRType::A())); - EXPECT_FALSE(message_render.hasRRset(Message::SECTION_AUTHORITY, test_name, - RRClass::IN(), RRType::AAAA())); - EXPECT_EQ(0, message_render.getRRCount(Message::SECTION_AUTHORITY)); -} - -TEST_F(MessageTest, clearAdditionalSection) { - // Add two RRsets, check they are present, clear the section, - // check if they are gone. - message_render.addRRset(Message::SECTION_ADDITIONAL, rrset_a); - message_render.addRRset(Message::SECTION_ADDITIONAL, rrset_aaaa); - ASSERT_TRUE(message_render.hasRRset(Message::SECTION_ADDITIONAL, test_name, - RRClass::IN(), RRType::A())); - ASSERT_TRUE(message_render.hasRRset(Message::SECTION_ADDITIONAL, test_name, - RRClass::IN(), RRType::AAAA())); - ASSERT_EQ(4, message_render.getRRCount(Message::SECTION_ADDITIONAL)); - - message_render.clearSection(Message::SECTION_ADDITIONAL); - EXPECT_FALSE(message_render.hasRRset(Message::SECTION_ADDITIONAL, test_name, - RRClass::IN(), RRType::A())); - EXPECT_FALSE(message_render.hasRRset(Message::SECTION_ADDITIONAL, test_name, - RRClass::IN(), RRType::AAAA())); - EXPECT_EQ(0, message_render.getRRCount(Message::SECTION_ADDITIONAL)); -} - -TEST_F(MessageTest, badClearSection) { - // attempt of clearing a message in the parse mode. - EXPECT_THROW(message_parse.clearSection(Message::SECTION_QUESTION), - InvalidMessageOperation); - // attempt of clearing out-of-range section - EXPECT_THROW(message_render.clearSection(bogus_section), OutOfRange); -} - -TEST_F(MessageTest, badBeginSection) { - // valid cases are tested via other tests - EXPECT_THROW(message_render.beginSection(Message::SECTION_QUESTION), - InvalidMessageSection); - EXPECT_THROW(message_render.beginSection(bogus_section), OutOfRange); -} - -TEST_F(MessageTest, badEndSection) { - // valid cases are tested via other tests - EXPECT_THROW(message_render.endSection(Message::SECTION_QUESTION), - InvalidMessageSection); - EXPECT_THROW(message_render.endSection(bogus_section), OutOfRange); -} - -TEST_F(MessageTest, appendSection) { - Message target(Message::RENDER); - - // Section check - EXPECT_THROW(target.appendSection(bogus_section, message_render), - OutOfRange); - - // Make sure nothing is copied if there is nothing to copy - target.appendSection(Message::SECTION_QUESTION, message_render); - EXPECT_EQ(0, target.getRRCount(Message::SECTION_QUESTION)); - target.appendSection(Message::SECTION_ANSWER, message_render); - EXPECT_EQ(0, target.getRRCount(Message::SECTION_ANSWER)); - target.appendSection(Message::SECTION_AUTHORITY, message_render); - EXPECT_EQ(0, target.getRRCount(Message::SECTION_AUTHORITY)); - target.appendSection(Message::SECTION_ADDITIONAL, message_render); - EXPECT_EQ(0, target.getRRCount(Message::SECTION_ADDITIONAL)); - - // Now add some data, copy again, and see if it got added - message_render.addQuestion(Question(Name("test.example.com"), - RRClass::IN(), RRType::A())); - message_render.addRRset(Message::SECTION_ANSWER, rrset_a); - message_render.addRRset(Message::SECTION_AUTHORITY, rrset_a); - message_render.addRRset(Message::SECTION_ADDITIONAL, rrset_a); - message_render.addRRset(Message::SECTION_ADDITIONAL, rrset_aaaa); - - target.appendSection(Message::SECTION_QUESTION, message_render); - EXPECT_EQ(1, target.getRRCount(Message::SECTION_QUESTION)); - - target.appendSection(Message::SECTION_ANSWER, message_render); - EXPECT_EQ(2, target.getRRCount(Message::SECTION_ANSWER)); - EXPECT_TRUE(target.hasRRset(Message::SECTION_ANSWER, test_name, - RRClass::IN(), RRType::A())); - - target.appendSection(Message::SECTION_AUTHORITY, message_render); - EXPECT_EQ(2, target.getRRCount(Message::SECTION_AUTHORITY)); - EXPECT_TRUE(target.hasRRset(Message::SECTION_AUTHORITY, test_name, - RRClass::IN(), RRType::A())); - - target.appendSection(Message::SECTION_ADDITIONAL, message_render); - EXPECT_EQ(4, target.getRRCount(Message::SECTION_ADDITIONAL)); - EXPECT_TRUE(target.hasRRset(Message::SECTION_ADDITIONAL, test_name, - RRClass::IN(), RRType::A())); - EXPECT_TRUE(target.hasRRset(Message::SECTION_ADDITIONAL, test_name, - RRClass::IN(), RRType::AAAA())); - - // One more test, test to see if the section gets added, not replaced - Message source2(Message::RENDER); - source2.addRRset(Message::SECTION_ANSWER, rrset_aaaa); - target.appendSection(Message::SECTION_ANSWER, source2); - EXPECT_EQ(4, target.getRRCount(Message::SECTION_ANSWER)); - EXPECT_TRUE(target.hasRRset(Message::SECTION_ANSWER, test_name, - RRClass::IN(), RRType::A())); - EXPECT_TRUE(target.hasRRset(Message::SECTION_ANSWER, test_name, - RRClass::IN(), RRType::AAAA())); - -} - -TEST_F(MessageTest, parseHeader) { - received_data.clear(); - UnitTestUtil::readWireData("message_fromWire1", received_data); - - // parseHeader() isn't allowed in the render mode. - InputBuffer buffer(&received_data[0], received_data.size()); - EXPECT_THROW(message_render.parseHeader(buffer), InvalidMessageOperation); - - message_parse.parseHeader(buffer); - EXPECT_EQ(0x1035, message_parse.getQid()); - EXPECT_EQ(Opcode::QUERY(), message_parse.getOpcode()); - EXPECT_EQ(Rcode::NOERROR(), message_parse.getRcode()); - EXPECT_TRUE(message_parse.getHeaderFlag(Message::HEADERFLAG_QR)); - EXPECT_TRUE(message_parse.getHeaderFlag(Message::HEADERFLAG_AA)); - EXPECT_FALSE(message_parse.getHeaderFlag(Message::HEADERFLAG_TC)); - EXPECT_TRUE(message_parse.getHeaderFlag(Message::HEADERFLAG_RD)); - EXPECT_FALSE(message_parse.getHeaderFlag(Message::HEADERFLAG_RA)); - EXPECT_FALSE(message_parse.getHeaderFlag(Message::HEADERFLAG_AD)); - EXPECT_FALSE(message_parse.getHeaderFlag(Message::HEADERFLAG_CD)); - EXPECT_EQ(1, message_parse.getRRCount(Message::SECTION_QUESTION)); - EXPECT_EQ(2, message_parse.getRRCount(Message::SECTION_ANSWER)); - EXPECT_EQ(0, message_parse.getRRCount(Message::SECTION_AUTHORITY)); - EXPECT_EQ(0, message_parse.getRRCount(Message::SECTION_ADDITIONAL)); - - // Only the header part should have been examined. - EXPECT_EQ(12, buffer.getPosition()); // 12 = size of the header section - EXPECT_TRUE(message_parse.beginQuestion() == message_parse.endQuestion()); - EXPECT_TRUE(message_parse.beginSection(Message::SECTION_ANSWER) == - message_parse.endSection(Message::SECTION_ANSWER)); - EXPECT_TRUE(message_parse.beginSection(Message::SECTION_AUTHORITY) == - message_parse.endSection(Message::SECTION_AUTHORITY)); - EXPECT_TRUE(message_parse.beginSection(Message::SECTION_ADDITIONAL) == - message_parse.endSection(Message::SECTION_ADDITIONAL)); -} - -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()); - EXPECT_TRUE(message_parse.getHeaderFlag(Message::HEADERFLAG_QR)); - EXPECT_TRUE(message_parse.getHeaderFlag(Message::HEADERFLAG_RD)); - EXPECT_TRUE(message_parse.getHeaderFlag(Message::HEADERFLAG_AA)); - - QuestionPtr q = *message_parse.beginQuestion(); - EXPECT_EQ(test_name, q->getName()); - EXPECT_EQ(RRType::A(), q->getType()); - EXPECT_EQ(RRClass::IN(), q->getClass()); - EXPECT_EQ(1, message_parse.getRRCount(Message::SECTION_QUESTION)); - EXPECT_EQ(2, message_parse.getRRCount(Message::SECTION_ANSWER)); - EXPECT_EQ(0, message_parse.getRRCount(Message::SECTION_AUTHORITY)); - EXPECT_EQ(0, message_parse.getRRCount(Message::SECTION_ADDITIONAL)); - - RRsetPtr rrset = *message_parse.beginSection(Message::SECTION_ANSWER); - EXPECT_EQ(test_name, rrset->getName()); - EXPECT_EQ(RRType::A(), rrset->getType()); - EXPECT_EQ(RRClass::IN(), rrset->getClass()); - // TTL should be 3600, even though that of the 2nd RR is 7200 - EXPECT_EQ(RRTTL(3600), rrset->getTTL()); - RdataIteratorPtr it = rrset->getRdataIterator(); - EXPECT_EQ("192.0.2.1", it->getCurrent().toText()); - it->next(); - EXPECT_EQ("192.0.2.2", it->getCurrent().toText()); - it->next(); - EXPECT_TRUE(it->isLast()); -} - - -TEST_F(MessageTest, fromWire) { - // fromWire() isn't allowed in the render mode. - EXPECT_THROW(factoryFromFile(message_render, "message_fromWire1"), - InvalidMessageOperation); - - factoryFromFile(message_parse, "message_fromWire1"); - checkMessageFromWire(message_parse, test_name); -} - -TEST_F(MessageTest, fromWireMultiple) { - // Parse from wire multiple times. - factoryFromFile(message_parse, "message_fromWire1"); - factoryFromFile(message_parse, "message_fromWire1"); - factoryFromFile(message_parse, "message_fromWire1"); - factoryFromFile(message_parse, "message_fromWire1"); - checkMessageFromWire(message_parse, test_name); - - // Calling parseHeader() directly before fromWire() should not cause - // any problems. - received_data.clear(); - UnitTestUtil::readWireData("message_fromWire1", received_data); - - InputBuffer buffer(&received_data[0], received_data.size()); - message_parse.parseHeader(buffer); - message_parse.fromWire(buffer); - message_parse.parseHeader(buffer); - message_parse.fromWire(buffer); - checkMessageFromWire(message_parse, test_name); -} - -TEST_F(MessageTest, fromWireShortBuffer) { - // We trim a valid message (ending with an SOA RR) for one byte. - // fromWire() should throw an exception while parsing the trimmed RR. - UnitTestUtil::readWireData("message_fromWire22.wire", received_data); - InputBuffer buffer(&received_data[0], received_data.size() - 1); - EXPECT_THROW(message_parse.fromWire(buffer), InvalidBufferPosition); -} - -TEST_F(MessageTest, fromWireCombineRRs) { - // This message contains 3 RRs in the answer section in the order of - // A, AAAA, A types. fromWire() should combine the two A RRs into a - // single RRset by default. - factoryFromFile(message_parse, "message_fromWire19.wire"); - - RRsetIterator it = message_parse.beginSection(Message::SECTION_ANSWER); - RRsetIterator it_end = message_parse.endSection(Message::SECTION_ANSWER); - ASSERT_TRUE(it != it_end); - EXPECT_EQ(RRType::A(), (*it)->getType()); - EXPECT_EQ(2, (*it)->getRdataCount()); - - ++it; - ASSERT_TRUE(it != it_end); - EXPECT_EQ(RRType::AAAA(), (*it)->getType()); - EXPECT_EQ(1, (*it)->getRdataCount()); -} - -// A helper function for a test pattern commonly used in several tests below. -void -preserveRRCheck(const Message& message, Message::Section section) { - RRsetIterator it = message.beginSection(section); - RRsetIterator it_end = message.endSection(section); - ASSERT_TRUE(it != it_end); - EXPECT_EQ(RRType::A(), (*it)->getType()); - EXPECT_EQ(1, (*it)->getRdataCount()); - EXPECT_EQ("192.0.2.1", (*it)->getRdataIterator()->getCurrent().toText()); - - ++it; - ASSERT_TRUE(it != it_end); - EXPECT_EQ(RRType::AAAA(), (*it)->getType()); - EXPECT_EQ(1, (*it)->getRdataCount()); - EXPECT_EQ("2001:db8::1", (*it)->getRdataIterator()->getCurrent().toText()); - - ++it; - ASSERT_TRUE(it != it_end); - EXPECT_EQ(RRType::A(), (*it)->getType()); - EXPECT_EQ(1, (*it)->getRdataCount()); - EXPECT_EQ("192.0.2.2", (*it)->getRdataIterator()->getCurrent().toText()); -} - -TEST_F(MessageTest, fromWirePreserveAnswer) { - // Using the same data as the previous test, but specify the PRESERVE_ORDER - // option. The received order of RRs should be preserved, and each RR - // should be stored in a single RRset. - factoryFromFile(message_parse, "message_fromWire19.wire", - Message::PRESERVE_ORDER); - { - SCOPED_TRACE("preserve answer RRs"); - preserveRRCheck(message_parse, Message::SECTION_ANSWER); - } -} - -TEST_F(MessageTest, fromWirePreserveAuthority) { - // Same for the previous test, but for the authority section. - factoryFromFile(message_parse, "message_fromWire20.wire", - Message::PRESERVE_ORDER); - { - SCOPED_TRACE("preserve authority RRs"); - preserveRRCheck(message_parse, Message::SECTION_AUTHORITY); - } -} - -TEST_F(MessageTest, fromWirePreserveAdditional) { - // Same for the previous test, but for the additional section. - factoryFromFile(message_parse, "message_fromWire21.wire", - Message::PRESERVE_ORDER); - { - SCOPED_TRACE("preserve additional RRs"); - preserveRRCheck(message_parse, Message::SECTION_ADDITIONAL); - } -} - -TEST_F(MessageTest, EDNS0ExtRcode) { - // Extended Rcode = BADVERS - factoryFromFile(message_parse, "message_fromWire10.wire"); - EXPECT_EQ(Rcode::BADVERS(), message_parse.getRcode()); - - // Maximum extended Rcode - message_parse.clear(Message::PARSE); - factoryFromFile(message_parse, "message_fromWire11.wire"); - EXPECT_EQ(0xfff, message_parse.getRcode().getCode()); -} - -TEST_F(MessageTest, BadEDNS0) { - // OPT RR in the answer section - EXPECT_THROW(factoryFromFile(message_parse, "message_fromWire4"), - DNSMessageFORMERR); - // multiple OPT RRs (in the additional section) - message_parse.clear(Message::PARSE); - EXPECT_THROW(factoryFromFile(message_parse, "message_fromWire5"), - DNSMessageFORMERR); -} - -TEST_F(MessageTest, toWire) { - message_render.setQid(0x1035); - message_render.setOpcode(Opcode::QUERY()); - message_render.setRcode(Rcode::NOERROR()); - message_render.setHeaderFlag(Message::HEADERFLAG_QR, true); - message_render.setHeaderFlag(Message::HEADERFLAG_RD, true); - message_render.setHeaderFlag(Message::HEADERFLAG_AA, true); - message_render.addQuestion(Question(Name("test.example.com"), RRClass::IN(), - RRType::A())); - message_render.addRRset(Message::SECTION_ANSWER, rrset_a); - - EXPECT_EQ(1, message_render.getRRCount(Message::SECTION_QUESTION)); - EXPECT_EQ(2, message_render.getRRCount(Message::SECTION_ANSWER)); - EXPECT_EQ(0, message_render.getRRCount(Message::SECTION_AUTHORITY)); - EXPECT_EQ(0, message_render.getRRCount(Message::SECTION_ADDITIONAL)); - - message_render.toWire(renderer); - vector<unsigned char> data; - UnitTestUtil::readWireData("message_toWire1", data); - matchWireData(&data[0], data.size(), - renderer.getData(), renderer.getLength()); -} - -TEST_F(MessageTest, toWireSigned) { - message_render.setQid(0x75c1); - message_render.setOpcode(Opcode::QUERY()); - message_render.setRcode(Rcode::NOERROR()); - message_render.setHeaderFlag(Message::HEADERFLAG_QR, true); - message_render.setHeaderFlag(Message::HEADERFLAG_RD, true); - message_render.setHeaderFlag(Message::HEADERFLAG_AA, true); - message_render.addQuestion(Question(Name("test.example.com"), RRClass::IN(), - RRType::A())); - - rrset_rrsig = RRsetPtr(new RRset(test_name, RRClass::IN(), - RRType::RRSIG(), RRTTL(3600))); - // one signature algorithm (5 = RSA/SHA-1) - rrset_rrsig->addRdata(generic::RRSIG("A 5 3 3600 " - "20000101000000 20000201000000 " - "12345 example.com. FAKEFAKEFAKE")); - // another signature algorithm (3 = DSA/SHA-1) - rrset_rrsig->addRdata(generic::RRSIG("A 3 3 3600 " - "20000101000000 20000201000000 " - "12345 example.com. FAKEFAKEFAKE")); - rrset_a->addRRsig(rrset_rrsig); - EXPECT_EQ(2, rrset_a->getRRsigDataCount()); - - message_render.addRRset(Message::SECTION_ANSWER, rrset_a); - - EXPECT_EQ(1, message_render.getRRCount(Message::SECTION_QUESTION)); - EXPECT_EQ(4, message_render.getRRCount(Message::SECTION_ANSWER)); - EXPECT_EQ(0, message_render.getRRCount(Message::SECTION_AUTHORITY)); - EXPECT_EQ(0, message_render.getRRCount(Message::SECTION_ADDITIONAL)); - - message_render.toWire(renderer); - vector<unsigned char> data; - UnitTestUtil::readWireData("message_toWire6", data); - matchWireData(&data[0], data.size(), - renderer.getData(), renderer.getLength()); -} - -TEST_F(MessageTest, toWireSignedAndTruncated) { - message_render.setQid(0x75c1); - message_render.setOpcode(Opcode::QUERY()); - message_render.setRcode(Rcode::NOERROR()); - message_render.setHeaderFlag(Message::HEADERFLAG_QR, true); - message_render.setHeaderFlag(Message::HEADERFLAG_RD, true); - message_render.setHeaderFlag(Message::HEADERFLAG_AA, true); - message_render.addQuestion(Question(Name("test.example.com"), RRClass::IN(), - RRType::TXT())); - - RRsetPtr rrset_txt = RRsetPtr(new RRset(test_name, RRClass::IN(), - RRType::TXT(), RRTTL(3600))); - rrset_txt->addRdata(generic::TXT(string(255, 'a'))); - rrset_txt->addRdata(generic::TXT(string(255, 'b'))); - rrset_txt->addRdata(generic::TXT(string(255, 'c'))); - rrset_txt->addRdata(generic::TXT(string(255, 'd'))); - rrset_txt->addRdata(generic::TXT(string(255, 'e'))); - rrset_txt->addRdata(generic::TXT(string(255, 'f'))); - rrset_txt->addRdata(generic::TXT(string(255, 'g'))); - rrset_txt->addRdata(generic::TXT(string(255, 'h'))); - - rrset_rrsig = RRsetPtr(new RRset(test_name, RRClass::IN(), - RRType::RRSIG(), RRTTL(3600))); - // one signature algorithm (5 = RSA/SHA-1) - rrset_rrsig->addRdata(generic::RRSIG("TXT 5 3 3600 " - "20000101000000 20000201000000 " - "12345 example.com. FAKEFAKEFAKE")); - rrset_txt->addRRsig(rrset_rrsig); - EXPECT_EQ(1, rrset_txt->getRRsigDataCount()); - - message_render.addRRset(Message::SECTION_ANSWER, rrset_txt); - - EXPECT_EQ(1, message_render.getRRCount(Message::SECTION_QUESTION)); - EXPECT_EQ(9, message_render.getRRCount(Message::SECTION_ANSWER)); - EXPECT_EQ(0, message_render.getRRCount(Message::SECTION_AUTHORITY)); - EXPECT_EQ(0, message_render.getRRCount(Message::SECTION_ADDITIONAL)); - - message_render.toWire(renderer); - vector<unsigned char> data; - UnitTestUtil::readWireData("message_toWire7", data); - matchWireData(&data[0], data.size(), - renderer.getData(), renderer.getLength()); -} - -TEST_F(MessageTest, toWireInParseMode) { - // toWire() isn't allowed in the parse mode. - EXPECT_THROW(message_parse.toWire(renderer), InvalidMessageOperation); -} - -// See dnssectime_unittest.cc -template <int64_t NOW> -int64_t -testGetTime() { - return (NOW); -} - -// bit-wise constant flags to configure DNS header flags for test -// messages. -const unsigned int QR_FLAG = 0x1; -const unsigned int AA_FLAG = 0x2; -const unsigned int RD_FLAG = 0x4; - -void -commonTSIGToWireCheck(Message& message, MessageRenderer& renderer, - TSIGContext& tsig_ctx, const char* const expected_file, - unsigned int message_flags = RD_FLAG, - RRType qtype = RRType::A(), - const vector<const char*>* answer_data = NULL) -{ - message.setOpcode(Opcode::QUERY()); - message.setRcode(Rcode::NOERROR()); - if ((message_flags & QR_FLAG) != 0) { - message.setHeaderFlag(Message::HEADERFLAG_QR); - } - if ((message_flags & AA_FLAG) != 0) { - message.setHeaderFlag(Message::HEADERFLAG_AA); - } - if ((message_flags & RD_FLAG) != 0) { - message.setHeaderFlag(Message::HEADERFLAG_RD); - } - message.addQuestion(Question(Name("www.example.com"), RRClass::IN(), - qtype)); - - if (answer_data != NULL) { - RRsetPtr ans_rrset(new RRset(Name("www.example.com"), RRClass::IN(), - qtype, RRTTL(86400))); - for (auto const& it : *answer_data) { - ans_rrset->addRdata(createRdata(qtype, RRClass::IN(), it)); - } - message.addRRset(Message::SECTION_ANSWER, ans_rrset); - } - - message.toWire(renderer, &tsig_ctx); - vector<unsigned char> expected_data; - UnitTestUtil::readWireData(expected_file, expected_data); - matchWireData(&expected_data[0], expected_data.size(), - renderer.getData(), renderer.getLength()); -} - -TEST_F(MessageTest, toWireWithTSIG) { - // Rendering a message with TSIG. Various special cases specific to - // TSIG are tested in the tsig tests. We only check the message contains - // a TSIG at the end and the ARCOUNT of the header is updated. - - isc::util::detail::gettimeFunction = testGetTime<0x4da8877a>; - - message_render.setQid(0x2d65); - - { - SCOPED_TRACE("Message sign with TSIG"); - commonTSIGToWireCheck(message_render, renderer, tsig_ctx, - "message_toWire2.wire"); - } -} - -TEST_F(MessageTest, toWireWithEDNSAndTSIG) { - // Similar to the previous test, but with an EDNS before TSIG. - // The wire data check will confirm the ordering. - isc::util::detail::gettimeFunction = testGetTime<0x4db60d1f>; - - message_render.setQid(0x6cd); - - EDNSPtr edns(new EDNS()); - edns->setUDPSize(4096); - message_render.setEDNS(edns); - - { - SCOPED_TRACE("Message sign with TSIG and EDNS"); - commonTSIGToWireCheck(message_render, renderer, tsig_ctx, - "message_toWire3.wire"); - } -} - -// Some of the following tests involve truncation. We use the query name -// "www.example.com" and some TXT question/answers. The length of the -// header and question will be 33 bytes. If we also try to include a -// TSIG of the same key name (not compressed) with HMAC-MD5, the TSIG RR -// will be 85 bytes. - -// A long TXT RDATA. With a fully compressed owner name, the corresponding -// RR will be 268 bytes. -const char* const long_txt1 = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcde"; - -// With a fully compressed owner name, the corresponding RR will be 212 bytes. -// It should result in truncation even without TSIG (33 + 268 + 212 = 513) -const char* const long_txt2 = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456"; - -// With a fully compressed owner name, the corresponding RR will be 127 bytes. -// So, it can fit in the standard 512 bytes with txt1 and without TSIG, but -// adding a TSIG would result in truncation (33 + 268 + 127 + 85 = 513) -const char* const long_txt3 = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef01"; - -// This is 1 byte shorter than txt3, which will result in a possible longest -// message containing answer RRs and TSIG. -const char* const long_txt4 = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0"; - -// Example output generated by -// "dig -y www.example.com:SFuWd/q99SzF8Yzd1QbB9g== www.example.com txt -// QID: 0x22c2 -// Time Signed: 0x00004e179212 -TEST_F(MessageTest, toWireTSIGTruncation) { - isc::util::detail::gettimeFunction = testGetTime<0x4e179212>; - - // Verify a validly signed query so that we can use the TSIG context - - factoryFromFile(message_parse, "message_fromWire17.wire"); - EXPECT_EQ(TSIGError::NOERROR(), - tsig_ctx.verify(message_parse.getTSIGRecord(), - &received_data[0], received_data.size())); - - message_render.setQid(0x22c2); - vector<const char*> answer_data; - answer_data.push_back(long_txt1); - answer_data.push_back(long_txt2); - { - SCOPED_TRACE("Message sign with TSIG and TC bit on"); - commonTSIGToWireCheck(message_render, renderer, tsig_ctx, - "message_toWire4.wire", - QR_FLAG|AA_FLAG|RD_FLAG, - RRType::TXT(), &answer_data); - } -} - -TEST_F(MessageTest, toWireTSIGTruncation2) { - // Similar to the previous test, but without TSIG it wouldn't cause - // truncation. - isc::util::detail::gettimeFunction = testGetTime<0x4e179212>; - factoryFromFile(message_parse, "message_fromWire17.wire"); - EXPECT_EQ(TSIGError::NOERROR(), - tsig_ctx.verify(message_parse.getTSIGRecord(), - &received_data[0], received_data.size())); - - message_render.setQid(0x22c2); - vector<const char*> answer_data; - answer_data.push_back(long_txt1); - answer_data.push_back(long_txt3); - { - SCOPED_TRACE("Message sign with TSIG and TC bit on (2)"); - commonTSIGToWireCheck(message_render, renderer, tsig_ctx, - "message_toWire4.wire", - QR_FLAG|AA_FLAG|RD_FLAG, - RRType::TXT(), &answer_data); - } -} - -TEST_F(MessageTest, toWireTSIGTruncation3) { - // Similar to previous ones, but truncation occurs due to too many - // Questions (very unusual, but not necessarily illegal). - - // We are going to create a message starting with a standard - // header (12 bytes) and multiple questions in the Question - // section of the same owner name (changing the RRType, just so - // that it would be the form that would be accepted by the BIND 9 - // parser). The first Question is 21 bytes in length, and the subsequent - // ones are 6 bytes. We'll also use a TSIG whose size is 85 bytes. - // Up to 66 questions can fit in the standard 512-byte buffer - // (12 + 21 + 6 * 65 + 85 = 508). If we try to add one more it would - // result in truncation. - message_render.setOpcode(Opcode::QUERY()); - message_render.setRcode(Rcode::NOERROR()); - for (int i = 1; i <= 67; ++i) { - message_render.addQuestion(Question(Name("www.example.com"), - RRClass::IN(), RRType(i))); - } - 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. - // Checking the signature wouldn't be necessary for this rare case - // scenario. - InputBuffer buffer(renderer.getData(), renderer.getLength()); - message_parse.fromWire(buffer); - EXPECT_TRUE(message_parse.getHeaderFlag(Message::HEADERFLAG_TC)); - // Note that the number of questions are 66, not 67 as we tried to add. - EXPECT_EQ(66, message_parse.getRRCount(Message::SECTION_QUESTION)); - EXPECT_TRUE(message_parse.getTSIGRecord() != NULL); -} - -TEST_F(MessageTest, toWireTSIGNoTruncation) { - // A boundary case that shouldn't cause truncation: the resulting - // response message with a TSIG will be 512 bytes long. - isc::util::detail::gettimeFunction = testGetTime<0x4e17b38d>; - factoryFromFile(message_parse, "message_fromWire18.wire"); - EXPECT_EQ(TSIGError::NOERROR(), - tsig_ctx.verify(message_parse.getTSIGRecord(), - &received_data[0], received_data.size())); - - message_render.setQid(0xd6e2); - vector<const char*> answer_data; - answer_data.push_back(long_txt1); - answer_data.push_back(long_txt4); - { - SCOPED_TRACE("Message sign with TSIG, no truncation"); - commonTSIGToWireCheck(message_render, renderer, tsig_ctx, - "message_toWire5.wire", - QR_FLAG|AA_FLAG|RD_FLAG, - RRType::TXT(), &answer_data); - } -} - -// This is a buggy renderer for testing. It behaves like the straightforward -// MessageRenderer, but once it has some data, its setLengthLimit() ignores -// the given parameter and resets the limit to the current length, making -// subsequent insertion result in truncation, which would make TSIG RR -// rendering fail unexpectedly in the test that follows. -class BadRenderer : public MessageRenderer { -public: - virtual void setLengthLimit(size_t len) { - if (getLength() > 0) { - MessageRenderer::setLengthLimit(getLength()); - } else { - MessageRenderer::setLengthLimit(len); - } - } -}; - -TEST_F(MessageTest, toWireTSIGLengthErrors) { - // specify an unusual short limit that wouldn't be able to hold - // the TSIG. - renderer.setLengthLimit(tsig_ctx.getTSIGLength() - 1); - // Use commonTSIGToWireCheck() only to call toWire() with otherwise valid - // conditions. The checks inside it don't matter because we expect an - // exception before any of the checks. - EXPECT_THROW(commonTSIGToWireCheck(message_render, renderer, tsig_ctx, - "message_toWire2.wire"), - InvalidParameter); - - // This one is large enough for TSIG, but the remaining limit isn't - // even enough for the Header section. - renderer.clear(); - message_render.clear(Message::RENDER); - renderer.setLengthLimit(tsig_ctx.getTSIGLength() + 1); - EXPECT_THROW(commonTSIGToWireCheck(message_render, renderer, tsig_ctx, - "message_toWire2.wire"), - InvalidParameter); - - // Trying to render a message with TSIG using a buggy renderer. - BadRenderer bad_renderer; - bad_renderer.setLengthLimit(512); - message_render.clear(Message::RENDER); - EXPECT_THROW(commonTSIGToWireCheck(message_render, bad_renderer, tsig_ctx, - "message_toWire2.wire"), - Unexpected); -} - -TEST_F(MessageTest, toWireWithoutOpcode) { - message_render.setRcode(Rcode::NOERROR()); - EXPECT_THROW(message_render.toWire(renderer), InvalidMessageOperation); -} - -TEST_F(MessageTest, toWireWithoutRcode) { - message_render.setOpcode(Opcode::QUERY()); - EXPECT_THROW(message_render.toWire(renderer), InvalidMessageOperation); -} - -TEST_F(MessageTest, toText) { - // Check toText() output for a typical DNS response with records in - // all sections - - factoryFromFile(message_parse, "message_toText1.wire"); - { - SCOPED_TRACE("Message toText test (basic case)"); - ifstream ifs; - unittests::openTestData("message_toText1.txt", ifs); - unittests::matchTextData(ifs, message_parse.toText()); - } - - // Another example with EDNS. The expected data was slightly modified - // from the dig output (other than replacing tabs with a space): adding - // a newline after the "OPT PSEUDOSECTION". This is an intentional change - // in our version for better readability. - message_parse.clear(Message::PARSE); - factoryFromFile(message_parse, "message_toText2.wire"); - { - SCOPED_TRACE("Message toText test with EDNS"); - ifstream ifs; - unittests::openTestData("message_toText2.txt", ifs); - unittests::matchTextData(ifs, message_parse.toText()); - } - - // Another example with TSIG. The expected data was slightly modified - // from the dig output (other than replacing tabs with a space): removing - // a redundant white space at the end of TSIG RDATA. We'd rather consider - // it a dig's defect than a feature. - message_parse.clear(Message::PARSE); - factoryFromFile(message_parse, "message_toText3.wire"); - { - SCOPED_TRACE("Message toText test with TSIG"); - ifstream ifs; - unittests::openTestData("message_toText3.txt", ifs); - unittests::matchTextData(ifs, message_parse.toText()); - } -} - -TEST_F(MessageTest, toTextWithoutOpcode) { - message_render.setRcode(Rcode::NOERROR()); - EXPECT_THROW(message_render.toText(), InvalidMessageOperation); -} - -TEST_F(MessageTest, toTextWithoutRcode) { - message_render.setOpcode(Opcode::QUERY()); - EXPECT_THROW(message_render.toText(), InvalidMessageOperation); -} -} diff --git a/src/lib/dns/tests/messagerenderer_unittest.cc b/src/lib/dns/tests/messagerenderer_unittest.cc index c3a53eb6ca..8b13789179 100644 --- a/src/lib/dns/tests/messagerenderer_unittest.cc +++ b/src/lib/dns/tests/messagerenderer_unittest.cc @@ -1,292 +1 @@ -// Copyright (C) 2009-2017 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. -#include <config.h> - -#include <exceptions/exceptions.h> -#include <util/buffer.h> -#include <dns/name.h> -#include <dns/labelsequence.h> -#include <dns/messagerenderer.h> - -#include <dns/tests/unittest_util.h> -#include <util/unittests/wiredata.h> - -#include <gtest/gtest.h> - -#include <boost/lexical_cast.hpp> - -#include <string> -#include <vector> - -using isc::UnitTestUtil; -using isc::dns::Name; -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 { -protected: - MessageRendererTest() : expected_size(0) { - data16 = (2 << 8) | 3; - data32 = (4 << 24) | (5 << 16) | (6 << 8) | 7; - } - size_t expected_size; - uint16_t data16; - uint32_t data32; - MessageRenderer renderer; - std::vector<unsigned char> data; - static const uint8_t testdata[5]; -}; - -const uint8_t MessageRendererTest::testdata[5] = {1, 2, 3, 4, 5}; - -// The test cases are borrowed from those for the OutputBuffer class. -TEST_F(MessageRendererTest, writeInteger) { - renderer.writeUint16(data16); - expected_size += sizeof(data16); - - matchWireData(&testdata[1], sizeof(data16), - renderer.getData(), renderer.getLength()); -} - -TEST_F(MessageRendererTest, writeName) { - UnitTestUtil::readWireData("name_toWire1", data); - renderer.writeName(Name("a.example.com.")); - renderer.writeName(Name("b.example.com.")); - renderer.writeName(Name("a.example.org.")); - matchWireData(&data[0], data.size(), - renderer.getData(), renderer.getLength()); -} - -TEST_F(MessageRendererTest, writeNameInLargeBuffer) { - size_t offset = 0x3fff; - renderer.skip(offset); - - UnitTestUtil::readWireData("name_toWire2", data); - renderer.writeName(Name("a.example.com.")); - renderer.writeName(Name("a.example.com.")); - renderer.writeName(Name("b.example.com.")); - matchWireData(&data[0], data.size(), - static_cast<const uint8_t*>(renderer.getData()) + offset, - renderer.getLength() - offset); -} - -TEST_F(MessageRendererTest, writeNameWithUncompressed) { - UnitTestUtil::readWireData("name_toWire3", data); - renderer.writeName(Name("a.example.com.")); - renderer.writeName(Name("b.example.com."), false); - renderer.writeName(Name("b.example.com.")); - matchWireData(&data[0], data.size(), - renderer.getData(), renderer.getLength()); -} - -TEST_F(MessageRendererTest, writeNamePointerChain) { - UnitTestUtil::readWireData("name_toWire4", data); - renderer.writeName(Name("a.example.com.")); - renderer.writeName(Name("b.example.com.")); - renderer.writeName(Name("b.example.com.")); - matchWireData(&data[0], data.size(), - renderer.getData(), renderer.getLength()); -} - -TEST_F(MessageRendererTest, compressMode) { - // By default the render performs case insensitive compression. - EXPECT_EQ(MessageRenderer::CASE_INSENSITIVE, renderer.getCompressMode()); - - // The mode can be explicitly changed. - renderer.setCompressMode(MessageRenderer::CASE_SENSITIVE); - EXPECT_EQ(MessageRenderer::CASE_SENSITIVE, renderer.getCompressMode()); - renderer.setCompressMode(MessageRenderer::CASE_INSENSITIVE); - EXPECT_EQ(MessageRenderer::CASE_INSENSITIVE, renderer.getCompressMode()); - - // The clear() method resets the mode to the default. - renderer.setCompressMode(MessageRenderer::CASE_SENSITIVE); - renderer.clear(); - EXPECT_EQ(MessageRenderer::CASE_INSENSITIVE, renderer.getCompressMode()); -} - -TEST_F(MessageRendererTest, writeNameCaseCompress) { - // By default MessageRenderer performs case insensitive compression. - - UnitTestUtil::readWireData("name_toWire1", data); - renderer.writeName(Name("a.example.com.")); - // this should match the first name in terms of compression: - renderer.writeName(Name("b.exAmple.CoM.")); - renderer.writeName(Name("a.example.org.")); - matchWireData(&data[0], data.size(), - renderer.getData(), renderer.getLength()); -} - -TEST_F(MessageRendererTest, writeNameCaseSensitiveCompress) { - // name compression in case sensitive manner. See the data file - // description for details. - renderer.setCompressMode(MessageRenderer::CASE_SENSITIVE); - UnitTestUtil::readWireData("name_toWire5.wire", data); - renderer.writeName(Name("a.example.com.")); - renderer.writeName(Name("b.eXample.com.")); - renderer.writeName(Name("c.eXample.com.")); - matchWireData(&data[0], data.size(), - renderer.getData(), renderer.getLength()); -} - -TEST_F(MessageRendererTest, writeNameMixedCaseCompress) { - renderer.setCompressMode(MessageRenderer::CASE_SENSITIVE); - UnitTestUtil::readWireData("name_toWire6.wire", data); - renderer.writeName(Name("a.example.com.")); - renderer.writeName(Name("b.eXample.com.")); - - // Change the compression mode in the middle of rendering. This is not - // allowed in this implementation. - EXPECT_THROW(renderer.setCompressMode(MessageRenderer::CASE_INSENSITIVE), - isc::InvalidParameter); - - // Once the renderer is cleared, it's okay again. - renderer.clear(); - EXPECT_NO_THROW(renderer.setCompressMode( - MessageRenderer::CASE_INSENSITIVE)); -} - -TEST_F(MessageRendererTest, writeRootName) { - // root name is special: it never causes compression or can (reasonably) - // be a compression pointer. So it makes sense to check this case - // explicitly. - Name example_name = Name("www.example.com"); - - OutputBuffer expected(0); - expected.writeUint8(0); // root name - example_name.toWire(expected); - - renderer.writeName(Name(".")); - renderer.writeName(example_name); - matchWireData(static_cast<const uint8_t*>(expected.getData()), - expected.getLength(), - static_cast<const uint8_t*>(renderer.getData()), - renderer.getLength()); -} - -TEST_F(MessageRendererTest, writeNameLabelSequence1) { - UnitTestUtil::readWireData("name_toWire7", data); - - Name n1("a.example.com"); - LabelSequence ls1(n1); - - // a.example.com. - renderer.writeName(ls1); - - ls1.stripLeft(1); - - // example.com. - renderer.writeName(ls1); - - matchWireData(&data[0], data.size(), - renderer.getData(), renderer.getLength()); -} - -TEST_F(MessageRendererTest, writeNameLabelSequence2) { - UnitTestUtil::readWireData("name_toWire8", data); - - Name n1("a.example.com"); - LabelSequence ls1(n1); - - ls1.stripRight(1); - - // a.example.com (without root .) - renderer.writeName(ls1); - - matchWireData(&data[0], data.size(), - renderer.getData(), renderer.getLength()); -} - -TEST_F(MessageRendererTest, writeNameLabelSequence3) { - UnitTestUtil::readWireData("name_toWire9", data); - - Name n1("a.example.com"); - LabelSequence ls1(n1); - - // a.example.com. - renderer.writeName(ls1); - - ls1.stripRight(1); - - // a.example.com (without root .) - renderer.writeName(ls1); - - ls1.stripRight(1); - - // a.example - renderer.writeName(ls1); - - ls1.stripLeft(1); - - // example - renderer.writeName(ls1); - - matchWireData(&data[0], data.size(), - renderer.getData(), renderer.getLength()); -} - -TEST_F(MessageRendererTest, setBuffer) { - OutputBuffer new_buffer(0); - renderer.setBuffer(&new_buffer); - EXPECT_EQ(0, new_buffer.getLength()); // the buffer should be still empty - renderer.writeUint32(42); - EXPECT_EQ(sizeof(uint32_t), new_buffer.getLength()); - EXPECT_EQ(sizeof(uint32_t), renderer.getLength()); - - // Change some other internal state for the reset test below. - EXPECT_EQ(512, renderer.getLengthLimit()); - renderer.setLengthLimit(4096); - EXPECT_EQ(4096, renderer.getLengthLimit()); - - // Reset the buffer to the default again. Other internal states and - // resources should be cleared. The used buffer should be intact. - renderer.setBuffer(NULL); - EXPECT_EQ(sizeof(uint32_t), new_buffer.getLength()); - EXPECT_EQ(0, renderer.getLength()); - EXPECT_EQ(512, renderer.getLengthLimit()); -} - -TEST_F(MessageRendererTest, setBufferErrors) { - OutputBuffer new_buffer(0); - - // Buffer cannot be reset when the renderer is in use. - renderer.writeUint32(10); - EXPECT_THROW(renderer.setBuffer(&new_buffer), isc::InvalidParameter); - - renderer.clear(); - renderer.setBuffer(&new_buffer); - renderer.writeUint32(10); - EXPECT_THROW(renderer.setBuffer(&new_buffer), isc::InvalidParameter); - - // Resetting the buffer isn't allowed for the default buffer. - renderer.setBuffer(NULL); - EXPECT_THROW(renderer.setBuffer(NULL), isc::InvalidParameter); - - // It's okay to reset a temporary buffer without using it. - renderer.setBuffer(&new_buffer); - EXPECT_NO_THROW(renderer.setBuffer(NULL)); -} - -TEST_F(MessageRendererTest, manyRRs) { - // Render a large number of names, and the confirm the resulting wire - // data store the expected names in the correct order (1000 is an - // arbitrary choice). - for (size_t i = 0; i < 1000; ++i) { - renderer.writeName(Name(lexical_cast<std::string>(i) + ".example")); - } - isc::util::InputBuffer b(renderer.getData(), renderer.getLength()); - for (size_t i = 0; i < 1000; ++i) { - EXPECT_EQ(Name(lexical_cast<std::string>(i) + ".example"), Name(b)); - } - // This will trigger trimming excessive hash items. It shouldn't cause - // any disruption. - EXPECT_NO_THROW(renderer.clear()); -} -} diff --git a/src/lib/dns/tests/name_unittest.cc b/src/lib/dns/tests/name_unittest.cc index 636a403f38..8b13789179 100644 --- a/src/lib/dns/tests/name_unittest.cc +++ b/src/lib/dns/tests/name_unittest.cc @@ -1,794 +1 @@ -// Copyright (C) 2009-2024 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. -#include <config.h> - -#include <vector> -#include <string> -#include <sstream> -#include <iomanip> -#include <limits> -#include <stdexcept> - -#include <util/buffer.h> -#include <dns/exceptions.h> -#include <dns/name.h> -#include <dns/messagerenderer.h> - -#include <dns/tests/unittest_util.h> -#include <util/unittests/wiredata.h> - -#include <gtest/gtest.h> - -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 -// seemingly cannot find the symbols when used in the EXPECT_xxx macros. -// -const size_t Name::MAX_WIRE; -const size_t Name::MAX_LABELS; - -// This is a name of maximum allowed number of labels -const char* max_labels_str = "0.1.2.3.4.5.6.7.8.9.0.1.2.3.4.5.6.7.8.9." // 40 - "0.1.2.3.4.5.6.7.8.9.0.1.2.3.4.5.6.7.8.9." // 80 - "0.1.2.3.4.5.6.7.8.9.0.1.2.3.4.5.6.7.8.9." // 120 - "0.1.2.3.4.5.6.7.8.9.0.1.2.3.4.5.6.7.8.9." // 160 - "0.1.2.3.4.5.6.7.8.9.0.1.2.3.4.5.6.7.8.9." // 200 - "0.1.2.3.4.5.6.7.8.9.0.1.2.3.4.5.6.7.8.9." // 240 - "0.1.2.3.4.5.6"; -// This is a name of maximum allowed length -const char* max_len_str = "123456789.123456789.123456789.123456789.123456789." - "123456789.123456789.123456789.123456789.123456789." - "123456789.123456789.123456789.123456789.123456789." - "123456789.123456789.123456789.123456789.123456789." - "123456789.123456789.123456789.123456789.123456789." - "123"; - -namespace { -class NameTest : public ::testing::Test { -protected: - NameTest() : example_name("www.example.com"), - example_name_upper("WWW.EXAMPLE.COM"), - small_name("aaa.example.com"), - large_name("zzz.example.com"), - origin_name("example.com."), - origin_name_upper("EXAMPLE.COM"), - buffer_actual(0), buffer_expected(0) - {} - - const Name example_name; - Name example_name_upper; // this will be modified and cannot be const - const Name small_name; - const Name large_name; - const Name origin_name; - const Name origin_name_upper; - OutputBuffer buffer_actual, buffer_expected; - - // - // helper methods - // - static Name nameFactoryFromWire(const char* datafile, size_t position, - bool downcase = false); - // construct a name including all non-upper-case-alphabet characters. - static Name nameFactoryLowerCase(); - void compareInWireFormat(const Name& name_actual, - const Name& name_expected); -}; - -const Name downcased_global("\\255.EXAMPLE.COM", true); - -Name -NameTest::nameFactoryFromWire(const char* datafile, size_t position, - bool downcase) -{ - vector<unsigned char> data; - UnitTestUtil::readWireData(datafile, data); - - InputBuffer buffer(&data[0], data.size()); - buffer.setPosition(position); - - return (Name(buffer, downcase)); -} - -Name -NameTest::nameFactoryLowerCase() { - string lowercase_namestr; - lowercase_namestr.reserve(Name::MAX_WIRE); - - unsigned int ch = 0; - unsigned int labelcount = 0; - do { - if (ch < 'A' || ch > 'Z') { - ostringstream ss; - ss.setf(ios_base::right, ios_base::adjustfield); - ss.width(3); - ss << setfill('0') << ch; - lowercase_namestr += '\\' + ss.str(); - - if (++labelcount == Name::MAX_LABELLEN) { - lowercase_namestr.push_back('.'); - labelcount = 0; - } - } - } while (++ch <= Name::MAX_WIRE); - - return (Name(lowercase_namestr)); -} - -void -NameTest::compareInWireFormat(const Name& name_actual, - const Name& name_expected) -{ - buffer_actual.clear(); - buffer_expected.clear(); - - name_actual.toWire(buffer_actual); - name_expected.toWire(buffer_expected); - - matchWireData(buffer_expected.getData(), buffer_expected.getLength(), - buffer_actual.getData(), buffer_actual.getLength()); -} - -TEST_F(NameTest, nonlocalObject) { - // A previous version of code relied on a non local static object for - // name construction, so a non local static Name object defined outside - // the name module might not be initialized correctly. This test detects - // that kind of bug. - EXPECT_EQ("\\255.example.com.", downcased_global.toText()); -} - -template <typename ExceptionType> -void -checkBadTextName(const string& txt) { - // Check it results in the specified type of exception as well as - // NameParserException. - EXPECT_THROW(Name(txt, false), ExceptionType); - EXPECT_THROW(Name(txt, false), NameParserException); - // The same is thrown when constructing by the master-file constructor - EXPECT_THROW(Name(txt.c_str(), txt.length(), &Name::ROOT_NAME()), - ExceptionType); - EXPECT_THROW(Name(txt.c_str(), txt.length(), &Name::ROOT_NAME()), - NameParserException); -} - -TEST_F(NameTest, checkExceptionsHierarchy) { - EXPECT_NO_THROW({ - const isc::dns::EmptyLabel exception("", 0, ""); - const isc::dns::NameParserException& exception_cast = - dynamic_cast<const isc::dns::NameParserException&>(exception); - // to avoid compiler warning - exception_cast.what(); - }); - - EXPECT_NO_THROW({ - const isc::dns::TooLongName exception("", 0, ""); - const isc::dns::NameParserException& exception_cast = - dynamic_cast<const isc::dns::NameParserException&>(exception); - // to avoid compiler warning - exception_cast.what(); - }); - - EXPECT_NO_THROW({ - const isc::dns::TooLongLabel exception("", 0, ""); - const isc::dns::NameParserException& exception_cast = - dynamic_cast<const isc::dns::NameParserException&>(exception); - // to avoid compiler warning - exception_cast.what(); - }); - - EXPECT_NO_THROW({ - const isc::dns::BadLabelType exception("", 0, ""); - const isc::dns::NameParserException& exception_cast = - dynamic_cast<const isc::dns::NameParserException&>(exception); - // to avoid compiler warning - exception_cast.what(); - }); - - EXPECT_NO_THROW({ - const isc::dns::BadEscape exception("", 0, ""); - const isc::dns::NameParserException& exception_cast = - dynamic_cast<const isc::dns::NameParserException&>(exception); - // to avoid compiler warning - exception_cast.what(); - }); - - EXPECT_NO_THROW({ - const isc::dns::IncompleteName exception("", 0, ""); - const isc::dns::NameParserException& exception_cast = - dynamic_cast<const isc::dns::NameParserException&>(exception); - // to avoid compiler warning - exception_cast.what(); - }); - - EXPECT_NO_THROW({ - const isc::dns::MissingNameOrigin exception("", 0, ""); - const isc::dns::NameParserException& exception_cast = - dynamic_cast<const isc::dns::NameParserException&>(exception); - // to avoid compiler warning - exception_cast.what(); - }); -} - -TEST_F(NameTest, fromText) { - vector<string> strnames; - strnames.push_back("www.example.com"); - strnames.push_back("www.example.com."); // with a trailing dot - strnames.push_back("wWw.exAmpLe.com"); // mixed cases - strnames.push_back("\\wWw.exAmpLe.com"); // escape with a backslash - // decimal representation for "WWW" - strnames.push_back("\\087\\087\\087.example.com"); - - for (auto const& it : strnames) { - EXPECT_PRED_FORMAT2(UnitTestUtil::matchName, example_name, Name(it)); - } - - // root names - EXPECT_PRED_FORMAT2(UnitTestUtil::matchName, Name("@"), Name(".")); - - // downcase - EXPECT_EQ(Name("Www.eXample.coM", true).toText(), example_name.toText()); - - // - // Tests for bogus names. These should trigger exceptions. - // - // empty label cannot be followed by another label - checkBadTextName<EmptyLabel>(".a"); - // duplicate period - checkBadTextName<EmptyLabel>("a.."); - // label length must be < 64 - checkBadTextName<TooLongLabel>("012345678901234567890123456789" - "012345678901234567890123456789" - "0123"); - // now-unsupported bitstring labels - checkBadTextName<BadLabelType>("\\[b11010000011101]"); - // label length must be < 64 - checkBadTextName<TooLongLabel>("012345678901234567890123456789" - "012345678901234567890123456789" - "012\\x"); - // but okay as long as resulting len < 64 even if the original string is - // "too long" - EXPECT_NO_THROW(Name("012345678901234567890123456789" - "012345678901234567890123456789" - "01\\x")); - // incomplete \DDD pattern (exactly 3 D's must appear) - checkBadTextName<BadEscape>("\\12abc"); - // \DDD must not exceed 255 - checkBadTextName<BadEscape>("\\256"); - // Same tests for \111 as for \\x above - checkBadTextName<TooLongLabel>("012345678901234567890123456789" - "012345678901234567890123456789" - "012\\111"); - EXPECT_NO_THROW(Name("012345678901234567890123456789" - "012345678901234567890123456789" - "01\\111")); - // A domain name must be 255 octets or less - checkBadTextName<TooLongName>("123456789.123456789.123456789.123456789." - "123456789.123456789.123456789.123456789." - "123456789.123456789.123456789.123456789." - "123456789.123456789.123456789.123456789." - "123456789.123456789.123456789.123456789." - "123456789.123456789.123456789.123456789." - "123456789.1234"); - // This is a possible longest name and should be accepted - EXPECT_NO_THROW(Name(string(max_len_str))); - // \DDD must consist of 3 digits. - checkBadTextName<IncompleteName>("\\12"); - - // a name with the max number of labels. should be constructed without - // an error, and its length should be the max value. - Name maxlabels = Name(string(max_labels_str)); - EXPECT_EQ(Name::MAX_LABELS, maxlabels.getLabelCount()); -} - -// The following test uses a name data that was produced by -// fuzz testing and causes an unexpected condition in stringParser. -// Formerly this condition was trapped by an assert, but for -// robustness it has been replaced by a throw. -TEST_F(NameTest, unexpectedParseError) { - std::vector<uint8_t> badname { - 0xff,0xff,0x7f,0x00,0x00,0x00,0x7f,0x00,0x00,0x00,0x00, - 0x00,0x00,0x04,0x63,0x82,0x53,0x63,0x35,0x01,0x01,0x3d,0x07,0x01,0x00,0x00,0x00, - 0x00,0x00,0x00,0x19,0x0c,0x4e,0x01,0x00,0x07,0x08,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x35,0x01,0x05,0x3a,0x04,0x00,0x00,0x07,0x08,0x3b,0x04,0x00, - 0x00,0x2e,0x3b,0x04,0x00,0x19,0x2e,0x00,0x00,0x00,0x0a,0x00,0x12,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x0b,0x82,0x01,0xfc,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x35,0x01,0x05,0x3a,0x04,0x00,0x00,0x07,0x08,0x3b,0x04, - 0x00,0x00,0x2e,0x3b,0x04,0x00,0x19,0x2e,0x56,0x00,0x00,0x0a,0x00,0x12,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x0b,0x82,0x01,0xfc,0x42,0x00,0x00,0x00,0x00,0x19,0x0c, - 0x4e,0x01,0x05,0x3a,0x04,0xde,0x00,0x07,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x35,0x01,0x05,0x3a,0x07,0x08,0x3b,0x04,0x00,0x00,0x2e,0x3b,0x04, - 0x00,0x19,0x2e,0x56,0x40,0x00,0x00,0x00,0x00,0x00,0x0a,0x00,0x12,0x00,0x00,0x00, - 0x00,0x00,0x19,0x00,0x0b,0x82,0x01,0xfc,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x35,0x01,0x05,0xff,0xff,0x05,0x00,0x07,0x08,0x3b,0x04, - 0x00,0x00,0x2e,0x3b - }; - - std::string badnamestr(badname.begin(), badname.end()); - EXPECT_THROW(Name(badnamestr, false), Unexpected); -} - -// on the rest while we prepare it. -// Check the @ syntax is accepted and it just copies the origin. -TEST_F(NameTest, copyOrigin) { - EXPECT_EQ(origin_name, Name("@", 1, &origin_name)); - // The downcase works on the origin too. But only when we provide it. - EXPECT_EQ(origin_name, Name("@", 1, &origin_name_upper, true)); - EXPECT_EQ(origin_name_upper, Name("@", 1, &origin_name_upper, true)); - // If we don't provide the origin, it throws - EXPECT_THROW(Name("@", 1, NULL), MissingNameOrigin); -} - -// Test the master-file constructor does not append the origin when the -// provided name is absolute -TEST_F(NameTest, dontAppendOrigin) { - EXPECT_EQ(example_name, Name("www.example.com.", 16, &origin_name)); - // The downcase works (only if provided, though) - EXPECT_EQ(example_name, Name("WWW.EXAMPLE.COM.", 16, &origin_name, true)); - EXPECT_EQ(example_name_upper, Name("WWW.EXAMPLE.COM.", 16, &origin_name)); - // And it does not require the origin to be provided - EXPECT_NO_THROW(Name("www.example.com.", 16, NULL)); -} - -// Test the master-file constructor properly appends the origin when -// the provided name is relative. -TEST_F(NameTest, appendOrigin) { - EXPECT_EQ(example_name, Name("www", 3, &origin_name)); - // Check the downcase works (if provided) - EXPECT_EQ(example_name, Name("WWW", 3, &origin_name, true)); - EXPECT_EQ(example_name, Name("WWW", 3, &origin_name_upper, true)); - EXPECT_EQ(example_name_upper, Name("WWW", 3, &origin_name_upper)); - // Check we can prepend more than one label - EXPECT_EQ(Name("a.b.c.d.example.com."), Name("a.b.c.d", 7, &origin_name)); - // When the name is relative, we throw. - EXPECT_THROW(Name("www", 3, NULL), MissingNameOrigin); -} - -// When we don't provide the data, it throws -TEST_F(NameTest, noDataProvided) { - EXPECT_THROW(Name(NULL, 10, NULL), isc::InvalidParameter); - EXPECT_THROW(Name(NULL, 10, &origin_name), isc::InvalidParameter); - EXPECT_THROW(Name("www", 0, NULL), isc::InvalidParameter); - EXPECT_THROW(Name("www", 0, &origin_name), isc::InvalidParameter); -} - -// When we combine the first part and the origin together, the resulting name -// is too long. It should throw. Other test checks this is valid when alone -// (without the origin appended). -TEST_F(NameTest, combinedTooLong) { - EXPECT_THROW(Name(max_len_str, strlen(max_len_str), &origin_name), - TooLongName); - EXPECT_THROW(Name(max_labels_str, strlen(max_labels_str), &origin_name), - TooLongName); - // Appending the root should be OK - EXPECT_NO_THROW(Name(max_len_str, strlen(max_len_str), - &Name::ROOT_NAME())); - EXPECT_NO_THROW(Name(max_labels_str, strlen(max_labels_str), - &Name::ROOT_NAME())); -} - -// Test the handling of @ in the name. If it is alone, it is the origin (when -// it exists) or the root. If it is somewhere else, it has no special meaning. -TEST_F(NameTest, atSign) { - // If it is alone, it is the origin - EXPECT_EQ(origin_name, Name("@", 1, &origin_name)); - EXPECT_THROW(Name("@", 1, NULL), MissingNameOrigin); - EXPECT_EQ(Name::ROOT_NAME(), Name("@")); - - // It is not alone. It is taken verbatim. We check the name converted - // back to the textual form, since checking it against other name object - // may be wrong -- if we create it wrong the same way as the tested - // object. - EXPECT_EQ("\\@.", Name("@.").toText()); - EXPECT_EQ("\\@.", Name("@.", 2, NULL).toText()); - EXPECT_EQ("\\@something.", Name("@something").toText()); - EXPECT_EQ("something\\@.", Name("something@").toText()); - EXPECT_EQ("\\@x.example.com.", Name("@x", 2, &origin_name).toText()); - EXPECT_EQ("x\\@.example.com.", Name("x@", 2, &origin_name).toText()); - - // An escaped at-sign isn't active - EXPECT_EQ("\\@.", Name("\\@").toText()); - EXPECT_EQ("\\@.example.com.", Name("\\@", 2, &origin_name).toText()); -} - -TEST_F(NameTest, fromWire) { - // - // test cases derived from BIND9 tests. - // - // normal case with a compression pointer - EXPECT_PRED_FORMAT2(UnitTestUtil::matchName, - nameFactoryFromWire("name_fromWire1", 25), - Name("vix.com")); - // bogus label character (looks like a local compression pointer) - EXPECT_THROW(nameFactoryFromWire("name_fromWire2", 25), DNSMessageFORMERR); - // a bad compression pointer (too big) - EXPECT_THROW(nameFactoryFromWire("name_fromWire3_1", 25), - DNSMessageFORMERR); - // forward reference - EXPECT_THROW(nameFactoryFromWire("name_fromWire3_2", 25), - DNSMessageFORMERR); - // invalid name length - EXPECT_THROW(nameFactoryFromWire("name_fromWire4", 550), DNSMessageFORMERR); - - // skip test for from Wire5. It's for disabling decompression, but our - // implementation always allows it. - - // bad pointer (too big) - EXPECT_THROW(nameFactoryFromWire("name_fromWire6", 25), DNSMessageFORMERR); - // input ends unexpectedly - EXPECT_THROW(nameFactoryFromWire("name_fromWire7", 25), DNSMessageFORMERR); - // many hops of compression but valid. should succeed. - EXPECT_PRED_FORMAT2(UnitTestUtil::matchName, - nameFactoryFromWire("name_fromWire8", 383), - Name("vix.com")); - - // - // Additional test cases - // - - // large names, a long but valid one, and invalid (too long) one. - EXPECT_EQ(Name::MAX_WIRE, - nameFactoryFromWire("name_fromWire9", 0).getLength()); - EXPECT_THROW(nameFactoryFromWire("name_fromWire10", 0).getLength(), - DNSMessageFORMERR); - - // A name with possible maximum number of labels; awkward but valid - EXPECT_EQ(nameFactoryFromWire("name_fromWire11", 0).getLabelCount(), - Name::MAX_LABELS); - - // Wire format including an invalid label length - EXPECT_THROW(nameFactoryFromWire("name_fromWire12", 0), DNSMessageFORMERR); - - // converting upper-case letters to down-case - EXPECT_EQ("vix.com.", - nameFactoryFromWire("name_fromWire1", 25, true).toText()); - EXPECT_EQ(3, nameFactoryFromWire("name_fromWire1", 25).getLabelCount()); -} - -TEST_F(NameTest, copyConstruct) { - Name copy(example_name); - EXPECT_EQ(copy, example_name); - - // Check the copied data is valid even after the original is deleted - Name* copy2 = new Name(example_name); - Name copy3(*copy2); - delete copy2; - EXPECT_EQ(copy3, example_name); -} - -TEST_F(NameTest, assignment) { - Name copy("."); - copy = example_name; - EXPECT_EQ(copy, example_name); - - // Check if the copied data is valid even after the original is deleted - Name* copy2 = new Name(example_name); - Name copy3("."); - copy3 = *copy2; - delete copy2; - EXPECT_EQ(copy3, example_name); - - // Self assignment - copy = *© - EXPECT_EQ(example_name, copy); -} - -TEST_F(NameTest, toText) { - // tests derived from BIND9 - EXPECT_EQ("a.b.c.d", Name("a.b.c.d").toText(true)); - EXPECT_EQ("a.\\\\[[.c.d", Name("a.\\\\[\\[.c.d").toText(true)); - EXPECT_EQ("a.b.C.d.", Name("a.b.C.d").toText(false)); - EXPECT_EQ("a.b.", Name("a.b.").toText(false)); - - // test omit_final_dot. It's false by default. - EXPECT_EQ("a.b.c.d", Name("a.b.c.d.").toText(true)); - EXPECT_EQ(Name("a.b.").toText(false), Name("a.b.").toText()); - - // the root name is a special case: omit_final_dot will be ignored. - EXPECT_EQ(".", Name(".").toText(true)); - - // test all printable characters to see whether special characters are - // escaped while the others are intact. note that the conversion is - // implementation specific; for example, it's not invalid to escape a - // "normal" character such as 'a' with regard to the standard. - string all_printable("!\\\"#\\$%&'\\(\\)*+,-\\./0123456789:\\;<=>?\\@" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "[\\\\]^_.`abcdefghijklmnopqrstuvwxyz{|}~."); - EXPECT_EQ(all_printable, - nameFactoryFromWire("name_fromWire13", 0).toText()); - - string all_nonprintable( - "\\000\\001\\002\\003\\004\\005\\006\\007\\008\\009" - "\\010\\011\\012\\013\\014\\015\\016\\017\\018\\019" - "\\020\\021\\022\\023\\024\\025\\026\\027\\028\\029" - "\\030\\031\\032\\127\\128\\129" - "\\130\\131\\132\\133\\134\\135\\136\\137\\138\\139" - "\\140\\141\\142\\143\\144\\145\\146\\147\\148\\149" - "\\150\\151\\152\\153\\154\\155\\156." - "\\157\\158\\159" - "\\160\\161\\162\\163\\164\\165\\166\\167\\168\\169" - "\\170\\171\\172\\173\\174\\175\\176\\177\\178\\179" - "\\180\\181\\182\\183\\184\\185\\186\\187\\188\\189" - "\\190\\191\\192\\193\\194\\195\\196\\197\\198\\199" - "\\200\\201\\202\\203\\204\\205\\206\\207\\208\\209" - "\\210\\211\\212\\213\\214\\215\\216\\217\\218\\219." - "\\220\\221\\222\\223\\224\\225\\226\\227\\228\\229" - "\\230\\231\\232\\233\\234\\235\\236\\237\\238\\239" - "\\240\\241\\242\\243\\244\\245\\246\\247\\248\\249" - "\\250\\251\\252\\253\\254\\255."); - EXPECT_EQ(all_nonprintable, - nameFactoryFromWire("name_fromWire14", 0).toText()); -} - -TEST_F(NameTest, toWireBuffer) { - vector<unsigned char> data; - OutputBuffer buffer(0); - - UnitTestUtil::readWireData(string("01610376697803636f6d00"), data); - Name("a.vix.com.").toWire(buffer); - matchWireData(&data[0], data.size(), - buffer.getData(), buffer.getLength()); -} - -// -// We test various corner cases in Renderer tests, but add this test case -// to fill the code coverage gap. -// -TEST_F(NameTest, toWireRenderer) { - vector<unsigned char> data; - MessageRenderer renderer; - - UnitTestUtil::readWireData(string("01610376697803636f6d00"), data); - Name("a.vix.com.").toWire(renderer); - matchWireData(&data[0], data.size(), - renderer.getData(), renderer.getLength()); -} - -// -// Helper class to hold comparison test parameters. -// -struct CompareParameters { - CompareParameters(const Name& n1, const Name& n2, - NameComparisonResult::NameRelation r, int o, - unsigned int l) : - name1(n1), name2(n2), reln(r), order(o), labels(l) {} - static int normalizeOrder(int o) - { - if (o > 0) { - return (1); - } else if (o < 0) { - return (-1); - } - return (0); - } - Name name1; - Name name2; - NameComparisonResult::NameRelation reln; - int order; - unsigned int labels; -}; - -TEST_F(NameTest, compare) { - vector<CompareParameters> params; - params.push_back(CompareParameters(Name("c.d"), Name("a.b.c.d"), - NameComparisonResult::SUPERDOMAIN, - -1, 3)); - params.push_back(CompareParameters(Name("a.b.c.d"), Name("c.d"), - NameComparisonResult::SUBDOMAIN, 1, 3)); - params.push_back(CompareParameters(Name("a.b.c.d"), Name("c.d.e.f"), - NameComparisonResult::COMMONANCESTOR, - -1, 1)); - params.push_back(CompareParameters(Name("a.b.c.d"), Name("f.g.c.d"), - NameComparisonResult::COMMONANCESTOR, - -1, 3)); - params.push_back(CompareParameters(Name("a.b.c.d"), Name("A.b.C.d."), - NameComparisonResult::EQUAL, - 0, 5)); - - for (auto const& it : params) { - NameComparisonResult result = it.name1.compare(it.name2); - EXPECT_EQ(it.reln, result.getRelation()); - EXPECT_EQ(it.order, CompareParameters::normalizeOrder(result.getOrder())); - EXPECT_EQ(it.labels, result.getCommonLabels()); - } -} - -TEST_F(NameTest, equal) { - EXPECT_TRUE(example_name == Name("WWW.EXAMPLE.COM.")); - EXPECT_TRUE(example_name.equals(Name("WWW.EXAMPLE.COM."))); - EXPECT_TRUE(example_name != Name("www.example.org.")); - EXPECT_TRUE(example_name.nequals(Name("www.example.org."))); - // lengths don't match - EXPECT_TRUE(example_name != Name("www2.example.com.")); - EXPECT_TRUE(example_name.nequals(Name("www2.example.com."))); - // lengths are equal, but # of labels don't match (first test checks the - // prerequisite). - EXPECT_EQ(example_name.getLength(), Name("www\\.example.com.").getLength()); - EXPECT_TRUE(example_name != Name("www\\.example.com.")); - EXPECT_TRUE(example_name.nequals(Name("www\\.example.com."))); -} - -TEST_F(NameTest, isWildcard) { - EXPECT_FALSE(example_name.isWildcard()); - EXPECT_TRUE(Name("*.a.example.com").isWildcard()); - EXPECT_FALSE(Name("a.*.example.com").isWildcard()); -} - -TEST_F(NameTest, concatenate) { - NameComparisonResult result = - Name("aaa.www.example.com.").compare(Name("aaa").concatenate(example_name)); - EXPECT_EQ(NameComparisonResult::EQUAL, result.getRelation()); - - result = example_name.compare(Name(".").concatenate(example_name)); - EXPECT_EQ(NameComparisonResult::EQUAL, result.getRelation()); - - result = example_name.compare(example_name.concatenate(Name("."))); - EXPECT_EQ(NameComparisonResult::EQUAL, result.getRelation()); - - // concatenating two valid names would result in too long a name. - Name n1("123456789.123456789.123456789.123456789.123456789." - "123456789.123456789.123456789.123456789.123456789." - "123456789.123456789.123456789.123456789.123456789."); - Name n2("123456789.123456789.123456789.123456789.123456789." - "123456789.123456789.123456789.123456789.123456789." - "1234."); - EXPECT_THROW(n1.concatenate(n2), TooLongName); -} - -TEST_F(NameTest, reverse) { - EXPECT_PRED_FORMAT2(UnitTestUtil::matchName, example_name.reverse(), - Name("com.example.www.")); - EXPECT_PRED_FORMAT2(UnitTestUtil::matchName, Name(".").reverse(), - Name(".")); - EXPECT_PRED_FORMAT2(UnitTestUtil::matchName, - Name("a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s").reverse(), - Name("s.r.q.p.o.n.m.l.k.j.i.h.g.f.e.d.c.b.a")); -} - -TEST_F(NameTest, split) { - // normal cases with or without explicitly specifying the trailing dot. - EXPECT_PRED_FORMAT2(UnitTestUtil::matchName, example_name.split(1, 2), - Name("example.com.")); - EXPECT_PRED_FORMAT2(UnitTestUtil::matchName, example_name.split(1, 3), - Name("example.com.")); - // edge cases: only the first or last label. - EXPECT_PRED_FORMAT2(UnitTestUtil::matchName, example_name.split(0, 1), - Name("www.")); - EXPECT_PRED_FORMAT2(UnitTestUtil::matchName, example_name.split(3, 1), - Name(".")); - // invalid range: an exception should be thrown. - EXPECT_THROW(example_name.split(1, 0), OutOfRange); - EXPECT_THROW(example_name.split(2, 3), OutOfRange); - - // invalid range: the following parameters would cause overflow, - // bypassing naive validation. - EXPECT_THROW(example_name.split(1, numeric_limits<unsigned int>::max()), - OutOfRange); -} - -TEST_F(NameTest, split_for_suffix) { - EXPECT_PRED_FORMAT2(UnitTestUtil::matchName, example_name.split(1), - Name("example.com")); - EXPECT_PRED_FORMAT2(UnitTestUtil::matchName, example_name.split(0), - example_name); - EXPECT_PRED_FORMAT2(UnitTestUtil::matchName, example_name.split(3), - Name(".")); - - // Invalid case: the level must be less than the original label count. - EXPECT_THROW(example_name.split(4), OutOfRange); -} - -TEST_F(NameTest, downcase) { - // usual case: all-upper case name to all-lower case - compareInWireFormat(example_name_upper.downcase(), example_name); - // confirm that non upper-case characters are intact - compareInWireFormat(nameFactoryLowerCase().downcase(), - nameFactoryLowerCase()); - // confirm the calling object is actually modified - example_name_upper.downcase(); - compareInWireFormat(example_name_upper, example_name); -} - -TEST_F(NameTest, at) { - // Confirm at() produces the exact sequence of wire-format name data - vector<uint8_t> data; - - for (size_t i = 0; i < example_name.getLength(); i++) { - data.push_back(example_name.at(i)); - } - - example_name.toWire(buffer_expected); - 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); -} - -// -// The following set of tests confirm the result of <=, <, >=, > -// The test logic is simple, and all tests are just straightforward variations -// of the first one. -// -TEST_F(NameTest, leq) { - // small <= large is true - EXPECT_TRUE(small_name.leq(large_name)); - EXPECT_TRUE(small_name <= large_name); - - // small <= small is true - EXPECT_TRUE(small_name.leq(small_name)); - EXPECT_LE(small_name, small_name); - - // large <= small is false - EXPECT_FALSE(large_name.leq(small_name)); - EXPECT_FALSE(large_name <= small_name); -} - -TEST_F(NameTest, geq) { - EXPECT_TRUE(large_name.geq(small_name)); - EXPECT_TRUE(large_name >= small_name); - - EXPECT_TRUE(large_name.geq(large_name)); - EXPECT_GE(large_name, large_name); - - EXPECT_FALSE(small_name.geq(large_name)); - EXPECT_FALSE(small_name >= large_name); -} - -TEST_F(NameTest, lthan) { - EXPECT_TRUE(small_name.lthan(large_name)); - EXPECT_TRUE(small_name < large_name); - - EXPECT_FALSE(small_name.lthan(small_name)); - // cppcheck-suppress duplicateExpression - EXPECT_FALSE(small_name < small_name); - - EXPECT_FALSE(large_name.lthan(small_name)); - EXPECT_FALSE(large_name < small_name); -} - -TEST_F(NameTest, gthan) { - EXPECT_TRUE(large_name.gthan(small_name)); - EXPECT_TRUE(large_name > small_name); - - EXPECT_FALSE(large_name.gthan(large_name)); - // cppcheck-suppress duplicateExpression - EXPECT_FALSE(large_name > large_name); - - EXPECT_FALSE(small_name.gthan(large_name)); - EXPECT_FALSE(small_name > large_name); -} - -TEST_F(NameTest, constants) { - EXPECT_EQ(Name("."), Name::ROOT_NAME()); -} - -// test operator<<. We simply confirm it appends the result of toText(). -TEST_F(NameTest, LeftShiftOperator) { - ostringstream oss; - oss << example_name; - EXPECT_EQ(example_name.toText(), oss.str()); -} - -// The following verifies that toRawText() returns a string -// actual characters in place of escape sequences. We do not -// bother with an exhaustive set of tests here as this is -// not a primary use case. -TEST_F(NameTest, toRawText) { - Name n("a bc.$exa(m)ple.@org"); - EXPECT_EQ("a bc.$exa(m)ple.@org", n.toRawText(true)); - EXPECT_EQ("a bc.$exa(m)ple.@org.", n.toRawText(false)); - // Verify default value of omit parameter is false. - EXPECT_EQ("a bc.$exa(m)ple.@org.", n.toRawText()); -} - -} diff --git a/src/lib/dns/tests/nsec3hash_unittest.cc b/src/lib/dns/tests/nsec3hash_unittest.cc index 39c8271d5f..8b13789179 100644 --- a/src/lib/dns/tests/nsec3hash_unittest.cc +++ b/src/lib/dns/tests/nsec3hash_unittest.cc @@ -1,269 +1 @@ -// Copyright (C) 2012-2024 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. -#include <config.h> - -#include <string> - -#include <gtest/gtest.h> - -#include <boost/scoped_ptr.hpp> - -#include <dns/nsec3hash.h> -#include <dns/labelsequence.h> -#include <dns/rdataclass.h> -#include <util/encode/encode.h> - -using boost::scoped_ptr; -using namespace std; -using namespace isc::dns; -using namespace isc::dns::rdata; -using namespace isc::util; -using namespace isc::util::encode; - -namespace { -typedef scoped_ptr<NSEC3Hash> NSEC3HashPtr; - -// Commonly used NSEC3 suffix, defined to reduce the amount of typing -const char* const nsec3_common = "2T7B4G4VSA5SMI47K61MV5BV1A22BOJR A RRSIG"; - -class NSEC3HashTest : public ::testing::Test { -protected: - NSEC3HashTest() : - test_hash(NSEC3Hash::create(generic::NSEC3PARAM("1 0 12 aabbccdd"))), - test_hash_nsec3(NSEC3Hash::create(generic::NSEC3 - ("1 0 12 aabbccdd " + - string(nsec3_common)))) - { - const uint8_t salt[] = {0xaa, 0xbb, 0xcc, 0xdd}; - test_hash_args.reset(NSEC3Hash::create(1, 12, salt, sizeof(salt))); - } - - ~NSEC3HashTest() { - // Make sure we reset the hash creator to the default - setNSEC3HashCreator(NULL); - } - - // An NSEC3Hash object commonly used in tests. Parameters are borrowed - // from the RFC5155 example. Construction of this object implicitly - // checks a successful case of the creation. - NSEC3HashPtr test_hash; - - // Similar to test_hash, but created from NSEC3 RR. - NSEC3HashPtr test_hash_nsec3; - - // Similar to test_hash, but created from passed args. - NSEC3HashPtr test_hash_args; -}; - -TEST_F(NSEC3HashTest, unknownAlgorithm) { - EXPECT_THROW(NSEC3HashPtr( - NSEC3Hash::create( - generic::NSEC3PARAM("2 0 12 aabbccdd"))), - UnknownNSEC3HashAlgorithm); - EXPECT_THROW(NSEC3HashPtr( - NSEC3Hash::create( - generic::NSEC3("2 0 12 aabbccdd " + - string(nsec3_common)))), - UnknownNSEC3HashAlgorithm); - - const uint8_t salt[] = {0xaa, 0xbb, 0xcc, 0xdd}; - EXPECT_THROW(NSEC3HashPtr(NSEC3Hash::create(2, 12, salt, sizeof(salt))), - UnknownNSEC3HashAlgorithm); -} - -// Common checks for NSEC3 hash calculation -void -calculateCheck(NSEC3Hash& hash) { - // A couple of normal cases from the RFC5155 example. - EXPECT_EQ("0P9MHAVEQVM6T7VBL5LOP2U3T2RP3TOM", - hash.calculate(Name("example"))); - EXPECT_EQ("35MTHGPGCU1QG68FAB165KLNSNK3DPVL", - hash.calculate(Name("a.example"))); - - // 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) { - { - SCOPED_TRACE("calculate check with NSEC3PARAM based hash"); - calculateCheck(*test_hash); - } - { - SCOPED_TRACE("calculate check with NSEC3 based hash"); - calculateCheck(*test_hash_nsec3); - } - { - SCOPED_TRACE("calculate check with args based hash"); - calculateCheck(*test_hash_args); - } - - // Some boundary cases: 0-iteration and empty salt. Borrowed from the - // .com zone data. - 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(LabelSequence(Name("example.org")))); -} - -// Common checks for match cases -template <typename RDATAType> -void -matchCheck(NSEC3Hash& hash, const string& postfix) { - // If all parameters match, it's considered to be matched. - EXPECT_TRUE(hash.match(RDATAType("1 0 12 aabbccdd" + postfix))); - - // Algorithm doesn't match - EXPECT_FALSE(hash.match(RDATAType("2 0 12 aabbccdd" + postfix))); - // Iterations doesn't match - EXPECT_FALSE(hash.match(RDATAType("1 0 1 aabbccdd" + postfix))); - // Salt doesn't match - EXPECT_FALSE(hash.match(RDATAType("1 0 12 aabbccde" + postfix))); - // Salt doesn't match: the other has an empty salt - EXPECT_FALSE(hash.match(RDATAType("1 0 12 -" + postfix))); - // Flags don't matter - EXPECT_TRUE(hash.match(RDATAType("1 1 12 aabbccdd" + postfix))); -} - -TEST_F(NSEC3HashTest, matchWithNSEC3) { - { - SCOPED_TRACE("match NSEC3PARAM based hash against NSEC3 parameters"); - matchCheck<generic::NSEC3>(*test_hash, " " + string(nsec3_common)); - } - { - SCOPED_TRACE("match NSEC3 based hash against NSEC3 parameters"); - matchCheck<generic::NSEC3>(*test_hash_nsec3, - " " + string(nsec3_common)); - } -} - -TEST_F(NSEC3HashTest, matchWithNSEC3PARAM) { - { - SCOPED_TRACE("match NSEC3PARAM based hash against NSEC3 parameters"); - matchCheck<generic::NSEC3PARAM>(*test_hash, ""); - } - { - SCOPED_TRACE("match NSEC3 based hash against NSEC3 parameters"); - matchCheck<generic::NSEC3PARAM>(*test_hash_nsec3, ""); - } -} - -// A simple faked hash calculator and a dedicated creator for it. -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); - } - virtual bool match(const generic::NSEC3&) const { - return (true); - } -}; - -// This faked creator basically creates the faked calculator regardless of -// the passed NSEC3PARAM or NSEC3. But if the most significant bit of flags -// is set, it will behave like the default creator. -class TestNSEC3HashCreator : public NSEC3HashCreator { -public: - virtual NSEC3Hash* create(const generic::NSEC3PARAM& param) const { - if ((param.getFlags() & 0x80) != 0) { - return (default_creator_.create(param)); - } - return (new TestNSEC3Hash); - } - virtual NSEC3Hash* create(const generic::NSEC3& nsec3) const { - if ((nsec3.getFlags() & 0x80) != 0) { - return (default_creator_.create(nsec3)); - } - return (new TestNSEC3Hash); - } - virtual NSEC3Hash* create(uint8_t, uint16_t, - const uint8_t*, size_t) const { - isc_throw(isc::Unexpected, - "This method is not implemented here."); - } -private: - DefaultNSEC3HashCreator default_creator_; -}; - -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; - setNSEC3HashCreator(&test_creator); - // Re-create the hash object with the new creator - 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. - test_hash.reset(NSEC3Hash::create(generic::NSEC3PARAM( - "1 128 12 aabbccdd"))); - EXPECT_EQ("0P9MHAVEQVM6T7VBL5LOP2U3T2RP3TOM", - test_hash->calculate(Name("example"))); - EXPECT_EQ("0P9MHAVEQVM6T7VBL5LOP2U3T2RP3TOM", - test_hash->calculate(LabelSequence(Name("example")))); - test_hash.reset(NSEC3Hash::create(generic::NSEC3 - ("1 128 12 aabbccdd " + - string(nsec3_common)))); - EXPECT_EQ("0P9MHAVEQVM6T7VBL5LOP2U3T2RP3TOM", - test_hash->calculate(Name("example"))); - EXPECT_EQ("0P9MHAVEQVM6T7VBL5LOP2U3T2RP3TOM", - test_hash->calculate(LabelSequence(Name("example")))); - - // Reset the creator to default, and confirm that - setNSEC3HashCreator(NULL); - test_hash.reset(NSEC3Hash::create(generic::NSEC3PARAM("1 0 12 aabbccdd"))); - EXPECT_EQ("0P9MHAVEQVM6T7VBL5LOP2U3T2RP3TOM", - test_hash->calculate(Name("example"))); - EXPECT_EQ("0P9MHAVEQVM6T7VBL5LOP2U3T2RP3TOM", - test_hash->calculate(LabelSequence(Name("example")))); -} - -} // end namespace diff --git a/src/lib/dns/tests/opcode_unittest.cc b/src/lib/dns/tests/opcode_unittest.cc index 9bc60b5b7e..8b13789179 100644 --- a/src/lib/dns/tests/opcode_unittest.cc +++ b/src/lib/dns/tests/opcode_unittest.cc @@ -1,100 +1 @@ -// Copyright (C) 2010-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. -#include <config.h> - -#include <vector> -#include <sstream> - -#include <exceptions/exceptions.h> - -#include <dns/opcode.h> - -#include <gtest/gtest.h> - -using namespace std; -using namespace isc::dns; - -namespace { -TEST(OpcodeTest, construct) { - // This test also tests getCode() - EXPECT_EQ(0, Opcode(0).getCode()); - EXPECT_EQ(15, Opcode(Opcode::RESERVED15_CODE).getCode()); - - EXPECT_THROW(Opcode(16), isc::OutOfRange); -} - -TEST(OpcodeTest, constants) { - // We'll only test arbitrarily chosen subsets of the codes. - // This class is quite simple, so it should be suffice. - - EXPECT_EQ(Opcode::QUERY_CODE, Opcode(0).getCode()); - EXPECT_EQ(Opcode::IQUERY_CODE, Opcode(1).getCode()); - EXPECT_EQ(Opcode::NOTIFY_CODE, Opcode(4).getCode()); - EXPECT_EQ(Opcode::UPDATE_CODE, Opcode(5).getCode()); - EXPECT_EQ(Opcode::RESERVED15_CODE, Opcode(15).getCode()); - - EXPECT_EQ(Opcode::QUERY_CODE, Opcode::QUERY().getCode()); - EXPECT_EQ(Opcode::IQUERY_CODE, Opcode::IQUERY().getCode()); - EXPECT_EQ(Opcode::NOTIFY_CODE, Opcode::NOTIFY().getCode()); - EXPECT_EQ(Opcode::UPDATE_CODE, Opcode::UPDATE().getCode()); - EXPECT_EQ(Opcode::RESERVED15_CODE, Opcode::RESERVED15().getCode()); -} - -TEST(OpcodeTest, equal) { - EXPECT_TRUE(Opcode::QUERY() == Opcode(Opcode::QUERY_CODE)); - EXPECT_TRUE(Opcode::QUERY().equals(Opcode(Opcode::QUERY_CODE))); - EXPECT_TRUE(Opcode::IQUERY() == Opcode(Opcode::IQUERY_CODE)); - EXPECT_TRUE(Opcode::IQUERY().equals(Opcode(Opcode::IQUERY_CODE))); - EXPECT_TRUE(Opcode::NOTIFY() == Opcode(Opcode::NOTIFY_CODE)); - EXPECT_TRUE(Opcode::NOTIFY().equals(Opcode(Opcode::NOTIFY_CODE))); - EXPECT_TRUE(Opcode::UPDATE() == Opcode(Opcode::UPDATE_CODE)); - EXPECT_TRUE(Opcode::UPDATE().equals(Opcode(Opcode::UPDATE_CODE))); - EXPECT_TRUE(Opcode::RESERVED15() == Opcode(Opcode::RESERVED15())); - EXPECT_TRUE(Opcode::RESERVED15().equals(Opcode(Opcode::RESERVED15()))); -} - -TEST(OpcodeTest, nequal) { - EXPECT_TRUE(Opcode::QUERY() != Opcode::IQUERY()); - EXPECT_TRUE(Opcode::QUERY().nequals(Opcode::IQUERY())); - EXPECT_TRUE(Opcode::NOTIFY() != Opcode(1)); - EXPECT_TRUE(Opcode::NOTIFY().nequals(Opcode(1))); - EXPECT_TRUE(Opcode(10) != Opcode(11)); - EXPECT_TRUE(Opcode(10).nequals(Opcode(11))); -} - -TEST(OpcodeTest, toText) { - vector<const char*> expects; - expects.resize(Opcode::RESERVED15_CODE + 1); - expects[Opcode::QUERY_CODE] = "QUERY"; - expects[Opcode::IQUERY_CODE] = "IQUERY"; - expects[Opcode::STATUS_CODE] = "STATUS"; - expects[Opcode::RESERVED3_CODE] = "RESERVED3"; - expects[Opcode::NOTIFY_CODE] = "NOTIFY"; - expects[Opcode::UPDATE_CODE] = "UPDATE"; - expects[Opcode::RESERVED6_CODE] = "RESERVED6"; - expects[Opcode::RESERVED7_CODE] = "RESERVED7"; - expects[Opcode::RESERVED8_CODE] = "RESERVED8"; - expects[Opcode::RESERVED9_CODE] = "RESERVED9"; - expects[Opcode::RESERVED10_CODE] = "RESERVED10"; - expects[Opcode::RESERVED11_CODE] = "RESERVED11"; - expects[Opcode::RESERVED12_CODE] = "RESERVED12"; - expects[Opcode::RESERVED13_CODE] = "RESERVED13"; - expects[Opcode::RESERVED14_CODE] = "RESERVED14"; - expects[Opcode::RESERVED15_CODE] = "RESERVED15"; - - for (unsigned int i = 0; i <= Opcode::RESERVED15_CODE; ++i) { - EXPECT_EQ(expects.at(i), Opcode(i).toText()); - } -} - -// test operator<<. We simply confirm it appends the result of toText(). -TEST(OpcodeTest, LeftShiftOperator) { - ostringstream oss; - oss << Opcode::NOTIFY(); - EXPECT_EQ(Opcode::NOTIFY().toText(), oss.str()); -} -} diff --git a/src/lib/dns/tests/qid_gen_unittest.cc b/src/lib/dns/tests/qid_gen_unittest.cc index 20a2dfa131..8b13789179 100644 --- a/src/lib/dns/tests/qid_gen_unittest.cc +++ b/src/lib/dns/tests/qid_gen_unittest.cc @@ -1,39 +1 @@ -// Copyright (C) 2011-2021 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. -/// \brief Test of QidGenerator -/// - -#include <config.h> - -#include <gtest/gtest.h> - -#include <dns/qid_gen.h> - -using namespace isc::dns; - -// Tests the operation of the Qid generator - -// Check that getInstance returns a singleton -TEST(QidGenerator, singleton) { - QidGenerator& g1 = QidGenerator::getInstance(); - QidGenerator& g2 = QidGenerator::getInstance(); - - EXPECT_TRUE(&g1 == &g2); -} - -TEST(QidGenerator, generate) { - // We'll assume that cryptolink's generator is 'good enough', and won't - // do full statistical checking here. Let's just call it the xkcd - // test (http://xkcd.com/221/), and check if three consecutive - // generates are not all the same. - uint16_t one, two, three; - QidGenerator& gen = QidGenerator::getInstance(); - one = gen.generateQid(); - two = gen.generateQid(); - three = gen.generateQid(); - ASSERT_FALSE((one == two) && (one == three)); -} diff --git a/src/lib/dns/tests/question_unittest.cc b/src/lib/dns/tests/question_unittest.cc index 03d31b1018..8b13789179 100644 --- a/src/lib/dns/tests/question_unittest.cc +++ b/src/lib/dns/tests/question_unittest.cc @@ -1,196 +1 @@ -// Copyright (C) 2010-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. -#include <config.h> - -#include <vector> -#include <sstream> - -#include <exceptions/exceptions.h> - -#include <util/buffer.h> -#include <dns/exceptions.h> -#include <dns/messagerenderer.h> -#include <dns/name.h> -#include <dns/question.h> -#include <dns/rrclass.h> -#include <dns/rrtype.h> - -#include <gtest/gtest.h> - -#include <dns/tests/unittest_util.h> -#include <util/unittests/wiredata.h> - -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 { -protected: - QuestionTest() : obuffer(0), - example_name1(Name("foo.example.com")), - example_name2(Name("bar.example.com")), - test_question1(example_name1, RRClass::IN(), - RRType::NS()), - test_question2(example_name2, RRClass::CH(), - RRType::A()) - {} - OutputBuffer obuffer; - MessageRenderer renderer; - Name example_name1; - Name example_name2; - Question test_question1; - Question test_question2; - vector<unsigned char> wiredata; -}; - -Question -questionFromWire(const char* datafile, size_t position = 0) { - vector<unsigned char> data; - UnitTestUtil::readWireData(datafile, data); - - InputBuffer buffer(&data[0], data.size()); - buffer.setPosition(position); - - return (Question(buffer)); -} - -TEST_F(QuestionTest, fromWire) { - Question q = questionFromWire("question_fromWire"); - - EXPECT_EQ(example_name1, q.getName()); - EXPECT_EQ(RRClass::IN(), q.getClass()); - EXPECT_EQ(RRType::NS(), q.getType()); - - // owner name of the second Question is compressed. It's uncommon - // (to have multiple questions), but isn't prohibited by the protocol. - q = questionFromWire("question_fromWire", 21); - EXPECT_EQ(example_name2, q.getName()); - EXPECT_EQ(RRClass::CH(), q.getClass()); - EXPECT_EQ(RRType::A(), q.getType()); - - // Pathological cases: Corresponding exceptions will be thrown from - // the underlying parser. - EXPECT_THROW(questionFromWire("question_fromWire", 31), DNSMessageFORMERR); - EXPECT_THROW(questionFromWire("question_fromWire", 36), IncompleteRRClass); -} - -TEST_F(QuestionTest, toText) { - EXPECT_EQ("foo.example.com. IN NS", test_question1.toText()); - EXPECT_EQ("bar.example.com. CH A", test_question2.toText()); - - EXPECT_EQ("foo.example.com. IN NS", test_question1.toText(false)); - EXPECT_EQ("bar.example.com. CH A", test_question2.toText(false)); - - EXPECT_EQ("foo.example.com. IN NS\n", test_question1.toText(true)); - EXPECT_EQ("bar.example.com. CH A\n", test_question2.toText(true)); -} - -TEST_F(QuestionTest, toWireBuffer) { - test_question1.toWire(obuffer); - test_question2.toWire(obuffer); - UnitTestUtil::readWireData("question_toWire1", wiredata); - 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); - matchWireData(&wiredata[0], wiredata.size(), - renderer.getData(), renderer.getLength()); -} - -TEST_F(QuestionTest, toWireTruncated) { - // If the available length in the renderer is too small, it would require - // truncation. This won't happen in normal cases, but protocol wise it - // could still happen if and when we support some (possibly future) opcode - // that allows multiple questions. - - // Set the length limit to the qname length so that the whole question - // would request truncated - renderer.setLengthLimit(example_name1.getLength()); - - EXPECT_FALSE(renderer.isTruncated()); // check pre-render condition - EXPECT_EQ(0, test_question1.toWire(renderer)); - EXPECT_TRUE(renderer.isTruncated()); - EXPECT_EQ(0, renderer.getLength()); // renderer shouldn't have any data -} - -// test operator<<. We simply confirm it appends the result of toText(). -TEST_F(QuestionTest, LeftShiftOperator) { - ostringstream oss; - oss << test_question1; - EXPECT_EQ(test_question1.toText(), oss.str()); -} - -TEST_F(QuestionTest, comparison) { - const Name a("a"), b("b"); - const RRClass in(RRClass::IN()), ch(RRClass::CH()); - const RRType ns(RRType::NS()), aaaa(RRType::AAAA()); - - EXPECT_TRUE(Question(a, in, ns) < Question(a, in, aaaa)); - EXPECT_FALSE(Question(a, in, aaaa) < Question(a, in, ns)); - - EXPECT_TRUE(Question(a, in, ns) < Question(a, ch, ns)); - EXPECT_FALSE(Question(a, ch, ns) < Question(a, in, ns)); - - EXPECT_TRUE(Question(a, in, ns) < Question(a, ch, aaaa)); - EXPECT_FALSE(Question(a, ch, aaaa) < Question(a, in, ns)); - - EXPECT_TRUE(Question(a, in, ns) < Question(b, in, ns)); - EXPECT_FALSE(Question(a, in, ns) < Question(a, in, ns)); - - EXPECT_TRUE(Question(a, in, ns) < Question(b, ch, ns)); - EXPECT_FALSE(Question(b, ch, ns) < Question(a, in, ns)); - - EXPECT_TRUE(Question(a, in, ns) < Question(b, ch, aaaa)); - EXPECT_FALSE(Question(b, ch, aaaa) < Question(a, in, ns)); - - EXPECT_FALSE(Question(a, in, ns) < Question(a, in, ns)); - EXPECT_FALSE(Question(a, ch, ns) < Question(a, ch, ns)); - EXPECT_FALSE(Question(b, in, ns) < Question(b, in, ns)); - EXPECT_FALSE(Question(b, in, aaaa) < Question(b, in, aaaa)); - - // Identical questions are equal - - EXPECT_TRUE(Question(a, in, ns) == Question(a, in, ns)); - EXPECT_FALSE(Question(a, in, ns) != Question(a, in, ns)); - - // Components differing by one component are unequal... - - EXPECT_FALSE(Question(b, in, ns) == Question(a, in, ns)); - EXPECT_TRUE(Question(b, in, ns) != Question(a, in, ns)); - - EXPECT_FALSE(Question(a, ch, ns) == Question(a, in, ns)); - EXPECT_TRUE(Question(a, ch, ns) != Question(a, in, ns)); - - EXPECT_FALSE(Question(a, in, aaaa) == Question(a, in, ns)); - EXPECT_TRUE(Question(a, in, aaaa) != Question(a, in, ns)); - - // ... as are those differing by two components - - EXPECT_FALSE(Question(b, ch, ns) == Question(a, in, ns)); - EXPECT_TRUE(Question(b, ch, ns) != Question(a, in, ns)); - - EXPECT_FALSE(Question(b, in, aaaa) == Question(a, in, ns)); - EXPECT_TRUE(Question(b, in, aaaa) != Question(a, in, ns)); - - EXPECT_FALSE(Question(a, ch, aaaa) == Question(a, in, ns)); - EXPECT_TRUE(Question(a, ch, aaaa) != Question(a, in, ns)); - - // ... and question differing by all three - - EXPECT_FALSE(Question(b, ch, aaaa) == Question(a, in, ns)); - EXPECT_TRUE(Question(b, ch, aaaa) != Question(a, in, ns)); - -} - -} diff --git a/src/lib/dns/tests/rcode_unittest.cc b/src/lib/dns/tests/rcode_unittest.cc index 220248f062..8b13789179 100644 --- a/src/lib/dns/tests/rcode_unittest.cc +++ b/src/lib/dns/tests/rcode_unittest.cc @@ -1,126 +1 @@ -// Copyright (C) 2010-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. -#include <config.h> - -#include <vector> -#include <sstream> - -#include <exceptions/exceptions.h> - -#include <dns/rcode.h> - -#include <gtest/gtest.h> - -using namespace std; -using namespace isc::dns; - -namespace { -TEST(RcodeTest, constructFromCode) { - // Normal cases. This test also tests getCode() - EXPECT_EQ(0, Rcode(0).getCode()); - EXPECT_EQ(0xfff, Rcode(0xfff).getCode()); // possible max code - - // should fail on attempt of construction with an out of range code - EXPECT_THROW(Rcode(0x1000), isc::OutOfRange); - EXPECT_THROW(Rcode(0xffff), isc::OutOfRange); -} - -TEST(RcodeTest, constructFromCodePair) { - EXPECT_EQ(3, Rcode(Rcode::NXDOMAIN_CODE, 0).getCode()); - EXPECT_EQ(Rcode::BADVERS_CODE, Rcode(0, 1).getCode()); - EXPECT_EQ(0xfff, Rcode(0xf, 0xff).getCode()); - EXPECT_THROW(Rcode(0x10, 0xff), isc::OutOfRange); -} - -TEST(RcodeTest, getExtendedCode) { - EXPECT_EQ(0, Rcode::NOERROR().getExtendedCode()); - EXPECT_EQ(0, Rcode::YXRRSET().getExtendedCode()); - EXPECT_EQ(1, Rcode::BADVERS().getExtendedCode()); - EXPECT_EQ(0xab, Rcode(0xabf).getExtendedCode()); - EXPECT_EQ(0xff, Rcode(0xfff).getExtendedCode()); -} - -TEST(RcodeTest, constants) { - // We'll only test arbitrarily chosen subsets of the codes. - // This class is quite simple, so it should be suffice. - - EXPECT_EQ(Rcode::NOERROR_CODE, Rcode(0).getCode()); - EXPECT_EQ(Rcode::FORMERR_CODE, Rcode(1).getCode()); - EXPECT_EQ(Rcode::NOTIMP_CODE, Rcode(4).getCode()); - EXPECT_EQ(Rcode::REFUSED_CODE, Rcode(5).getCode()); - EXPECT_EQ(Rcode::RESERVED15_CODE, Rcode(15).getCode()); - EXPECT_EQ(Rcode::BADVERS_CODE, Rcode(16).getCode()); - - EXPECT_EQ(Rcode::NOERROR_CODE, Rcode::NOERROR().getCode()); - EXPECT_EQ(Rcode::FORMERR_CODE, Rcode::FORMERR().getCode()); - EXPECT_EQ(Rcode::NOTIMP_CODE, Rcode::NOTIMP().getCode()); - EXPECT_EQ(Rcode::REFUSED_CODE, Rcode::REFUSED().getCode()); - EXPECT_EQ(Rcode::RESERVED15_CODE, Rcode::RESERVED15().getCode()); - EXPECT_EQ(Rcode::BADVERS_CODE, Rcode::BADVERS().getCode()); -} - -TEST(RcodeTest, equal) { - EXPECT_TRUE(Rcode::NOERROR() == Rcode(Rcode::NOERROR_CODE)); - EXPECT_TRUE(Rcode::NOERROR().equals(Rcode(Rcode::NOERROR_CODE))); - EXPECT_TRUE(Rcode::FORMERR() == Rcode(Rcode::FORMERR_CODE)); - EXPECT_TRUE(Rcode::FORMERR().equals(Rcode(Rcode::FORMERR_CODE))); - EXPECT_TRUE(Rcode::NOTIMP() == Rcode(Rcode::NOTIMP_CODE)); - EXPECT_TRUE(Rcode::NOTIMP().equals(Rcode(Rcode::NOTIMP_CODE))); - EXPECT_TRUE(Rcode::REFUSED() == Rcode(Rcode::REFUSED_CODE)); - EXPECT_TRUE(Rcode::REFUSED().equals(Rcode(Rcode::REFUSED_CODE))); - EXPECT_TRUE(Rcode::RESERVED15() == Rcode(Rcode::RESERVED15())); - EXPECT_TRUE(Rcode::RESERVED15().equals(Rcode(Rcode::RESERVED15()))); - EXPECT_TRUE(Rcode::BADVERS() == Rcode(Rcode::BADVERS_CODE)); - EXPECT_TRUE(Rcode::BADVERS().equals(Rcode(Rcode::BADVERS_CODE))); -} - -TEST(RcodeTest, nequal) { - EXPECT_TRUE(Rcode::NOERROR() != Rcode::FORMERR()); - EXPECT_TRUE(Rcode::NOERROR().nequals(Rcode::FORMERR())); - EXPECT_TRUE(Rcode::NOTIMP() != Rcode(1)); - EXPECT_TRUE(Rcode::NOTIMP().nequals(Rcode(1))); - EXPECT_TRUE(Rcode(10) != Rcode(11)); - EXPECT_TRUE(Rcode(10).nequals(Rcode(11))); -} - -TEST(RcodeTest, toText) { - vector<const char*> expects; - expects.resize(Rcode::BADVERS_CODE + 1); - expects[Rcode::NOERROR_CODE] = "NOERROR"; - expects[Rcode::FORMERR_CODE] = "FORMERR"; - expects[Rcode::SERVFAIL_CODE] = "SERVFAIL"; - expects[Rcode::NXDOMAIN_CODE] = "NXDOMAIN"; - expects[Rcode::NOTIMP_CODE] = "NOTIMP"; - expects[Rcode::REFUSED_CODE] = "REFUSED"; - expects[Rcode::YXDOMAIN_CODE] = "YXDOMAIN"; - expects[Rcode::YXRRSET_CODE] = "YXRRSET"; - expects[Rcode::NXRRSET_CODE] = "NXRRSET"; - expects[Rcode::NOTAUTH_CODE] = "NOTAUTH"; - expects[Rcode::NOTZONE_CODE] = "NOTZONE"; - expects[Rcode::RESERVED11_CODE] = "RESERVED11"; - expects[Rcode::RESERVED12_CODE] = "RESERVED12"; - expects[Rcode::RESERVED13_CODE] = "RESERVED13"; - expects[Rcode::RESERVED14_CODE] = "RESERVED14"; - expects[Rcode::RESERVED15_CODE] = "RESERVED15"; - expects[Rcode::BADVERS_CODE] = "BADVERS"; - - for (unsigned int i = 0; i <= Rcode::BADVERS_CODE; ++i) { - EXPECT_EQ(expects.at(i), Rcode(i).toText()); - } - - // Non well-known Rcodes - EXPECT_EQ("17", Rcode(Rcode::BADVERS().getCode() + 1).toText()); - EXPECT_EQ("4095", Rcode(Rcode(0xfff)).toText()); -} - -// test operator<<. We simply confirm it appends the result of toText(). -TEST(RcodeTest, LeftShiftOperator) { - ostringstream oss; - oss << Rcode::SERVFAIL(); - EXPECT_EQ(Rcode::SERVFAIL().toText(), oss.str()); -} -} diff --git a/src/lib/dns/tests/rdata_afsdb_unittest.cc b/src/lib/dns/tests/rdata_afsdb_unittest.cc index 26c31352f8..8b13789179 100644 --- a/src/lib/dns/tests/rdata_afsdb_unittest.cc +++ b/src/lib/dns/tests/rdata_afsdb_unittest.cc @@ -1,235 +1 @@ -// Copyright (C) 2011-2019 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. -#include <config.h> - -#include <util/buffer.h> -#include <dns/exceptions.h> -#include <dns/messagerenderer.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> -#include <dns/rrclass.h> -#include <dns/rrtype.h> - -#include <gtest/gtest.h> - -#include <dns/tests/unittest_util.h> -#include <dns/tests/rdata_unittest.h> -#include <util/unittests/wiredata.h> - -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."; -const char* const too_long_label("012345678901234567890123456789" - "0123456789012345678901234567890123."); - -namespace { -class Rdata_AFSDB_Test : public RdataTest { -protected: - Rdata_AFSDB_Test() : - rdata_afsdb(string(afsdb_text)), rdata_afsdb2(string(afsdb_text2)) - {} - - const generic::AFSDB rdata_afsdb; - const generic::AFSDB rdata_afsdb2; - vector<uint8_t> expected_wire; -}; - - -TEST_F(Rdata_AFSDB_Test, createFromText) { - EXPECT_EQ(1, rdata_afsdb.getSubtype()); - EXPECT_EQ(Name("afsdb.example.com."), rdata_afsdb.getServer()); - - EXPECT_EQ(0, rdata_afsdb2.getSubtype()); - EXPECT_EQ(Name("root.example.com."), rdata_afsdb2.getServer()); -} - -TEST_F(Rdata_AFSDB_Test, badText) { - // subtype is too large - EXPECT_THROW(const generic::AFSDB rdata_afsdb("99999999 afsdb.example.com."), - InvalidRdataText); - // incomplete text - EXPECT_THROW(const generic::AFSDB rdata_afsdb("10"), InvalidRdataText); - EXPECT_THROW(const generic::AFSDB rdata_afsdb("SPOON"), InvalidRdataText); - EXPECT_THROW(const generic::AFSDB rdata_afsdb("1root.example.com."), InvalidRdataText); - // number of fields (must be 2) is incorrect - EXPECT_THROW(const generic::AFSDB rdata_afsdb("10 afsdb. example.com."), - InvalidRdataText); - // No origin and relative - EXPECT_THROW(const generic::AFSDB rdata_afsdb("1 afsdb.example.com"), - MissingNameOrigin); - // bad name - EXPECT_THROW(const generic::AFSDB rdata_afsdb("1 afsdb.example.com." + - string(too_long_label)), TooLongLabel); -} - -TEST_F(Rdata_AFSDB_Test, copy) { - const generic::AFSDB rdata_afsdb2(rdata_afsdb); - EXPECT_EQ(0, rdata_afsdb.compare(rdata_afsdb2)); -} - -TEST_F(Rdata_AFSDB_Test, assignment) { - generic::AFSDB copy((string(afsdb_text2))); - copy = rdata_afsdb; - EXPECT_EQ(0, copy.compare(rdata_afsdb)); - - // Check if the copied data is valid even after the original is deleted - generic::AFSDB* copy2 = new generic::AFSDB(rdata_afsdb); - generic::AFSDB copy3((string(afsdb_text2))); - copy3 = *copy2; - delete copy2; - EXPECT_EQ(0, copy3.compare(rdata_afsdb)); - - // Self assignment - copy = *© - EXPECT_EQ(0, copy.compare(rdata_afsdb)); -} - -TEST_F(Rdata_AFSDB_Test, createFromWire) { - // uncompressed names - EXPECT_EQ(0, rdata_afsdb.compare( - *rdataFactoryFromFile(RRType::AFSDB(), RRClass::IN(), - "rdata_afsdb_fromWire1.wire"))); - // compressed name - EXPECT_EQ(0, rdata_afsdb.compare( - *rdataFactoryFromFile(RRType::AFSDB(), RRClass::IN(), - "rdata_afsdb_fromWire2.wire", 13))); - // RDLENGTH is too short - EXPECT_THROW(rdataFactoryFromFile(RRType::AFSDB(), RRClass::IN(), - "rdata_afsdb_fromWire3.wire"), - InvalidRdataLength); - // RDLENGTH is too long - EXPECT_THROW(rdataFactoryFromFile(RRType::AFSDB(), RRClass::IN(), - "rdata_afsdb_fromWire4.wire"), - InvalidRdataLength); - // bogus server name, the error should be detected in the name - // constructor - EXPECT_THROW(rdataFactoryFromFile(RRType::AFSDB(), RRClass::IN(), - "rdata_afsdb_fromWire5.wire"), - DNSMessageFORMERR); -} - -TEST_F(Rdata_AFSDB_Test, createFromLexer) { - EXPECT_EQ(0, rdata_afsdb.compare( - *test::createRdataUsingLexer(RRType::AFSDB(), RRClass::IN(), - afsdb_text))); - - // test::createRdataUsingLexer() constructs relative to - // "example.org." origin. - generic::AFSDB tmp = generic::AFSDB("1 afsdb2.example.org."); - EXPECT_EQ(0, tmp.compare( - *test::createRdataUsingLexer(RRType::AFSDB(), RRClass::IN(), - "1 afsdb2"))); - - // Exceptions cause NULL to be returned. - EXPECT_FALSE(test::createRdataUsingLexer(RRType::AFSDB(), RRClass::IN(), - "1root.example.com.")); - - // 65536 is larger than maximum possible subtype - EXPECT_FALSE(test::createRdataUsingLexer(RRType::AFSDB(), RRClass::IN(), - "65536 afsdb.example.com.")); - - // Extra text at end of line - EXPECT_FALSE(test::createRdataUsingLexer(RRType::AFSDB(), RRClass::IN(), - "1 afsdb.example.com. extra.")); -} - -TEST_F(Rdata_AFSDB_Test, toWireBuffer) { - // construct actual data - rdata_afsdb.toWire(obuffer); - - // construct expected data - UnitTestUtil::readWireData("rdata_afsdb_toWire1.wire", expected_wire); - - // then compare them - matchWireData(&expected_wire[0], expected_wire.size(), - obuffer.getData(), obuffer.getLength()); - - // clear buffer for the next test - obuffer.clear(); - - // construct actual data - Name("example.com.").toWire(obuffer); - rdata_afsdb2.toWire(obuffer); - - // construct expected data - UnitTestUtil::readWireData("rdata_afsdb_toWire2.wire", expected_wire); - - // then compare them - matchWireData(&expected_wire[0], expected_wire.size(), - obuffer.getData(), obuffer.getLength()); -} - -TEST_F(Rdata_AFSDB_Test, toWireRenderer) { - // similar to toWireBuffer, but names in RDATA could be compressed due to - // preceding names. Actually they must not be compressed according to - // RFC3597, and this test checks that. - - // construct actual data - rdata_afsdb.toWire(renderer); - - // construct expected data - UnitTestUtil::readWireData("rdata_afsdb_toWire1.wire", expected_wire); - - // then compare them - matchWireData(&expected_wire[0], expected_wire.size(), - renderer.getData(), renderer.getLength()); - - // clear renderer for the next test - renderer.clear(); - - // construct actual data - renderer.writeName(Name("example.com.")); - rdata_afsdb2.toWire(renderer); - - // construct expected data - UnitTestUtil::readWireData("rdata_afsdb_toWire2.wire", expected_wire); - - // then compare them - matchWireData(&expected_wire[0], expected_wire.size(), - renderer.getData(), renderer.getLength()); -} - -TEST_F(Rdata_AFSDB_Test, toText) { - EXPECT_EQ(afsdb_text, rdata_afsdb.toText()); - EXPECT_EQ(afsdb_text2, rdata_afsdb2.toText()); -} - -TEST_F(Rdata_AFSDB_Test, compare) { - // check reflexivity - EXPECT_EQ(0, rdata_afsdb.compare(rdata_afsdb)); - - // name must be compared in case-insensitive manner - EXPECT_EQ(0, rdata_afsdb.compare(generic::AFSDB("1 " - "AFSDB.example.com."))); - - const generic::AFSDB small1("10 afsdb.example.com."); - const generic::AFSDB large1("65535 afsdb.example.com."); - const generic::AFSDB large2("256 afsdb.example.com."); - - // confirm these are compared as unsigned values - EXPECT_GT(0, rdata_afsdb.compare(large1)); - EXPECT_LT(0, large1.compare(rdata_afsdb)); - - // confirm these are compared in network byte order - EXPECT_GT(0, small1.compare(large2)); - EXPECT_LT(0, large2.compare(small1)); - - // another AFSDB whose server name is larger than that of rdata_afsdb. - const generic::AFSDB large3("256 zzzzz.example.com."); - EXPECT_GT(0, large2.compare(large3)); - EXPECT_LT(0, large3.compare(large2)); - - // comparison attempt between incompatible RR types should be rejected - EXPECT_THROW(rdata_afsdb.compare(*rdata_nomatch), bad_cast); -} -} diff --git a/src/lib/dns/tests/rdata_caa_unittest.cc b/src/lib/dns/tests/rdata_caa_unittest.cc index 48b9076d18..8b13789179 100644 --- a/src/lib/dns/tests/rdata_caa_unittest.cc +++ b/src/lib/dns/tests/rdata_caa_unittest.cc @@ -1,322 +1 @@ -// Copyright (C) 2014-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. -#include <config.h> - -#include <algorithm> -#include <string> - -#include <util/buffer.h> -#include <dns/messagerenderer.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> -#include <dns/rrclass.h> -#include <dns/rrtype.h> - -#include <gtest/gtest.h> - -#include <dns/tests/unittest_util.h> -#include <dns/tests/rdata_unittest.h> -#include <util/unittests/wiredata.h> - -#include <boost/algorithm/string.hpp> - -using namespace std; -using namespace isc; -using namespace isc::dns; -using namespace isc::util; -using namespace isc::dns::rdata; -using isc::UnitTestUtil; -using isc::util::unittests::matchWireData; - -namespace { -class Rdata_CAA_Test : public RdataTest { -protected: - Rdata_CAA_Test() : - caa_txt("0 issue \"ca.example.net\""), - rdata_caa(caa_txt) - {} - - void checkFromText_None(const string& rdata_str) { - checkFromText<generic::CAA, isc::Exception, isc::Exception>( - rdata_str, rdata_caa, false, false); - } - - void checkFromText_InvalidText(const string& rdata_str) { - checkFromText<generic::CAA, InvalidRdataText, InvalidRdataText>( - rdata_str, rdata_caa, true, true); - } - - void checkFromText_LexerError(const string& rdata_str) { - checkFromText - <generic::CAA, InvalidRdataText, MasterLexer::LexerError>( - rdata_str, rdata_caa, true, true); - } - - void checkFromText_BadString(const string& rdata_str) { - checkFromText - <generic::CAA, InvalidRdataText, isc::Exception>( - rdata_str, rdata_caa, true, false); - } - - const string caa_txt; - const generic::CAA rdata_caa; -}; - -const uint8_t rdata_caa_wiredata[] = { - // flags - 0x00, - // tag length - 0x5, - // tag - 'i', 's', 's', 'u', 'e', - // value - 'c', 'a', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', - '.', 'n', 'e', 't' -}; - -TEST_F(Rdata_CAA_Test, createFromText) { - // Basic test - checkFromText_None(caa_txt); - - // With different spacing - checkFromText_None("0 issue \"ca.example.net\""); - - // Combination of lowercase and uppercase - checkFromText_None("0 IssUE \"ca.example.net\""); - - // string constructor throws if there's extra text, - // but lexer constructor doesn't - checkFromText_BadString(caa_txt + "\n" + caa_txt); - - // Missing value field - EXPECT_NO_THROW(const generic::CAA rdata_caa2("0 issue")); -} - -TEST_F(Rdata_CAA_Test, fields) { - // Some of these may not be RFC conformant, but we relax the check - // in our code to work with other field values that may show up in - // the future. - EXPECT_NO_THROW(const generic::CAA rdata_caa2("1 issue \"ca.example.net\"")); - EXPECT_NO_THROW(const generic::CAA rdata_caa2("2 issue \"ca.example.net\"")); - EXPECT_NO_THROW(const generic::CAA rdata_caa2("3 issue \"ca.example.net\"")); - EXPECT_NO_THROW(const generic::CAA rdata_caa2("128 issue \"ca.example.net\"")); - EXPECT_NO_THROW(const generic::CAA rdata_caa2("255 issue \"ca.example.net\"")); - - EXPECT_NO_THROW(const generic::CAA rdata_caa2("0 foo \"ca.example.net\"")); - EXPECT_NO_THROW(const generic::CAA rdata_caa2("0 bar \"ca.example.net\"")); - EXPECT_NO_THROW(const generic::CAA rdata_caa2("0 12345 \"ca.example.net\"")); - EXPECT_NO_THROW(const generic::CAA rdata_caa2("0 w0x1y2z3 \"ca.example.net\"")); - EXPECT_NO_THROW(const generic::CAA rdata_caa2("0 relaxed-too \"ca.example.net\"")); - EXPECT_NO_THROW(const generic::CAA rdata_caa2("0 RELAXED.too \"ca.example.net\"")); - - // No value (this is redundant to the last test case in the - // .createFromText test - EXPECT_NO_THROW(const generic::CAA rdata_caa2("0 issue")); - - // > 255 would be broken - EXPECT_THROW(const generic::CAA rdata_caa2("256 issue \"ca.example.net\""), - InvalidRdataText); - - // Missing tag causes the value to be parsed as the tag field. As - // the tag field does not allow quoted strings, this throws. - EXPECT_THROW(const generic::CAA rdata_caa2("0 \"ca.example.net\""), - InvalidRdataText); - - // Tag is too long - const std::string tag(256, 'a'); - const std::string rdata_txt("0 " + tag + " \"ca.example.net\""); - EXPECT_THROW(const generic::CAA rdata_caa2(rdata_txt), InvalidRdataText); -} - -TEST_F(Rdata_CAA_Test, characterStringValue) { - const generic::CAA rdata_caa_unquoted("0 issue ca.example.net"); - EXPECT_EQ(0, rdata_caa_unquoted.compare(rdata_caa)); - - const generic::CAA rdata_caa_escape_X("0 issue ca.e\\xample.net"); - EXPECT_EQ(0, rdata_caa_escape_X.compare(rdata_caa)); - - const generic::CAA rdata_caa_escape_DDD("0 issue ca.e\\120ample.net"); - EXPECT_EQ(0, rdata_caa_escape_DDD.compare(rdata_caa)); - - const generic::CAA rdata_caa_multiline("0 issue (\nca.example.net)"); - EXPECT_EQ(0, rdata_caa_multiline.compare(rdata_caa)); -} - -TEST_F(Rdata_CAA_Test, badText) { - checkFromText_LexerError("0"); - checkFromText_LexerError("ZERO issue \"ca.example.net\""); - EXPECT_THROW(const generic::CAA rdata_caa2(caa_txt + " extra text"), - InvalidRdataText); - - // Yes, this is redundant to the last test cases in the .fields test - checkFromText_InvalidText("2345 issue \"ca.example.net\""); - - // negative values are trapped in the lexer rather than the - // constructor - checkFromText_LexerError("-2 issue \"ca.example.net\""); -} - -TEST_F(Rdata_CAA_Test, copyAndAssign) { - // Copy construct - generic::CAA rdata_caa2(rdata_caa); - EXPECT_EQ(0, rdata_caa.compare(rdata_caa2)); - - // Assignment, mainly to confirm it doesn't cause disruption. - rdata_caa2 = rdata_caa; - EXPECT_EQ(0, rdata_caa.compare(rdata_caa2)); -} - -TEST_F(Rdata_CAA_Test, createFromWire) { - // Basic test - EXPECT_EQ(0, rdata_caa.compare( - *rdataFactoryFromFile(RRType("CAA"), RRClass("IN"), - "rdata_caa_fromWire1.wire"))); - - // Combination of lowercase and uppercase - EXPECT_EQ(0, rdata_caa.compare( - *rdataFactoryFromFile(RRType("CAA"), RRClass("IN"), - "rdata_caa_fromWire2.wire"))); - - // Value field is empty - EXPECT_NO_THROW(rdataFactoryFromFile(RRType("CAA"), RRClass("IN"), - "rdata_caa_fromWire3.wire")); - - // Tag field is empty - EXPECT_THROW(rdataFactoryFromFile(RRType("CAA"), RRClass("IN"), - "rdata_caa_fromWire4.wire"), - InvalidRdataText); - - // Value field is shorter than rdata len - EXPECT_THROW(rdataFactoryFromFile(RRType("CAA"), RRClass("IN"), - "rdata_caa_fromWire5"), - InvalidBufferPosition); - - // all RDATA is missing - EXPECT_THROW(rdataFactoryFromFile(RRType("CAA"), RRClass("IN"), - "rdata_caa_fromWire6"), - InvalidBufferPosition); -} - -TEST_F(Rdata_CAA_Test, createFromParams) { - const generic::CAA rdata_caa2(0, "issue", "ca.example.net"); - EXPECT_EQ(0, rdata_caa2.compare(rdata_caa)); - - const generic::CAA rdata_caa4(0, "issue", "ca.e\\xample.net"); - EXPECT_EQ(0, rdata_caa4.compare(rdata_caa)); - - const generic::CAA rdata_caa5(0, "issue", "ca.e\\120ample.net"); - EXPECT_EQ(0, rdata_caa5.compare(rdata_caa)); - - // Tag is empty - EXPECT_THROW(const generic::CAA rdata_caa3(0, "", "ca.example.net"), - isc::InvalidParameter); - - // Tag is too long - const std::string tag(256, 'a'); - EXPECT_THROW(const generic::CAA rdata_caa3(0, tag, "ca.example.net"), - isc::InvalidParameter); - - // Value is too long - const std::string value(65536, 'a'); - EXPECT_THROW(const generic::CAA rdata_caa3(0, "issue", value), - InvalidRdataLength); -} - -TEST_F(Rdata_CAA_Test, toText) { - EXPECT_TRUE(boost::iequals(caa_txt, rdata_caa.toText())); - - const string caa_txt2("1 issue \"\""); - const generic::CAA rdata_caa2(caa_txt2); - EXPECT_TRUE(boost::iequals(caa_txt2, rdata_caa2.toText())); -} - -TEST_F(Rdata_CAA_Test, toWire) { - obuffer.clear(); - rdata_caa.toWire(obuffer); - - matchWireData(rdata_caa_wiredata, sizeof(rdata_caa_wiredata), - obuffer.getData(), obuffer.getLength()); -} - -TEST_F(Rdata_CAA_Test, compare) { - // Equality test is repeated from createFromWire tests above. - EXPECT_EQ(0, rdata_caa.compare( - *rdataFactoryFromFile(RRType("CAA"), RRClass("IN"), - "rdata_caa_fromWire1.wire"))); - - const generic::CAA rdata_caa2("1 issue \"ca.example.net\""); - - EXPECT_EQ(1, rdata_caa2.compare(rdata_caa)); - EXPECT_EQ(-1, rdata_caa.compare(rdata_caa2)); -} - -TEST_F(Rdata_CAA_Test, getFlags) { - EXPECT_EQ(0, rdata_caa.getFlags()); -} - -TEST_F(Rdata_CAA_Test, getTag) { - EXPECT_EQ("issue", rdata_caa.getTag()); -} - -TEST_F(Rdata_CAA_Test, getValue) { - const uint8_t value_data[] = { - 'c', 'a', '.', - 'e', 'x', 'a', 'm', 'p', 'l', 'e', '.', - 'n', 'e', 't' - }; - - const std::vector<uint8_t>& value = rdata_caa.getValue(); - matchWireData(value_data, sizeof(value_data), - &value[0], value.size()); -} - -TEST_F(Rdata_CAA_Test, emptyValueFromWire) { - const uint8_t rdf_wiredata[] = { - // flags - 0x00, - // tag length - 0x5, - // tag - 'i', 's', 's', 'u', 'e' - }; - - const generic::CAA rdf = - dynamic_cast<const generic::CAA&> - (*rdataFactoryFromFile(RRType("CAA"), RRClass("IN"), - "rdata_caa_fromWire3.wire")); - - EXPECT_EQ(0, rdf.getFlags()); - EXPECT_EQ("issue", rdf.getTag()); - - obuffer.clear(); - rdf.toWire(obuffer); - - matchWireData(rdf_wiredata, sizeof(rdf_wiredata), - obuffer.getData(), obuffer.getLength()); -} - -TEST_F(Rdata_CAA_Test, emptyValueFromString) { - const generic::CAA rdata_caa2("0 issue"); - const uint8_t rdata_caa2_wiredata[] = { - // flags - 0x00, - // tag length - 0x5, - // tag - 'i', 's', 's', 'u', 'e' - }; - - EXPECT_EQ(0, rdata_caa2.getFlags()); - EXPECT_EQ("issue", rdata_caa2.getTag()); - - obuffer.clear(); - rdata_caa2.toWire(obuffer); - - matchWireData(rdata_caa2_wiredata, sizeof(rdata_caa2_wiredata), - obuffer.getData(), obuffer.getLength()); -} -} diff --git a/src/lib/dns/tests/rdata_char_string_data_unittest.cc b/src/lib/dns/tests/rdata_char_string_data_unittest.cc index 4ffeadb593..8b13789179 100644 --- a/src/lib/dns/tests/rdata_char_string_data_unittest.cc +++ b/src/lib/dns/tests/rdata_char_string_data_unittest.cc @@ -1,181 +1 @@ -// Copyright (C) 2014-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. -#include <config.h> - -#include <util/unittests/wiredata.h> - -#include <dns/exceptions.h> -#include <dns/rdata.h> -#include <dns/rdata/generic/detail/char_string.h> -#include <util/buffer.h> - -#include <gtest/gtest.h> - -#include <string> -#include <vector> - -using namespace isc::dns; -using namespace isc::dns::rdata; -using isc::dns::rdata::generic::detail::CharStringData; -using isc::dns::rdata::generic::detail::stringToCharStringData; -using isc::dns::rdata::generic::detail::charStringDataToString; -using isc::dns::rdata::generic::detail::compareCharStringDatas; -using isc::util::unittests::matchWireData; - -namespace { -const uint8_t test_charstr[] = { - 'T', 'e', 's', 't', ' ', 'S', 't', 'r', 'i', 'n', 'g' -}; - -class CharStringDataTest : public ::testing::Test { -protected: - CharStringDataTest() : - // char-string representation for test data using two types of escape - // ('r' = 114) - test_str("Test\\ St\\114ing") - { - str_region.beg = &test_str[0]; - str_region.len = test_str.size(); - } - CharStringData chstr; // place holder - const std::string test_str; - MasterToken::StringRegion str_region; -}; - -MasterToken::StringRegion -createStringRegion(const std::string& str) { - MasterToken::StringRegion region; - region.beg = &str[0]; // note std ensures this works even if str is empty - region.len = str.size(); - return (region); -} - -TEST_F(CharStringDataTest, normalConversion) { - uint8_t tmp[3]; // placeholder for expected sequence - - stringToCharStringData(str_region, chstr); - matchWireData(test_charstr, sizeof(test_charstr), &chstr[0], chstr.size()); - - // Empty string - chstr.clear(); - stringToCharStringData(createStringRegion(""), chstr); - EXPECT_TRUE(chstr.empty()); - - // Possible largest char string - chstr.clear(); - std::string long_str(255, 'x'); - stringToCharStringData(createStringRegion(long_str), chstr); - std::vector<uint8_t> expected; - expected.insert(expected.end(), long_str.begin(), long_str.end()); - matchWireData(&expected[0], expected.size(), &chstr[0], chstr.size()); - - // Escaped '\' - chstr.clear(); - tmp[0] = '\\'; - stringToCharStringData(createStringRegion("\\\\"), chstr); - matchWireData(tmp, 1, &chstr[0], chstr.size()); - - // Boundary values for \DDD - chstr.clear(); - tmp[0] = 0; - stringToCharStringData(createStringRegion("\\000"), chstr); - matchWireData(tmp, 1, &chstr[0], chstr.size()); - - chstr.clear(); - stringToCharStringData(createStringRegion("\\255"), chstr); - tmp[0] = 255; - matchWireData(tmp, 1, &chstr[0], chstr.size()); - - // Another digit follows DDD; it shouldn't cause confusion - chstr.clear(); - stringToCharStringData(createStringRegion("\\2550"), chstr); - tmp[1] = '0'; - matchWireData(tmp, 2, &chstr[0], chstr.size()); -} - -TEST_F(CharStringDataTest, badConversion) { - // input string ending with (non escaped) '\' - chstr.clear(); - EXPECT_THROW(stringToCharStringData(createStringRegion("foo\\"), chstr), - InvalidRdataText); -} - -TEST_F(CharStringDataTest, badDDD) { - // Check various type of bad form of \DDD - - // Not a number - EXPECT_THROW(stringToCharStringData(createStringRegion("\\1a2"), chstr), - InvalidRdataText); - EXPECT_THROW(stringToCharStringData(createStringRegion("\\12a"), chstr), - InvalidRdataText); - - // Not in the range of uint8_t - EXPECT_THROW(stringToCharStringData(createStringRegion("\\256"), chstr), - InvalidRdataText); - - // Short buffer - EXPECT_THROW(stringToCharStringData(createStringRegion("\\42"), chstr), - InvalidRdataText); -} - -const struct TestData { - const char *data; - const char *expected; -} conversion_data[] = { - {"Test\"Test", "Test\\\"Test"}, - {"Test;Test", "Test\\;Test"}, - {"Test\\Test", "Test\\\\Test"}, - {"Test\x1fTest", "Test\\031Test"}, - {"Test ~ Test", "Test ~ Test"}, - {"Test\x7fTest", "Test\\127Test"}, - {NULL, NULL} -}; - -TEST_F(CharStringDataTest, charStringDataToString) { - for (const TestData* cur = conversion_data; cur->data != NULL; ++cur) { - uint8_t idata[32]; - size_t length = std::strlen(cur->data); - ASSERT_LT(length, sizeof(idata)); - std::memcpy(idata, cur->data, length); - const CharStringData test_data(idata, idata + length); - EXPECT_EQ(cur->expected, charStringDataToString(test_data)); - } -} - -TEST_F(CharStringDataTest, compareCharStringData) { - CharStringData charstr; - CharStringData charstr2; - CharStringData charstr_small1; - CharStringData charstr_small2; - CharStringData charstr_large1; - CharStringData charstr_large2; - CharStringData charstr_empty; - - stringToCharStringData(createStringRegion("test string"), charstr); - stringToCharStringData(createStringRegion("test string"), charstr2); - stringToCharStringData(createStringRegion("test strin"), charstr_small1); - stringToCharStringData(createStringRegion("test strina"), charstr_small2); - stringToCharStringData(createStringRegion("test stringa"), charstr_large1); - stringToCharStringData(createStringRegion("test strinz"), charstr_large2); - - EXPECT_EQ(0, compareCharStringDatas(charstr, charstr2)); - EXPECT_EQ(0, compareCharStringDatas(charstr2, charstr)); - EXPECT_EQ(1, compareCharStringDatas(charstr, charstr_small1)); - EXPECT_EQ(1, compareCharStringDatas(charstr, charstr_small2)); - EXPECT_EQ(-1, compareCharStringDatas(charstr, charstr_large1)); - EXPECT_EQ(-1, compareCharStringDatas(charstr, charstr_large2)); - EXPECT_EQ(-1, compareCharStringDatas(charstr_small1, charstr)); - EXPECT_EQ(-1, compareCharStringDatas(charstr_small2, charstr)); - EXPECT_EQ(1, compareCharStringDatas(charstr_large1, charstr)); - EXPECT_EQ(1, compareCharStringDatas(charstr_large2, charstr)); - - EXPECT_EQ(-1, compareCharStringDatas(charstr_empty, charstr)); - EXPECT_EQ(1, compareCharStringDatas(charstr, charstr_empty)); - EXPECT_EQ(0, compareCharStringDatas(charstr_empty, charstr_empty)); -} - -} // unnamed namespace diff --git a/src/lib/dns/tests/rdata_char_string_unittest.cc b/src/lib/dns/tests/rdata_char_string_unittest.cc index f1618b526c..8b13789179 100644 --- a/src/lib/dns/tests/rdata_char_string_unittest.cc +++ b/src/lib/dns/tests/rdata_char_string_unittest.cc @@ -1,246 +1 @@ -// Copyright (C) 2012-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. -#include <config.h> - -#include <util/unittests/wiredata.h> - -#include <dns/exceptions.h> -#include <dns/rdata.h> -#include <dns/rdata/generic/detail/char_string.h> -#include <util/buffer.h> - -#include <gtest/gtest.h> - -#include <string> -#include <vector> - -using namespace isc::dns; -using namespace isc::dns::rdata; -using isc::dns::rdata::generic::detail::CharString; -using isc::dns::rdata::generic::detail::bufferToCharString; -using isc::dns::rdata::generic::detail::stringToCharString; -using isc::dns::rdata::generic::detail::charStringToString; -using isc::dns::rdata::generic::detail::compareCharStrings; -using isc::util::unittests::matchWireData; - -namespace { -const uint8_t test_charstr[] = { - sizeof("Test String") - 1, - 'T', 'e', 's', 't', ' ', 'S', 't', 'r', 'i', 'n', 'g' -}; - -class CharStringTest : public ::testing::Test { -protected: - CharStringTest() : - // 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(); - } - CharString 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(CharStringTest, normalConversion) { - uint8_t tmp[3]; // placeholder for expected sequence - - stringToCharString(str_region, chstr); - matchWireData(test_charstr, sizeof(test_charstr), &chstr[0], chstr.size()); - - // Empty string - chstr.clear(); - stringToCharString(createStringRegion(""), chstr); - tmp[0] = 0; - matchWireData(tmp, 1, &chstr[0], chstr.size()); - - // Possible largest char string - chstr.clear(); - std::string long_str(255, 'x'); - stringToCharString(createStringRegion(long_str), chstr); - std::vector<uint8_t> expected; - expected.push_back(255); // len of char string - expected.insert(expected.end(), long_str.begin(), long_str.end()); - matchWireData(&expected[0], expected.size(), &chstr[0], chstr.size()); - - // Same data as the previous case, but the original string is longer than - // the max; this shouldn't be rejected - chstr.clear(); - long_str.at(254) = '\\'; // replace the last 'x' with '\' - long_str.append("120"); // 'x' = 120 - stringToCharString(createStringRegion(long_str), chstr); - matchWireData(&expected[0], expected.size(), &chstr[0], chstr.size()); - - // Escaped '\' - chstr.clear(); - tmp[0] = 1; - tmp[1] = '\\'; - stringToCharString(createStringRegion("\\\\"), chstr); - matchWireData(tmp, 2, &chstr[0], chstr.size()); - - // Boundary values for \DDD - chstr.clear(); - tmp[0] = 1; - tmp[1] = 0; - stringToCharString(createStringRegion("\\000"), chstr); - matchWireData(tmp, 2, &chstr[0], chstr.size()); - - chstr.clear(); - stringToCharString(createStringRegion("\\255"), chstr); - tmp[0] = 1; - tmp[1] = 255; - matchWireData(tmp, 2, &chstr[0], chstr.size()); - - // Another digit follows DDD; it shouldn't cause confusion - chstr.clear(); - stringToCharString(createStringRegion("\\2550"), chstr); - tmp[0] = 2; // string len is now 2 - tmp[2] = '0'; - matchWireData(tmp, 3, &chstr[0], chstr.size()); -} - -TEST_F(CharStringTest, badConversion) { - // string cannot exceed 255 bytes - EXPECT_THROW(stringToCharString(createStringRegion(std::string(256, 'a')), - chstr), - CharStringTooLong); - - // input string ending with (non escaped) '\' - chstr.clear(); - EXPECT_THROW(stringToCharString(createStringRegion("foo\\"), chstr), - InvalidRdataText); -} - -TEST_F(CharStringTest, badDDD) { - // Check various type of bad form of \DDD - - // Not a number - EXPECT_THROW(stringToCharString(createStringRegion("\\1a2"), chstr), - InvalidRdataText); - EXPECT_THROW(stringToCharString(createStringRegion("\\12a"), chstr), - InvalidRdataText); - - // Not in the range of uint8_t - EXPECT_THROW(stringToCharString(createStringRegion("\\256"), chstr), - InvalidRdataText); - - // Short buffer - EXPECT_THROW(stringToCharString(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(CharStringTest, charStringToString) { - for (const TestData* cur = conversion_data; cur->data != NULL; ++cur) { - uint8_t idata[32]; - size_t length = std::strlen(cur->data); - // length (1 byte) + string (length bytes) - assert(sizeof(idata) > length); - idata[0] = static_cast<uint8_t>(length); - std::memcpy(idata + 1, cur->data, length); - const CharString test_data(idata, idata + length + 1); - EXPECT_EQ(cur->expected, charStringToString(test_data)); - } -} - -TEST_F(CharStringTest, bufferToCharString) { - const size_t chstr_size = sizeof(test_charstr); - isc::util::InputBuffer buf(test_charstr, chstr_size); - size_t read = bufferToCharString(buf, chstr_size, chstr); - - EXPECT_EQ(chstr_size, read); - EXPECT_EQ("Test String", charStringToString(chstr)); -} - -TEST_F(CharStringTest, bufferToCharString_bad) { - const size_t chstr_size = sizeof(test_charstr); - isc::util::InputBuffer buf(test_charstr, chstr_size); - // Set valid data in both so we can make sure the charstr is not - // modified - bufferToCharString(buf, chstr_size, chstr); - ASSERT_EQ("Test String", charStringToString(chstr)); - - // Should be at end of buffer now, so it should fail - EXPECT_THROW(bufferToCharString(buf, chstr_size - 1, chstr), - DNSMessageFORMERR); - EXPECT_EQ("Test String", charStringToString(chstr)); - - // reset and try to read with too low rdata_len - buf.setPosition(0); - EXPECT_THROW(bufferToCharString(buf, chstr_size - 1, chstr), - DNSMessageFORMERR); - EXPECT_EQ("Test String", charStringToString(chstr)); - - // set internal charstring len too high - const uint8_t test_charstr_err[] = { - sizeof("Test String") + 1, - 'T', 'e', 's', 't', ' ', 'S', 't', 'r', 'i', 'n', 'g' - }; - buf = isc::util::InputBuffer(test_charstr_err, sizeof(test_charstr_err)); - EXPECT_THROW(bufferToCharString(buf, chstr_size, chstr), - DNSMessageFORMERR); - EXPECT_EQ("Test String", charStringToString(chstr)); - -} - - - -TEST_F(CharStringTest, compareCharString) { - CharString charstr; - CharString charstr2; - CharString charstr_small1; - CharString charstr_small2; - CharString charstr_large1; - CharString charstr_large2; - CharString charstr_empty; - - stringToCharString(createStringRegion("test string"), charstr); - stringToCharString(createStringRegion("test string"), charstr2); - stringToCharString(createStringRegion("test strin"), charstr_small1); - stringToCharString(createStringRegion("test strina"), charstr_small2); - stringToCharString(createStringRegion("test stringa"), charstr_large1); - stringToCharString(createStringRegion("test strinz"), charstr_large2); - - EXPECT_EQ(0, compareCharStrings(charstr, charstr2)); - EXPECT_EQ(0, compareCharStrings(charstr2, charstr)); - EXPECT_EQ(1, compareCharStrings(charstr, charstr_small1)); - EXPECT_EQ(1, compareCharStrings(charstr, charstr_small2)); - EXPECT_EQ(-1, compareCharStrings(charstr, charstr_large1)); - EXPECT_EQ(-1, compareCharStrings(charstr, charstr_large2)); - EXPECT_EQ(-1, compareCharStrings(charstr_small1, charstr)); - EXPECT_EQ(-1, compareCharStrings(charstr_small2, charstr)); - EXPECT_EQ(1, compareCharStrings(charstr_large1, charstr)); - EXPECT_EQ(1, compareCharStrings(charstr_large2, charstr)); - - EXPECT_EQ(-1, compareCharStrings(charstr_empty, charstr)); - EXPECT_EQ(1, compareCharStrings(charstr, charstr_empty)); - EXPECT_EQ(0, compareCharStrings(charstr_empty, charstr_empty)); -} - -} // unnamed namespace diff --git a/src/lib/dns/tests/rdata_cname_unittest.cc b/src/lib/dns/tests/rdata_cname_unittest.cc index e6663559d2..8b13789179 100644 --- a/src/lib/dns/tests/rdata_cname_unittest.cc +++ b/src/lib/dns/tests/rdata_cname_unittest.cc @@ -1,135 +1 @@ -// Copyright (C) 2010-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. -#include <config.h> - -#include <util/buffer.h> -#include <dns/exceptions.h> -#include <dns/messagerenderer.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> -#include <dns/rrclass.h> -#include <dns/rrtype.h> - -#include <gtest/gtest.h> - -#include <dns/tests/unittest_util.h> -#include <dns/tests/rdata_unittest.h> -#include <util/unittests/wiredata.h> - -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 { -public: - Rdata_CNAME_Test() : - rdata_cname("cn.example.com."), - rdata_cname2("cn2.example.com.") - {} - - const generic::CNAME rdata_cname; - const generic::CNAME rdata_cname2; -}; - -const uint8_t wiredata_cname[] = { - 0x02, 0x63, 0x6e, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x03, - 0x63, 0x6f, 0x6d, 0x00 }; -const uint8_t wiredata_cname2[] = { - // first name: cn.example.com. - 0x02, 0x63, 0x6e, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x03, - 0x63, 0x6f, 0x6d, 0x00, - // second name: cn2.example.com. all labels except the first should be - // compressed. - 0x03, 0x63, 0x6e, 0x32, 0xc0, 0x03 }; - -TEST_F(Rdata_CNAME_Test, createFromText) { - EXPECT_EQ(0, rdata_cname.compare(generic::CNAME("cn.example.com."))); - // explicitly add a trailing dot. should be the same RDATA. - EXPECT_EQ(0, rdata_cname.compare(generic::CNAME("cn.example.com."))); - // should be case sensitive. - EXPECT_EQ(0, rdata_cname.compare(generic::CNAME("CN.EXAMPLE.COM."))); - // RDATA of a class-independent type should be recognized for any - // "unknown" class. - EXPECT_EQ(0, rdata_cname.compare(*createRdata(RRType("CNAME"), - RRClass(65000), - "cn.example.com."))); -} - -TEST_F(Rdata_CNAME_Test, badText) { - // Extra text at end of line - EXPECT_THROW(generic::CNAME("cname.example.com. extra."), InvalidRdataText); -} - -TEST_F(Rdata_CNAME_Test, createFromWire) { - EXPECT_EQ(0, rdata_cname.compare( - *rdataFactoryFromFile(RRType("CNAME"), RRClass("IN"), - "rdata_cname_fromWire"))); - // RDLENGTH is too short - EXPECT_THROW(rdataFactoryFromFile(RRType("CNAME"), RRClass("IN"), - "rdata_cname_fromWire", 18), - InvalidRdataLength); - // RDLENGTH is too long - EXPECT_THROW(rdataFactoryFromFile(RRType("CNAME"), RRClass("IN"), - "rdata_cname_fromWire", 36), - InvalidRdataLength); - // incomplete name. the error should be detected in the name constructor - EXPECT_THROW(rdataFactoryFromFile(RRType("CNAME"), RRClass("IN"), - "rdata_cname_fromWire", 71), - DNSMessageFORMERR); - - EXPECT_EQ(0, generic::CNAME("cn2.example.com.").compare( - *rdataFactoryFromFile(RRType("CNAME"), RRClass("IN"), - "rdata_cname_fromWire", 55))); - EXPECT_THROW(*rdataFactoryFromFile(RRType("CNAME"), RRClass("IN"), - "rdata_cname_fromWire", 63), - InvalidRdataLength); -} - -TEST_F(Rdata_CNAME_Test, createFromLexer) { - EXPECT_EQ(0, rdata_cname.compare( - *test::createRdataUsingLexer(RRType::CNAME(), RRClass::IN(), - "cn.example.com."))); - - // test::createRdataUsingLexer() constructs relative to - // "example.org." origin. - EXPECT_EQ(0, generic::CNAME("cname10.example.org.").compare( - *test::createRdataUsingLexer(RRType::CNAME(), RRClass::IN(), - "cname10"))); - - // Extra text at end of line - EXPECT_FALSE(test::createRdataUsingLexer(RRType::CNAME(), RRClass::IN(), - "cname.example.com. extra.")); -} - -TEST_F(Rdata_CNAME_Test, toWireBuffer) { - rdata_cname.toWire(obuffer); - matchWireData(wiredata_cname, sizeof(wiredata_cname), - obuffer.getData(), obuffer.getLength()); -} - -TEST_F(Rdata_CNAME_Test, toWireRenderer) { - rdata_cname.toWire(renderer); - matchWireData(wiredata_cname, sizeof(wiredata_cname), - renderer.getData(), renderer.getLength()); - - rdata_cname2.toWire(renderer); - matchWireData(wiredata_cname2, sizeof(wiredata_cname2), - renderer.getData(), renderer.getLength()); -} - -TEST_F(Rdata_CNAME_Test, toText) { - EXPECT_EQ("cn.example.com.", rdata_cname.toText()); -} - -TEST_F(Rdata_CNAME_Test, getCname) { - EXPECT_EQ(Name("cn.example.com."), rdata_cname.getCname()); -} -} diff --git a/src/lib/dns/tests/rdata_dhcid_unittest.cc b/src/lib/dns/tests/rdata_dhcid_unittest.cc index c2cedee57c..8b13789179 100644 --- a/src/lib/dns/tests/rdata_dhcid_unittest.cc +++ b/src/lib/dns/tests/rdata_dhcid_unittest.cc @@ -1,165 +1 @@ -// Copyright (C) 2011-2024 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. -#include <config.h> - -#include <exceptions/exceptions.h> - -#include <util/buffer.h> -#include <dns/rdataclass.h> -#include <util/encode/encode.h> - -#include <gtest/gtest.h> - -#include <dns/tests/unittest_util.h> -#include <dns/tests/rdata_unittest.h> -#include <util/unittests/wiredata.h> - -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 { - -class Rdata_DHCID_Test : public RdataTest { -protected: - Rdata_DHCID_Test() : - dhcid_txt("0LIg0LvQtdGB0YMg0YDQvtC00LjQu9Cw0YHRjCDRkdC70L7Rh9C60LA="), - rdata_dhcid(dhcid_txt) - {} - - void checkFromText_None(const string& rdata_str) { - checkFromText<in::DHCID, isc::Exception, isc::Exception>( - rdata_str, rdata_dhcid, false, false); - } - - void checkFromText_BadValue(const string& rdata_str) { - checkFromText<in::DHCID, BadValue, BadValue>( - rdata_str, rdata_dhcid, true, true); - } - - void checkFromText_LexerError(const string& rdata_str) { - checkFromText - <in::DHCID, InvalidRdataText, MasterLexer::LexerError>( - rdata_str, rdata_dhcid, true, true); - } - - void checkFromText_BadString(const string& rdata_str) { - checkFromText - <in::DHCID, InvalidRdataText, isc::Exception>( - rdata_str, rdata_dhcid, true, false); - } - - const string dhcid_txt; - const in::DHCID rdata_dhcid; -}; - -TEST_F(Rdata_DHCID_Test, fromText) { - EXPECT_EQ(dhcid_txt, rdata_dhcid.toText()); - - // Space in digest data is OK - checkFromText_None( - "0LIg0LvQtdGB0YMg 0YDQvtC00LjQu9Cw 0YHRjCDRkdC70L7R h9C60LA="); - - // Multi-line digest data is OK, if enclosed in parentheses - checkFromText_None( - "( 0LIg0LvQtdGB0YMg0YDQvtC00LjQu9Cw\n0YHRjCDRkdC70L7R h9C60LA= )"); - - // Trailing garbage. This should cause only the string constructor - // to fail, but the lexer constructor must be able to continue - // parsing from it. - checkFromText_BadString( - "0LIg0LvQtdGB0YMg0YDQvtC00LjQu9Cw0YHRjCDRkdC70L7Rh9C60LA=" - " ; comment\n" - "AAIBY2/AuCccgoJbsaxcQc9TUapptP69lOjxfNuVAA2kjEA="); -} - -TEST_F(Rdata_DHCID_Test, badText) { - // missing digest data - checkFromText_LexerError(""); - - // invalid base64 - checkFromText_BadValue("EEeeeeeeEEEeeeeeeGaaahAAAAAAAAHHHHHHHHHHH!="); - - // unterminated multi-line base64 - checkFromText_LexerError( - "( 0LIg0LvQtdGB0YMg0YDQvtC00LjQu9Cw\n0YHRjCDRkdC70L7R h9C60LA="); -} - -TEST_F(Rdata_DHCID_Test, copy) { - const in::DHCID rdata_dhcid2(rdata_dhcid); - EXPECT_EQ(0, rdata_dhcid.compare(rdata_dhcid2)); -} - -TEST_F(Rdata_DHCID_Test, createFromWire) { - EXPECT_EQ(0, rdata_dhcid.compare( - *rdataFactoryFromFile(RRType("DHCID"), RRClass("IN"), - "rdata_dhcid_fromWire"))); - - InputBuffer buffer(NULL, 0); - EXPECT_THROW(in::DHCID(buffer, 0), InvalidRdataLength); - - // TBD: more tests -} - -TEST_F(Rdata_DHCID_Test, createFromLexer) { - EXPECT_EQ(0, rdata_dhcid.compare( - *test::createRdataUsingLexer(RRType::DHCID(), RRClass::IN(), - dhcid_txt))); -} - -TEST_F(Rdata_DHCID_Test, toWireRenderer) { - rdata_dhcid.toWire(renderer); - - vector<unsigned char> data; - UnitTestUtil::readWireData("rdata_dhcid_toWire", data); - matchWireData(&data[0], data.size(), - renderer.getData(), renderer.getLength()); -} - -TEST_F(Rdata_DHCID_Test, toWireBuffer) { - rdata_dhcid.toWire(obuffer); - - vector<unsigned char> data; - UnitTestUtil::readWireData("rdata_dhcid_toWire", data); - matchWireData(&data[0], data.size(), - obuffer.getData(), obuffer.getLength()); -} - -TEST_F(Rdata_DHCID_Test, toText) { - EXPECT_EQ(dhcid_txt, rdata_dhcid.toText()); -} - -TEST_F(Rdata_DHCID_Test, getDHCIDDigest) { - const string dhcid_txt1(encodeBase64(rdata_dhcid.getDigest())); - - EXPECT_EQ(dhcid_txt, dhcid_txt1); -} - -TEST_F(Rdata_DHCID_Test, compare) { - // trivial case: self equivalence - // cppcheck-suppress uselessCallsCompare - EXPECT_EQ(0, rdata_dhcid.compare(rdata_dhcid)); - - in::DHCID rdata_dhcid1("0YLQvtC/0L7Qu9GPINC00LLQsCDRgNGD0LHQu9GP"); - in::DHCID rdata_dhcid2("0YLQvtC/0L7Qu9GPINGC0YDQuCDRgNGD0LHQu9GP"); - in::DHCID rdata_dhcid3("0YLQvtC/0L7Qu9GPINGH0LXRgtGL0YDQtSDRgNGD0LHQu9GP"); - - EXPECT_LT(rdata_dhcid1.compare(rdata_dhcid2), 0); - EXPECT_GT(rdata_dhcid2.compare(rdata_dhcid1), 0); - - EXPECT_LT(rdata_dhcid2.compare(rdata_dhcid3), 0); - EXPECT_GT(rdata_dhcid3.compare(rdata_dhcid2), 0); - - // comparison attempt between incompatible RR types should be rejected - EXPECT_THROW(rdata_dhcid.compare(*rdata_nomatch), bad_cast); -} -} diff --git a/src/lib/dns/tests/rdata_dname_unittest.cc b/src/lib/dns/tests/rdata_dname_unittest.cc index 3bdfb235b3..8b13789179 100644 --- a/src/lib/dns/tests/rdata_dname_unittest.cc +++ b/src/lib/dns/tests/rdata_dname_unittest.cc @@ -1,137 +1 @@ -// Copyright (C) 2010-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. -#include <config.h> - -#include <util/buffer.h> -#include <dns/exceptions.h> -#include <dns/messagerenderer.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> -#include <dns/rrclass.h> -#include <dns/rrtype.h> - -#include <gtest/gtest.h> - -#include <dns/tests/unittest_util.h> -#include <dns/tests/rdata_unittest.h> -#include <util/unittests/wiredata.h> - -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 { -public: - Rdata_DNAME_Test() : - rdata_dname("dn.example.com."), - rdata_dname2("dn2.example.com.") - {} - - const generic::DNAME rdata_dname; - const generic::DNAME rdata_dname2; -}; - -const uint8_t wiredata_dname[] = { - 0x02, 0x64, 0x6e, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x03, - 0x63, 0x6f, 0x6d, 0x00 }; -const uint8_t wiredata_dname2[] = { - // first name: dn.example.com. - 0x02, 0x64, 0x6e, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x03, - 0x63, 0x6f, 0x6d, 0x00, - // second name: dn2.example.com. The "example.com" shouldn't be compressed - // because DNAME is not a well know type per RFC3597. - 0x03, 0x64, 0x6e, 0x32, - 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x03, - 0x63, 0x6f, 0x6d, 0x00 }; - -TEST_F(Rdata_DNAME_Test, createFromText) { - EXPECT_EQ(0, rdata_dname.compare(generic::DNAME("dn.example.com."))); - // explicitly add a trailing dot. should be the same RDATA. - EXPECT_EQ(0, rdata_dname.compare(generic::DNAME("dn.example.com."))); - // should be case sensitive. - EXPECT_EQ(0, rdata_dname.compare(generic::DNAME("DN.EXAMPLE.COM."))); - // RDATA of a class-independent type should be recognized for any - // "unknown" class. - EXPECT_EQ(0, rdata_dname.compare(*createRdata(RRType("DNAME"), - RRClass(65000), - "dn.example.com."))); -} - -TEST_F(Rdata_DNAME_Test, badText) { - // Extra text at end of line - EXPECT_THROW(generic::DNAME("dname.example.com. extra."), InvalidRdataText); -} - -TEST_F(Rdata_DNAME_Test, createFromWire) { - EXPECT_EQ(0, rdata_dname.compare( - *rdataFactoryFromFile(RRType("DNAME"), RRClass("IN"), - "rdata_dname_fromWire"))); - // RDLENGTH is too short - EXPECT_THROW(rdataFactoryFromFile(RRType("DNAME"), RRClass("IN"), - "rdata_dname_fromWire", 18), - InvalidRdataLength); - // RDLENGTH is too long - EXPECT_THROW(rdataFactoryFromFile(RRType("DNAME"), RRClass("IN"), - "rdata_dname_fromWire", 36), - InvalidRdataLength); - // incomplete name. the error should be detected in the name constructor - EXPECT_THROW(rdataFactoryFromFile(RRType("DNAME"), RRClass("IN"), - "rdata_dname_fromWire", 71), - DNSMessageFORMERR); - - EXPECT_EQ(0, generic::DNAME("dn2.example.com.").compare( - *rdataFactoryFromFile(RRType("DNAME"), RRClass("IN"), - "rdata_dname_fromWire", 55))); - EXPECT_THROW(*rdataFactoryFromFile(RRType("DNAME"), RRClass("IN"), - "rdata_dname_fromWire", 63), - InvalidRdataLength); -} - -TEST_F(Rdata_DNAME_Test, createFromLexer) { - EXPECT_EQ(0, rdata_dname.compare( - *test::createRdataUsingLexer(RRType::DNAME(), RRClass::IN(), - "dn.example.com."))); - - // test::createRdataUsingLexer() constructs relative to - // "example.org." origin. - EXPECT_EQ(0, generic::DNAME("dname8.example.org.").compare( - *test::createRdataUsingLexer(RRType::DNAME(), RRClass::IN(), - "dname8"))); - - // Extra text at end of line - EXPECT_FALSE(test::createRdataUsingLexer(RRType::DNAME(), RRClass::IN(), - "dname.example.com. extra.")); -} - -TEST_F(Rdata_DNAME_Test, toWireBuffer) { - rdata_dname.toWire(obuffer); - matchWireData(wiredata_dname, sizeof(wiredata_dname), - obuffer.getData(), obuffer.getLength()); -} - -TEST_F(Rdata_DNAME_Test, toWireRenderer) { - rdata_dname.toWire(renderer); - matchWireData(wiredata_dname, sizeof(wiredata_dname), - renderer.getData(), renderer.getLength()); - - rdata_dname2.toWire(renderer); - matchWireData(wiredata_dname2, sizeof(wiredata_dname2), - renderer.getData(), renderer.getLength()); -} - -TEST_F(Rdata_DNAME_Test, toText) { - EXPECT_EQ("dn.example.com.", rdata_dname.toText()); -} - -TEST_F(Rdata_DNAME_Test, getDname) { - EXPECT_EQ(Name("dn.example.com."), rdata_dname.getDname()); -} -} diff --git a/src/lib/dns/tests/rdata_dnskey_unittest.cc b/src/lib/dns/tests/rdata_dnskey_unittest.cc index 6f0866df73..8b13789179 100644 --- a/src/lib/dns/tests/rdata_dnskey_unittest.cc +++ b/src/lib/dns/tests/rdata_dnskey_unittest.cc @@ -1,200 +1 @@ -// Copyright (C) 2010-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. -#include <config.h> - -#include <string> - -#include <exceptions/exceptions.h> - -#include <util/buffer.h> -#include <dns/messagerenderer.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> -#include <dns/rrclass.h> -#include <dns/rrtype.h> - -#include <gtest/gtest.h> - -#include <dns/tests/unittest_util.h> -#include <dns/tests/rdata_unittest.h> -#include <util/unittests/wiredata.h> - -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 { -protected: - Rdata_DNSKEY_Test() : - dnskey_txt("257 3 5 BEAAAAOhHQDBrhQbtphgq2wQUpEQ5t4DtUHxoMV" - "Fu2hWLDMvoOMRXjGrhhCeFvAZih7yJHf8ZGfW6hd38hXG/x" - "ylYCO6Krpbdojwx8YMXLA5/kA+u50WIL8ZR1R6KTbsYVMf/" - "Qx5RiNbPClw+vT+U8eXEJmO20jIS1ULgqy347cBB1zMnnz/" - "4LJpA0da9CbKj3A254T515sNIMcwsB8/2+2E63/zZrQzBkj" - "0BrN/9Bexjpiks3jRhZatEsXn3dTy47R09Uix5WcJt+xzqZ" - "7+ysyLKOOedS39Z7SDmsn2eA0FKtQpwA6LXeG2w+jxmw3oA" - "8lVUgEf/rzeC/bByBNsO70aEFTd"), - dnskey_txt2("257 3 5 YmluZDEwLmlzYy5vcmc="), - rdata_dnskey(dnskey_txt), - rdata_dnskey2(dnskey_txt2) - {} - - void checkFromText_None(const string& rdata_str) { - checkFromText<generic::DNSKEY, isc::Exception, isc::Exception>( - rdata_str, rdata_dnskey2, false, false); - } - - void checkFromText_InvalidText(const string& rdata_str) { - checkFromText<generic::DNSKEY, InvalidRdataText, InvalidRdataText>( - rdata_str, rdata_dnskey2, true, true); - } - - void checkFromText_InvalidLength(const string& rdata_str) { - checkFromText<generic::DNSKEY, InvalidRdataLength, InvalidRdataLength>( - rdata_str, rdata_dnskey2, true, true); - } - - void checkFromText_BadValue(const string& rdata_str) { - checkFromText<generic::DNSKEY, BadValue, BadValue>( - rdata_str, rdata_dnskey2, true, true); - } - - void checkFromText_LexerError(const string& rdata_str) { - checkFromText - <generic::DNSKEY, InvalidRdataText, MasterLexer::LexerError>( - rdata_str, rdata_dnskey2, true, true); - } - - void checkFromText_BadString(const string& rdata_str) { - checkFromText - <generic::DNSKEY, InvalidRdataText, isc::Exception>( - rdata_str, rdata_dnskey2, true, false); - } - - const string dnskey_txt; - const string dnskey_txt2; - const generic::DNSKEY rdata_dnskey; - const generic::DNSKEY rdata_dnskey2; -}; - -TEST_F(Rdata_DNSKEY_Test, fromText) { - EXPECT_EQ(dnskey_txt, rdata_dnskey.toText()); - - // Space in key data is OK - checkFromText_None("257 3 5 YmluZDEw LmlzYy5vcmc="); - - // Delimited number in key data is OK - checkFromText_None("257 3 5 YmluZDEwLmlzYy 5 vcmc="); - - // Missing keydata is OK - EXPECT_NO_THROW(const generic::DNSKEY rdata_dnskey3("257 3 5")); - - // Key data too short for RSA/MD5 algorithm is OK when - // constructing. But getTag() on this object would throw (see - // .getTag tests). - EXPECT_NO_THROW(const generic::DNSKEY rdata_dnskey4("1 1 1 YQ==")); - - // Flags field out of range - checkFromText_InvalidText("65536 3 5 YmluZDEwLmlzYy5vcmc="); - - // Protocol field out of range - checkFromText_InvalidText("257 256 5 YmluZDEwLmlzYy5vcmc="); - - // Algorithm field out of range - checkFromText_InvalidText("257 3 256 YmluZDEwLmlzYy5vcmc="); - - // Missing algorithm field - checkFromText_LexerError("257 3 YmluZDEwLmlzYy5vcmc="); - - // Invalid key data field (not Base64) - checkFromText_BadValue("257 3 5 BAAAAAAAAAAAD"); - - // String instead of number - checkFromText_LexerError("foo 3 5 YmluZDEwLmlzYy5vcmc="); - checkFromText_LexerError("257 foo 5 YmluZDEwLmlzYy5vcmc="); - checkFromText_LexerError("257 3 foo YmluZDEwLmlzYy5vcmc="); - - // Trailing garbage. This should cause only the string constructor - // to fail, but the lexer constructor must be able to continue - // parsing from it. - checkFromText_BadString("257 3 5 YmluZDEwLmlzYy5vcmc= ; comment\n" - "257 3 4 YmluZDEwLmlzYy5vcmc="); - - // Unmatched parenthesis should cause a lexer error - checkFromText_LexerError("257 3 5 )YmluZDEwLmlzYy5vcmc="); -} - -TEST_F(Rdata_DNSKEY_Test, assign) { - generic::DNSKEY rdata_dnskey2("257 3 5 YQ=="); - rdata_dnskey2 = rdata_dnskey; - EXPECT_EQ(0, rdata_dnskey.compare(rdata_dnskey2)); -} - -TEST_F(Rdata_DNSKEY_Test, createFromLexer) { - EXPECT_EQ(0, rdata_dnskey.compare( - *test::createRdataUsingLexer(RRType::DNSKEY(), RRClass::IN(), - dnskey_txt))); -} - -TEST_F(Rdata_DNSKEY_Test, toWireRenderer) { - renderer.skip(2); - rdata_dnskey.toWire(renderer); - - vector<unsigned char> data; - UnitTestUtil::readWireData("rdata_dnskey_fromWire.wire", data); - matchWireData(&data[2], data.size() - 2, - static_cast<const uint8_t *>(renderer.getData()) + 2, - renderer.getLength() - 2); -} - -TEST_F(Rdata_DNSKEY_Test, toWireBuffer) { - rdata_dnskey.toWire(obuffer); - - vector<unsigned char> data; - UnitTestUtil::readWireData("rdata_dnskey_fromWire.wire", data); - matchWireData(&data[2], data.size() - 2, - obuffer.getData(), obuffer.getLength()); -} - -TEST_F(Rdata_DNSKEY_Test, createFromWire) { - EXPECT_EQ(0, rdata_dnskey.compare( - *rdataFactoryFromFile(RRType("DNSKEY"), RRClass("IN"), - "rdata_dnskey_fromWire.wire"))); - - // Missing keydata is OK - const generic::DNSKEY rdata_dnskey_missing_keydata("257 3 5"); - EXPECT_EQ(0, rdata_dnskey_missing_keydata.compare( - *rdataFactoryFromFile(RRType("DNSKEY"), RRClass("IN"), - "rdata_dnskey_empty_keydata_fromWire.wire"))); -} - -TEST_F(Rdata_DNSKEY_Test, getTag) { - EXPECT_EQ(12892, rdata_dnskey.getTag()); - - // Short keydata with algorithm RSA/MD5 must throw. - const generic::DNSKEY rdata_dnskey_short_keydata1("1 1 1 YQ=="); - EXPECT_THROW(rdata_dnskey_short_keydata1.getTag(), isc::OutOfRange); - - // Short keydata with algorithm not RSA/MD5 must not throw. - const generic::DNSKEY rdata_dnskey_short_keydata2("257 3 5 YQ=="); - EXPECT_NO_THROW(rdata_dnskey_short_keydata2.getTag()); -} - -TEST_F(Rdata_DNSKEY_Test, getAlgorithm) { - EXPECT_EQ(5, rdata_dnskey.getAlgorithm()); -} - -TEST_F(Rdata_DNSKEY_Test, getFlags) { - EXPECT_EQ(257, rdata_dnskey.getFlags()); -} - -} diff --git a/src/lib/dns/tests/rdata_ds_like_unittest.cc b/src/lib/dns/tests/rdata_ds_like_unittest.cc index d4ea924020..8b13789179 100644 --- a/src/lib/dns/tests/rdata_ds_like_unittest.cc +++ b/src/lib/dns/tests/rdata_ds_like_unittest.cc @@ -1,229 +1 @@ -// Copyright (C) 2011-2019 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. -#include <config.h> - -#include <algorithm> -#include <string> - -#include <util/buffer.h> -#include <dns/messagerenderer.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> -#include <dns/rrclass.h> -#include <dns/rrtype.h> - -#include <gtest/gtest.h> - -#include <dns/tests/unittest_util.h> -#include <dns/tests/rdata_unittest.h> -#include <util/unittests/wiredata.h> - -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 -template <class T> -class RRTYPE : public RRType { -public: - RRTYPE(); -}; - -template<> RRTYPE<generic::DS>::RRTYPE() : RRType(RRType::DS()) {} -template<> RRTYPE<generic::DLV>::RRTYPE() : RRType(RRType::DLV()) {} - -template <class DS_LIKE> -class Rdata_DS_LIKE_Test : public RdataTest { -protected: - Rdata_DS_LIKE_Test() : - ds_like_txt("12892 5 2 F1E184C0E1D615D20EB3C223ACED3B03C773DD952D" - "5F0EB5C777586DE18DA6B5"), - rdata_ds_like(ds_like_txt) - {} - const string ds_like_txt; - const DS_LIKE rdata_ds_like; -}; - -// The list of types we want to test. -typedef testing::Types<generic::DS, generic::DLV> Implementations; - -#ifdef TYPED_TEST_SUITE -TYPED_TEST_SUITE(Rdata_DS_LIKE_Test, Implementations); -#else -TYPED_TEST_CASE(Rdata_DS_LIKE_Test, Implementations); -#endif - -TYPED_TEST(Rdata_DS_LIKE_Test, createFromText) { - // It's valid for the digest's presentation format to contain - // spaces. See RFC4034 section 5.3. - EXPECT_EQ(0, this->rdata_ds_like.compare( - TypeParam("12892 5 2 F1E184C0E1D615D20EB3C223ACED3B03C773DD952D5F0EB5" - "C777 58 6DE18 \t DA6B5"))); -} - -TYPED_TEST(Rdata_DS_LIKE_Test, toText_DS_LIKE) { - EXPECT_EQ(this->ds_like_txt, this->rdata_ds_like.toText()); -} - -TYPED_TEST(Rdata_DS_LIKE_Test, badText_DS_LIKE) { - EXPECT_THROW(const TypeParam ds_like2("99999 5 2 BEEF"), InvalidRdataText); - EXPECT_THROW(const TypeParam ds_like2("11111 555 2 BEEF"), - InvalidRdataText); - EXPECT_THROW(const TypeParam ds_like2("11111 5 22222 BEEF"), - InvalidRdataText); - EXPECT_THROW(const TypeParam ds_like2("11111 5 2"), InvalidRdataText); - EXPECT_THROW(const TypeParam ds_like2("GARBAGE IN"), InvalidRdataText); - // no space between the digest type and the digest. - EXPECT_THROW(const TypeParam ds_like2( - "12892 5 2F1E184C0E1D615D20EB3C223ACED3B03C773DD952D" - "5F0EB5C777586DE18DA6B5"), InvalidRdataText); -} - -TYPED_TEST(Rdata_DS_LIKE_Test, createFromWire_DS_LIKE) { - EXPECT_EQ(0, this->rdata_ds_like.compare( - *this->rdataFactoryFromFile(RRTYPE<TypeParam>(), RRClass::IN(), - "rdata_ds_fromWire"))); -} - -TYPED_TEST(Rdata_DS_LIKE_Test, createFromLexer_DS_LIKE) { - EXPECT_EQ(0, this->rdata_ds_like.compare( - *test::createRdataUsingLexer(RRTYPE<TypeParam>(), RRClass::IN(), - this->ds_like_txt))); - - // Whitespace is okay - EXPECT_EQ(0, this->rdata_ds_like.compare( - *test::createRdataUsingLexer(RRTYPE<TypeParam>(), RRClass::IN(), - "12892 5 2 F1E184C0E1D615D20EB3C223ACED3B0" - "3C773DD952D5F0EB5C777 58 6DE18 \t DA6B5" - ))); - - // Exceptions cause NULL to be returned. - - // Bad tag - EXPECT_FALSE(test::createRdataUsingLexer(RRTYPE<TypeParam>(), RRClass::IN(), - "65536 5 2 BEEF")); - - // Bad algorithm - EXPECT_FALSE(test::createRdataUsingLexer(RRTYPE<TypeParam>(), RRClass::IN(), - "1024 256 2 BEEF")); - - // Bad digest type - EXPECT_FALSE(test::createRdataUsingLexer(RRTYPE<TypeParam>(), RRClass::IN(), - "2048 2 256 BEEF")); -} - -TYPED_TEST(Rdata_DS_LIKE_Test, assignment_DS_LIKE) { - TypeParam copy(this->ds_like_txt); - copy = this->rdata_ds_like; - EXPECT_EQ(0, copy.compare(this->rdata_ds_like)); - - // Check if the copied data is valid even after the original is deleted - TypeParam* copy2 = new TypeParam(this->rdata_ds_like); - TypeParam copy3(this->ds_like_txt); - copy3 = *copy2; - delete copy2; - EXPECT_EQ(0, copy3.compare(this->rdata_ds_like)); - - // Self assignment - copy = *© - EXPECT_EQ(0, copy.compare(this->rdata_ds_like)); -} - -TYPED_TEST(Rdata_DS_LIKE_Test, getTag_DS_LIKE) { - EXPECT_EQ(12892, this->rdata_ds_like.getTag()); -} - -TYPED_TEST(Rdata_DS_LIKE_Test, toWireRenderer) { - Rdata_DS_LIKE_Test<TypeParam>::renderer.skip(2); - TypeParam rdata_ds_like(this->ds_like_txt); - rdata_ds_like.toWire(this->renderer); - - vector<unsigned char> data; - UnitTestUtil::readWireData("rdata_ds_fromWire", data); - matchWireData(&data[2], data.size() - 2, - static_cast<const uint8_t*>(this->renderer.getData()) + 2, - this->renderer.getLength() - 2); -} - -TYPED_TEST(Rdata_DS_LIKE_Test, toWireBuffer) { - TypeParam rdata_ds_like(this->ds_like_txt); - rdata_ds_like.toWire(this->obuffer); -} - -string ds_like_txt1("12892 5 2 F1E184C0E1D615D20EB3C223ACED3B03C773DD952D" - "5F0EB5C777586DE18DA6B5"); -// different tag -string ds_like_txt2("12893 5 2 F1E184C0E1D615D20EB3C223ACED3B03C773DD952D" - "5F0EB5C777586DE18DA6B5"); -// different algorithm -string ds_like_txt3("12892 6 2 F1E184C0E1D615D20EB3C223ACED3B03C773DD952D" - "5F0EB5C777586DE18DA6B5"); -// different digest type -string ds_like_txt4("12892 5 3 F1E184C0E1D615D20EB3C223ACED3B03C773DD952D" - "5F0EB5C777586DE18DA6B5"); -// different digest -string ds_like_txt5("12892 5 2 F2E184C0E1D615D20EB3C223ACED3B03C773DD952D" - "5F0EB5C777586DE18DA6B5"); -// different digest length -string ds_like_txt6("12892 5 2 F2E184C0E1D615D20EB3C223ACED3B03C773DD952D" - "5F0EB5C777586DE18DA6B555"); - -TYPED_TEST(Rdata_DS_LIKE_Test, compare) { - const string ds_like_txt1( - "12892 5 2 F1E184C0E1D615D20EB3C223ACED3B03C773DD952D" - "5F0EB5C777586DE18DA6B5"); - // different tag - const string ds_like_txt2( - "12893 5 2 F1E184C0E1D615D20EB3C223ACED3B03C773DD952D" - "5F0EB5C777586DE18DA6B5"); - // different algorithm - const string ds_like_txt3( - "12892 6 2 F1E184C0E1D615D20EB3C223ACED3B03C773DD952D" - "5F0EB5C777586DE18DA6B5"); - // different digest type - const string ds_like_txt4( - "12892 5 3 F1E184C0E1D615D20EB3C223ACED3B03C773DD952D" - "5F0EB5C777586DE18DA6B5"); - // different digest - const string ds_like_txt5( - "12892 5 2 F2E184C0E1D615D20EB3C223ACED3B03C773DD952D" - "5F0EB5C777586DE18DA6B5"); - // different digest length - const string ds_like_txt6( - "12892 5 2 F2E184C0E1D615D20EB3C223ACED3B03C773DD952D" - "5F0EB5C777586DE18DA6B555"); - - // trivial case: self equivalence - EXPECT_EQ(0, TypeParam(this->ds_like_txt). - compare(TypeParam(this->ds_like_txt))); - - // non-equivalence tests - EXPECT_LT(TypeParam(ds_like_txt1).compare(TypeParam(ds_like_txt2)), 0); - EXPECT_GT(TypeParam(ds_like_txt2).compare(TypeParam(ds_like_txt1)), 0); - - EXPECT_LT(TypeParam(ds_like_txt1).compare(TypeParam(ds_like_txt3)), 0); - EXPECT_GT(TypeParam(ds_like_txt3).compare(TypeParam(ds_like_txt1)), 0); - - EXPECT_LT(TypeParam(ds_like_txt1).compare(TypeParam(ds_like_txt4)), 0); - EXPECT_GT(TypeParam(ds_like_txt4).compare(TypeParam(ds_like_txt1)), 0); - - EXPECT_LT(TypeParam(ds_like_txt1).compare(TypeParam(ds_like_txt5)), 0); - EXPECT_GT(TypeParam(ds_like_txt5).compare(TypeParam(ds_like_txt1)), 0); - - EXPECT_LT(TypeParam(ds_like_txt1).compare(TypeParam(ds_like_txt6)), 0); - EXPECT_GT(TypeParam(ds_like_txt6).compare(TypeParam(ds_like_txt1)), 0); - - // comparison attempt between incompatible RR types should be rejected - EXPECT_THROW(this->rdata_ds_like.compare(*this->rdata_nomatch), - bad_cast); -} - -} diff --git a/src/lib/dns/tests/rdata_hinfo_unittest.cc b/src/lib/dns/tests/rdata_hinfo_unittest.cc index 1830f0550e..8b13789179 100644 --- a/src/lib/dns/tests/rdata_hinfo_unittest.cc +++ b/src/lib/dns/tests/rdata_hinfo_unittest.cc @@ -1,154 +1 @@ -// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. -#include <config.h> - -#include <util/buffer.h> -#include <dns/exceptions.h> -#include <dns/messagerenderer.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> -#include <dns/rrclass.h> -#include <dns/rrtype.h> - -#include <gtest/gtest.h> - -#include <dns/tests/unittest_util.h> -#include <dns/tests/rdata_unittest.h> -#include <util/unittests/wiredata.h> - -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 { -}; - -static uint8_t hinfo_rdata[] = {0x07,0x50,0x65,0x6e,0x74,0x69,0x75,0x6d,0x05, - 0x4c,0x69,0x6e,0x75,0x78}; -static const char *hinfo_str = "\"Pentium\" \"Linux\""; -static const char *hinfo_str1 = "\"Pen\\\"tium\" \"Linux\""; - -static const char *hinfo_str_equal = "\"Pentium\"\"Linux\""; -static const char *hinfo_str_small1 = "\"Lentium\" \"Linux\""; -static const char *hinfo_str_small2 = "\"Pentium\" \"Kinux\""; -static const char *hinfo_str_large1 = "\"Qentium\" \"Linux\""; -static const char *hinfo_str_large2 = "\"Pentium\" \"UNIX\""; - -TEST_F(Rdata_HINFO_Test, createFromText) { - HINFO hinfo(hinfo_str); - EXPECT_EQ(string("Pentium"), hinfo.getCPU()); - EXPECT_EQ(string("Linux"), hinfo.getOS()); - // Test the text with double quotes in the middle of string - HINFO hinfo1(hinfo_str1); - EXPECT_EQ(string("Pen\\\"tium"), hinfo1.getCPU()); -} - -TEST_F(Rdata_HINFO_Test, badText) { - // Only 2 fields must exist - EXPECT_THROW(const HINFO hinfo("\"Pentium\"\"Linux\"\"Computer\""), - InvalidRdataText); - EXPECT_THROW(const HINFO hinfo("\"Pentium\" \"Linux\" \"Computer\""), - InvalidRdataText); - // Field cannot be missing - EXPECT_THROW(const HINFO hinfo("Pentium"), InvalidRdataText); - // The <character-string> cannot exceed 255 characters - string hinfo_str; - for (int i = 0; i < 257; ++i) { - hinfo_str += 'A'; - } - hinfo_str += " Linux"; - EXPECT_THROW(const HINFO hinfo(hinfo_str), CharStringTooLong); -} - -TEST_F(Rdata_HINFO_Test, createFromWire) { - InputBuffer input_buffer(hinfo_rdata, sizeof(hinfo_rdata)); - HINFO hinfo(input_buffer, sizeof(hinfo_rdata)); - EXPECT_EQ(string("Pentium"), hinfo.getCPU()); - EXPECT_EQ(string("Linux"), hinfo.getOS()); -} - -TEST_F(Rdata_HINFO_Test, createFromLexer) { - HINFO rdata_hinfo(hinfo_str); - EXPECT_EQ(0, rdata_hinfo.compare( - *test::createRdataUsingLexer(RRType::HINFO(), RRClass::IN(), - hinfo_str))); - EXPECT_EQ(0, rdata_hinfo.compare( - *test::createRdataUsingLexer(RRType::HINFO(), RRClass::IN(), - "\"Pentium\"\"Linux\""))); - // Exceptions cause NULL to be returned. - EXPECT_FALSE(test::createRdataUsingLexer(RRType::HINFO(), RRClass::IN(), - "\"Pentium\"\"Linux\"" - "\"Computer\"")); - EXPECT_FALSE(test::createRdataUsingLexer(RRType::HINFO(), RRClass::IN(), - "\"Pentium\" \"Linux\" " - "\"Computer\"")); - EXPECT_FALSE(test::createRdataUsingLexer(RRType::HINFO(), RRClass::IN(), - "\"Pentium\"")); -} - -TEST_F(Rdata_HINFO_Test, toText) { - HINFO hinfo(hinfo_str); - EXPECT_EQ(hinfo_str, hinfo.toText()); - - // will add quotes even if they were not in the original input - EXPECT_EQ("\"a\" \"b\"", HINFO("a b").toText()); - // will not add additional quotes - EXPECT_EQ("\"a\" \"b\"", HINFO("\"a\" \"b\"").toText()); - // And make sure escaped quotes and spaces are left intact - EXPECT_EQ("\"a\\\"\" \"b c\"", HINFO("\"a\\\"\" \"b c\"").toText()); -} - -TEST_F(Rdata_HINFO_Test, toWire) { - HINFO hinfo(hinfo_str); - - 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); - matchWireData(hinfo_rdata, sizeof (hinfo_rdata), - renderer.getData(), renderer.getLength()); -} - -TEST_F(Rdata_HINFO_Test, compare) { - HINFO hinfo(hinfo_str); - HINFO hinfo_small1(hinfo_str_small1); - HINFO hinfo_small2(hinfo_str_small2); - HINFO hinfo_large1(hinfo_str_large1); - HINFO hinfo_large2(hinfo_str_large2); - - EXPECT_EQ(0, hinfo.compare(HINFO(hinfo_str))); - EXPECT_EQ(0, hinfo.compare(HINFO(hinfo_str_equal))); - EXPECT_EQ(1, hinfo.compare(HINFO(hinfo_str_small1))); - EXPECT_EQ(1, hinfo.compare(HINFO(hinfo_str_small2))); - EXPECT_EQ(-1, hinfo.compare(HINFO(hinfo_str_large1))); - EXPECT_EQ(-1, hinfo.compare(HINFO(hinfo_str_large2))); -} - -// Copy/assign test -TEST_F(Rdata_HINFO_Test, copy) { - HINFO hinfo(hinfo_str); - HINFO hinfo2(hinfo); - HINFO hinfo3 = hinfo; - - EXPECT_EQ(0, hinfo.compare(hinfo2)); - EXPECT_EQ(0, hinfo.compare(hinfo3)); - - hinfo3 = hinfo; - EXPECT_EQ(0, hinfo.compare(hinfo3)); -} - -} diff --git a/src/lib/dns/tests/rdata_in_a_unittest.cc b/src/lib/dns/tests/rdata_in_a_unittest.cc index 809cfb5bd4..8b13789179 100644 --- a/src/lib/dns/tests/rdata_in_a_unittest.cc +++ b/src/lib/dns/tests/rdata_in_a_unittest.cc @@ -1,159 +1 @@ -// Copyright (C) 2010-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. -#include <config.h> - -#include <dns/rdataclass.h> - -#include <util/buffer.h> -#include <dns/exceptions.h> -#include <dns/messagerenderer.h> -#include <dns/master_lexer.h> -#include <dns/master_loader.h> -#include <dns/rdata.h> -#include <dns/rrclass.h> -#include <dns/rrtype.h> - -#include <gtest/gtest.h> - -#include <dns/tests/unittest_util.h> -#include <dns/tests/rdata_unittest.h> -#include <util/unittests/wiredata.h> - -#include <sstream> - -#include <arpa/inet.h> -#include <sys/socket.h> - -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 { -protected: - Rdata_IN_A_Test() : rdata_in_a("192.0.2.1") {} - - void checkFromTextIN_A(const std::string& rdata_txt, - bool throw_str_version = true, - bool throw_lexer_version = true) { - checkFromText<in::A, InvalidRdataText, InvalidRdataText>( - rdata_txt, rdata_in_a, throw_str_version, throw_lexer_version); - } - - const in::A rdata_in_a; -}; - -const uint8_t wiredata_in_a[] = { 192, 0, 2, 1 }; - -TEST_F(Rdata_IN_A_Test, createFromText) { - // Normal case: no exception for either case, so the exception type - // doesn't matter. - checkFromText<in::A, isc::Exception, isc::Exception>("192.0.2.1", - rdata_in_a, false, - false); - - // should reject an abbreviated form of IPv4 address - checkFromTextIN_A("10.1"); - // or an IPv6 address - checkFromTextIN_A("2001:db8::1234"); - // or any meaningless text as an IP address - checkFromTextIN_A("xxx"); - - // NetBSD's inet_pton accepts trailing space after an IPv4 address, which - // would confuse some of the tests below. We check the case differently - // in these cases depending on the strictness of inet_pton (most - // implementations seem to be stricter). - uint8_t v4addr_buf[4]; - const bool reject_extra_space = - inet_pton(AF_INET, "192.0.2.1 ", v4addr_buf) == 0; - - // trailing white space: only string version throws - checkFromTextIN_A("192.0.2.1 ", reject_extra_space, false); - // same for beginning white space. - checkFromTextIN_A(" 192.0.2.1", true, false); - // same for trailing non-space garbage (note that lexer version still - // ignore it; it's expected to be detected at a higher layer). - checkFromTextIN_A("192.0.2.1 xxx", reject_extra_space, false); - - // nul character after a valid textual representation. - string nul_after_addr = "192.0.2.1"; - nul_after_addr.push_back(0); - checkFromTextIN_A(nul_after_addr, true, true); - - // a valid address surrounded by parentheses; only okay with lexer - checkFromTextIN_A("(192.0.2.1)", true, false); - - // input that would cause lexer-specific error; it's bad text as an - // address so should result in the string version, too. - checkFromText<in::A, InvalidRdataText, MasterLexer::LexerError>( - ")192.0.2.1", rdata_in_a); -} - -TEST_F(Rdata_IN_A_Test, createFromWire) { - // Valid data - EXPECT_EQ(0, rdata_in_a.compare( - *rdataFactoryFromFile(RRType::A(), RRClass::IN(), - "rdata_in_a_fromWire"))); - // RDLENGTH is too short - EXPECT_THROW(rdataFactoryFromFile(RRType::A(), RRClass::IN(), - "rdata_in_a_fromWire", 6), - DNSMessageFORMERR); - // RDLENGTH is too long - EXPECT_THROW(rdataFactoryFromFile(RRType::A(), RRClass::IN(), - "rdata_in_a_fromWire", 12), - DNSMessageFORMERR); - // buffer too short. - EXPECT_THROW(rdataFactoryFromFile(RRType::A(), RRClass::IN(), - "rdata_in_a_fromWire", 19), - DNSMessageFORMERR); -} - -TEST_F(Rdata_IN_A_Test, toWireBuffer) { - rdata_in_a.toWire(obuffer); - matchWireData(wiredata_in_a, sizeof (wiredata_in_a), - obuffer.getData(), obuffer.getLength()); -} - -TEST_F(Rdata_IN_A_Test, toWireRenderer) { - rdata_in_a.toWire(renderer); - matchWireData(wiredata_in_a, sizeof (wiredata_in_a), - renderer.getData(), renderer.getLength()); -} - -TEST_F(Rdata_IN_A_Test, toText) { - EXPECT_EQ("192.0.2.1", rdata_in_a.toText()); - - // this shouldn't make the code crash - const string longaddr("255.255.255.255"); - EXPECT_EQ(longaddr, in::A(longaddr).toText()); -} - -TEST_F(Rdata_IN_A_Test, compare) { - const in::A small1("1.1.1.1"); - const in::A small2("1.2.3.4"); - const in::A large1("255.255.255.255"); - const in::A large2("4.3.2.1"); - - // trivial case: self equivalence - // cppcheck-suppress uselessCallsCompare - EXPECT_EQ(0, small1.compare(small1)); - - // confirm these are compared as unsigned values - EXPECT_GT(0, small1.compare(large1)); - EXPECT_LT(0, large1.compare(small1)); - - // confirm these are compared in network byte order - EXPECT_GT(0, small2.compare(large2)); - EXPECT_LT(0, large2.compare(small2)); - - // comparison attempt between incompatible RR types should be rejected - EXPECT_THROW(rdata_in_a.compare(*RdataTest::rdata_nomatch), bad_cast); -} -} diff --git a/src/lib/dns/tests/rdata_in_aaaa_unittest.cc b/src/lib/dns/tests/rdata_in_aaaa_unittest.cc index cc7b07d8c6..8b13789179 100644 --- a/src/lib/dns/tests/rdata_in_aaaa_unittest.cc +++ b/src/lib/dns/tests/rdata_in_aaaa_unittest.cc @@ -1,151 +1 @@ -// Copyright (C) 2010-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. -#include <config.h> - -#include <util/buffer.h> -#include <dns/exceptions.h> -#include <dns/messagerenderer.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> -#include <dns/rrclass.h> -#include <dns/rrtype.h> - -#include <gtest/gtest.h> - -#include <dns/tests/unittest_util.h> -#include <dns/tests/rdata_unittest.h> -#include <util/unittests/wiredata.h> - -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 { -protected: - Rdata_IN_AAAA_Test() : rdata_in_aaaa("2001:db8::1234") {} - - // Common check to see the result of in::A Rdata construction either from - // std::string or with MasterLexer object. If it's expected to succeed - // the result should be identical to the commonly used test data - // (rdata_in_a); otherwise it should result in the exception specified as - // the template parameter. - void checkFromTextIN_AAAA(const string& in_aaaa_txt, - bool throw_str_version = true, - bool throw_lexer_version = true) - { - checkFromText<in::AAAA, InvalidRdataText, InvalidRdataText>( - in_aaaa_txt, rdata_in_aaaa, throw_str_version, - throw_lexer_version); - } - - const in::AAAA rdata_in_aaaa; -}; - -const uint8_t wiredata_in_aaaa[] = { - 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x12, 0x34 }; - -TEST_F(Rdata_IN_AAAA_Test, createFromText) { - // Normal case: no exception for either case, so the exception type - // doesn't matter. - checkFromText<in::AAAA, isc::Exception, isc::Exception>( - "2001:db8::1234", rdata_in_aaaa, false, false); - - // should reject an IP4 address. - checkFromTextIN_AAAA("192.0.2.1"); - // or any meaningless text as an IPv6 address - checkFromTextIN_AAAA("xxx"); - - // trailing white space: only string version throws - checkFromTextIN_AAAA("2001:db8::1234 ", true, false); - // same for beginning white space. - checkFromTextIN_AAAA(" 2001:db8::1234", true, false); - // same for trailing non-space garbage (note that lexer version still - // ignore it; it's expected to be detected at a higher layer). - checkFromTextIN_AAAA("2001:db8::1234 xxx", true, false); - - // nul character after a valid textual representation. - string nul_after_addr = "2001:db8::1234"; - nul_after_addr.push_back(0); - checkFromTextIN_AAAA(nul_after_addr, true, true); - - // a valid address surrounded by parentheses; only okay with lexer - checkFromTextIN_AAAA("(2001:db8::1234)", true, false); - - // input that would cause lexer-specific error; it's bad text as an - // address so should result in the string version, too. - checkFromText<in::AAAA, InvalidRdataText, MasterLexer::LexerError>( - ")2001:db8::1234", rdata_in_aaaa); -} - -TEST_F(Rdata_IN_AAAA_Test, createFromWire) { - // Valid data - EXPECT_EQ(0, rdata_in_aaaa.compare( - *rdataFactoryFromFile(RRType::AAAA(), RRClass::IN(), - "rdata_in_aaaa_fromWire"))); - // RDLENGTH is too short - EXPECT_THROW(rdataFactoryFromFile(RRType::AAAA(), RRClass::IN(), - "rdata_in_aaaa_fromWire", 18), - DNSMessageFORMERR); - // RDLENGTH is too long - EXPECT_THROW(rdataFactoryFromFile(RRType::AAAA(), RRClass::IN(), - "rdata_in_aaaa_fromWire", 36), - DNSMessageFORMERR); - // buffer too short. - EXPECT_THROW(rdataFactoryFromFile(RRType::AAAA(), RRClass::IN(), - "rdata_in_aaaa_fromWire", 55), - DNSMessageFORMERR); -} - -TEST_F(Rdata_IN_AAAA_Test, createFromLexer) { - EXPECT_EQ(0, rdata_in_aaaa.compare( - *test::createRdataUsingLexer(RRType::AAAA(), RRClass::IN(), - "2001:db8::1234"))); -} - -TEST_F(Rdata_IN_AAAA_Test, toWireBuffer) { - rdata_in_aaaa.toWire(obuffer); - matchWireData(wiredata_in_aaaa, sizeof (wiredata_in_aaaa), - obuffer.getData(), obuffer.getLength()); -} - -TEST_F(Rdata_IN_AAAA_Test, toWireRenderer) { - rdata_in_aaaa.toWire(renderer); - matchWireData(wiredata_in_aaaa, sizeof (wiredata_in_aaaa), - renderer.getData(), renderer.getLength()); -} - -TEST_F(Rdata_IN_AAAA_Test, toText) { - EXPECT_EQ("2001:db8::1234", rdata_in_aaaa.toText()); -} - -TEST_F(Rdata_IN_AAAA_Test, compare) { - in::AAAA small1("::1"); - in::AAAA small2("1:2:3:4:5:6:7:8"); - in::AAAA large1("ffff::"); - in::AAAA large2("8:7:6:5:4:3:2:1"); - - // trivial case: self equivalence - // cppcheck-suppress uselessCallsCompare - EXPECT_EQ(0, small1.compare(small1)); - - // confirm these are compared as unsigned values - EXPECT_GT(0, small1.compare(large1)); - EXPECT_LT(0, large1.compare(small1)); - - // confirm these are compared in network byte order - EXPECT_GT(0, small2.compare(large2)); - EXPECT_LT(0, large2.compare(small2)); - - // comparison attempt between incompatible RR types should be rejected - EXPECT_THROW(rdata_in_aaaa.compare(*RdataTest::rdata_nomatch), bad_cast); -} -} diff --git a/src/lib/dns/tests/rdata_minfo_unittest.cc b/src/lib/dns/tests/rdata_minfo_unittest.cc index 35ff55cb91..8b13789179 100644 --- a/src/lib/dns/tests/rdata_minfo_unittest.cc +++ b/src/lib/dns/tests/rdata_minfo_unittest.cc @@ -1,230 +1 @@ -// Copyright (C) 2011-2019 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. -#include <config.h> - -#include <string> - -#include <util/buffer.h> -#include <dns/exceptions.h> -#include <dns/messagerenderer.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> -#include <dns/rrclass.h> -#include <dns/rrtype.h> - -#include <gtest/gtest.h> - -#include <dns/tests/unittest_util.h> -#include <dns/tests/rdata_unittest.h> -#include <util/unittests/wiredata.h> - -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 { -protected: - Rdata_MINFO_Test(): - minfo_txt("rmailbox.example.com. emailbox.example.com."), - minfo_txt2("root.example.com. emailbox.example.com."), - too_long_label("01234567890123456789012345678901234567" - "89012345678901234567890123."), - rdata_minfo(minfo_txt), - rdata_minfo2(minfo_txt2) - {} - - void checkFromText_None(const string& rdata_str) { - checkFromText<generic::MINFO, isc::Exception, isc::Exception>( - rdata_str, rdata_minfo, false, false); - } - - void checkFromText_LexerError(const string& rdata_str) { - checkFromText - <generic::MINFO, InvalidRdataText, MasterLexer::LexerError>( - rdata_str, rdata_minfo, true, true); - } - - void checkFromText_TooLongLabel(const string& rdata_str) { - checkFromText<generic::MINFO, TooLongLabel, TooLongLabel>( - rdata_str, rdata_minfo, true, true); - } - - void checkFromText_BadString(const string& rdata_str) { - checkFromText<generic::MINFO, InvalidRdataText, isc::Exception>( - rdata_str, rdata_minfo, true, false); - } - - void checkFromText_EmptyLabel(const string& rdata_str) { - checkFromText<generic::MINFO, EmptyLabel, EmptyLabel>( - rdata_str, rdata_minfo, true, true); - } - - void checkFromText_MissingOrigin(const string& rdata_str) { - checkFromText - <generic::MINFO, MissingNameOrigin, MissingNameOrigin>( - rdata_str, rdata_minfo, true, true); - } - - void checkFromText_Origin(const string& rdata_str, const Name* origin) { - checkFromText<generic::MINFO, MissingNameOrigin, isc::Exception>( - rdata_str, rdata_minfo, true, false, origin); - } - - const string minfo_txt; - const string minfo_txt2; - const string too_long_label; - const generic::MINFO rdata_minfo; - const generic::MINFO rdata_minfo2; -}; - - -TEST_F(Rdata_MINFO_Test, createFromText) { - EXPECT_EQ(Name("rmailbox.example.com."), rdata_minfo.getRmailbox()); - EXPECT_EQ(Name("emailbox.example.com."), rdata_minfo.getEmailbox()); - - EXPECT_EQ(Name("root.example.com."), rdata_minfo2.getRmailbox()); - EXPECT_EQ(Name("emailbox.example.com."), rdata_minfo2.getEmailbox()); - - checkFromText_None(minfo_txt); - - // origin defined for lexer constructor, but not string constructor - const Name origin("example.com"); - checkFromText_Origin("rmailbox emailbox", &origin); - - // lexer constructor accepts extra text, but string constructor doesn't - checkFromText_BadString("rmailbox.example.com. emailbox.example.com. " - "extra.example.com."); -} - -TEST_F(Rdata_MINFO_Test, badText) { - // too long names - checkFromText_TooLongLabel("root.example.com." + too_long_label + - " emailbox.example.com."); - checkFromText_TooLongLabel("root.example.com. emailbox.example.com." + - too_long_label); - - // invalid names - checkFromText_EmptyLabel("root..example.com. emailbox.example.com."); - checkFromText_EmptyLabel("root.example.com. emailbox..example.com."); - - // missing name - checkFromText_LexerError("root.example.com."); - - // missing origin - checkFromText_MissingOrigin("root.example.com emailbox.example.com."); - checkFromText_MissingOrigin("root.example.com. emailbox.example.com"); -} - -TEST_F(Rdata_MINFO_Test, createFromWire) { - // uncompressed names - EXPECT_EQ(0, rdata_minfo.compare( - *rdataFactoryFromFile(RRType::MINFO(), RRClass::IN(), - "rdata_minfo_fromWire1.wire"))); - // compressed names - EXPECT_EQ(0, rdata_minfo.compare( - *rdataFactoryFromFile(RRType::MINFO(), RRClass::IN(), - "rdata_minfo_fromWire2.wire", 15))); - // RDLENGTH is too short - EXPECT_THROW(rdataFactoryFromFile(RRType::MINFO(), RRClass::IN(), - "rdata_minfo_fromWire3.wire"), - InvalidRdataLength); - // RDLENGTH is too long - EXPECT_THROW(rdataFactoryFromFile(RRType::MINFO(), RRClass::IN(), - "rdata_minfo_fromWire4.wire"), - InvalidRdataLength); - // bogus rmailbox name, the error should be detected in the name - // constructor - EXPECT_THROW(rdataFactoryFromFile(RRType::MINFO(), RRClass::IN(), - "rdata_minfo_fromWire5.wire"), - DNSMessageFORMERR); - // bogus emailbox name, the error should be detected in the name - // constructor - EXPECT_THROW(rdataFactoryFromFile(RRType::MINFO(), RRClass::IN(), - "rdata_minfo_fromWire6.wire"), - DNSMessageFORMERR); -} - -TEST_F(Rdata_MINFO_Test, assignment) { - generic::MINFO copy((string(minfo_txt2))); - copy = rdata_minfo; - EXPECT_EQ(0, copy.compare(rdata_minfo)); - - // Check if the copied data is valid even after the original is deleted - generic::MINFO* copy2 = new generic::MINFO(rdata_minfo); - generic::MINFO copy3((string(minfo_txt2))); - copy3 = *copy2; - delete copy2; - EXPECT_EQ(0, copy3.compare(rdata_minfo)); - - // Self assignment - copy = *© - EXPECT_EQ(0, copy.compare(rdata_minfo)); -} - -TEST_F(Rdata_MINFO_Test, toWireBuffer) { - rdata_minfo.toWire(obuffer); - vector<unsigned char> data; - UnitTestUtil::readWireData("rdata_minfo_toWireUncompressed1.wire", data); - matchWireData(&data[0], data.size(), - obuffer.getData(), obuffer.getLength()); - - obuffer.clear(); - rdata_minfo2.toWire(obuffer); - vector<unsigned char> data2; - UnitTestUtil::readWireData("rdata_minfo_toWireUncompressed2.wire", data2); - matchWireData(&data2[0], data2.size(), - obuffer.getData(), obuffer.getLength()); -} - -TEST_F(Rdata_MINFO_Test, toWireRenderer) { - rdata_minfo.toWire(renderer); - vector<unsigned char> data; - UnitTestUtil::readWireData("rdata_minfo_toWire1.wire", data); - matchWireData(&data[0], data.size(), - renderer.getData(), renderer.getLength()); - - renderer.clear(); - rdata_minfo2.toWire(renderer); - vector<unsigned char> data2; - UnitTestUtil::readWireData("rdata_minfo_toWire2.wire", data2); - matchWireData(&data2[0], data2.size(), - renderer.getData(), renderer.getLength()); -} - -TEST_F(Rdata_MINFO_Test, toText) { - EXPECT_EQ(minfo_txt, rdata_minfo.toText()); - EXPECT_EQ(minfo_txt2, rdata_minfo2.toText()); -} - -TEST_F(Rdata_MINFO_Test, compare) { - // check reflexivity - EXPECT_EQ(0, rdata_minfo.compare(rdata_minfo)); - - // names must be compared in case-insensitive manner - EXPECT_EQ(0, rdata_minfo.compare(generic::MINFO("RMAILBOX.example.com. " - "emailbox.EXAMPLE.com."))); - - // another MINFO whose rmailbox name is larger than that of rdata_minfo. - const generic::MINFO large1_minfo("zzzzzzzz.example.com. " - "emailbox.example.com."); - EXPECT_GT(0, rdata_minfo.compare(large1_minfo)); - EXPECT_LT(0, large1_minfo.compare(rdata_minfo)); - - // another MINFO whose emailbox name is larger than that of rdata_minfo. - const generic::MINFO large2_minfo("rmailbox.example.com. " - "zzzzzzzzzzz.example.com."); - EXPECT_GT(0, rdata_minfo.compare(large2_minfo)); - EXPECT_LT(0, large2_minfo.compare(rdata_minfo)); - - // comparison attempt between incompatible RR types should be rejected - EXPECT_THROW(rdata_minfo.compare(*RdataTest::rdata_nomatch), bad_cast); -} -} diff --git a/src/lib/dns/tests/rdata_mx_unittest.cc b/src/lib/dns/tests/rdata_mx_unittest.cc index b11411f24c..8b13789179 100644 --- a/src/lib/dns/tests/rdata_mx_unittest.cc +++ b/src/lib/dns/tests/rdata_mx_unittest.cc @@ -1,147 +1 @@ -// Copyright (C) 2010-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. -#include <config.h> - -#include <util/buffer.h> -#include <dns/messagerenderer.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> -#include <dns/rrclass.h> -#include <dns/rrtype.h> - -#include <gtest/gtest.h> - -#include <dns/tests/unittest_util.h> -#include <dns/tests/rdata_unittest.h> -#include <util/unittests/wiredata.h> - -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 { -public: - Rdata_MX_Test() : - rdata_mx(10, Name("mx.example.com")) - {} - - const generic::MX rdata_mx; -}; - -TEST_F(Rdata_MX_Test, createFromText) { - const generic::MX rdata_mx2("10 mx.example.com."); - EXPECT_EQ(0, rdata_mx2.compare(rdata_mx)); -} - -TEST_F(Rdata_MX_Test, badText) { - EXPECT_THROW(const generic::MX rdata_mx("99999999 mx."), InvalidRdataText); - EXPECT_THROW(const generic::MX rdata_mx("10"), InvalidRdataText); - EXPECT_THROW(const generic::MX rdata_mx("SPOON"), InvalidRdataText); - EXPECT_THROW(const generic::MX rdata_mx("10 mx. example.com."), - InvalidRdataText); - // No origin and relative - EXPECT_THROW(const generic::MX rdata_mx("10 mx.example.com"), - MissingNameOrigin); - // Extra text at end of line - EXPECT_THROW(const generic::MX rdata_mx("10 mx.example.com. extra."), - InvalidRdataText); -} - -TEST_F(Rdata_MX_Test, copy) { - const generic::MX rdata_mx2(rdata_mx); - EXPECT_EQ(0, rdata_mx.compare(rdata_mx2)); -} - -TEST_F(Rdata_MX_Test, createFromWire) { - EXPECT_EQ(0, rdata_mx.compare( - *rdataFactoryFromFile(RRType("MX"), RRClass("IN"), - "rdata_mx_fromWire"))); - // TBD: more tests -} - -TEST_F(Rdata_MX_Test, createFromLexer) { - EXPECT_EQ(0, rdata_mx.compare( - *test::createRdataUsingLexer(RRType::MX(), RRClass::IN(), - "10 mx.example.com."))); - - // test::createRdataUsingLexer() constructs relative to - // "example.org." origin. - EXPECT_EQ(0, generic::MX("10 mx2.example.org.").compare( - *test::createRdataUsingLexer(RRType::MX(), RRClass::IN(), - "10 mx2"))); - - // Exceptions cause NULL to be returned. - EXPECT_FALSE(test::createRdataUsingLexer(RRType::MX(), RRClass::IN(), - "10 mx. example.com.")); - - // 65536 is larger than maximum possible preference - EXPECT_FALSE(test::createRdataUsingLexer(RRType::MX(), RRClass::IN(), - "65536 mx.example.com.")); - - // Extra text at end of line - EXPECT_FALSE(test::createRdataUsingLexer(RRType::MX(), RRClass::IN(), - "10 mx.example.com. extra.")); -} - -TEST_F(Rdata_MX_Test, toWireRenderer) { - renderer.writeName(Name("example.com")); - rdata_mx.toWire(renderer); - - vector<unsigned char> data; - UnitTestUtil::readWireData("rdata_mx_toWire1", data); - matchWireData(&data[0], data.size(), - renderer.getData(), renderer.getLength()); -} - -TEST_F(Rdata_MX_Test, toWireBuffer) { - Name("example.com").toWire(obuffer); - rdata_mx.toWire(obuffer); - - vector<unsigned char> data; - UnitTestUtil::readWireData("rdata_mx_toWire2", data); - matchWireData(&data[0], data.size(), - obuffer.getData(), obuffer.getLength()); -} - -TEST_F(Rdata_MX_Test, toText) { - EXPECT_EQ("10 mx.example.com.", rdata_mx.toText()); -} - -TEST_F(Rdata_MX_Test, getMXName) { - EXPECT_EQ(Name("mx.example.com."), rdata_mx.getMXName()); -} - -TEST_F(Rdata_MX_Test, getMXPref) { - EXPECT_EQ(10, rdata_mx.getMXPref()); -} - -TEST_F(Rdata_MX_Test, compare) { - generic::MX small1(1, Name("mx.example.com")); - generic::MX small2(10, Name("mx.example.com")); - generic::MX large1(65535, Name("mx.example.com")); - generic::MX large2(256, Name("mx.example.com")); - - // trivial case: self equivalence - // cppcheck-suppress uselessCallsCompare - EXPECT_EQ(0, small1.compare(small1)); - - // confirm these are compared as unsigned values - EXPECT_GT(0, small1.compare(large1)); - EXPECT_LT(0, large1.compare(small1)); - - // confirm these are compared in network byte order - EXPECT_GT(0, small2.compare(large2)); - EXPECT_LT(0, large2.compare(small2)); - - // comparison attempt between incompatible RR types should be rejected - EXPECT_THROW(rdata_mx.compare(*rdata_nomatch), bad_cast); -} -} diff --git a/src/lib/dns/tests/rdata_naptr_unittest.cc b/src/lib/dns/tests/rdata_naptr_unittest.cc index 4ce008edb6..8b13789179 100644 --- a/src/lib/dns/tests/rdata_naptr_unittest.cc +++ b/src/lib/dns/tests/rdata_naptr_unittest.cc @@ -1,239 +1 @@ -// Copyright (C) 2011-2015,2021 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. -#include <config.h> - -#include <util/buffer.h> -#include <dns/exceptions.h> -#include <dns/messagerenderer.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> -#include <dns/rrclass.h> -#include <dns/rrtype.h> - -#include <gtest/gtest.h> - -#include <dns/tests/unittest_util.h> -#include <dns/tests/rdata_unittest.h> -#include <util/unittests/wiredata.h> - -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 { -}; - -// 10 100 "S" "SIP+D2U" "" _sip._udp.example.com. -static uint8_t naptr_rdata[] = {0x00,0x0a,0x00,0x64,0x01,0x53,0x07,0x53,0x49, - 0x50,0x2b,0x44,0x32,0x55,0x00,0x04,0x5f,0x73,0x69,0x70,0x04,0x5f,0x75,0x64, - 0x70,0x07,0x65,0x78,0x61,0x6d,0x70,0x6c,0x65,0x03,0x63,0x6f,0x6d,0x00}; - -static const char *naptr_str = - "10 100 \"S\" \"SIP+D2U\" \"\" _sip._udp.example.com."; -static const char *naptr_str2 = - "10 100 S SIP+D2U \"\" _sip._udp.example.com."; - -static const char *naptr_str_small1 = - "9 100 \"S\" \"SIP+D2U\" \"\" _sip._udp.example.com."; -static const char *naptr_str_small2 = - "10 90 \"S\" \"SIP+D2U\" \"\" _sip._udp.example.com."; -static const char *naptr_str_small3 = - "10 100 \"R\" \"SIP+D2U\" \"\" _sip._udp.example.com."; -static const char *naptr_str_small4 = - "10 100 \"S\" \"SIP+C2U\" \"\" _sip._udp.example.com."; -static const char *naptr_str_small5 = - "10 100 \"S\" \"SIP+D2U\" \"\" _rip._udp.example.com."; - -static const char *naptr_str_large1 = - "11 100 \"S\" \"SIP+D2U\" \"\" _sip._udp.example.com."; -static const char *naptr_str_large2 = - "10 110 \"S\" \"SIP+D2U\" \"\" _sip._udp.example.com."; -static const char *naptr_str_large3 = - "10 100 \"T\" \"SIP+D2U\" \"\" _sip._udp.example.com."; -static const char *naptr_str_large4 = - "10 100 \"S\" \"SIP+E2U\" \"\" _sip._udp.example.com."; -static const char *naptr_str_large5 = - "10 100 \"S\" \"SIP+D2U\" \"\" _tip._udp.example.com."; - -TEST_F(Rdata_NAPTR_Test, createFromText) { - NAPTR naptr(naptr_str); - EXPECT_EQ(10, naptr.getOrder()); - EXPECT_EQ(100, naptr.getPreference()); - EXPECT_EQ(string("S"), naptr.getFlags()); - EXPECT_EQ(string("SIP+D2U"), naptr.getServices()); - EXPECT_EQ(string(""), naptr.getRegexp()); - EXPECT_EQ(Name("_sip._udp.example.com."), naptr.getReplacement()); - - // Test <char-string> that separated by space - NAPTR naptr2(naptr_str2); - EXPECT_EQ(string("S"), naptr2.getFlags()); - EXPECT_EQ(string("SIP+D2U"), naptr2.getServices()); -} - -TEST_F(Rdata_NAPTR_Test, badText) { - // Order number cannot exceed 65535 - EXPECT_THROW(const NAPTR naptr("65536 10 S SIP \"\" _sip._udp.example.com."), - InvalidRdataText); - // Preference number cannot exceed 65535 - EXPECT_THROW(const NAPTR naptr("100 65536 S SIP \"\" _sip._udp.example.com."), - InvalidRdataText); - // No regexp given - EXPECT_THROW(const NAPTR naptr("100 10 S SIP _sip._udp.example.com."), - InvalidRdataText); - // The double quotes seperator must match - EXPECT_THROW(const NAPTR naptr("100 10 \"S SIP \"\" _sip._udp.example.com."), - InvalidRdataText); - // Order or preference cannot be missed - EXPECT_THROW(const NAPTR naptr("10 \"S\" SIP \"\" _sip._udp.example.com."), - InvalidRdataText); - // Unquoted fields must be separated by spaces - EXPECT_THROW(const NAPTR naptr("100 10S SIP \"\" _sip._udp.example.com."), - InvalidRdataText); - EXPECT_THROW(const NAPTR naptr("10010 \"S\" \"SIP\" \"\" _sip._udp.example.com."), - InvalidRdataText); - EXPECT_THROW(const NAPTR naptr("100 10 SSIP \"\" _sip._udp.example.com."), - InvalidRdataText); - // Field cannot be missing - EXPECT_THROW(const NAPTR naptr("100 10 \"S\""), InvalidRdataText); - - // The <character-string> cannot exceed 255 characters - string naptr_str; - naptr_str += "100 10 "; - for (int i = 0; i < 257; ++i) { - naptr_str += 'A'; - } - naptr_str += " SIP \"\" _sip._udp.example.com."; - EXPECT_THROW(const NAPTR naptr(naptr_str), CharStringTooLong); -} - -TEST_F(Rdata_NAPTR_Test, createFromWire) { - InputBuffer input_buffer(naptr_rdata, sizeof(naptr_rdata)); - NAPTR naptr(input_buffer, sizeof(naptr_rdata)); - EXPECT_EQ(10, naptr.getOrder()); - EXPECT_EQ(100, naptr.getPreference()); - EXPECT_EQ(string("S"), naptr.getFlags()); - EXPECT_EQ(string("SIP+D2U"), naptr.getServices()); - EXPECT_EQ(string(""), naptr.getRegexp()); - EXPECT_EQ(Name("_sip._udp.example.com."), naptr.getReplacement()); -} - -TEST_F(Rdata_NAPTR_Test, createFromWireTooLongDataLen) { - static uint8_t naptr_rdata_long[] = { - 0x00,0x0a,0x00,0x64,0x01,0x53,0x07,0x53,0x49,0x50,0x2b,0x44,0x32,0x55, - 0x00,0x04,0x5f,0x73,0x69,0x70,0x04,0x5f,0x75,0x64,0x70,0x07,0x65,0x78, - 0x61,0x6d,0x70,0x6c,0x65,0x03,0x63,0x6f,0x6d,0x00,0xff,0xff,0xff,0xff}; - InputBuffer input_buffer(naptr_rdata_long, sizeof(naptr_rdata_long)); - EXPECT_THROW(NAPTR naptr(input_buffer, sizeof(naptr_rdata_long)), - isc::dns::DNSMessageFORMERR); -} - -TEST_F(Rdata_NAPTR_Test, createFromWireTooShortDataLen) { - // missing data (just set rdata_len too low) - for (size_t i = 0; i < sizeof(naptr_rdata); ++i) { - // Just use existing correct buffer but set rdata_len too low - InputBuffer input_buffer(naptr_rdata, sizeof(naptr_rdata)); - EXPECT_THROW(NAPTR naptr(input_buffer, i), - isc::dns::DNSMessageFORMERR); - } -} - -TEST_F(Rdata_NAPTR_Test, createFromLexer) { - const NAPTR rdata_naptr(naptr_str); - - EXPECT_EQ(0, rdata_naptr.compare( - *test::createRdataUsingLexer(RRType::NAPTR(), RRClass::IN(), - naptr_str))); - - // Exceptions cause NULL to be returned. - EXPECT_FALSE(test::createRdataUsingLexer(RRType::NAPTR(), RRClass::IN(), - "65536 10 S SIP \"\" " - "_sip._udp.example.com.")); -} - -TEST_F(Rdata_NAPTR_Test, toWire) { - NAPTR naptr(naptr_str); - - 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); - matchWireData(naptr_rdata, sizeof(naptr_rdata), - renderer.getData(), renderer.getLength()); -} - -TEST_F(Rdata_NAPTR_Test, toText) { - NAPTR naptr(naptr_str); - EXPECT_EQ(naptr_str, naptr.toText()); - - // will add quotes even if they were not in the original input - EXPECT_EQ("10 100 \"S\" \"SIP+D2U\" \".*\" _sip._udp.example.com.", - NAPTR("10 100 S SIP+D2U .* _sip._udp.example.com.").toText()); - // will not add additional quotes - EXPECT_EQ("10 100 \"S\" \"SIP+D2U\" \".*\" _sip._udp.example.com.", - NAPTR("10 100 \"S\" \"SIP+D2U\" \".*\" _sip._udp.example.com.") - .toText()); -} - -TEST_F(Rdata_NAPTR_Test, compare) { - NAPTR naptr(naptr_str); - NAPTR naptr_small1(naptr_str_small1); - NAPTR naptr_small2(naptr_str_small2); - NAPTR naptr_small3(naptr_str_small3); - NAPTR naptr_small4(naptr_str_small4); - NAPTR naptr_small5(naptr_str_small5); - NAPTR naptr_large1(naptr_str_large1); - NAPTR naptr_large2(naptr_str_large2); - NAPTR naptr_large3(naptr_str_large3); - NAPTR naptr_large4(naptr_str_large4); - NAPTR naptr_large5(naptr_str_large5); - - EXPECT_EQ(0, naptr.compare(NAPTR(naptr_str))); - EXPECT_EQ(1, naptr.compare(naptr_small1)); - EXPECT_EQ(1, naptr.compare(naptr_small2)); - EXPECT_EQ(1, naptr.compare(naptr_small3)); - EXPECT_EQ(1, naptr.compare(naptr_small4)); - EXPECT_EQ(1, naptr.compare(naptr_small5)); - EXPECT_EQ(-1, naptr.compare(naptr_large1)); - EXPECT_EQ(-1, naptr.compare(naptr_large2)); - EXPECT_EQ(-1, naptr.compare(naptr_large3)); - EXPECT_EQ(-1, naptr.compare(naptr_large4)); - EXPECT_EQ(-1, naptr.compare(naptr_large5)); - EXPECT_EQ(-1, naptr_small1.compare(naptr)); - EXPECT_EQ(-1, naptr_small2.compare(naptr)); - EXPECT_EQ(-1, naptr_small3.compare(naptr)); - EXPECT_EQ(-1, naptr_small4.compare(naptr)); - EXPECT_EQ(-1, naptr_small5.compare(naptr)); - EXPECT_EQ(1, naptr_large1.compare(naptr)); - EXPECT_EQ(1, naptr_large2.compare(naptr)); - EXPECT_EQ(1, naptr_large3.compare(naptr)); - EXPECT_EQ(1, naptr_large4.compare(naptr)); - EXPECT_EQ(1, naptr_large5.compare(naptr)); -} - -TEST_F(Rdata_NAPTR_Test, copy) { - NAPTR naptr(naptr_str); - NAPTR naptr2(naptr); - NAPTR naptr3 = naptr; - - EXPECT_EQ(0, naptr.compare(naptr2)); - EXPECT_EQ(0, naptr.compare(naptr3)); - - naptr3 = naptr; - EXPECT_EQ(0, naptr.compare(naptr3)); -} - -} diff --git a/src/lib/dns/tests/rdata_ns_unittest.cc b/src/lib/dns/tests/rdata_ns_unittest.cc index 31bb50800e..8b13789179 100644 --- a/src/lib/dns/tests/rdata_ns_unittest.cc +++ b/src/lib/dns/tests/rdata_ns_unittest.cc @@ -1,145 +1 @@ -// Copyright (C) 2010-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. -#include <config.h> - -#include <util/buffer.h> -#include <dns/exceptions.h> -#include <dns/messagerenderer.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> -#include <dns/rrclass.h> -#include <dns/rrtype.h> - -#include <gtest/gtest.h> - -#include <dns/tests/unittest_util.h> -#include <dns/tests/rdata_unittest.h> -#include <util/unittests/wiredata.h> - -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 { -public: - Rdata_NS_Test() : - rdata_ns("ns.example.com."), - rdata_ns2("ns2.example.com.") - {} - - const generic::NS rdata_ns; - const generic::NS rdata_ns2; -}; - -const uint8_t wiredata_ns[] = { - 0x02, 0x6e, 0x73, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x03, - 0x63, 0x6f, 0x6d, 0x00 }; -const uint8_t wiredata_ns2[] = { - // first name: ns.example.com. - 0x02, 0x6e, 0x73, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x03, - 0x63, 0x6f, 0x6d, 0x00, - // second name: ns2.example.com. all labels except the first should be - // compressed. - 0x03, 0x6e, 0x73, 0x32, 0xc0, 0x03 }; - -TEST_F(Rdata_NS_Test, createFromText) { - EXPECT_EQ(0, rdata_ns.compare(generic::NS("ns.example.com."))); - // explicitly add a trailing dot. should be the same RDATA. - EXPECT_EQ(0, rdata_ns.compare(generic::NS("ns.example.com."))); - // should be case sensitive. - EXPECT_EQ(0, rdata_ns.compare(generic::NS("NS.EXAMPLE.COM."))); - // RDATA of a class-independent type should be recognized for any - // "unknown" class. - EXPECT_EQ(0, rdata_ns.compare(*createRdata(RRType("NS"), RRClass(65000), - "ns.example.com."))); -} - -TEST_F(Rdata_NS_Test, badText) { - // Extra input at end of line - EXPECT_THROW(generic::NS("ns.example.com. extra."), InvalidRdataText); -} - -TEST_F(Rdata_NS_Test, createFromWire) { - EXPECT_EQ(0, rdata_ns.compare( - *rdataFactoryFromFile(RRType("NS"), RRClass("IN"), - "rdata_ns_fromWire"))); - // RDLENGTH is too short - EXPECT_THROW(rdataFactoryFromFile(RRType("NS"), RRClass("IN"), - "rdata_ns_fromWire", 18), - InvalidRdataLength); - // RDLENGTH is too long - EXPECT_THROW(rdataFactoryFromFile(RRType("NS"), RRClass("IN"), - "rdata_ns_fromWire", 36), - InvalidRdataLength); - // incomplete name. the error should be detected in the name constructor - EXPECT_THROW(rdataFactoryFromFile(RRType("NS"), RRClass("IN"), - "rdata_ns_fromWire", 71), - DNSMessageFORMERR); - - EXPECT_EQ(0, generic::NS("ns2.example.com.").compare( - *rdataFactoryFromFile(RRType("NS"), RRClass("IN"), - "rdata_ns_fromWire", 55))); - EXPECT_THROW(*rdataFactoryFromFile(RRType("NS"), RRClass("IN"), - "rdata_ns_fromWire", 63), - InvalidRdataLength); -} - -TEST_F(Rdata_NS_Test, createFromLexer) { - EXPECT_EQ(0, rdata_ns.compare( - *test::createRdataUsingLexer(RRType::NS(), RRClass::IN(), - "ns.example.com."))); - - // test::createRdataUsingLexer() constructs relative to - // "example.org." origin. - EXPECT_EQ(0, generic::NS("ns8.example.org.").compare( - *test::createRdataUsingLexer(RRType::NS(), RRClass::IN(), - "ns8"))); - - // Exceptions cause NULL to be returned. - EXPECT_FALSE(test::createRdataUsingLexer(RRType::NS(), RRClass::IN(), - "")); - - // Extra input at end of line - EXPECT_FALSE(test::createRdataUsingLexer(RRType::NS(), RRClass::IN(), - "ns.example.com. extra.")); -} - -TEST_F(Rdata_NS_Test, toWireBuffer) { - rdata_ns.toWire(obuffer); - matchWireData(wiredata_ns, sizeof(wiredata_ns), - obuffer.getData(), obuffer.getLength()); -} - -TEST_F(Rdata_NS_Test, toWireRenderer) { - rdata_ns.toWire(renderer); - matchWireData(wiredata_ns, sizeof(wiredata_ns), - renderer.getData(), renderer.getLength()); - - rdata_ns2.toWire(renderer); - matchWireData(wiredata_ns2, sizeof(wiredata_ns2), - renderer.getData(), renderer.getLength()); -} - -TEST_F(Rdata_NS_Test, toText) { - EXPECT_EQ("ns.example.com.", rdata_ns.toText()); -} - -TEST_F(Rdata_NS_Test, compare) { - generic::NS small("a.example."); - generic::NS large("example."); - EXPECT_TRUE(Name("a.example") > Name("example")); - EXPECT_GT(0, small.compare(large)); -} - -TEST_F(Rdata_NS_Test, getNSName) { - EXPECT_EQ(Name("ns.example.com."), rdata_ns.getNSName()); -} -} diff --git a/src/lib/dns/tests/rdata_nsec3_unittest.cc b/src/lib/dns/tests/rdata_nsec3_unittest.cc index c6d3a07a72..8b13789179 100644 --- a/src/lib/dns/tests/rdata_nsec3_unittest.cc +++ b/src/lib/dns/tests/rdata_nsec3_unittest.cc @@ -1,226 +1 @@ -// Copyright (C) 2010-2017 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. -#include <config.h> - -#include <string> - -#include <exceptions/exceptions.h> - -#include <util/buffer.h> -#include <dns/exceptions.h> -#include <dns/messagerenderer.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> -#include <dns/rrclass.h> -#include <dns/rrtype.h> - -#include <gtest/gtest.h> - -#include <dns/tests/unittest_util.h> -#include <dns/tests/rdata_unittest.h> - -using isc::UnitTestUtil; -using namespace std; -using namespace isc; -using namespace isc::dns; -using namespace isc::util; -using namespace isc::dns::rdata; - -namespace { - -// Note: some tests can be shared with NSEC3PARAM. They are unified as -// typed tests defined in nsec3param_like_unittest. -class Rdata_NSEC3_Test : public RdataTest { -protected: - Rdata_NSEC3_Test() : - nsec3_txt("1 1 1 D399EAAB H9RSFB7FPF2L8HG35CMPC765TDK23RP6 " - "A NS SOA"), - nsec3_nosalt_txt("1 1 1 - H9RSFB7FPF2L8HG35CMPC765TDK23RP6 A NS SOA"), - nsec3_notype_txt("1 1 1 D399EAAB H9RSFB7FPF2L8HG35CMPC765TDK23RP6"), - rdata_nsec3(nsec3_txt) - {} - - void checkFromText_None(const string& rdata_str) { - checkFromText<generic::NSEC3, isc::Exception, isc::Exception>( - rdata_str, rdata_nsec3, false, false); - } - - void checkFromText_InvalidText(const string& rdata_str) { - checkFromText<generic::NSEC3, InvalidRdataText, InvalidRdataText>( - rdata_str, rdata_nsec3, true, true); - } - - void checkFromText_BadValue(const string& rdata_str) { - checkFromText<generic::NSEC3, BadValue, BadValue>( - rdata_str, rdata_nsec3, true, true); - } - - void checkFromText_LexerError(const string& rdata_str) { - checkFromText - <generic::NSEC3, InvalidRdataText, MasterLexer::LexerError>( - rdata_str, rdata_nsec3, true, true); - } - - void checkFromText_BadString(const string& rdata_str) { - checkFromText - <generic::NSEC3, InvalidRdataText, isc::Exception>( - rdata_str, rdata_nsec3, true, false); - } - - const string nsec3_txt; - const string nsec3_nosalt_txt; - const string nsec3_notype_txt; - const generic::NSEC3 rdata_nsec3; -}; - -TEST_F(Rdata_NSEC3_Test, fromText) { - // Hash that has the possible max length - EXPECT_EQ(255, generic::NSEC3("1 1 1 D399EAAB " + - string((255 * 8) / 5, '0') + - " NS").getNext().size()); - - // Hash is too long. Max = 255 bytes, base32-hex converts each 5 bytes - // of the original to 8 characters, so 260 * 8 / 5 is the smallest length - // of the encoded string that exceeds the max and doesn't require padding. - checkFromText_InvalidText("1 1 1 D399EAAB " + string((260 * 8) / 5, '0') + - " A NS SOA"); - - // Type bitmap is empty. it's possible and allowed for NSEC3. - EXPECT_NO_THROW(const generic::NSEC3 rdata_notype_nsec3(nsec3_notype_txt)); - - // Empty salt is also okay. - EXPECT_NO_THROW(const generic::NSEC3 rdata_nosalt_nsec3(nsec3_nosalt_txt)); - - // Bad type mnemonics - checkFromText_InvalidText("1 1 1 D399EAAB H9RSFB7FPF2L8HG35CMPC765TDK23RP6" - " BIFF POW SPOON"); - - // Bad base32hex - checkFromText_BadValue("1 1 1 D399EAAB " - "WXYZWXYZWXYZ=WXYZWXYZ==WXYZWXYZW A NS SOA"); - - // Hash algorithm out of range - checkFromText_InvalidText("256 1 1 D399EAAB " - "H9RSFB7FPF2L8HG35CMPC765TDK23RP6 A NS SOA"); - - // Flags out of range - checkFromText_InvalidText("1 256 1 D399EAAB " - "H9RSFB7FPF2L8HG35CMPC765TDK23RP6 A NS SOA"); - - // Iterations out of range - checkFromText_InvalidText("1 1 65536 D399EAAB " - "H9RSFB7FPF2L8HG35CMPC765TDK23RP6 A NS SOA"); - - // Space is not allowed in salt or the next hash. This actually - // causes the Base32 decoder that parses the next hash that comes - // afterwards, to throw. - checkFromText_BadValue("1 1 1 D399 EAAB H9RSFB7FPF2L8" - "HG35CMPC765TDK23RP6 A NS SOA"); - - // Next hash must not contain padding (trailing '=' characters) - checkFromText_InvalidText("1 1 1 D399EAAB " - "AAECAwQFBgcICQoLDA0ODw== A NS SOA"); - - // String instead of number - checkFromText_LexerError("foo 1 1 D399EAAB " - "H9RSFB7FPF2L8HG35CMPC765TDK23RP6 A NS SOA"); - checkFromText_LexerError("1 foo 1 D399EAAB " - "H9RSFB7FPF2L8HG35CMPC765TDK23RP6 A NS SOA"); - checkFromText_LexerError("1 1 foo D399EAAB " - "H9RSFB7FPF2L8HG35CMPC765TDK23RP6 A NS SOA"); - - // Trailing garbage. This should cause only the string constructor - // to fail, but the lexer constructor must be able to continue - // parsing from it. - checkFromText_BadString( - "1 1 1 D399EAAB H9RSFB7FPF2L8HG35CMPC765TDK23RP6 A NS SOA ;comment\n" - "1 1 1 D399EAAB H9RSFB7FPF2L8HG35CMPC765TDK23RP6 A NS SOA"); - - // Unmatched parenthesis should cause a lexer error - checkFromText_LexerError("1 1 1 D399EAAB " - "H9RSFB7FPF2L8HG35CMPC765TDK23RP6 A ) NS SOA"); -} - -TEST_F(Rdata_NSEC3_Test, createFromWire) { - // A valid NSEC3 RR with empty type bitmap. - EXPECT_NO_THROW(rdataFactoryFromFile(RRType::NSEC3(), RRClass::IN(), - "rdata_nsec3_fromWire15.wire")); - - // Invalid bitmap cases are tested in Rdata_NSECBITMAP_Test. - - // hash length is too large - EXPECT_THROW(rdataFactoryFromFile(RRType::NSEC3(), RRClass::IN(), - "rdata_nsec3_fromWire12.wire"), - DNSMessageFORMERR); - - // empty hash. invalid. - EXPECT_THROW(rdataFactoryFromFile(RRType::NSEC3(), RRClass::IN(), - "rdata_nsec3_fromWire14.wire"), - DNSMessageFORMERR); - - // RDLEN is too short to hold the hash length field - EXPECT_THROW(rdataFactoryFromFile(RRType::NSEC3(), RRClass::IN(), - "rdata_nsec3_fromWire17.wire"), - DNSMessageFORMERR); - - // Short buffer cases. The data is valid NSEC3 RDATA, but the buffer - // is trimmed at the end. All cases should result in an exception from - // the buffer class. - vector<uint8_t> data; - UnitTestUtil::readWireData("rdata_nsec3_fromWire1", data); - const uint16_t rdlen = (data.at(0) << 8) + data.at(1); - for (int i = 0; i < rdlen; ++i) { - // intentionally construct a short buffer - InputBuffer b(&data[0] + 2, i); - EXPECT_THROW(createRdata(RRType::NSEC3(), RRClass::IN(), b, 39), - InvalidBufferPosition); - } -} - -TEST_F(Rdata_NSEC3_Test, createFromLexer) { - EXPECT_EQ(0, rdata_nsec3.compare( - *test::createRdataUsingLexer(RRType::NSEC3(), RRClass::IN(), - nsec3_txt))); - - // empty salt is also okay. - const generic::NSEC3 rdata_nosalt_nsec3(nsec3_nosalt_txt); - EXPECT_EQ(0, rdata_nosalt_nsec3.compare( - *test::createRdataUsingLexer(RRType::NSEC3(), RRClass::IN(), - nsec3_nosalt_txt))); -} - -TEST_F(Rdata_NSEC3_Test, assign) { - generic::NSEC3 other_nsec3 = rdata_nsec3; - EXPECT_EQ(0, rdata_nsec3.compare(other_nsec3)); -} - -TEST_F(Rdata_NSEC3_Test, compare) { - // trivial case: self equivalence - EXPECT_EQ(0, generic::NSEC3(nsec3_txt).compare(generic::NSEC3(nsec3_txt))); - - // comparison attempt between incompatible RR types should be rejected - EXPECT_THROW(generic::NSEC3(nsec3_txt).compare(*rdata_nomatch), - bad_cast); - - // test RDATAs, sorted in the ascending order. We only check comparison - // on NSEC3-specific fields. Bitmap comparison is tested in the bitmap - // tests. Common cases for NSEC3 and NSECPARAM3 are in their shared tests. - vector<generic::NSEC3> compare_set; - compare_set.push_back(generic::NSEC3("1 1 1 FF99EA0000 D1K6GQ38")); - compare_set.push_back(generic::NSEC3("1 1 1 FF99EA0000 D1K6GQ0000000000")); - compare_set.push_back(generic::NSEC3("1 1 1 FF99EA0000 D1K6GQ00UUUUUUUU")); - - vector<generic::NSEC3>::const_iterator it; - const vector<generic::NSEC3>::const_iterator it_end = compare_set.end(); - for (it = compare_set.begin(); it != it_end - 1; ++it) { - SCOPED_TRACE("compare " + it->toText() + " to " + (it + 1)->toText()); - EXPECT_GT(0, (*it).compare(*(it + 1))); - EXPECT_LT(0, (*(it + 1)).compare(*it)); - } -} - -} diff --git a/src/lib/dns/tests/rdata_nsec3param_like_unittest.cc b/src/lib/dns/tests/rdata_nsec3param_like_unittest.cc index 914a6f443c..8b13789179 100644 --- a/src/lib/dns/tests/rdata_nsec3param_like_unittest.cc +++ b/src/lib/dns/tests/rdata_nsec3param_like_unittest.cc @@ -1,272 +1 @@ -// Copyright (C) 2012-2019 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. -#include <config.h> - -#include <dns/exceptions.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> -#include <dns/rrclass.h> -#include <dns/rrtype.h> - -#include <gtest/gtest.h> - -#include <dns/tests/unittest_util.h> -#include <dns/tests/rdata_unittest.h> -#include <util/unittests/wiredata.h> - -#include <string> -#include <vector> - -using namespace std; -using namespace isc::dns; -using namespace isc::dns::rdata; -using namespace isc::util; -using isc::UnitTestUtil; -using isc::util::unittests::matchWireData; - -namespace { - -// Template for shared tests for NSEC3 and NSEC3PARAM -template <typename RDATA_TYPE> -class NSEC3PARAMLikeTest : public RdataTest { -protected: - NSEC3PARAMLikeTest() : - salt_txt("1 1 1 D399EAAB" + getCommonText()), - nosalt_txt("1 1 1 -" + getCommonText()), - obuffer(0) - {} - - RDATA_TYPE fromText(const string& rdata_text) { - return (RDATA_TYPE(rdata_text)); - } - - void compareCheck() const { - typename vector<RDATA_TYPE>::const_iterator it; - typename vector<RDATA_TYPE>::const_iterator const it_end = - compare_set.end(); - for (it = compare_set.begin(); it != it_end - 1; ++it) { - SCOPED_TRACE("compare " + it->toText() + " to " + - (it + 1)->toText()); - EXPECT_GT(0, (*it).compare(*(it + 1))); - EXPECT_LT(0, (*(it + 1)).compare(*it)); - } - } - - const string salt_txt; // RDATA text with salt - const string nosalt_txt; // RDATA text without salt - OutputBuffer obuffer; // used in toWire() tests - MessageRenderer renderer; // ditto - vector<RDATA_TYPE> compare_set; // used in compare() tests - - // Convert generic Rdata to the corresponding derived Rdata class object. - // Defined here because it depends on the template parameter. - static const RDATA_TYPE& convert(const Rdata& rdata) { - return (dynamic_cast<const RDATA_TYPE&>(rdata)); - } - - // These depend on the specific RR type. We use specialized methods - // for them. - static RRType getType(); // return either RRType::NSEC3() or NSEC3PARAM() - static string getWireFilePrefix(); - static string getCommonText(); // commonly used part of textual form -}; - -// Instantiate specific typed tests -typedef ::testing::Types<generic::NSEC3, generic::NSEC3PARAM> TestRdataTypes; -#ifdef TYPED_TEST_SUITE -TYPED_TEST_SUITE(NSEC3PARAMLikeTest, TestRdataTypes); -#else -TYPED_TEST_CASE(NSEC3PARAMLikeTest, TestRdataTypes); -#endif - -template <> -RRType -NSEC3PARAMLikeTest<generic::NSEC3>::getType() { - return (RRType::NSEC3()); -} - -template <> -RRType -NSEC3PARAMLikeTest<generic::NSEC3PARAM>::getType() { - return (RRType::NSEC3PARAM()); -} - -template <> -string -NSEC3PARAMLikeTest<generic::NSEC3>::getWireFilePrefix() { - return ("rdata_nsec3_"); -} - -template <> -string -NSEC3PARAMLikeTest<generic::NSEC3PARAM>::getWireFilePrefix() { - return ("rdata_nsec3param_"); -} - -template <> -string -NSEC3PARAMLikeTest<generic::NSEC3>::getCommonText() { - // next hash + RR type bitmap - return (" H9RSFB7FPF2L8HG35CMPC765TDK23RP6 " - "NS SOA RRSIG DNSKEY NSEC3PARAM"); -} - -template <> -string -NSEC3PARAMLikeTest<generic::NSEC3PARAM>::getCommonText() { - // there's no more text for NSEC3PARAM - return (""); -} - -TYPED_TEST(NSEC3PARAMLikeTest, fromText) { - // Numeric parameters have possible maximum values. Unusual, but must - // be accepted. - EXPECT_NO_THROW(this->fromText("255 255 65535 D399EAAB" + - this->getCommonText())); - - // 0-length salt - EXPECT_EQ(0, this->fromText(this->nosalt_txt).getSalt().size()); - - // salt that has the possible max length - EXPECT_EQ(255, this->fromText("1 1 1 " + string(255 * 2, '0') + - this->getCommonText()).getSalt().size()); -} - -TYPED_TEST(NSEC3PARAMLikeTest, badText) { - // Bad salt hex - EXPECT_THROW(this->fromText("1 1 1 SPORK0" + this->getCommonText()), - isc::BadValue); - EXPECT_THROW(this->fromText("1 1 1 ADDAFEE" + this->getCommonText()), - isc::BadValue); - - // Space within salt - EXPECT_THROW(this->fromText("1 1 1 ADDAFE ADDAFEEE" + - this->getCommonText()), - InvalidRdataText); - - // Similar to empty salt, but not really. This shouldn't cause confusion. - EXPECT_THROW(this->fromText("1 1 1 --" + this->getCommonText()), - isc::BadValue); - - // Too large algorithm - EXPECT_THROW(this->fromText("1000000 1 1 ADDAFEEE" + this->getCommonText()), - InvalidRdataText); - - // Too large flags - EXPECT_THROW(this->fromText("1 1000000 1 ADDAFEEE" + this->getCommonText()), - InvalidRdataText); - - // Too large iterations - EXPECT_THROW(this->fromText("1 1 65536 ADDAFEEE" + this->getCommonText()), - InvalidRdataText); - - // There should be a space between "1" and "D399EAAB" (salt) - EXPECT_THROW(this->fromText("1 1 1D399EAAB" + this->getCommonText()), - InvalidRdataText); - - // Salt is too long (possible max + 1 bytes) - EXPECT_THROW(this->fromText("1 1 1 " + string(256 * 2, '0') + - this->getCommonText()), - InvalidRdataText); -} - -TYPED_TEST(NSEC3PARAMLikeTest, toText) { - // normal case - EXPECT_EQ(this->salt_txt, this->fromText(this->salt_txt).toText()); - - // empty salt case - EXPECT_EQ(this->nosalt_txt, this->fromText(this->nosalt_txt).toText()); -} - -TYPED_TEST(NSEC3PARAMLikeTest, createFromWire) { - // Normal case - EXPECT_EQ(0, this->fromText(this->salt_txt).compare( - *this->rdataFactoryFromFile(this->getType(), RRClass::IN(), - (this->getWireFilePrefix() + - "fromWire1").c_str()))); - - // Too short RDLENGTH: it doesn't even contain the first 5 octets. - EXPECT_THROW(this->rdataFactoryFromFile(this->getType(), RRClass::IN(), - (this->getWireFilePrefix() + - "fromWire2.wire").c_str()), - DNSMessageFORMERR); - - // salt length is too large - EXPECT_THROW(this->rdataFactoryFromFile(this->getType(), RRClass::IN(), - (this->getWireFilePrefix() + - "fromWire11.wire").c_str()), - DNSMessageFORMERR); - - // empty salt. not so usual, but valid. - ConstRdataPtr rdata = - this->rdataFactoryFromFile(this->getType(), RRClass::IN(), - (this->getWireFilePrefix() + - "fromWire13.wire").c_str()); - EXPECT_EQ(0, this->convert(*rdata).getSalt().size()); -} - -TYPED_TEST(NSEC3PARAMLikeTest, createFromLexer) { - EXPECT_EQ(0, this->fromText(this->salt_txt).compare( - *test::createRdataUsingLexer(this->getType(), RRClass::IN(), - this->salt_txt))); - - // Exceptions cause NULL to be returned. - EXPECT_FALSE(test::createRdataUsingLexer(this->getType(), RRClass::IN(), - "1000000 1 1 ADDAFEEE" + - this->getCommonText())); -} - -template <typename OUTPUT_TYPE> -void -toWireCheck(RRType rrtype, OUTPUT_TYPE& output, const string& data_file) { - vector<uint8_t> data; - UnitTestUtil::readWireData(data_file.c_str(), data); - InputBuffer buffer(&data[0], data.size()); - const uint16_t rdlen = buffer.readUint16(); - - output.clear(); - output.writeUint16(rdlen); - createRdata(rrtype, RRClass::IN(), buffer, rdlen)->toWire(output); - matchWireData(&data[0], data.size(), - output.getData(), output.getLength()); -} - -TYPED_TEST(NSEC3PARAMLikeTest, toWire) { - // normal case - toWireCheck(this->getType(), this->renderer, - this->getWireFilePrefix() + "fromWire1"); - toWireCheck(this->getType(), this->obuffer, - this->getWireFilePrefix() + "fromWire1"); - - // empty salt - toWireCheck(this->getType(), this->renderer, - this->getWireFilePrefix() + "fromWire13.wire"); - toWireCheck(this->getType(), this->obuffer, - this->getWireFilePrefix() + "fromWire13.wire"); -} - -TYPED_TEST(NSEC3PARAMLikeTest, compare) { - // test RDATAs, sorted in the ascending order. - this->compare_set.push_back(this->fromText("0 0 0 D399EAAB" + - this->getCommonText())); - this->compare_set.push_back(this->fromText("1 0 0 D399EAAB" + - this->getCommonText())); - this->compare_set.push_back(this->fromText("1 1 0 D399EAAB" + - this->getCommonText())); - this->compare_set.push_back(this->fromText("1 1 1 -" + - this->getCommonText())); - this->compare_set.push_back(this->fromText("1 1 1 D399EAAB" + - this->getCommonText())); - this->compare_set.push_back(this->fromText("1 1 1 FF99EAAB" + - this->getCommonText())); - this->compare_set.push_back(this->fromText("1 1 1 FF99EA0000" + - this->getCommonText())); - - this->compareCheck(); -} - -} diff --git a/src/lib/dns/tests/rdata_nsec3param_unittest.cc b/src/lib/dns/tests/rdata_nsec3param_unittest.cc index 9a677be145..8b13789179 100644 --- a/src/lib/dns/tests/rdata_nsec3param_unittest.cc +++ b/src/lib/dns/tests/rdata_nsec3param_unittest.cc @@ -1,209 +1 @@ -// Copyright (C) 2010-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. -#include <config.h> - -#include <string> - -#include <exceptions/exceptions.h> - -#include <util/buffer.h> -#include <dns/messagerenderer.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> -#include <dns/rrclass.h> -#include <dns/rrtype.h> - -#include <gtest/gtest.h> - -#include <dns/tests/unittest_util.h> -#include <dns/tests/rdata_unittest.h> -#include <util/unittests/wiredata.h> - -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 { -protected: - Rdata_NSEC3PARAM_Test() : - nsec3param_txt("1 1 1 D399EAAB"), - nsec3param_nosalt_txt("1 1 1 -"), - rdata_nsec3param(nsec3param_txt) - {} - - void checkFromText_None(const string& rdata_str) { - checkFromText<generic::NSEC3PARAM, isc::Exception, isc::Exception>( - rdata_str, rdata_nsec3param, false, false); - } - - void checkFromText_InvalidText(const string& rdata_str) { - checkFromText<generic::NSEC3PARAM, InvalidRdataText, InvalidRdataText>( - rdata_str, rdata_nsec3param, true, true); - } - - void checkFromText_BadValue(const string& rdata_str) { - checkFromText<generic::NSEC3PARAM, BadValue, BadValue>( - rdata_str, rdata_nsec3param, true, true); - } - - void checkFromText_LexerError(const string& rdata_str) { - checkFromText - <generic::NSEC3PARAM, InvalidRdataText, MasterLexer::LexerError>( - rdata_str, rdata_nsec3param, true, true); - } - - void checkFromText_BadString(const string& rdata_str, - const generic::NSEC3PARAM& rdata) - { - checkFromText - <generic::NSEC3PARAM, InvalidRdataText, isc::Exception>( - rdata_str, rdata, true, false); - } - - const string nsec3param_txt; - const string nsec3param_nosalt_txt; - const generic::NSEC3PARAM rdata_nsec3param; -}; - -TEST_F(Rdata_NSEC3PARAM_Test, fromText) { - // Empty salt is okay. - EXPECT_EQ(0, generic::NSEC3PARAM(nsec3param_nosalt_txt).getSalt().size()); - - // Salt is missing. - checkFromText_LexerError("1 1 1"); - - // Salt has whitespace within. This only fails in the string - // constructor, as the lexer constructor stops reading at the end of - // its RDATA. - const generic::NSEC3PARAM rdata_nsec3param2("1 1 1 D399"); - checkFromText_BadString("1 1 1 D399 EAAB", rdata_nsec3param2); - - // Hash algorithm out of range. - checkFromText_InvalidText("256 1 1 D399EAAB"); - - // Flags out of range. - checkFromText_InvalidText("1 256 1 D399EAAB"); - - // Iterations out of range. - checkFromText_InvalidText("1 1 65536 D399EAAB"); - - // Bad hex sequence - checkFromText_BadValue("1 1 256 D399EAABZOO"); - - // String instead of number - checkFromText_LexerError("foo 1 256 D399EAAB"); - checkFromText_LexerError("1 foo 256 D399EAAB"); - checkFromText_LexerError("1 1 foo D399EAAB"); - - // Trailing garbage. This should cause only the string constructor - // to fail, but the lexer constructor must be able to continue - // parsing from it. - checkFromText_BadString("1 1 1 D399EAAB ; comment\n" - "1 1 1 D399EAAB", rdata_nsec3param); -} - -TEST_F(Rdata_NSEC3PARAM_Test, toText) { - EXPECT_EQ(nsec3param_txt, rdata_nsec3param.toText()); - - // Garbage space at the end should be ok. RFC5155 only forbids - // whitespace within the salt field, but any whitespace afterwards - // should be fine. - EXPECT_NO_THROW(generic::NSEC3PARAM("1 1 1 D399EAAB ")); - - // Hash algorithm in range. - EXPECT_NO_THROW(generic::NSEC3PARAM("255 1 1 D399EAAB")); - - // Flags in range. - EXPECT_NO_THROW(generic::NSEC3PARAM("1 255 1 D399EAAB")); - - // Iterations in range. - EXPECT_NO_THROW(generic::NSEC3PARAM("1 1 65535 D399EAAB")); -} - -TEST_F(Rdata_NSEC3PARAM_Test, createFromWire) { - EXPECT_EQ(0, rdata_nsec3param.compare( - *rdataFactoryFromFile(RRType::NSEC3PARAM(), RRClass::IN(), - "rdata_nsec3param_fromWire1"))); - - // Short buffer cases. The data is valid NSEC3PARAM RDATA, but the buffer - // is trimmed at the end. All cases should result in an exception from - // the buffer class. - vector<uint8_t> data; - UnitTestUtil::readWireData("rdata_nsec3param_fromWire1", data); - const uint16_t rdlen = (data.at(0) << 8) + data.at(1); - for (int i = 0; i < rdlen; ++i) { - // intentionally construct a short buffer - InputBuffer b(&data[0] + 2, i); - EXPECT_THROW(createRdata(RRType::NSEC3PARAM(), RRClass::IN(), b, 9), - InvalidBufferPosition); - } -} - -TEST_F(Rdata_NSEC3PARAM_Test, createFromLexer) { - EXPECT_EQ(0, rdata_nsec3param.compare( - *test::createRdataUsingLexer(RRType::NSEC3PARAM(), RRClass::IN(), - nsec3param_txt))); - - // empty salt is also okay. - const generic::NSEC3PARAM rdata_nosalt_nsec3param(nsec3param_nosalt_txt); - EXPECT_EQ(0, rdata_nosalt_nsec3param.compare( - *test::createRdataUsingLexer(RRType::NSEC3PARAM(), RRClass::IN(), - nsec3param_nosalt_txt))); -} - -TEST_F(Rdata_NSEC3PARAM_Test, toWireRenderer) { - renderer.skip(2); - rdata_nsec3param.toWire(renderer); - - vector<unsigned char> data; - UnitTestUtil::readWireData("rdata_nsec3param_fromWire1", data); - matchWireData(&data[2], data.size() - 2, - static_cast<const uint8_t *>(renderer.getData()) + 2, - renderer.getLength() - 2); -} - -TEST_F(Rdata_NSEC3PARAM_Test, toWireBuffer) { - rdata_nsec3param.toWire(obuffer); - - vector<unsigned char> data; - UnitTestUtil::readWireData("rdata_nsec3param_fromWire1", data); - matchWireData(&data[2], data.size() - 2, - obuffer.getData(), obuffer.getLength()); -} - -TEST_F(Rdata_NSEC3PARAM_Test, getHashAlg) { - EXPECT_EQ(1, rdata_nsec3param.getHashalg()); -} - -TEST_F(Rdata_NSEC3PARAM_Test, getFlags) { - EXPECT_EQ(1, rdata_nsec3param.getFlags()); -} - -TEST_F(Rdata_NSEC3PARAM_Test, assign) { - generic::NSEC3PARAM other_nsec3param("1 1 1 -"); - other_nsec3param = rdata_nsec3param; - EXPECT_EQ(0, rdata_nsec3param.compare(other_nsec3param)); -} - -TEST_F(Rdata_NSEC3PARAM_Test, compare) { - // trivial case: self equivalence - EXPECT_EQ(0, generic::NSEC3PARAM(nsec3param_txt). - compare(generic::NSEC3PARAM(nsec3param_txt))); - EXPECT_EQ(0, generic::NSEC3PARAM("1 1 1 -"). - compare(generic::NSEC3PARAM("1 1 1 -"))); - - // comparison attempt between incompatible RR types should be rejected - EXPECT_THROW(generic::NSEC3PARAM(nsec3param_txt).compare(*rdata_nomatch), - bad_cast); -} - -} diff --git a/src/lib/dns/tests/rdata_nsec_unittest.cc b/src/lib/dns/tests/rdata_nsec_unittest.cc index 8d911f26bf..8b13789179 100644 --- a/src/lib/dns/tests/rdata_nsec_unittest.cc +++ b/src/lib/dns/tests/rdata_nsec_unittest.cc @@ -1,139 +1 @@ -// Copyright (C) 2010-2024 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. -#include <config.h> - -#include <string> - -#include <util/buffer.h> -#include <dns/exceptions.h> -#include <dns/messagerenderer.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> -#include <dns/rrclass.h> -#include <dns/rrtype.h> - -#include <gtest/gtest.h> - -#include <dns/tests/unittest_util.h> -#include <dns/tests/rdata_unittest.h> -#include <util/unittests/wiredata.h> - -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 { - // there's nothing to specialize -}; - -const char* const nsec_txt = "www2.isc.org. CNAME RRSIG NSEC"; - -TEST_F(Rdata_NSEC_Test, toText_NSEC) { - const generic::NSEC rdata_nsec(nsec_txt); - EXPECT_EQ(nsec_txt, rdata_nsec.toText()); -} - -TEST_F(Rdata_NSEC_Test, badText_NSEC) { - EXPECT_THROW(generic::NSEC rdata_nsec("www.isc.org. BIFF POW SPOON"), - InvalidRdataText); - EXPECT_THROW(generic::NSEC rdata_nsec("www.isc.org."), - InvalidRdataText); -} - -TEST_F(Rdata_NSEC_Test, createFromWire_NSEC) { - const generic::NSEC rdata_nsec(nsec_txt); - EXPECT_EQ(0, rdata_nsec.compare( - *rdataFactoryFromFile(RRType::NSEC(), RRClass::IN(), - "rdata_nsec_fromWire1"))); - - // Too short RDLENGTH - EXPECT_THROW(rdataFactoryFromFile(RRType::NSEC(), RRClass::IN(), - "rdata_nsec_fromWire2"), - DNSMessageFORMERR); - - // Invalid bitmap cases are tested in Rdata_NSECBITMAP_Test. -} - -TEST_F(Rdata_NSEC_Test, createFromLexer_NSEC) { - const generic::NSEC rdata_nsec(nsec_txt); - EXPECT_EQ(0, rdata_nsec.compare( - *test::createRdataUsingLexer(RRType::NSEC(), RRClass::IN(), - nsec_txt))); - - // test::createRdataUsingLexer() constructs relative to - // "example.org." origin. - EXPECT_EQ(0, generic::NSEC("www2.example.org. CNAME RRSIG NSEC").compare( - *test::createRdataUsingLexer(RRType::NSEC(), RRClass::IN(), - "www2 CNAME RRSIG NSEC"))); - - // Exceptions cause NULL to be returned. - EXPECT_FALSE(test::createRdataUsingLexer(RRType::NSEC(), RRClass::IN(), - "www.isc.org.")); -} - -TEST_F(Rdata_NSEC_Test, toWireRenderer_NSEC) { - renderer.skip(2); - const generic::NSEC rdata_nsec(nsec_txt); - rdata_nsec.toWire(renderer); - - vector<unsigned char> data; - UnitTestUtil::readWireData("rdata_nsec_fromWire1", data); - matchWireData(&data[2], data.size() - 2, - static_cast<const uint8_t *>(renderer.getData()) + 2, - renderer.getLength() - 2); -} - -TEST_F(Rdata_NSEC_Test, toWireBuffer_NSEC) { - const generic::NSEC rdata_nsec(nsec_txt); - rdata_nsec.toWire(obuffer); -} - -TEST_F(Rdata_NSEC_Test, assign) { - generic::NSEC rdata_nsec(nsec_txt); - generic::NSEC rdata_nsec2 = rdata_nsec; - EXPECT_EQ(0, rdata_nsec.compare(rdata_nsec2)); -} - -TEST_F(Rdata_NSEC_Test, getNextName) { - // The implementation is quite trivial, so we simply check it's actually - // defined and does work as intended in a simple case. - EXPECT_EQ(Name("www2.isc.org"), generic::NSEC((nsec_txt)).getNextName()); -} - -TEST_F(Rdata_NSEC_Test, compare) { - // trivial case: self equivalence - EXPECT_EQ(0, generic::NSEC("example. A"). - compare(generic::NSEC("example. A"))); - EXPECT_EQ(0, generic::NSEC("EXAMPLE. A"). // should be case insensitive - compare(generic::NSEC("example. A"))); - - // comparison attempt between incompatible RR types should be rejected - EXPECT_THROW(generic::NSEC(nsec_txt).compare(*rdata_nomatch), - bad_cast); - - // test RDATAs, sorted in the ascending order. We only compare the - // next name here. Bitmap comparison is tested in the bitmap tests. - // Note that names are compared as wire-format data, not based on the - // domain name comparison. - vector<generic::NSEC> compare_set; - compare_set.push_back(generic::NSEC("a.example. A")); - compare_set.push_back(generic::NSEC("example. A")); - - vector<generic::NSEC>::const_iterator it; - const vector<generic::NSEC>::const_iterator it_end = compare_set.end(); - for (it = compare_set.begin(); it != it_end - 1; ++it) { - SCOPED_TRACE("compare " + it->toText() + " to " + (it + 1)->toText()); - EXPECT_GT(0, (*it).compare(*(it + 1))); - EXPECT_LT(0, (*(it + 1)).compare(*it)); - } -} - -} diff --git a/src/lib/dns/tests/rdata_nsecbitmap_unittest.cc b/src/lib/dns/tests/rdata_nsecbitmap_unittest.cc index f18e9dfbfa..8b13789179 100644 --- a/src/lib/dns/tests/rdata_nsecbitmap_unittest.cc +++ b/src/lib/dns/tests/rdata_nsecbitmap_unittest.cc @@ -1,269 +1 @@ -// Copyright (C) 2011-2019 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. -#include <config.h> - -#include <dns/tests/unittest_util.h> - -#include <dns/exceptions.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> -#include <dns/rrclass.h> -#include <dns/rrtype.h> - -#include <gtest/gtest.h> - -#include <dns/tests/rdata_unittest.h> -#include <util/unittests/wiredata.h> - -#include <boost/lexical_cast.hpp> - -#include <string> -#include <vector> - -using namespace std; -using namespace isc::dns; -using namespace isc::dns::rdata; -using namespace isc::util; -using isc::UnitTestUtil; -using isc::util::unittests::matchWireData; -using boost::lexical_cast; - -namespace { - -// Template for shared tests for NSEC and NSEC3 bitmaps -template <typename RDATA_TYPE> -class NSECLikeBitmapTest : public RdataTest { -protected: - RDATA_TYPE fromText(const string& rdata_text) { - return (RDATA_TYPE(rdata_text)); - } - - vector<RDATA_TYPE> compare_set; // used in compare() tests - - void compareCheck() const { - typename vector<RDATA_TYPE>::const_iterator it; - typename vector<RDATA_TYPE>::const_iterator const it_end = - compare_set.end(); - for (it = compare_set.begin(); it != it_end - 1; ++it) { - SCOPED_TRACE("compare " + it->toText() + " to " + - (it + 1)->toText()); - EXPECT_GT(0, (*it).compare(*(it + 1))); - EXPECT_LT(0, (*(it + 1)).compare(*it)); - } - } - - // These depend on the specific RR type. We use specialized methods - // for them. - static RRType getType(); // return either RRType::NSEC() or NSEC3() - static string getWireFilePrefix(); - static string getCommonText(); // commonly used part of textual form -}; - -// Instantiate specific typed tests -typedef ::testing::Types<generic::NSEC, generic::NSEC3> TestRdataTypes; -#ifdef TYPED_TEST_SUITE -TYPED_TEST_SUITE(NSECLikeBitmapTest, TestRdataTypes); -#else -TYPED_TEST_CASE(NSECLikeBitmapTest, TestRdataTypes); -#endif - -// NSEC and NSEC3 bitmaps have some subtle differences, in which case we -// need to test them separately. Using these typedef type names with TEST_F -// will do the trick. -typedef NSECLikeBitmapTest<generic::NSEC3> NSEC3BitmapTest; -typedef NSECLikeBitmapTest<generic::NSEC> NSECBitmapTest; - -template <> -string -NSECLikeBitmapTest<generic::NSEC>::getWireFilePrefix() { - return ("rdata_nsec_"); -} - -template <> -RRType -NSECLikeBitmapTest<generic::NSEC>::getType() { - return (RRType::NSEC()); -} - -template <> -string -NSECLikeBitmapTest<generic::NSEC3>::getWireFilePrefix() { - return ("rdata_nsec3_"); -} - -template <> -RRType -NSECLikeBitmapTest<generic::NSEC3>::getType() { - return (RRType::NSEC3()); -} - -template <> -string -NSECLikeBitmapTest<generic::NSEC>::getCommonText() { - return ("next. "); -} - -template <> -string -NSECLikeBitmapTest<generic::NSEC3>::getCommonText() { - return ("1 1 12 AABBCCDD 2T7B4G4VSA5SMI47K61MV5BV1A22BOJR "); -} - -// Tests against various types of bogus NSEC/NSEC3 type bitmaps. -// The syntax and semantics are common for both RR types, and our -// implementation of that part is shared, so in theory it should be sufficient -// to test for only one RR type. But we check for both just in case. -TYPED_TEST(NSECLikeBitmapTest, createFromWire) { - // A malformed NSEC bitmap length field that could cause overflow. - EXPECT_THROW(this->rdataFactoryFromFile(this->getType(), RRClass::IN(), - (this->getWireFilePrefix() + - "fromWire4.wire").c_str()), - DNSMessageFORMERR); - - // The bitmap field is incomplete (only the first byte is included) - EXPECT_THROW(this->rdataFactoryFromFile(this->getType(), RRClass::IN(), - (this->getWireFilePrefix() + - "fromWire5.wire").c_str()), - DNSMessageFORMERR); - - // Bitmap length is 0, which is invalid. - EXPECT_THROW(this->rdataFactoryFromFile(this->getType(), RRClass::IN(), - (this->getWireFilePrefix() + - "fromWire6.wire").c_str()), - DNSMessageFORMERR); - - // Too large bitmap length with a short buffer. - EXPECT_THROW(this->rdataFactoryFromFile(this->getType(), RRClass::IN(), - (this->getWireFilePrefix() + - "fromWire3").c_str()), - DNSMessageFORMERR); - - // A boundary case: longest possible bitmaps (32 maps). This should be - // accepted. - EXPECT_NO_THROW(this->rdataFactoryFromFile(this->getType(), RRClass::IN(), - (this->getWireFilePrefix() + - "fromWire7.wire").c_str())); - - // Another boundary condition: 33 bitmaps, which should be rejected. - EXPECT_THROW(this->rdataFactoryFromFile(this->getType(), RRClass::IN(), - (this->getWireFilePrefix() + - "fromWire8.wire").c_str()), - DNSMessageFORMERR); - - // Disordered bitmap window blocks. - EXPECT_THROW(this->rdataFactoryFromFile(this->getType(), RRClass::IN(), - (this->getWireFilePrefix() + - "fromWire9.wire").c_str()), - DNSMessageFORMERR); - - // Bitmap ending with all-zero bytes. Not necessarily harmful except - // the additional overhead of parsing, but invalid according to the - // spec anyway. - EXPECT_THROW(this->rdataFactoryFromFile(this->getType(), RRClass::IN(), - (this->getWireFilePrefix() + - "fromWire10.wire").c_str()), - DNSMessageFORMERR); -} - -// This tests the result of toText() with various kinds of NSEC/NSEC3 bitmaps. -// It also tests the "from text" constructor as a result. -TYPED_TEST(NSECLikeBitmapTest, toText) { - // A simple case (some commonly seen RR types in NSEC(3) bitmaps) - string rdata_text = this->getCommonText() + "NS SOA RRSIG DNSKEY"; - EXPECT_EQ(rdata_text, this->fromText(rdata_text).toText()); - - // Similar to above, but involves more than one bitmap window blocks. - rdata_text = this->getCommonText() + "NS DLV"; - EXPECT_EQ(rdata_text, this->fromText(rdata_text).toText()); - - // Make sure all possible bits in a one-octet bitmap field are handled - // correctly. - // We use the range around 1024 (reasonably higher number) so it's - // unlikely that they have predefined mnemonic and can be safely converted - // to TYPEnnnn by toText(). - for (unsigned int i = 1024; i < 1032; ++i) { - rdata_text = this->getCommonText() + "TYPE" + lexical_cast<string>(i); - EXPECT_EQ(rdata_text, this->fromText(rdata_text).toText()); - } - - // Make sure all possible 32 octets in a longest possible block are - // handled correctly. - for (unsigned int i = 1024; i < 1024 + 256; i += 8) { - rdata_text = this->getCommonText() + "TYPE" + lexical_cast<string>(i); - EXPECT_EQ(rdata_text, this->fromText(rdata_text).toText()); - } - - // Check for the highest window block. - rdata_text = this->getCommonText() + "TYPE65535"; - EXPECT_EQ(rdata_text, this->fromText(rdata_text).toText()); -} - -TYPED_TEST(NSECLikeBitmapTest, compare) { - // Bit map: [win=0][len=1] 00000010 - this->compare_set.push_back(this->fromText(this->getCommonText() + "SOA")); - // Bit map: [win=0][len=1] 00000010, [win=4][len=1] 10000000 - this->compare_set.push_back(this->fromText(this->getCommonText() + - "SOA TYPE1024")); - // Bit map: [win=0][len=1] 00100000 - this->compare_set.push_back(this->fromText(this->getCommonText() + "NS")); - // Bit map: [win=0][len=1] 00100010 - this->compare_set.push_back(this->fromText(this->getCommonText() + - "NS SOA")); - // Bit map: [win=0][len=2] 00100000, 00000001 - this->compare_set.push_back(this->fromText(this->getCommonText() + - "NS MX")); - // Bit map: [win=4][len=1] 10000000 - this->compare_set.push_back(this->fromText(this->getCommonText() + - "TYPE1024")); - - this->compareCheck(); -} - -// NSEC bitmaps must not be empty -TEST_F(NSECBitmapTest, emptyMap) { - EXPECT_THROW(this->fromText("next.example.").toText(), InvalidRdataText); - - EXPECT_THROW(this->rdataFactoryFromFile(this->getType(), RRClass::IN(), - (this->getWireFilePrefix() + - "fromWire16.wire").c_str()), - DNSMessageFORMERR); -} - -// NSEC3 bitmaps can be empty -TEST_F(NSEC3BitmapTest, emptyMap) { - // Read wire data wit an empty NSEC3 bitmap. This should succeed. - vector<uint8_t> data; - UnitTestUtil::readWireData((this->getWireFilePrefix() + - "fromWire16.wire").c_str(), data); - InputBuffer buffer(&data[0], data.size()); - const uint16_t rdlen = buffer.readUint16(); - const generic::NSEC3 empty_nsec3 = - dynamic_cast<const generic::NSEC3&>(*createRdata( - RRType::NSEC3(), RRClass::IN(), - buffer, rdlen)); - - // Check the toText() result. - EXPECT_EQ("1 0 1 7373737373 D1K6GQ38D1K6GQ38D1K6GQ38D1K6GQ38", - empty_nsec3.toText()); - - // Check the toWire() result. - OutputBuffer obuffer(0); - obuffer.writeUint16(rdlen); - empty_nsec3.toWire(obuffer); - matchWireData(&data[0], data.size(), - obuffer.getData(), obuffer.getLength()); - - // Same for MessageRenderer. - obuffer.clear(); - MessageRenderer renderer; - renderer.writeUint16(rdlen); - empty_nsec3.toWire(renderer); - matchWireData(&data[0], data.size(), - renderer.getData(), renderer.getLength()); -} - -} diff --git a/src/lib/dns/tests/rdata_opt_unittest.cc b/src/lib/dns/tests/rdata_opt_unittest.cc index a235183529..8b13789179 100644 --- a/src/lib/dns/tests/rdata_opt_unittest.cc +++ b/src/lib/dns/tests/rdata_opt_unittest.cc @@ -1,198 +1 @@ -// Copyright (C) 2010-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. -#include <config.h> - -#include <util/buffer.h> -#include <dns/messagerenderer.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> -#include <dns/rrclass.h> -#include <dns/rrtype.h> - -#include <gtest/gtest.h> - -#include <dns/tests/unittest_util.h> -#include <dns/tests/rdata_unittest.h> -#include <util/unittests/wiredata.h> - -using namespace std; -using namespace isc::dns; -using namespace isc::util; -using namespace isc::dns::rdata; -using isc::UnitTestUtil; -using isc::util::unittests::matchWireData; - -namespace { -class Rdata_OPT_Test : public RdataTest { - // there's nothing to specialize -}; - -const uint8_t rdata_opt_wiredata[] = { - // Option code - 0x00, 0x2a, - // Option length - 0x00, 0x03, - // Option data - 0x00, 0x01, 0x02 -}; - -TEST_F(Rdata_OPT_Test, createFromText) { - // OPT RR cannot be created from text. - EXPECT_THROW(generic::OPT("this does not matter"), InvalidRdataText); -} - -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_fromWire1")); - EXPECT_NO_THROW(rdataFactoryFromFile(RRType::OPT(), RRClass::CH(), - "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_fromWire1", 11), - InvalidBufferPosition); -} - -TEST_F(Rdata_OPT_Test, createFromLexer) { - // OPT RR cannot be created from text. Exceptions cause NULL to be - // returned. - EXPECT_FALSE(test::createRdataUsingLexer(RRType::OPT(), RRClass::IN(), - "this does not matter")); -} - -TEST_F(Rdata_OPT_Test, toWireBuffer) { - const generic::OPT rdata_opt = - dynamic_cast<const generic::OPT&> - (*rdataFactoryFromFile(RRType("OPT"), RRClass("IN"), - "rdata_opt_fromWire1", 2)); - - obuffer.clear(); - rdata_opt.toWire(obuffer); - - matchWireData(rdata_opt_wiredata, sizeof(rdata_opt_wiredata), - obuffer.getData(), obuffer.getLength()); -} - -TEST_F(Rdata_OPT_Test, toWireRenderer) { - const generic::OPT rdata_opt = - dynamic_cast<const generic::OPT&> - (*rdataFactoryFromFile(RRType("OPT"), RRClass("IN"), - "rdata_opt_fromWire1", 2)); - - renderer.clear(); - rdata_opt.toWire(renderer); - - matchWireData(rdata_opt_wiredata, sizeof(rdata_opt_wiredata), - renderer.getData(), renderer.getLength()); -} - -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)), - isc::InvalidOperation); - - // comparison attempt between incompatible RR types also results in - // isc::InvalidOperation. - EXPECT_THROW(rdata_opt.compare(*RdataTest::rdata_nomatch), - isc::InvalidOperation); -} - -TEST_F(Rdata_OPT_Test, appendPseudoRR) { - generic::OPT rdata_opt; - - // Append empty option data - rdata_opt.appendPseudoRR(0x0042, NULL, 0); - - // Append simple option data - const uint8_t option_data[] = {'H', 'e', 'l', 'l', 'o'}; - rdata_opt.appendPseudoRR(0x0043, option_data, sizeof(option_data)); - - // Duplicate option codes are okay. - rdata_opt.appendPseudoRR(0x0042, option_data, sizeof(option_data)); - - // When option length may overflow RDLEN, append should throw. - const std::vector<uint8_t> buffer((1 << 16) - 1); - EXPECT_THROW(rdata_opt.appendPseudoRR(0x0044, &buffer[0], buffer.size()), - isc::InvalidParameter); - - const uint8_t rdata_opt_wiredata2[] = { - // OPTION #1 - // ` Option code - 0x00, 0x42, - // ` Option length - 0x00, 0x00, - - // OPTION #2 - // ` Option code - 0x00, 0x43, - // ` Option length - 0x00, 0x05, - // ` Option data - 'H', 'e', 'l', 'l', 'o', - - // OPTION #3 - // ` Option code - 0x00, 0x42, - // ` Option length - 0x00, 0x05, - // ` Option data - 'H', 'e', 'l', 'l', 'o' - }; - - obuffer.clear(); - rdata_opt.toWire(obuffer); - - matchWireData(rdata_opt_wiredata2, sizeof(rdata_opt_wiredata2), - obuffer.getData(), obuffer.getLength()); -} - -TEST_F(Rdata_OPT_Test, getPseudoRRs) { - const generic::OPT rdf = - dynamic_cast<const generic::OPT&> - (*rdataFactoryFromFile(RRType("OPT"), RRClass("IN"), - "rdata_opt_fromWire1", 2)); - - const std::vector<generic::OPT::PseudoRR>& rrs = rdf.getPseudoRRs(); - ASSERT_FALSE(rrs.empty()); - EXPECT_EQ(1, rrs.size()); - EXPECT_EQ(0x2a, rrs.at(0).getCode()); - EXPECT_EQ(3, rrs.at(0).getLength()); - - const uint8_t expected_data[] = {0x00, 0x01, 0x02}; - const uint8_t* actual_data = rrs.at(0).getData(); - EXPECT_EQ(0, std::memcmp(expected_data, actual_data, - sizeof(expected_data))); -} -} diff --git a/src/lib/dns/tests/rdata_pimpl_holder_unittest.cc b/src/lib/dns/tests/rdata_pimpl_holder_unittest.cc index d639541949..8b13789179 100644 --- a/src/lib/dns/tests/rdata_pimpl_holder_unittest.cc +++ b/src/lib/dns/tests/rdata_pimpl_holder_unittest.cc @@ -1,56 +1 @@ -// Copyright (C) 2014-2017 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. -#include <config.h> - -#include <dns/rdata_pimpl_holder.h> - -#include <gtest/gtest.h> - -using namespace isc::dns::rdata; - -namespace { - -TEST(RdataPimplHolderTest, all) { - // Let's check with an integer - int* i1 = new int(42); - RdataPimplHolder<int> holder1(i1); - // The same pointer must be returned. - EXPECT_EQ(i1, holder1.get()); - // Obviously the value should match too. - EXPECT_EQ(42, *holder1.get()); - // We don't explicitly delete i or holder1, so it should not leak - // anything when the test is done (checked by Valgrind). - - // The following cases are similar: - - // Test no-argument reset() - int* i2 = new int(43); - RdataPimplHolder<int> holder2(i2); - holder2.reset(); - EXPECT_EQ(NULL, holder2.get()); - - // Test reset() with argument - int* i3 = new int(44); - int* i4 = new int(45); - RdataPimplHolder<int> holder3(i3); - EXPECT_EQ(i3, holder3.get()); - holder3.reset(i4); - EXPECT_EQ(i4, holder3.get()); - EXPECT_EQ(45, *holder3.get()); - - // Test release() - RdataPimplHolder<int> holder4(new int(46)); - EXPECT_NE(static_cast<void*>(NULL), holder4.get()); - EXPECT_EQ(46, *holder4.get()); - int* i5 = holder4.release(); - EXPECT_EQ(NULL, holder4.get()); - EXPECT_NE(static_cast<void*>(NULL), i5); - EXPECT_EQ(46, *i5); - delete i5; -} - -} diff --git a/src/lib/dns/tests/rdata_ptr_unittest.cc b/src/lib/dns/tests/rdata_ptr_unittest.cc index 5ed3bce0f8..8b13789179 100644 --- a/src/lib/dns/tests/rdata_ptr_unittest.cc +++ b/src/lib/dns/tests/rdata_ptr_unittest.cc @@ -1,145 +1 @@ -// Copyright (C) 2010-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. -#include <config.h> - -#include <util/buffer.h> -#include <dns/exceptions.h> -#include <dns/messagerenderer.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> -#include <dns/rrclass.h> -#include <dns/rrtype.h> - -#include <gtest/gtest.h> - -#include <dns/tests/unittest_util.h> -#include <dns/tests/rdata_unittest.h> -#include <util/unittests/wiredata.h> - -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. -// - -namespace { -class Rdata_PTR_Test : public RdataTest { -public: - Rdata_PTR_Test() : - rdata_ptr("ns.example.com."), - rdata_ptr2("ns2.example.com.") - {} - - const generic::PTR rdata_ptr; - const generic::PTR rdata_ptr2; -}; - -const uint8_t wiredata_ptr[] = { - 0x02, 0x6e, 0x73, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x03, - 0x63, 0x6f, 0x6d, 0x00 }; -const uint8_t wiredata_ptr2[] = { - // first name: ns.example.com. - 0x02, 0x6e, 0x73, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x03, - 0x63, 0x6f, 0x6d, 0x00, - // second name: ns2.example.com. all labels except the first should be - // compressed. - 0x03, 0x6e, 0x73, 0x32, 0xc0, 0x03 }; - -TEST_F(Rdata_PTR_Test, createFromText) { - EXPECT_EQ(0, rdata_ptr.compare(generic::PTR("ns.example.com."))); - // explicitly add a trailing dot. should be the same RDATA. - EXPECT_EQ(0, rdata_ptr.compare(generic::PTR("ns.example.com."))); - // should be case sensitive. - EXPECT_EQ(0, rdata_ptr.compare(generic::PTR("NS.EXAMPLE.COM."))); - // RDATA of a class-independent type should be recognized for any - // "unknown" class. - EXPECT_EQ(0, rdata_ptr.compare(*createRdata(RRType("PTR"), RRClass(65000), - "ns.example.com."))); -} - -TEST_F(Rdata_PTR_Test, badText) { - // Extra text at end of line - EXPECT_THROW(generic::PTR("foo.example.com. extra."), InvalidRdataText); -} - -TEST_F(Rdata_PTR_Test, createFromWire) { - EXPECT_EQ(0, rdata_ptr.compare( - *rdataFactoryFromFile(RRType("PTR"), RRClass("IN"), - "rdata_ns_fromWire"))); - // RDLENGTH is too short - EXPECT_THROW(rdataFactoryFromFile(RRType("PTR"), RRClass("IN"), - "rdata_ns_fromWire", 18), - InvalidRdataLength); - // RDLENGTH is too long - EXPECT_THROW(rdataFactoryFromFile(RRType("PTR"), RRClass("IN"), - "rdata_ns_fromWire", 36), - InvalidRdataLength); - // incomplete name. the error should be detected in the name constructor - EXPECT_THROW(rdataFactoryFromFile(RRType("PTR"), RRClass("IN"), - "rdata_ns_fromWire", 71), - DNSMessageFORMERR); - - EXPECT_EQ(0, generic::PTR("ns2.example.com.").compare( - *rdataFactoryFromFile(RRType("PTR"), RRClass("IN"), - "rdata_ns_fromWire", 55))); - EXPECT_THROW(*rdataFactoryFromFile(RRType("PTR"), RRClass("IN"), - "rdata_ns_fromWire", 63), - InvalidRdataLength); -} - -TEST_F(Rdata_PTR_Test, createFromLexer) { - EXPECT_EQ(0, rdata_ptr.compare( - *test::createRdataUsingLexer(RRType::PTR(), RRClass::IN(), - "ns.example.com."))); - - // test::createRdataUsingLexer() constructs relative to - // "example.org." origin. - EXPECT_EQ(0, generic::PTR("foo0.example.org.").compare( - *test::createRdataUsingLexer(RRType::PTR(), RRClass::IN(), - "foo0"))); - - // Extra text at end of line - EXPECT_FALSE(test::createRdataUsingLexer(RRType::PTR(), RRClass::IN(), - "foo.example.com. extra.")); -} - -TEST_F(Rdata_PTR_Test, toWireBuffer) { - rdata_ptr.toWire(obuffer); - matchWireData(wiredata_ptr, sizeof(wiredata_ptr), - obuffer.getData(), obuffer.getLength()); -} - -TEST_F(Rdata_PTR_Test, toWireRenderer) { - rdata_ptr.toWire(renderer); - matchWireData(wiredata_ptr, sizeof(wiredata_ptr), - renderer.getData(), renderer.getLength()); - - rdata_ptr2.toWire(renderer); - matchWireData(wiredata_ptr2, sizeof(wiredata_ptr2), - renderer.getData(), renderer.getLength()); -} - -TEST_F(Rdata_PTR_Test, toText) { - EXPECT_EQ("ns.example.com.", rdata_ptr.toText()); -} - -TEST_F(Rdata_PTR_Test, compare) { - generic::PTR small("a.example."); - generic::PTR large("example."); - EXPECT_TRUE(Name("a.example") > Name("example")); - EXPECT_GT(0, small.compare(large)); -} - -TEST_F(Rdata_PTR_Test, getPTRName) { - EXPECT_EQ(Name("ns.example.com"), rdata_ptr.getPTRName()); -} -} diff --git a/src/lib/dns/tests/rdata_rp_unittest.cc b/src/lib/dns/tests/rdata_rp_unittest.cc index e752f13772..8b13789179 100644 --- a/src/lib/dns/tests/rdata_rp_unittest.cc +++ b/src/lib/dns/tests/rdata_rp_unittest.cc @@ -1,200 +1 @@ -// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. -#include <config.h> - -#include <string> - -#include <util/buffer.h> -#include <dns/exceptions.h> -#include <dns/rdataclass.h> - -#include <gtest/gtest.h> - -#include <dns/tests/unittest_util.h> -#include <dns/tests/rdata_unittest.h> -#include <util/unittests/wiredata.h> - -using namespace std; -using namespace isc::util; -using namespace isc::dns; -using namespace isc::dns::rdata; -using isc::UnitTestUtil; -using isc::util::unittests::matchWireData; - -namespace { -class Rdata_RP_Test : public RdataTest { -protected: - Rdata_RP_Test() : - mailbox_name("root.example.com."), - text_name("rp-text.example.com."), - // this also serves as a test for "from text" constructor in a normal - // case. - rdata_rp("root.example.com. rp-text.example.com."), - obuffer(0) - {} - - void checkFromText_None(const string& rdata_str) { - checkFromText<generic::RP, isc::Exception, isc::Exception>( - rdata_str, rdata_rp, false, false); - } - - void checkFromText_LexerError(const string& rdata_str) { - checkFromText - <generic::RP, InvalidRdataText, MasterLexer::LexerError>( - rdata_str, rdata_rp, true, true); - } - - void checkFromText_BadString(const string& rdata_str) { - checkFromText<generic::RP, InvalidRdataText, isc::Exception>( - rdata_str, rdata_rp, true, false); - } - - void checkFromText_EmptyLabel(const string& rdata_str) { - checkFromText<generic::RP, EmptyLabel, EmptyLabel>( - rdata_str, rdata_rp, true, true); - } - - void checkFromText_MissingOrigin(const string& rdata_str) { - checkFromText - <generic::RP, MissingNameOrigin, MissingNameOrigin>( - rdata_str, rdata_rp, true, true); - } - - void checkFromText_Origin(const string& rdata_str, const Name* origin) { - checkFromText<generic::RP, MissingNameOrigin, isc::Exception>( - rdata_str, rdata_rp, true, false, origin); - } - - const Name mailbox_name, text_name; - const generic::RP rdata_rp; // commonly used test RDATA - OutputBuffer obuffer; - MessageRenderer renderer; - vector<uint8_t> expected_wire; -}; - -TEST_F(Rdata_RP_Test, createFromText) { - EXPECT_EQ(mailbox_name, rdata_rp.getMailbox()); - EXPECT_EQ(text_name, rdata_rp.getText()); - - checkFromText_None("root.example.com. rp-text.example.com."); - - // origin defined for lexer constructor, but not string constructor - const Name origin("example.com"); - checkFromText_Origin("root rp-text", &origin); - - // lexer constructor accepts extra text, but string constructor doesn't - checkFromText_BadString("root.example.com. rp-text.example.com. " - "extra.example.com."); -} - -TEST_F(Rdata_RP_Test, badText) { - // invalid names - checkFromText_EmptyLabel("root..example.com. rp-text.example.com."); - checkFromText_EmptyLabel("root.example.com. rp-text..example.com."); - - // missing field - checkFromText_LexerError("root.example.com."); - - // missing origin - checkFromText_MissingOrigin("root.example.com rp-text.example.com."); - checkFromText_MissingOrigin("root.example.com. rp-text.example.com"); -} - -TEST_F(Rdata_RP_Test, createFromWire) { - RdataPtr rdata(rdataFactoryFromFile(RRType::RP(), RRClass::IN(), - "rdata_rp_fromWire1.wire")); - EXPECT_EQ(mailbox_name, dynamic_cast<generic::RP&>(*rdata).getMailbox()); - EXPECT_EQ(text_name, dynamic_cast<generic::RP&>(*rdata).getText()); - - // a similar test with names being compressed - rdata = rdataFactoryFromFile(RRType::RP(), RRClass::IN(), - "rdata_rp_fromWire2.wire", 30); - EXPECT_EQ(mailbox_name, dynamic_cast<generic::RP&>(*rdata).getMailbox()); - EXPECT_EQ(Name("rp-text.example.net"), - dynamic_cast<generic::RP&>(*rdata).getText()); -} - -TEST_F(Rdata_RP_Test, badFromWire) { - // RDLEN is too short - EXPECT_THROW(rdataFactoryFromFile(RRType::RP(), RRClass::IN(), - "rdata_rp_fromWire3.wire"), - InvalidRdataLength); - - // RDLEN is too long - EXPECT_THROW(rdataFactoryFromFile(RRType::RP(), RRClass::IN(), - "rdata_rp_fromWire4.wire"), - InvalidRdataLength); - - // bogus mailbox name - EXPECT_THROW(rdataFactoryFromFile(RRType::RP(), RRClass::IN(), - "rdata_rp_fromWire5.wire"), - DNSMessageFORMERR); - - // bogus text name - EXPECT_THROW(rdataFactoryFromFile(RRType::RP(), RRClass::IN(), - "rdata_rp_fromWire6.wire"), - DNSMessageFORMERR); -} - -TEST_F(Rdata_RP_Test, createFromParams) { - EXPECT_EQ(mailbox_name, generic::RP(mailbox_name, text_name).getMailbox()); - EXPECT_EQ(text_name, generic::RP(mailbox_name, text_name).getText()); -} - -TEST_F(Rdata_RP_Test, toWireBuffer) { - // construct expected data - UnitTestUtil::readWireData("rdata_rp_toWire1.wire", expected_wire); - - // construct actual data - rdata_rp.toWire(obuffer); - - // then compare them - matchWireData(&expected_wire[0], expected_wire.size(), - obuffer.getData(), obuffer.getLength()); -} - -TEST_F(Rdata_RP_Test, toWireRenderer) { - // similar to toWireBuffer, but names in RDATA could be compressed due to - // preceding names. Actually they must not be compressed according to - // RFC3597, and this test checks that. - - UnitTestUtil::readWireData("rdata_rp_toWire2.wire", expected_wire); - - renderer.writeName(Name("a.example.com")); - renderer.writeName(Name("b.example.net")); - generic::RP(mailbox_name, Name("rp-text.example.net")).toWire(renderer); - matchWireData(&expected_wire[0], expected_wire.size(), - renderer.getData(), renderer.getLength()); -} - -TEST_F(Rdata_RP_Test, toText) { - // there's not much to test for this method. Only checking a simple case. - EXPECT_EQ("root.example.com. rp-text.example.com.", rdata_rp.toText()); -} - -TEST_F(Rdata_RP_Test, compare) { - // check reflexivity - EXPECT_EQ(0, rdata_rp.compare(rdata_rp)); - - // names must be compared in case-insensitive manner - EXPECT_EQ(0, rdata_rp.compare(generic::RP("ROOT.example.com. " - "rp-text.EXAMPLE.com."))); - - // another RP whose mailbox name is larger than that of rdata_rp. - const generic::RP large1_rp("zzzz.example.com. rp-text.example.com."); - EXPECT_GT(0, rdata_rp.compare(large1_rp)); - EXPECT_LT(0, large1_rp.compare(rdata_rp)); - - // yet another RP whose text name is larger than that of rdata_rp. - const generic::RP large2_rp("root.example.com. zzzzzzz.example.com."); - EXPECT_GT(0, rdata_rp.compare(large2_rp)); - EXPECT_LT(0, large2_rp.compare(rdata_rp)); - - // comparison attempt between incompatible RR types should be rejected - EXPECT_THROW(rdata_rp.compare(*RdataTest::rdata_nomatch), bad_cast); -} -} diff --git a/src/lib/dns/tests/rdata_rrsig_unittest.cc b/src/lib/dns/tests/rdata_rrsig_unittest.cc index b198d15c62..8b13789179 100644 --- a/src/lib/dns/tests/rdata_rrsig_unittest.cc +++ b/src/lib/dns/tests/rdata_rrsig_unittest.cc @@ -1,369 +1 @@ -// Copyright (C) 2010-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. -#include <config.h> - -#include <exceptions/exceptions.h> - -#include <util/buffer.h> -#include <util/time_utilities.h> -#include <dns/messagerenderer.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> -#include <dns/rrclass.h> -#include <dns/rrtype.h> - -#include <gtest/gtest.h> - -#include <dns/tests/unittest_util.h> -#include <util/unittests/wiredata.h> -#include <dns/tests/rdata_unittest.h> - -using namespace std; -using namespace isc; -using namespace isc::dns; -using namespace isc::util; -using namespace isc::dns::rdata; -using isc::UnitTestUtil; -using isc::util::unittests::matchWireData; - -namespace { - -const uint8_t wiredata_rrsig[] = { - // type covered = A - 0x00, 0x01, - // algorithm = 5 - 0x05, - // labels = 4 - 0x04, - // original TTL = 43200 (0x0000a8c0) - 0x00, 0x00, 0xa8, 0xc0, - // signature expiration = 1266961577 (0x4b844ca9) - 0x4b, 0x84, 0x4c, 0xa9, - // signature inception = 1266875177 (0x4b82fb29) - 0x4b, 0x82, 0xfb, 0x29, - // key tag = 8496 (0x2130) - 0x21, 0x30, - // signer's name (isc.org.) - // 3 i s c 3 o r g 0 - 0x03, 0x69, 0x73, 0x63, 0x03, 0x6f, 0x72, 0x67, 0x00, - // signature data follows - 0x7a, 0xfc, 0x61, 0x94, 0x6c, - 0x75, 0xde, 0x6a, 0x4a, 0x2d, 0x59, 0x0a, 0xb2, - 0x3a, 0x46, 0xcf, 0x27, 0x12, 0xe6, 0xdc, 0x2d, - 0x22, 0x8c, 0x4e, 0x9a, 0x53, 0x75, 0xe3, 0x0f, - 0x6d, 0xe4, 0x08, 0x33, 0x18, 0x19, 0xb3, 0x76, - 0x21, 0x9d, 0x2c, 0x8a, 0xc5, 0x69, 0xba, 0xab, - 0xef, 0x66, 0x9f, 0xda, 0xb5, 0x2a, 0xf9, 0x40, - 0xc1, 0x28, 0xc5, 0x97, 0xba, 0x3c, 0x19, 0x4d, - 0x95, 0x13, 0xc2, 0xcd, 0xf6, 0xb1, 0x59, 0x5d, - 0x0c, 0xf9, 0x3f, 0x35, 0xbb, 0x9a, 0x70, 0x93, - 0x36, 0xe5, 0xf4, 0x17, 0x7e, 0xfe, 0x66, 0x3b, - 0x70, 0x1f, 0xed, 0x33, 0xa8, 0xa3, 0x0d, 0xc0, - 0x8c, 0xc6, 0x95, 0x1b, 0xd8, 0x9c, 0x8c, 0x25, - 0xb4, 0x57, 0x9e, 0x56, 0x71, 0x64, 0x14, 0x7f, - 0x8f, 0x6d, 0xfa, 0xc5, 0xca, 0x3f, 0x36, 0xe2, - 0xa4, 0xdf, 0x60, 0xfa, 0xcd, 0x59, 0x3e, 0x22, - 0x32, 0xa1, 0xf7 -}; - -class Rdata_RRSIG_Test : public RdataTest { -protected: - Rdata_RRSIG_Test() : - rrsig_txt("A 5 4 43200 20100223214617 20100222214617 8496 isc.org. " - "evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz" - "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/" - "NbuacJM25fQXfv5mO3Af7TOoow3AjMaVG9icjCW0V55WcWQU" - "f49t+sXKPzbipN9g+s1ZPiIyofc="), - rdata_rrsig(rrsig_txt) - {} - - void checkFromText_None(const string& rdata_str) { - checkFromText<generic::RRSIG, isc::Exception, isc::Exception>( - rdata_str, rdata_rrsig, false, false); - } - - void checkFromText_InvalidText(const string& rdata_str) { - checkFromText<generic::RRSIG, InvalidRdataText, InvalidRdataText>( - rdata_str, rdata_rrsig, true, true); - } - - void checkFromText_InvalidType(const string& rdata_str) { - checkFromText<generic::RRSIG, InvalidRRType, InvalidRRType>( - rdata_str, rdata_rrsig, true, true); - } - - void checkFromText_InvalidTime(const string& rdata_str) { - checkFromText<generic::RRSIG, InvalidTime, InvalidTime>( - rdata_str, rdata_rrsig, true, true); - } - - void checkFromText_BadValue(const string& rdata_str) { - checkFromText<generic::RRSIG, BadValue, BadValue>( - rdata_str, rdata_rrsig, true, true); - } - - void checkFromText_LexerError(const string& rdata_str) { - checkFromText - <generic::RRSIG, InvalidRdataText, MasterLexer::LexerError>( - rdata_str, rdata_rrsig, true, true); - } - - void checkFromText_MissingOrigin(const string& rdata_str) { - checkFromText - <generic::RRSIG, MissingNameOrigin, MissingNameOrigin>( - rdata_str, rdata_rrsig, true, true); - } - - void checkFromText_BadString(const string& rdata_str) { - checkFromText - <generic::RRSIG, InvalidRdataText, isc::Exception>( - rdata_str, rdata_rrsig, true, false); - } - - const string rrsig_txt; - const generic::RRSIG rdata_rrsig; -}; - -TEST_F(Rdata_RRSIG_Test, fromText) { - EXPECT_EQ(rrsig_txt, rdata_rrsig.toText()); - EXPECT_EQ(isc::dns::RRType::A(), rdata_rrsig.typeCovered()); - - // Missing signature is OK - EXPECT_NO_THROW(const generic::RRSIG sig( - "A 5 4 43200 20100223214617 20100222214617 8496 isc.org.")); - - // Space in signature data is OK - checkFromText_None( - "A 5 4 43200 20100223214617 20100222214617 8496 isc.org. " - "evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz " - "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/ " - "NbuacJM25fQXfv5mO3Af7TOoow3AjMaVG9icjCW0V55WcWQU " - "f49t+sXKPzbipN9g+s1ZPiIyofc="); - - // Multi-line signature data is OK, if enclosed in parentheses - checkFromText_None( - "A 5 4 43200 20100223214617 20100222214617 8496 isc.org. " - "( evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz\n" - "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/\n" - "NbuacJM25fQXfv5mO3Af7TOoow3AjMaVG9icjCW0V55WcWQU\n" - "f49t+sXKPzbipN9g+s1ZPiIyofc= )"); - - // Trailing garbage. This should cause only the string constructor - // to fail, but the lexer constructor must be able to continue - // parsing from it. - checkFromText_BadString( - "A 5 4 43200 20100223214617 20100222214617 8496 isc.org. " - "evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz" - "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/" - "NbuacJM25fQXfv5mO3Af7TOoow3AjMaVG9icjCW0V55WcWQU" - "f49t+sXKPzbipN9g+s1ZPiIyofc= ; comment\n" - "A 5 4 43200 20100223214617 20100222214617 8496 isc.org. " - "evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz" - "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/" - "NbuacJM25fQXfv5mO3Af7TOoow3AjMaVG9icjCW0V55WcWQU" - "f49t+sXKPzbipN9g+s1ZPiIyofc="); -} - -TEST_F(Rdata_RRSIG_Test, badText_missingFields) { - checkFromText_LexerError("A"); - checkFromText_LexerError("A 5"); - checkFromText_LexerError("A 5 4"); - checkFromText_LexerError("A 5 4 43200"); - checkFromText_LexerError("A 5 4 43200 20100223214617"); - checkFromText_LexerError("A 5 4 43200 20100223214617 20100222214617"); - checkFromText_LexerError("A 5 4 43200 20100223214617 20100222214617 " - "8496"); -} - -TEST_F(Rdata_RRSIG_Test, badText_coveredType) { - checkFromText_InvalidType("SPORK"); -} - -TEST_F(Rdata_RRSIG_Test, badText_algorithm) { - checkFromText_InvalidText( - "A 555 4 43200 " - "20100223214617 20100222214617 8496 isc.org. " - "evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz" - "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/" - "NbuacJM25fQXfv5mO3Af7TOoow3AjMaVG9icjCW0V55WcWQU" - "f49t+sXKPzbipN9g+s1ZPiIyofc="); - checkFromText_LexerError( - "A FIVE 4 43200 " - "20100223214617 20100222214617 8496 isc.org. " - "evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz" - "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/" - "NbuacJM25fQXfv5mO3Af7TOoow3AjMaVG9icjCW0V55WcWQU" - "f49t+sXKPzbipN9g+s1ZPiIyofc="); -} - -TEST_F(Rdata_RRSIG_Test, badText_labels) { - checkFromText_InvalidText( - "A 5 4444 43200 " - "20100223214617 20100222214617 8496 isc.org. " - "evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz" - "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/" - "NbuacJM25fQXfv5mO3Af7TOoow3AjMaVG9icjCW0V55WcWQU" - "f49t+sXKPzbipN9g+s1ZPiIyofc="); - checkFromText_LexerError( - "A 5 FOUR 43200 " - "20100223214617 20100222214617 8496 isc.org. " - "evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz" - "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/" - "NbuacJM25fQXfv5mO3Af7TOoow3AjMaVG9icjCW0V55WcWQU" - "f49t+sXKPzbipN9g+s1ZPiIyofc="); -} - -TEST_F(Rdata_RRSIG_Test, badText_ttl) { - checkFromText_LexerError( - "A 5 4 999999999999 " - "20100223214617 20100222214617 8496 isc.org. " - "evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz" - "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/" - "NbuacJM25fQXfv5mO3Af7TOoow3AjMaVG9icjCW0V55WcWQU" - "f49t+sXKPzbipN9g+s1ZPiIyofc="); - checkFromText_LexerError( - "A 5 4 TTL " - "20100223214617 20100222214617 8496 isc.org. " - "evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz" - "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/" - "NbuacJM25fQXfv5mO3Af7TOoow3AjMaVG9icjCW0V55WcWQU" - "f49t+sXKPzbipN9g+s1ZPiIyofc="); - - // alternate form of TTL is not okay - checkFromText_LexerError( - "A 5 4 12H 20100223214617 20100222214617 8496 isc.org. " - "evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz " - "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/ " - "NbuacJM25fQXfv5mO3Af7TOoow3AjMaVG9icjCW0V55WcWQU " - "f49t+sXKPzbipN9g+s1ZPiIyofc="); -} - -TEST_F(Rdata_RRSIG_Test, badText_expiration) { - checkFromText_InvalidTime( - "A 5 4 43200 " - "201002232 20100222214617 8496 isc.org. " - "evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz" - "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/" - "NbuacJM25fQXfv5mO3Af7TOoow3AjMaVG9icjCW0V55WcWQU" - "f49t+sXKPzbipN9g+s1ZPiIyofc="); - checkFromText_InvalidTime( - "A 5 4 43200 " - "EXPIRATION 20100222214617 8496 isc.org. " - "evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz" - "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/" - "NbuacJM25fQXfv5mO3Af7TOoow3AjMaVG9icjCW0V55WcWQU" - "f49t+sXKPzbipN9g+s1ZPiIyofc="); -} - -TEST_F(Rdata_RRSIG_Test, badText_inception) { - checkFromText_InvalidTime( - "A 5 4 43200 " - "20100223214617 20100227 8496 isc.org. " - "evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz" - "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/" - "NbuacJM25fQXfv5mO3Af7TOoow3AjMaVG9icjCW0V55WcWQU" - "f49t+sXKPzbipN9g+s1ZPiIyofc="); - checkFromText_InvalidTime( - "A 5 4 43200 " - "20100223214617 INCEPTION 8496 isc.org. " - "evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz" - "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/" - "NbuacJM25fQXfv5mO3Af7TOoow3AjMaVG9icjCW0V55WcWQU" - "f49t+sXKPzbipN9g+s1ZPiIyofc="); -} - -TEST_F(Rdata_RRSIG_Test, badText_keytag) { - checkFromText_InvalidText( - "A 5 4 43200 " - "20100223214617 20100222214617 999999 isc.org. " - "evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz" - "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/" - "NbuacJM25fQXfv5mO3Af7TOoow3AjMaVG9icjCW0V55WcWQU" - "f49t+sXKPzbipN9g+s1ZPiIyofc="); - checkFromText_LexerError( - "A 5 4 43200 " - "20100223214617 20100222214617 TAG isc.org. " - "evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz" - "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/" - "NbuacJM25fQXfv5mO3Af7TOoow3AjMaVG9icjCW0V55WcWQU" - "f49t+sXKPzbipN9g+s1ZPiIyofc="); -} - -TEST_F(Rdata_RRSIG_Test, badText_signer) { - checkFromText_MissingOrigin( - "A 5 4 43200 " - "20100223214617 20100222214617 8496 isc.org " - "evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz" - "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/" - "NbuacJM25fQXfv5mO3Af7TOoow3AjMaVG9icjCW0V55WcWQU" - "f49t+sXKPzbipN9g+s1ZPiIyofc="); -} - -TEST_F(Rdata_RRSIG_Test, badText_signature) { - checkFromText_BadValue( - "A 5 4 43200 " - "20100223214617 20100222214617 8496 isc.org. " - "EEeeeeeeEEEeeeeeeGaaahAAAAAAAAHHHHHHHHHHH!="); - - // no space between the tag and signer - checkFromText_LexerError( - "A 5 4 43200 20100223214617 20100222214617 " - "8496isc.org. ofc="); - - // unterminated multi-line base64 - checkFromText_LexerError( - "A 5 4 43200 20100223214617 20100222214617 8496 isc.org. " - "( evxhlGx13mpKLVkKsjpGzycS5twtIoxOmlN14w9t5AgzGBmz\n" - "diGdLIrFabqr72af2rUq+UDBKMWXujwZTZUTws32sVldDPk/\n" - "NbuacJM25fQXfv5mO3Af7TOoow3AjMaVG9icjCW0V55WcWQU\n" - "f49t+sXKPzbipN9g+s1ZPiIyofc="); -} - -TEST_F(Rdata_RRSIG_Test, createFromLexer) { - EXPECT_EQ(0, rdata_rrsig.compare( - *test::createRdataUsingLexer(RRType::RRSIG(), RRClass::IN(), - rrsig_txt))); - - // Exceptions cause NULL to be returned. - EXPECT_FALSE(test::createRdataUsingLexer(RRType::RRSIG(), RRClass::IN(), - "INVALIDINPUT")); -} - -TEST_F(Rdata_RRSIG_Test, toWireRenderer) { - rdata_rrsig.toWire(renderer); - - matchWireData(wiredata_rrsig, sizeof(wiredata_rrsig), - renderer.getData(), renderer.getLength()); -} - -TEST_F(Rdata_RRSIG_Test, toWireBuffer) { - rdata_rrsig.toWire(obuffer); - - matchWireData(wiredata_rrsig, sizeof(wiredata_rrsig), - obuffer.getData(), obuffer.getLength()); -} - -TEST_F(Rdata_RRSIG_Test, createFromWire) { - const string rrsig_txt2( - "A 5 2 43200 20100327070149 20100225070149 2658 isc.org. " - "HkJk/xZTvzePU8NENl/ley8bbUumhk1hXciyqhLnz1VQFzkDooej6neX" - "ZgWZzQKeTKPOYWrnYtdZW4PnPQFeUl3orgLev7F8J6FZlDn0y/J/ThR5" - "m36Mo2/Gdxjj8lJ/IjPVkdpKyBpcnYND8KEIma5MyNCNeyO1UkfPQZGHNSQ="); - EXPECT_EQ(rrsig_txt2, - rdataFactoryFromFile(RRType("RRSIG"), RRClass("IN"), - "rdata_rrsig_fromWire1")->toText()); - const generic::RRSIG rdata_rrsig2(rrsig_txt2); - EXPECT_EQ(0, rdata_rrsig2.compare( - *rdataFactoryFromFile(RRType("RRSIG"), RRClass("IN"), - "rdata_rrsig_fromWire1"))); - - // RDLEN is too short - EXPECT_THROW(rdataFactoryFromFile(RRType::RRSIG(), RRClass::IN(), - "rdata_rrsig_fromWire2.wire"), - InvalidRdataLength); -} -} diff --git a/src/lib/dns/tests/rdata_soa_unittest.cc b/src/lib/dns/tests/rdata_soa_unittest.cc index 21f4dc4854..8b13789179 100644 --- a/src/lib/dns/tests/rdata_soa_unittest.cc +++ b/src/lib/dns/tests/rdata_soa_unittest.cc @@ -1,249 +1 @@ -// Copyright (C) 2010-2017 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. -#include <config.h> - -#include <util/buffer.h> -#include <dns/messagerenderer.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> -#include <dns/rrclass.h> -#include <dns/rrtype.h> - -#include <gtest/gtest.h> - -#include <dns/tests/unittest_util.h> -#include <dns/tests/rdata_unittest.h> -#include <util/unittests/wiredata.h> - -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 { -protected: - Rdata_SOA_Test() : - rdata_soa(Name("ns.example.com"), - Name("root.example.com"), - 2010012601, 3600, 300, 3600000, 1200) - {} - - template <typename ExForString, typename ExForLexer> - void checkFromTextSOA(const string& soa_txt, const Name* origin = NULL, - bool throw_str_version = true, - bool throw_lexer_version = true) - { - checkFromText<generic::SOA, ExForString, ExForLexer>( - soa_txt, rdata_soa, throw_str_version, throw_lexer_version, - origin); - } - - const generic::SOA rdata_soa; -}; - -TEST_F(Rdata_SOA_Test, createFromText) { - // Below we specify isc::Exception as a dummy value for the exception type - // in case it's not expected to throw an exception; the type isn't used - // in the check code. - - // A simple case. - checkFromTextSOA<isc::Exception, isc::Exception>( - "ns.example.com. root.example.com. 2010012601 3600 300 3600000 1200", - NULL, false, false); - - // Beginning and trailing space are ignored. - checkFromTextSOA<isc::Exception, isc::Exception>( - " ns.example.com. root.example.com. " - "2010012601 3600 300 3600000 1200 ", NULL, false, false); - - // using extended TTL-like form for some parameters. - checkFromTextSOA<isc::Exception, isc::Exception>( - "ns.example.com. root.example.com. 2010012601 1H 5M 1000H 20M", - NULL, false, false); - - // multi-line. - checkFromTextSOA<isc::Exception, isc::Exception>( - "ns.example.com. (root.example.com.\n" - "2010012601 1H 5M 1000H) 20M", NULL, false, false); - - // relative names for MNAME and RNAME with a separate origin (lexer - // version only) - const Name origin("example.com"); - checkFromTextSOA<MissingNameOrigin, isc::Exception>( - "ns root 2010012601 1H 5M 1000H 20M", &origin, true, false); - - // with the '@' notation with a separate origin (lexer version only; - // string version would throw) - const Name full_mname("ns.example.com"); - checkFromTextSOA<MissingNameOrigin, isc::Exception>( - "@ root.example.com. 2010012601 1H 5M 1000H 20M", &full_mname, true, - false); - - // bad MNAME/RNAMEs - checkFromTextSOA<EmptyLabel, EmptyLabel>( - "bad..example. . 2010012601 1H 5M 1000H 20M"); - checkFromTextSOA<EmptyLabel, EmptyLabel>( - ". bad..example. 2010012601 1H 5M 1000H 20M"); - - // Names shouldn't be quoted. - checkFromTextSOA<InvalidRdataText, MasterLexer::LexerError>( - "\".\" . 0 0 0 0 0"); - checkFromTextSOA<InvalidRdataText, MasterLexer::LexerError>( - ". \".\" 0 0 0 0 0"); - - // Missing MAME or RNAME: for the string version, the serial would be - // tried as RNAME and result in "not absolute". For the lexer version, - // it reaches the end-of-line, missing min TTL. - checkFromTextSOA<MissingNameOrigin, MasterLexer::LexerError>( - ". 2010012601 0 0 0 0", &Name::ROOT_NAME()); - - // bad serial. the string version converts lexer error to - // InvalidRdataText. - checkFromTextSOA<InvalidRdataText, MasterLexer::LexerError>( - ". . bad 0 0 0 0"); - - // bad serial; exceeding the uint32_t range (4294967296 = 2^32) - checkFromTextSOA<InvalidRdataText, MasterLexer::LexerError>( - ". . 4294967296 0 0 0 0"); - - // Bad format for other numeric parameters. These will be tried as a TTL, - // and result in an exception there. - checkFromTextSOA<InvalidRRTTL, InvalidRRTTL>( - ". . 2010012601 bad 0 0 0"); - checkFromTextSOA<InvalidRRTTL, InvalidRRTTL>( - ". . 2010012601 4294967296 0 0 0"); - checkFromTextSOA<InvalidRRTTL, InvalidRRTTL>( - ". . 2010012601 0 bad 0 0"); - checkFromTextSOA<InvalidRRTTL, InvalidRRTTL>( - ". . 2010012601 0 4294967296 0 0"); - checkFromTextSOA<InvalidRRTTL, InvalidRRTTL>( - ". . 2010012601 0 0 bad 0"); - checkFromTextSOA<InvalidRRTTL, InvalidRRTTL>( - ". . 2010012601 0 0 4294967296 0"); - checkFromTextSOA<InvalidRRTTL, InvalidRRTTL>( - ". . 2010012601 0 0 0 bad"); - checkFromTextSOA<InvalidRRTTL, InvalidRRTTL>( - ". . 2010012601 0 0 0 4294967296"); - - // No space between RNAME and serial. This case is the same as missing - // M/RNAME. - checkFromTextSOA<MissingNameOrigin, MasterLexer::LexerError>( - ". example.0 0 0 0 0", &Name::ROOT_NAME()); - - // Extra parameter. string version immediately detects the error. - // lexer version defers the check to the upper layer (we pass origin - // to skip the check with the string version). - checkFromTextSOA<InvalidRdataText, isc::Exception>( - "ns.example.com. root.example.com. 2010012601 1H 5M 1000H 20M " - "extra", &origin, true, false); - - // Likewise. Redundant newline is also considered an error. The lexer - // version accepts trailing newline, but not the beginning one (where - // the lexer expects a string excluding newline and EOF). - checkFromTextSOA<InvalidRdataText, isc::Exception>( - "ns.example.com. root.example.com. 2010012601 1H 5M 1000H 20M\n", - NULL, true, false); - checkFromTextSOA<InvalidRdataText, MasterLexer::LexerError>( - "\nns.example.com. root.example.com. 2010012601 1H 5M 1000H 20M", - NULL, true, true); -} - -TEST_F(Rdata_SOA_Test, createFromWire) { - EXPECT_EQ(0, rdata_soa.compare( - *rdataFactoryFromFile(RRType("SOA"), RRClass("IN"), - "rdata_soa_fromWire"))); - // TBD: more tests -} - -TEST_F(Rdata_SOA_Test, createFromLexer) { - EXPECT_EQ(0, rdata_soa.compare( - *test::createRdataUsingLexer(RRType::SOA(), RRClass::IN(), - "ns.example.com. root.example.com. " - "2010012601 3600 300 3600000 1200"))); -} - -TEST_F(Rdata_SOA_Test, toWireRenderer) { - renderer.skip(2); - rdata_soa.toWire(renderer); - - vector<unsigned char> data; - UnitTestUtil::readWireData("rdata_soa_fromWire", data); - matchWireData(&data[2], data.size() - 2, - static_cast<const uint8_t *>(renderer.getData()) + 2, - renderer.getLength() - 2); -} - -TEST_F(Rdata_SOA_Test, toWireBuffer) { - obuffer.skip(2); - rdata_soa.toWire(obuffer); - vector<unsigned char> data; - UnitTestUtil::readWireData("rdata_soa_toWireUncompressed.wire", data); - matchWireData(&data[2], data.size() - 2, - static_cast<const uint8_t *>(obuffer.getData()) + 2, - obuffer.getLength() - 2); -} - -TEST_F(Rdata_SOA_Test, toText) { - EXPECT_EQ("ns.example.com. root.example.com. " - "2010012601 3600 300 3600000 1200", rdata_soa.toText()); -} - -TEST_F(Rdata_SOA_Test, getSerial) { - EXPECT_EQ(2010012601, rdata_soa.getSerial().getValue()); -} - -TEST_F(Rdata_SOA_Test, getMinimum) { - EXPECT_EQ(1200, rdata_soa.getMinimum()); - - // Also check with a very large number (with the MSB being 1). - EXPECT_EQ(2154848336u, generic::SOA(Name("ns.example.com"), - Name("root.example.com"), - 0, 0, 0, 0, 0x80706050).getMinimum()); -} - -void -compareCheck(const generic::SOA& small, const generic::SOA& large) { - EXPECT_GT(0, small.compare(large)); - EXPECT_LT(0, large.compare(small)); -} - -TEST_F(Rdata_SOA_Test, compare) { - // Check simple equivalence - EXPECT_EQ(0, rdata_soa.compare(generic::SOA( - "ns.example.com. root.example.com. " - "2010012601 3600 300 3600000 1200"))); - // Check name comparison is case insensitive - EXPECT_EQ(0, rdata_soa.compare(generic::SOA( - "NS.example.com. root.EXAMPLE.com. " - "2010012601 3600 300 3600000 1200"))); - - // Check names are compared in the RDATA comparison semantics (different - // from DNSSEC ordering for owner names) - compareCheck(generic::SOA("a.example. . 0 0 0 0 0"), - generic::SOA("example. . 0 0 0 0 0")); - compareCheck(generic::SOA(". a.example. 0 0 0 0 0"), - generic::SOA(". example. 0 0 0 0 0")); - - // Compare other numeric fields: 1076895760 = 0x40302010, - // 270544960 = 0x10203040. These are chosen to make sure that machine - // endianness doesn't confuse the comparison results. - compareCheck(generic::SOA(". . 270544960 0 0 0 0"), - generic::SOA(". . 1076895760 0 0 0 0")); - compareCheck(generic::SOA(". . 0 270544960 0 0 0"), - generic::SOA(". . 0 1076895760 0 0 0")); - compareCheck(generic::SOA(". . 0 0 270544960 0 0"), - generic::SOA(". . 0 0 1076895760 0 0")); - compareCheck(generic::SOA(". . 0 0 0 270544960 0"), - generic::SOA(". . 0 0 0 1076895760 0")); - compareCheck(generic::SOA(". . 0 0 0 0 270544960"), - generic::SOA(". . 0 0 0 0 1076895760")); -} - -} diff --git a/src/lib/dns/tests/rdata_srv_unittest.cc b/src/lib/dns/tests/rdata_srv_unittest.cc index a3296f2f8c..8b13789179 100644 --- a/src/lib/dns/tests/rdata_srv_unittest.cc +++ b/src/lib/dns/tests/rdata_srv_unittest.cc @@ -1,205 +1 @@ -// Copyright (C) 2011-2019 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. -#include <config.h> - -#include <util/buffer.h> -#include <dns/exceptions.h> -#include <dns/messagerenderer.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> -#include <dns/rrclass.h> -#include <dns/rrtype.h> - -#include <gtest/gtest.h> - -#include <dns/tests/unittest_util.h> -#include <dns/tests/rdata_unittest.h> -#include <util/unittests/wiredata.h> - -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 { -public: - Rdata_SRV_Test() : - srv_txt("1 5 1500 a.example.com."), - srv_txt2("1 5 1400 example.com."), - too_long_label("012345678901234567890123456789" - "0123456789012345678901234567890123."), - rdata_srv(srv_txt), - rdata_srv2(srv_txt2) - {} - - const string srv_txt; - const string srv_txt2; - const string too_long_label; - const in::SRV rdata_srv; - const in::SRV rdata_srv2; -}; - -// 1 5 1500 a.example.com. -const uint8_t wiredata_srv[] = { - 0x00, 0x01, 0x00, 0x05, 0x05, 0xdc, 0x01, 0x61, 0x07, 0x65, 0x78, - 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x03, 0x63, 0x6f, 0x6d, 0x00}; -// 1 5 1400 example.com. -const uint8_t wiredata_srv2[] = { - 0x00, 0x01, 0x00, 0x05, 0x05, 0x78, 0x07, 0x65, 0x78, 0x61, 0x6d, - 0x70, 0x6c, 0x65, 0x03, 0x63, 0x6f, 0x6d, 0x00}; - -TEST_F(Rdata_SRV_Test, createFromText) { - EXPECT_EQ(1, rdata_srv.getPriority()); - EXPECT_EQ(5, rdata_srv.getWeight()); - EXPECT_EQ(1500, rdata_srv.getPort()); - EXPECT_EQ(Name("a.example.com."), rdata_srv.getTarget()); -} - -TEST_F(Rdata_SRV_Test, badText) { - // priority is too large (2814...6 is 2^48) - EXPECT_THROW(in::SRV("281474976710656 5 1500 a.example.com."), - InvalidRdataText); - // weight is too large - EXPECT_THROW(in::SRV("1 281474976710656 1500 a.example.com."), - InvalidRdataText); - // port is too large - EXPECT_THROW(in::SRV("1 5 281474976710656 a.example.com."), - InvalidRdataText); - // incomplete text - EXPECT_THROW(in::SRV("1 5 a.example.com."), - InvalidRdataText); - EXPECT_THROW(in::SRV("1 5 1500a.example.com."), - InvalidRdataText); - // bad name - EXPECT_THROW(in::SRV("1 5 1500 a.example.com." + too_long_label), - TooLongLabel); - // Extra text at end of line - EXPECT_THROW(in::SRV("1 5 1500 a.example.com. extra."), InvalidRdataText); -} - -TEST_F(Rdata_SRV_Test, assignment) { - in::SRV copy((string(srv_txt2))); - copy = rdata_srv; - EXPECT_EQ(0, copy.compare(rdata_srv)); - - // Check if the copied data is valid even after the original is deleted - in::SRV* copy2 = new in::SRV(rdata_srv); - in::SRV copy3((string(srv_txt2))); - copy3 = *copy2; - delete copy2; - EXPECT_EQ(0, copy3.compare(rdata_srv)); - - // Self assignment - copy = *© - EXPECT_EQ(0, copy.compare(rdata_srv)); -} - -TEST_F(Rdata_SRV_Test, createFromWire) { - EXPECT_EQ(0, rdata_srv.compare( - *rdataFactoryFromFile(RRType("SRV"), RRClass("IN"), - "rdata_srv_fromWire"))); - // RDLENGTH is too short - EXPECT_THROW(rdataFactoryFromFile(RRType("SRV"), RRClass("IN"), - "rdata_srv_fromWire", 23), - InvalidRdataLength); - // RDLENGTH is too long - EXPECT_THROW(rdataFactoryFromFile(RRType("SRV"), RRClass("IN"), - "rdata_srv_fromWire", 46), - InvalidRdataLength); - // incomplete name. the error should be detected in the name constructor - EXPECT_THROW(rdataFactoryFromFile(RRType("SRV"), RRClass("IN"), - "rdata_cname_fromWire", 69), - DNSMessageFORMERR); - // parse compressed target name - EXPECT_EQ(0, rdata_srv.compare( - *rdataFactoryFromFile(RRType("SRV"), RRClass("IN"), - "rdata_srv_fromWire", 89))); -} - -TEST_F(Rdata_SRV_Test, createFromLexer) { - EXPECT_EQ(0, rdata_srv.compare( - *test::createRdataUsingLexer(RRType::SRV(), RRClass::IN(), - "1 5 1500 a.example.com."))); - - // test::createRdataUsingLexer() constructs relative to - // "example.org." origin. - EXPECT_EQ(0, in::SRV("1 5 1500 server16.example.org.").compare( - *test::createRdataUsingLexer(RRType::SRV(), RRClass::IN(), - "1 5 1500 server16"))); - - // Exceptions cause NULL to be returned. - - // Bad priority - EXPECT_FALSE(test::createRdataUsingLexer(RRType::SRV(), RRClass::IN(), - "65536 5 1500 " - "a.example.com.")); - // Bad weight - EXPECT_FALSE(test::createRdataUsingLexer(RRType::SRV(), RRClass::IN(), - "1 65536 1500 " - "a.example.com.")); - // Bad port - EXPECT_FALSE(test::createRdataUsingLexer(RRType::SRV(), RRClass::IN(), - "1 5 281474976710656 " - "a.example.com.")); - // Extra text at end of line - EXPECT_FALSE(test::createRdataUsingLexer(RRType::SRV(), RRClass::IN(), - "1 5 1500 a.example.com. extra.")); -} - -TEST_F(Rdata_SRV_Test, toWireBuffer) { - rdata_srv.toWire(obuffer); - matchWireData(wiredata_srv, sizeof(wiredata_srv), - obuffer.getData(), obuffer.getLength()); - - obuffer.clear(); - rdata_srv2.toWire(obuffer); - matchWireData(wiredata_srv2, sizeof(wiredata_srv2), - obuffer.getData(), obuffer.getLength()); -} - -TEST_F(Rdata_SRV_Test, toWireRenderer) { - rdata_srv.toWire(renderer); - matchWireData(wiredata_srv, sizeof(wiredata_srv), - renderer.getData(), renderer.getLength()); - - renderer.clear(); - rdata_srv2.toWire(renderer); - matchWireData(wiredata_srv2, sizeof(wiredata_srv2), - renderer.getData(), renderer.getLength()); -} - -TEST_F(Rdata_SRV_Test, toText) { - EXPECT_EQ(srv_txt, rdata_srv.toText()); - EXPECT_EQ(srv_txt2, rdata_srv2.toText()); -} - -TEST_F(Rdata_SRV_Test, compare) { - // test RDATAs, sorted in the ascending order. - vector<in::SRV> compare_set; - compare_set.push_back(in::SRV("1 5 1500 a.example.com.")); - compare_set.push_back(in::SRV("2 5 1500 a.example.com.")); - compare_set.push_back(in::SRV("2 6 1500 a.example.com.")); - compare_set.push_back(in::SRV("2 6 1600 a.example.com.")); - compare_set.push_back(in::SRV("2 6 1600 example.com.")); - - EXPECT_EQ(0, compare_set[0].compare( - in::SRV("1 5 1500 a.example.com."))); - - vector<in::SRV>::const_iterator it; - vector<in::SRV>::const_iterator it_end = compare_set.end(); - for (it = compare_set.begin(); it != it_end - 1; ++it) { - EXPECT_GT(0, (*it).compare(*(it + 1))); - EXPECT_LT(0, (*(it + 1)).compare(*it)); - } - - // comparison attempt between incompatible RR types should be rejected - EXPECT_THROW(rdata_srv.compare(*RdataTest::rdata_nomatch), bad_cast); -} -} diff --git a/src/lib/dns/tests/rdata_sshfp_unittest.cc b/src/lib/dns/tests/rdata_sshfp_unittest.cc index 2bf88f38ef..8b13789179 100644 --- a/src/lib/dns/tests/rdata_sshfp_unittest.cc +++ b/src/lib/dns/tests/rdata_sshfp_unittest.cc @@ -1,311 +1 @@ -// Copyright (C) 2012-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. -#include <config.h> - -#include <algorithm> -#include <string> - -#include <util/buffer.h> -#include <dns/messagerenderer.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> -#include <dns/rrclass.h> -#include <dns/rrtype.h> - -#include <gtest/gtest.h> - -#include <dns/tests/unittest_util.h> -#include <dns/tests/rdata_unittest.h> -#include <util/unittests/wiredata.h> - -#include <boost/algorithm/string.hpp> - -using namespace std; -using namespace isc; -using namespace isc::dns; -using namespace isc::util; -using namespace isc::dns::rdata; -using isc::UnitTestUtil; -using isc::util::unittests::matchWireData; - -namespace { -class Rdata_SSHFP_Test : public RdataTest { -protected: - Rdata_SSHFP_Test() : - sshfp_txt("2 1 123456789abcdef67890123456789abcdef67890"), - rdata_sshfp(sshfp_txt) - {} - - void checkFromText_None(const string& rdata_str) { - checkFromText<generic::SSHFP, isc::Exception, isc::Exception>( - rdata_str, rdata_sshfp, false, false); - } - - void checkFromText_InvalidText(const string& rdata_str) { - checkFromText<generic::SSHFP, InvalidRdataText, InvalidRdataText>( - rdata_str, rdata_sshfp, true, true); - } - - void checkFromText_LexerError(const string& rdata_str) { - checkFromText - <generic::SSHFP, InvalidRdataText, MasterLexer::LexerError>( - rdata_str, rdata_sshfp, true, true); - } - - void checkFromText_BadString(const string& rdata_str) { - checkFromText - <generic::SSHFP, InvalidRdataText, isc::Exception>( - rdata_str, rdata_sshfp, true, false); - } - - const string sshfp_txt; - const generic::SSHFP rdata_sshfp; -}; - -const uint8_t rdata_sshfp_wiredata[] = { - // algorithm - 0x02, - // fingerprint type - 0x01, - // fingerprint - 0x12, 0x34, 0x56, 0x78, - 0x9a, 0xbc, 0xde, 0xf6, - 0x78, 0x90, 0x12, 0x34, - 0x56, 0x78, 0x9a, 0xbc, - 0xde, 0xf6, 0x78, 0x90 -}; - -TEST_F(Rdata_SSHFP_Test, createFromText) { - // Basic test - checkFromText_None(sshfp_txt); - - // With different spacing - checkFromText_None("2 1 123456789abcdef67890123456789abcdef67890"); - - // Combination of lowercase and uppercase - checkFromText_None("2 1 123456789ABCDEF67890123456789abcdef67890"); - - // spacing in the fingerprint field - checkFromText_None("2 1 123456789abcdef67890 123456789abcdef67890"); - - // multi-line fingerprint field - checkFromText_None("2 1 ( 123456789abcdef67890\n 123456789abcdef67890 )"); - - // string constructor throws if there's extra text, - // but lexer constructor doesn't - checkFromText_BadString(sshfp_txt + "\n" + sshfp_txt); -} - -TEST_F(Rdata_SSHFP_Test, algorithmTypes) { - // Some of these may not be RFC conformant, but we relax the check - // in our code to work with algorithm and fingerprint types that may - // show up in the future. - EXPECT_NO_THROW(const generic::SSHFP rdata_sshfp("1 1 12ab")); - EXPECT_NO_THROW(const generic::SSHFP rdata_sshfp("2 1 12ab")); - EXPECT_NO_THROW(const generic::SSHFP rdata_sshfp("3 1 12ab")); - EXPECT_NO_THROW(const generic::SSHFP rdata_sshfp("128 1 12ab")); - EXPECT_NO_THROW(const generic::SSHFP rdata_sshfp("255 1 12ab")); - EXPECT_NO_THROW(const generic::SSHFP rdata_sshfp("1 1 12ab")); - EXPECT_NO_THROW(const generic::SSHFP rdata_sshfp("1 2 12ab")); - EXPECT_NO_THROW(const generic::SSHFP rdata_sshfp("1 3 12ab")); - EXPECT_NO_THROW(const generic::SSHFP rdata_sshfp("1 128 12ab")); - EXPECT_NO_THROW(const generic::SSHFP rdata_sshfp("1 255 12ab")); - - // 0 is reserved, but we allow that too - EXPECT_NO_THROW(const generic::SSHFP rdata_sshfp("0 1 12ab")); - EXPECT_NO_THROW(const generic::SSHFP rdata_sshfp("1 0 12ab")); - - // > 255 would be broken - EXPECT_THROW(const generic::SSHFP rdata_sshfp("256 1 12ab"), - InvalidRdataText); - EXPECT_THROW(const generic::SSHFP rdata_sshfp("2 256 12ab"), - InvalidRdataText); -} - -TEST_F(Rdata_SSHFP_Test, badText) { - checkFromText_LexerError("1"); - checkFromText_LexerError("ONE 2 123456789abcdef67890123456789abcdef67890"); - checkFromText_LexerError("1 TWO 123456789abcdef67890123456789abcdef67890"); - checkFromText_InvalidText("1 2 BUCKLEMYSHOE"); - checkFromText_InvalidText(sshfp_txt + " extra text"); - - // yes, these are redundant to the last test cases in algorithmTypes - checkFromText_InvalidText( - "2345 1 123456789abcdef67890123456789abcdef67890"); - checkFromText_InvalidText( - "2 1234 123456789abcdef67890123456789abcdef67890"); - - // negative values are trapped in the lexer rather than the constructor - checkFromText_LexerError("-2 1 123456789abcdef67890123456789abcdef67890"); - checkFromText_LexerError("2 -1 123456789abcdef67890123456789abcdef67890"); -} - -TEST_F(Rdata_SSHFP_Test, copyAndAssign) { - // Copy construct - generic::SSHFP rdata_sshfp2(rdata_sshfp); - EXPECT_EQ(0, rdata_sshfp.compare(rdata_sshfp2)); - - // Assignment, mainly to confirm it doesn't cause disruption. - rdata_sshfp2 = rdata_sshfp; - EXPECT_EQ(0, rdata_sshfp.compare(rdata_sshfp2)); -} - -TEST_F(Rdata_SSHFP_Test, createFromWire) { - // Basic test - EXPECT_EQ(0, rdata_sshfp.compare( - *rdataFactoryFromFile(RRType("SSHFP"), RRClass("IN"), - "rdata_sshfp_fromWire"))); - // Combination of lowercase and uppercase - EXPECT_EQ(0, rdata_sshfp.compare( - *rdataFactoryFromFile(RRType("SSHFP"), RRClass("IN"), - "rdata_sshfp_fromWire2"))); - // algorithm=1, fingerprint=1 - EXPECT_NO_THROW(rdataFactoryFromFile(RRType("SSHFP"), RRClass("IN"), - "rdata_sshfp_fromWire3.wire")); - - // algorithm=255, fingerprint=1 - EXPECT_NO_THROW(rdataFactoryFromFile(RRType("SSHFP"), RRClass("IN"), - "rdata_sshfp_fromWire4.wire")); - - // algorithm=0, fingerprint=1 - EXPECT_NO_THROW(rdataFactoryFromFile(RRType("SSHFP"), RRClass("IN"), - "rdata_sshfp_fromWire5.wire")); - - // algorithm=5, fingerprint=0 - EXPECT_NO_THROW(rdataFactoryFromFile(RRType("SSHFP"), RRClass("IN"), - "rdata_sshfp_fromWire6.wire")); - - // algorithm=255, fingerprint=255 - EXPECT_NO_THROW(rdataFactoryFromFile(RRType("SSHFP"), RRClass("IN"), - "rdata_sshfp_fromWire7.wire")); - - // short fingerprint data - EXPECT_NO_THROW(rdataFactoryFromFile(RRType("SSHFP"), RRClass("IN"), - "rdata_sshfp_fromWire8.wire")); - - // fingerprint is shorter than rdata len - EXPECT_THROW(rdataFactoryFromFile(RRType("SSHFP"), RRClass("IN"), - "rdata_sshfp_fromWire9"), - InvalidBufferPosition); - - // fingerprint is missing - EXPECT_THROW(rdataFactoryFromFile(RRType("SSHFP"), RRClass("IN"), - "rdata_sshfp_fromWire10"), - InvalidBufferPosition); - - // all rdata is missing - EXPECT_THROW(rdataFactoryFromFile(RRType("SSHFP"), RRClass("IN"), - "rdata_sshfp_fromWire11"), - InvalidBufferPosition); -} - -TEST_F(Rdata_SSHFP_Test, createFromParams) { - const generic::SSHFP rdata_sshfp2( - 2, 1, "123456789abcdef67890123456789abcdef67890"); - EXPECT_EQ(0, rdata_sshfp2.compare(rdata_sshfp)); -} - -TEST_F(Rdata_SSHFP_Test, toText) { - EXPECT_TRUE(boost::iequals(sshfp_txt, rdata_sshfp.toText())); - - const string sshfp_txt2("2 1"); - const generic::SSHFP rdata_sshfp2(sshfp_txt2); - EXPECT_TRUE(boost::iequals(sshfp_txt2, rdata_sshfp2.toText())); - - const generic::SSHFP rdata_sshfp3("2 1 "); - EXPECT_TRUE(boost::iequals(sshfp_txt2, rdata_sshfp3.toText())); -} - -TEST_F(Rdata_SSHFP_Test, toWire) { - this->obuffer.clear(); - rdata_sshfp.toWire(this->obuffer); - - EXPECT_EQ(sizeof (rdata_sshfp_wiredata), - this->obuffer.getLength()); - - matchWireData(rdata_sshfp_wiredata, sizeof(rdata_sshfp_wiredata), - obuffer.getData(), obuffer.getLength()); -} - -TEST_F(Rdata_SSHFP_Test, compare) { - const generic::SSHFP rdata_sshfp2("2 1"); - EXPECT_EQ(-1, rdata_sshfp2.compare(rdata_sshfp)); - EXPECT_EQ(1, rdata_sshfp.compare(rdata_sshfp2)); -} - -TEST_F(Rdata_SSHFP_Test, getAlgorithmNumber) { - EXPECT_EQ(2, rdata_sshfp.getAlgorithmNumber()); -} - -TEST_F(Rdata_SSHFP_Test, getFingerprintType) { - EXPECT_EQ(1, rdata_sshfp.getFingerprintType()); -} - -TEST_F(Rdata_SSHFP_Test, getFingerprint) { - const std::vector<uint8_t>& fingerprint = - rdata_sshfp.getFingerprint(); - - EXPECT_EQ(rdata_sshfp.getFingerprintLength(), - fingerprint.size()); - for (size_t i = 0; i < fingerprint.size(); ++i) { - EXPECT_EQ(rdata_sshfp_wiredata[i + 2], - fingerprint.at(i)); - } -} - -TEST_F(Rdata_SSHFP_Test, getFingerprintLength) { - EXPECT_EQ(20, rdata_sshfp.getFingerprintLength()); -} - -TEST_F(Rdata_SSHFP_Test, emptyFingerprintFromWire) { - const uint8_t rdf_wiredata[] = { - // algorithm - 0x04, - // fingerprint type - 0x09 - }; - - const generic::SSHFP rdf = - dynamic_cast<const generic::SSHFP&> - (*rdataFactoryFromFile(RRType("SSHFP"), RRClass("IN"), - "rdata_sshfp_fromWire12")); - - EXPECT_EQ(4, rdf.getAlgorithmNumber()); - EXPECT_EQ(9, rdf.getFingerprintType()); - EXPECT_EQ(0, rdf.getFingerprintLength()); - - this->obuffer.clear(); - rdf.toWire(this->obuffer); - - EXPECT_EQ(2, this->obuffer.getLength()); - - matchWireData(rdf_wiredata, sizeof(rdf_wiredata), - obuffer.getData(), obuffer.getLength()); -} - -TEST_F(Rdata_SSHFP_Test, emptyFingerprintFromString) { - const generic::SSHFP rdata_sshfp2("5 6"); - const uint8_t rdata_sshfp2_wiredata[] = { - // algorithm - 0x05, - // fingerprint type - 0x06 - }; - - EXPECT_EQ(5, rdata_sshfp2.getAlgorithmNumber()); - EXPECT_EQ(6, rdata_sshfp2.getFingerprintType()); - EXPECT_EQ(0, rdata_sshfp2.getFingerprintLength()); - - this->obuffer.clear(); - rdata_sshfp2.toWire(this->obuffer); - - EXPECT_EQ(2, this->obuffer.getLength()); - - matchWireData(rdata_sshfp2_wiredata, sizeof(rdata_sshfp2_wiredata), - obuffer.getData(), obuffer.getLength()); -} -} diff --git a/src/lib/dns/tests/rdata_tkey_unittest.cc b/src/lib/dns/tests/rdata_tkey_unittest.cc index 8592a27a01..8b13789179 100644 --- a/src/lib/dns/tests/rdata_tkey_unittest.cc +++ b/src/lib/dns/tests/rdata_tkey_unittest.cc @@ -1,450 +1 @@ -// Copyright (C) 2021 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. -#include <config.h> - -#include <string> - -#include <exceptions/exceptions.h> - -#include <util/buffer.h> -#include <util/time_utilities.h> -#include <dns/exceptions.h> -#include <dns/messagerenderer.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> -#include <dns/rrclass.h> -#include <dns/rrtype.h> -#include <dns/tsigerror.h> - -#include <gtest/gtest.h> - -#include <dns/tests/unittest_util.h> -#include <dns/tests/rdata_unittest.h> -#include <util/unittests/wiredata.h> - -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_TKEY_Test : public RdataTest { -protected: - Rdata_TKEY_Test() : - // no Key or Other Data - valid_text1("gss-tsig. 20210501120000 20210501130000 GSS-API NOERROR 0 0"), - // Key but no Other Data - valid_text2("GSS-TSIG. 20210501120000 20210501130000 GSS-API BADSIG " - "12 FAKEFAKEFAKEFAKE 0"), - // Key and Other Data - valid_text3("gss.tsig. 20210501120000 20210501130000 GSS-API BADSIG " - "12 FAKEFAKEFAKEFAKE 6 FAKEFAKE"), - // Key and Other Data (with Error that doesn't expect Other Data) - valid_text4("gss.tsig. 20210501120000 20210501130000 3 BADSIG 12 " - "FAKEFAKEFAKEFAKE 6 FAKEFAKE"), - // numeric error code - valid_text5("GSS-TSIG. 20210501120000 20210501130000 GSS-API 2845 12 " - "FAKEFAKEFAKEFAKE 0"), - // GSS-API mode - valid_text6("gss-tsig. 20210501120000 20210501130000 GSS-API 0 12 " - "FAKEFAKEFAKEFAKE 0"), - rdata_tkey(valid_text1) - {} - - void checkFromText_None(const string& rdata_str) { - checkFromText<generic::TKEY, isc::Exception, isc::Exception>( - rdata_str, rdata_tkey, false, false); - } - - void checkFromText_InvalidTime(const string& rdata_str) { - checkFromText<generic::TKEY, InvalidTime, InvalidTime>( - rdata_str, rdata_tkey, true, true); - } - - void checkFromText_InvalidText(const string& rdata_str) { - checkFromText<generic::TKEY, InvalidRdataText, InvalidRdataText>( - rdata_str, rdata_tkey, true, true); - } - - void checkFromText_BadValue(const string& rdata_str) { - checkFromText<generic::TKEY, BadValue, BadValue>( - rdata_str, rdata_tkey, true, true); - } - - void checkFromText_LexerError(const string& rdata_str) { - checkFromText - <generic::TKEY, InvalidRdataText, MasterLexer::LexerError>( - rdata_str, rdata_tkey, true, true); - } - - void checkFromText_TooLongLabel(const string& rdata_str) { - checkFromText<generic::TKEY, TooLongLabel, TooLongLabel>( - rdata_str, rdata_tkey, true, true); - } - - void checkFromText_EmptyLabel(const string& rdata_str) { - checkFromText<generic::TKEY, EmptyLabel, EmptyLabel>( - rdata_str, rdata_tkey, true, true); - } - - void checkFromText_BadString(const string& rdata_str) { - checkFromText - <generic::TKEY, InvalidRdataText, isc::Exception>( - rdata_str, rdata_tkey, true, false); - } - - template <typename Output> - void toWireCommonChecks(Output& output) const; - - const string valid_text1; - const string valid_text2; - const string valid_text3; - const string valid_text4; - const string valid_text5; - const string valid_text6; - vector<uint8_t> expect_data; - const generic::TKEY rdata_tkey; // commonly used test RDATA -}; - -TEST_F(Rdata_TKEY_Test, fromText) { - // normal case. it also tests getter methods. - EXPECT_EQ(Name("gss-tsig"), rdata_tkey.getAlgorithm()); - EXPECT_EQ(1619870400, rdata_tkey.getInception()); - EXPECT_EQ("20210501120000", rdata_tkey.getInceptionDate()); - EXPECT_EQ(1619874000, rdata_tkey.getExpire()); - EXPECT_EQ("20210501130000", rdata_tkey.getExpireDate()); - EXPECT_EQ(3, rdata_tkey.getMode()); - EXPECT_EQ(0, rdata_tkey.getError()); - EXPECT_EQ(0, rdata_tkey.getKeyLen()); - EXPECT_EQ(static_cast<void*>(0), rdata_tkey.getKey()); - EXPECT_EQ(0, rdata_tkey.getOtherLen()); - EXPECT_EQ(static_cast<void*>(0), rdata_tkey.getOtherData()); - - generic::TKEY tkey2(valid_text2); - EXPECT_EQ(12, tkey2.getKeyLen()); - EXPECT_EQ(TSIGError::BAD_SIG_CODE, tkey2.getError()); - - generic::TKEY tkey3(valid_text3); - EXPECT_EQ(6, tkey3.getOtherLen()); - - // The other data is unusual, but we don't reject it. - EXPECT_NO_THROW(generic::TKEY tkey4(valid_text4)); - - // numeric representation of TKEY error - generic::TKEY tkey5(valid_text5); - EXPECT_EQ(2845, tkey5.getError()); - - // symbolic representation of TKEY mode - generic::TKEY tkey6(valid_text6); - EXPECT_EQ(generic::TKEY::GSS_API_MODE, tkey6.getMode()); - - // not fully qualified algorithm name - generic::TKEY tkey1("gss-tsig 20210501120000 20210501130000 3 0 0 0"); - EXPECT_EQ(0, tkey1.compare(rdata_tkey)); - - // multi-line rdata - checkFromText_None("gss-tsig. ( 20210501120000 20210501130000 GSS-API \n" - "NOERROR 0 0 )"); -}; - -TEST_F(Rdata_TKEY_Test, badText) { - // too many fields - checkFromText_BadString(valid_text1 + " 0 0"); - // not enough fields - checkFromText_LexerError("foo 20210501120000 20210501130000 0 BADKEY"); - // bad domain name - checkFromText_TooLongLabel( - "0123456789012345678901234567890123456789012345678901234567890123" - " 20210501120000 20210501130000 0 0 0 0"); - checkFromText_EmptyLabel("foo..bar 20210501120000 20210501130000 0 0 0 0"); - // invalid inception (no digit) - checkFromText_InvalidTime("foo TIME 20210501130000 0 0 0 0"); - // invalid inception (bad format) - checkFromText_InvalidTime("foo 0 20210501130000 0 0 0 0"); - // invalid expire (no digit) - checkFromText_InvalidTime("foo 20210501120000 TIME 0 0 0 0"); - // invalid expire (bad format) - checkFromText_InvalidTime("foo 20210501120000 0 0 0 0 0"); - // Unknown mode - checkFromText_InvalidText("foo 20210501120000 20210501130000 TEST 0 0 0"); - // Numeric mode is is too large - checkFromText_InvalidText("foo 20210501120000 20210501130000 65536 0 0 0"); - // Numeric mode is negative - checkFromText_InvalidText("foo 20210501120000 20210501130000 -1 0 0 0 0"); - // Unknown error code - checkFromText_InvalidText("foo 20210501120000 20210501130000 0 TEST 0 0"); - // Numeric error code is too large - checkFromText_InvalidText("foo 20210501120000 20210501130000 0 65536 0 0"); - // Numeric error code is negative - checkFromText_InvalidText("foo 20210501120000 20210501130000 0 -1 0 0"); - // Key len is too large - checkFromText_InvalidText("foo 20210501120000 20210501130000 0 0 65536 0"); - // invalid Key len (negative) - checkFromText_LexerError("foo 20210501120000 20210501130000 0 0 -1 0"); - // invalid Key len (not a number) - checkFromText_LexerError("foo 20210501120000 20210501130000 0 0 MACSIZE 0"); - // Key len and Key mismatch - checkFromText_InvalidText("foo 20210501120000 20210501130000 0 0 9 FAKE 0"); - // Key is bad base64 - checkFromText_BadValue("foo 20210501120000 20210501130000 0 0 3 FAK= 0"); - // Other len is too large - checkFromText_InvalidText("foo 20210501120000 20210501130000 0 0 0 65536 FAKE"); - // Other len is negative - checkFromText_LexerError("foo 20210501120000 20210501130000 0 0 0 -1 FAKE"); - // invalid Other len - checkFromText_LexerError("foo 20210501120000 20210501130000 0 0 0 LEN FAKE"); - // Other len and data mismatch - checkFromText_InvalidText("foo 20210501120000 20210501130000 0 0 0 9 FAKE"); -} - -void -fromWireCommonChecks(const generic::TKEY& tkey) { - EXPECT_EQ(Name("gss-tsig"), tkey.getAlgorithm()); - EXPECT_EQ(1619870400, tkey.getInception()); - EXPECT_EQ("20210501120000", tkey.getInceptionDate()); - EXPECT_EQ(1619874000, tkey.getExpire()); - EXPECT_EQ("20210501130000", tkey.getExpireDate()); - EXPECT_EQ(3, tkey.getMode()); - EXPECT_EQ(0, tkey.getError()); - - vector<uint8_t> expect_key(32, 'x'); - matchWireData(&expect_key[0], expect_key.size(), - tkey.getKey(), tkey.getKeyLen()); - - EXPECT_EQ(0, tkey.getOtherLen()); - EXPECT_EQ(static_cast<const void*>(0), tkey.getOtherData()); -} - -TEST_F(Rdata_TKEY_Test, createFromWire) { - RdataPtr rdata(rdataFactoryFromFile(RRType::TKEY(), RRClass::ANY(), - "rdata_tkey_fromWire1.wire")); - fromWireCommonChecks(dynamic_cast<generic::TKEY&>(*rdata)); -} - -TEST_F(Rdata_TKEY_Test, createFromWireWithOtherData) { - RdataPtr rdata(rdataFactoryFromFile(RRType::TKEY(), RRClass::ANY(), - "rdata_tkey_fromWire2.wire")); - const generic::TKEY& tkey(dynamic_cast<generic::TKEY&>(*rdata)); - - vector<uint8_t> expect_key(32, 'x'); - matchWireData(&expect_key[0], expect_key.size(), - tkey.getKey(), tkey.getKeyLen()); - - vector<uint8_t> expect_data = { 'a', 'b', 'c', 'd', '0', '1', '2', '3' }; - matchWireData(&expect_data[0], expect_data.size(), - tkey.getOtherData(), tkey.getOtherLen()); -} - -TEST_F(Rdata_TKEY_Test, createFromWireWithoutKey) { - RdataPtr rdata(rdataFactoryFromFile(RRType::TKEY(), RRClass::ANY(), - "rdata_tkey_fromWire3.wire")); - const generic::TKEY& tkey(dynamic_cast<generic::TKEY&>(*rdata)); - EXPECT_EQ(0, tkey.getKeyLen()); - EXPECT_EQ(static_cast<const void*>(0), tkey.getKey()); - - vector<uint8_t> expect_data = { 'a', 'b', 'c', 'd', '0', '1', '2', '3' }; - matchWireData(&expect_data[0], expect_data.size(), - tkey.getOtherData(), tkey.getOtherLen()); -} - -TEST_F(Rdata_TKEY_Test, createFromWireWithCompression) { - RdataPtr rdata(rdataFactoryFromFile(RRType::TKEY(), RRClass::ANY(), - "rdata_tkey_fromWire4.wire", - // we need to skip the dummy name: - Name("gss-tsig").getLength())); - fromWireCommonChecks(dynamic_cast<generic::TKEY&>(*rdata)); -} - -TEST_F(Rdata_TKEY_Test, badFromWire) { - // RDLENGTH is too short: - EXPECT_THROW(rdataFactoryFromFile(RRType::TKEY(), RRClass::ANY(), - "rdata_tkey_fromWire5.wire"), - InvalidRdataLength); - // RDLENGTH is too long: - EXPECT_THROW(rdataFactoryFromFile(RRType::TKEY(), RRClass::ANY(), - "rdata_tkey_fromWire6.wire"), - InvalidRdataLength); - // Algorithm name is broken: - EXPECT_THROW(rdataFactoryFromFile(RRType::TKEY(), RRClass::ANY(), - "rdata_tkey_fromWire7.wire"), - DNSMessageFORMERR); - // Key length is bogus: - EXPECT_THROW(rdataFactoryFromFile(RRType::TKEY(), RRClass::ANY(), - "rdata_tkey_fromWire8.wire"), - InvalidBufferPosition); - // Other-data length is bogus: - EXPECT_THROW(rdataFactoryFromFile(RRType::TKEY(), RRClass::ANY(), - "rdata_tkey_fromWire9.wire"), - InvalidBufferPosition); -} - -TEST_F(Rdata_TKEY_Test, copyConstruct) { - const generic::TKEY copy(rdata_tkey); - EXPECT_EQ(0, copy.compare(rdata_tkey)); - - // Check the copied data is valid even after the original is deleted - generic::TKEY* copy2 = new generic::TKEY(rdata_tkey); - generic::TKEY copy3(*copy2); - delete copy2; - EXPECT_EQ(0, copy3.compare(rdata_tkey)); -} - -TEST_F(Rdata_TKEY_Test, createFromParams) { - EXPECT_EQ(0, rdata_tkey.compare(generic::TKEY(Name("gss-tsig"), - 1619870400, - 1619874000, - 3, 0, 0, 0, 0, 0))); - - const uint8_t fake_data[] = { 0x14, 0x02, 0x84, 0x14, 0x02, 0x84, - 0x14, 0x02, 0x84, 0x14, 0x02, 0x84 }; - EXPECT_EQ(0, generic::TKEY(valid_text2).compare( - generic::TKEY(Name("GSS-TSIG"), 1619870400, 1619874000, - 3, 16, 12, fake_data, 0, 0))); - - const uint8_t fake_data2[] = { 0x14, 0x02, 0x84, 0x14, 0x02, 0x84 }; - EXPECT_EQ(0, generic::TKEY(valid_text3).compare( - generic::TKEY(Name("gss.tsig"), 1619870400, 1619874000, - 3, 16, 12, fake_data, 6, fake_data2))); - - EXPECT_THROW(generic::TKEY(Name("gss-tsig"), 0, 0, 0, 0, 0, fake_data, 0, 0), - isc::InvalidParameter); - EXPECT_THROW(generic::TKEY(Name("gss-tsig"), 0, 0, 0, 0, 12, 0, 0, 0), - isc::InvalidParameter); - EXPECT_THROW(generic::TKEY(Name("gss-tsig"), 0, 0, 0, 0, 0, 0, 0, fake_data), - isc::InvalidParameter); - EXPECT_THROW(generic::TKEY(Name("fake_data"), 0, 0, 0, 0, 0, 0, 6, 0), - isc::InvalidParameter); -} - -TEST_F(Rdata_TKEY_Test, assignment) { - generic::TKEY copy(valid_text2); - copy = rdata_tkey; - EXPECT_EQ(0, copy.compare(rdata_tkey)); - - // Check if the copied data is valid even after the original is deleted - generic::TKEY* copy2 = new generic::TKEY(rdata_tkey); - generic::TKEY copy3(valid_text2); - copy3 = *copy2; - delete copy2; - EXPECT_EQ(0, copy3.compare(rdata_tkey)); - - // Self assignment - copy = *© - EXPECT_EQ(0, copy.compare(rdata_tkey)); -} - -template <typename Output> -void -Rdata_TKEY_Test::toWireCommonChecks(Output& output) const { - vector<uint8_t> expect_data; - - output.clear(); - expect_data.clear(); - rdata_tkey.toWire(output); - // read the expected wire format data and trim the RDLEN part. - UnitTestUtil::readWireData("rdata_tkey_toWire1.wire", expect_data); - expect_data.erase(expect_data.begin(), expect_data.begin() + 2); - matchWireData(&expect_data[0], expect_data.size(), - output.getData(), output.getLength()); - - expect_data.clear(); - output.clear(); - generic::TKEY(valid_text2).toWire(output); - UnitTestUtil::readWireData("rdata_tkey_toWire2.wire", expect_data); - expect_data.erase(expect_data.begin(), expect_data.begin() + 2); - matchWireData(&expect_data[0], expect_data.size(), - output.getData(), output.getLength()); - - expect_data.clear(); - output.clear(); - generic::TKEY(valid_text3).toWire(output); - UnitTestUtil::readWireData("rdata_tkey_toWire3.wire", expect_data); - expect_data.erase(expect_data.begin(), expect_data.begin() + 2); - matchWireData(&expect_data[0], expect_data.size(), - output.getData(), output.getLength()); -} - -TEST_F(Rdata_TKEY_Test, toWireBuffer) { - toWireCommonChecks<OutputBuffer>(obuffer); -} - -TEST_F(Rdata_TKEY_Test, toWireRenderer) { - toWireCommonChecks<MessageRenderer>(renderer); - - // check algorithm name won't compressed when it would otherwise. - expect_data.clear(); - renderer.clear(); - renderer.writeName(Name("gss-tsig")); - renderer.writeUint16(26); // RDLEN - rdata_tkey.toWire(renderer); - UnitTestUtil::readWireData("rdata_tkey_toWire4.wire", expect_data); - matchWireData(&expect_data[0], expect_data.size(), - renderer.getData(), renderer.getLength()); - - // check algorithm can be used as a compression target. - expect_data.clear(); - renderer.clear(); - renderer.writeUint16(26); - rdata_tkey.toWire(renderer); - renderer.writeName(Name("gss-tsig")); - UnitTestUtil::readWireData("rdata_tkey_toWire5.wire", expect_data); - matchWireData(&expect_data[0], expect_data.size(), - renderer.getData(), renderer.getLength()); -} - -TEST_F(Rdata_TKEY_Test, toText) { - EXPECT_EQ(valid_text1, rdata_tkey.toText()); - EXPECT_EQ(valid_text2, generic::TKEY(valid_text2).toText()); - EXPECT_EQ(valid_text3, generic::TKEY(valid_text3).toText()); - EXPECT_EQ(valid_text5, generic::TKEY(valid_text5).toText()); -} - -TEST_F(Rdata_TKEY_Test, compare) { - // test RDATAs, sorted in the ascending order. - // "AAAA" encoded in BASE64 corresponds to 0x000000, so it should be the - // smallest data of the same length. - vector<generic::TKEY> compare_set; - compare_set.push_back(generic::TKEY("a.example 20210501120000 " - "20210501130000 3 0 0 0")); - compare_set.push_back(generic::TKEY("example 20210501120000 " - "20210501130000 3 0 0 0")); - compare_set.push_back(generic::TKEY("example 20210501120001 " - "20210501130000 3 0 0 0")); - compare_set.push_back(generic::TKEY("example 20210501120001 " - "20210501130001 3 0 0 0")); - compare_set.push_back(generic::TKEY("example 20210501120001 " - "20210501130001 4 0 0 0")); - compare_set.push_back(generic::TKEY("example 20210501120001 " - "20210501130001 4 1 0 0")); - compare_set.push_back(generic::TKEY("example 20210501120001 " - "20210501130001 4 1 3 AAAA 0")); - compare_set.push_back(generic::TKEY("example 20210501120001 " - "20210501130001 4 1 3 FAKE 0")); - compare_set.push_back(generic::TKEY("example 20210501120001 " - "20210501130001 4 1 3 FAKE 3 AAAA")); - compare_set.push_back(generic::TKEY("example 20210501120001 " - "20210501130001 4 1 3 FAKE 3 FAKE")); - - EXPECT_EQ(0, - compare_set[0].compare(generic::TKEY("A.EXAMPLE 20210501120000 " - "20210501130000 3 0 0 0"))); - - vector<generic::TKEY>::const_iterator it; - vector<generic::TKEY>::const_iterator it_end = compare_set.end(); - for (it = compare_set.begin(); it != it_end - 1; ++it) { - EXPECT_GT(0, (*it).compare(*(it + 1))); - EXPECT_LT(0, (*(it + 1)).compare(*it)); - } - - // comparison attempt between incompatible RR types should be rejected - EXPECT_THROW(rdata_tkey.compare(*RdataTest::rdata_nomatch), bad_cast); -} -} diff --git a/src/lib/dns/tests/rdata_tlsa_unittest.cc b/src/lib/dns/tests/rdata_tlsa_unittest.cc index 92970cb011..8b13789179 100644 --- a/src/lib/dns/tests/rdata_tlsa_unittest.cc +++ b/src/lib/dns/tests/rdata_tlsa_unittest.cc @@ -1,276 +1 @@ -// Copyright (C) 2014-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. -#include <config.h> - -#include <algorithm> -#include <string> - -#include <util/buffer.h> -#include <dns/messagerenderer.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> -#include <dns/rrclass.h> -#include <dns/rrtype.h> - -#include <gtest/gtest.h> - -#include <dns/tests/unittest_util.h> -#include <dns/tests/rdata_unittest.h> -#include <util/unittests/wiredata.h> - -#include <boost/algorithm/string.hpp> - -using namespace std; -using namespace isc; -using namespace isc::dns; -using namespace isc::util; -using namespace isc::dns::rdata; -using isc::UnitTestUtil; -using isc::util::unittests::matchWireData; - -namespace { -class Rdata_TLSA_Test : public RdataTest { -protected: - Rdata_TLSA_Test() : - tlsa_txt("0 0 1 d2abde240d7cd3ee6b4b28c54df034b9" - "7983a1d16e8a410e4561cb106618e971"), - rdata_tlsa(tlsa_txt) - {} - - void checkFromText_None(const string& rdata_str) { - checkFromText<generic::TLSA, isc::Exception, isc::Exception>( - rdata_str, rdata_tlsa, false, false); - } - - void checkFromText_InvalidText(const string& rdata_str) { - checkFromText<generic::TLSA, InvalidRdataText, InvalidRdataText>( - rdata_str, rdata_tlsa, true, true); - } - - void checkFromText_LexerError(const string& rdata_str) { - checkFromText - <generic::TLSA, InvalidRdataText, MasterLexer::LexerError>( - rdata_str, rdata_tlsa, true, true); - } - - void checkFromText_BadString(const string& rdata_str) { - checkFromText - <generic::TLSA, InvalidRdataText, isc::Exception>( - rdata_str, rdata_tlsa, true, false); - } - - const string tlsa_txt; - const generic::TLSA rdata_tlsa; -}; - -const uint8_t rdata_tlsa_wiredata[] = { - // certificate usage - 0x00, - // selector - 0x00, - // matching type - 0x01, - // certificate association data - 0xd2, 0xab, 0xde, 0x24, 0x0d, 0x7c, 0xd3, 0xee, - 0x6b, 0x4b, 0x28, 0xc5, 0x4d, 0xf0, 0x34, 0xb9, - 0x79, 0x83, 0xa1, 0xd1, 0x6e, 0x8a, 0x41, 0x0e, - 0x45, 0x61, 0xcb, 0x10, 0x66, 0x18, 0xe9, 0x71 -}; - -TEST_F(Rdata_TLSA_Test, createFromText) { - // Basic test - checkFromText_None(tlsa_txt); - - // With different spacing - checkFromText_None("0 0 1 d2abde240d7cd3ee6b4b28c54df034b9" - "7983a1d16e8a410e4561cb106618e971"); - - // Combination of lowercase and uppercase - checkFromText_None("0 0 1 D2ABDE240D7CD3EE6B4B28C54DF034B9" - "7983a1d16e8a410e4561cb106618e971"); - - // spacing in the certificate association data field - checkFromText_None("0 0 1 d2abde240d7cd3ee6b4b28c54df034b9" - " 7983a1d16e8a410e4561cb106618e971"); - - // multi-line certificate association data field - checkFromText_None("0 0 1 ( d2abde240d7cd3ee6b4b28c54df034b9\n" - " 7983a1d16e8a410e4561cb106618e971 )"); - - // string constructor throws if there's extra text, - // but lexer constructor doesn't - checkFromText_BadString(tlsa_txt + "\n" + tlsa_txt); -} - -TEST_F(Rdata_TLSA_Test, fields) { - // Some of these may not be RFC conformant, but we relax the check - // in our code to work with other field values that may show up in - // the future. - EXPECT_NO_THROW(const generic::TLSA rdata_tlsa("1 0 1 12ab")); - EXPECT_NO_THROW(const generic::TLSA rdata_tlsa("2 0 1 12ab")); - EXPECT_NO_THROW(const generic::TLSA rdata_tlsa("3 0 1 12ab")); - EXPECT_NO_THROW(const generic::TLSA rdata_tlsa("128 0 1 12ab")); - EXPECT_NO_THROW(const generic::TLSA rdata_tlsa("255 0 1 12ab")); - - EXPECT_NO_THROW(const generic::TLSA rdata_tlsa("0 1 1 12ab")); - EXPECT_NO_THROW(const generic::TLSA rdata_tlsa("0 2 1 12ab")); - EXPECT_NO_THROW(const generic::TLSA rdata_tlsa("0 3 1 12ab")); - EXPECT_NO_THROW(const generic::TLSA rdata_tlsa("0 128 1 12ab")); - EXPECT_NO_THROW(const generic::TLSA rdata_tlsa("0 255 1 12ab")); - - EXPECT_NO_THROW(const generic::TLSA rdata_tlsa("0 0 1 12ab")); - EXPECT_NO_THROW(const generic::TLSA rdata_tlsa("0 0 2 12ab")); - EXPECT_NO_THROW(const generic::TLSA rdata_tlsa("0 0 3 12ab")); - EXPECT_NO_THROW(const generic::TLSA rdata_tlsa("0 0 128 12ab")); - EXPECT_NO_THROW(const generic::TLSA rdata_tlsa("0 0 255 12ab")); - - // > 255 would be broken - EXPECT_THROW(const generic::TLSA rdata_tlsa("256 0 1 12ab"), - InvalidRdataText); - EXPECT_THROW(const generic::TLSA rdata_tlsa("0 256 1 12ab"), - InvalidRdataText); - EXPECT_THROW(const generic::TLSA rdata_tlsa("0 0 256 12ab"), - InvalidRdataText); -} - -TEST_F(Rdata_TLSA_Test, badText) { - checkFromText_LexerError("1"); - checkFromText_LexerError("ONE 2 3 123456789abcdef67890123456789abcdef67890"); - checkFromText_LexerError("1 TWO 3 123456789abcdef67890123456789abcdef67890"); - checkFromText_LexerError("1 2 THREE 123456789abcdef67890123456789abcdef67890"); - checkFromText_InvalidText("1 2 3 BAABAABLACKSHEEP"); - checkFromText_InvalidText(tlsa_txt + " extra text"); - - // yes, these are redundant to the last test cases in the .fields - // test - checkFromText_InvalidText( - "2345 1 2 123456789abcdef67890123456789abcdef67890"); - checkFromText_InvalidText( - "3 1234 4 123456789abcdef67890123456789abcdef67890"); - checkFromText_InvalidText( - "5 6 1234 123456789abcdef67890123456789abcdef67890"); - - // negative values are trapped in the lexer rather than the - // constructor - checkFromText_LexerError("-2 0 1 123456789abcdef67890123456789abcdef67890"); - checkFromText_LexerError("0 -2 1 123456789abcdef67890123456789abcdef67890"); - checkFromText_LexerError("0 0 -2 123456789abcdef67890123456789abcdef67890"); -} - -TEST_F(Rdata_TLSA_Test, copyAndAssign) { - // Copy construct - generic::TLSA rdata_tlsa2(rdata_tlsa); - EXPECT_EQ(0, rdata_tlsa.compare(rdata_tlsa2)); - - // Assignment, mainly to confirm it doesn't cause disruption. - rdata_tlsa2 = rdata_tlsa; - EXPECT_EQ(0, rdata_tlsa.compare(rdata_tlsa2)); -} - -TEST_F(Rdata_TLSA_Test, createFromWire) { - // Basic test - EXPECT_EQ(0, rdata_tlsa.compare( - *rdataFactoryFromFile(RRType("TLSA"), RRClass("IN"), - "rdata_tlsa_fromWire"))); - // Combination of lowercase and uppercase - EXPECT_EQ(0, rdata_tlsa.compare( - *rdataFactoryFromFile(RRType("TLSA"), RRClass("IN"), - "rdata_tlsa_fromWire2"))); - // certificate_usage=0, selector=0, matching_type=1 - EXPECT_NO_THROW(rdataFactoryFromFile(RRType("TLSA"), RRClass("IN"), - "rdata_tlsa_fromWire3.wire")); - - // certificate_usage=255, selector=0, matching_type=1 - EXPECT_NO_THROW(rdataFactoryFromFile(RRType("TLSA"), RRClass("IN"), - "rdata_tlsa_fromWire4.wire")); - - // certificate_usage=0, selector=255, matching_type=1 - EXPECT_NO_THROW(rdataFactoryFromFile(RRType("TLSA"), RRClass("IN"), - "rdata_tlsa_fromWire5.wire")); - - // certificate_usage=0, selector=0, matching_type=255 - EXPECT_NO_THROW(rdataFactoryFromFile(RRType("TLSA"), RRClass("IN"), - "rdata_tlsa_fromWire6.wire")); - - // certificate_usage=3, selector=1, matching_type=2 - EXPECT_NO_THROW(rdataFactoryFromFile(RRType("TLSA"), RRClass("IN"), - "rdata_tlsa_fromWire7.wire")); - - // short certificate association data - EXPECT_NO_THROW(rdataFactoryFromFile(RRType("TLSA"), RRClass("IN"), - "rdata_tlsa_fromWire8.wire")); - - // certificate association data is shorter than rdata len - EXPECT_THROW(rdataFactoryFromFile(RRType("TLSA"), RRClass("IN"), - "rdata_tlsa_fromWire9"), - InvalidBufferPosition); - - // certificate association data is missing - EXPECT_THROW(rdataFactoryFromFile(RRType("TLSA"), RRClass("IN"), - "rdata_tlsa_fromWire10"), - InvalidBufferPosition); - - // certificate association data is empty - EXPECT_THROW(rdataFactoryFromFile(RRType("TLSA"), RRClass("IN"), - "rdata_tlsa_fromWire12"), - InvalidRdataLength); - - // all RDATA is missing - EXPECT_THROW(rdataFactoryFromFile(RRType("TLSA"), RRClass("IN"), - "rdata_tlsa_fromWire11"), - InvalidBufferPosition); -} - -TEST_F(Rdata_TLSA_Test, createFromParams) { - const generic::TLSA rdata_tlsa2( - 0, 0, 1, "d2abde240d7cd3ee6b4b28c54df034b9" - "7983a1d16e8a410e4561cb106618e971"); - EXPECT_EQ(0, rdata_tlsa2.compare(rdata_tlsa)); - - // empty certificate association data should throw - EXPECT_THROW(const generic::TLSA rdata_tlsa2(0, 0, 1, ""), - InvalidRdataText); -} - -TEST_F(Rdata_TLSA_Test, toText) { - EXPECT_TRUE(boost::iequals(tlsa_txt, rdata_tlsa.toText())); -} - -TEST_F(Rdata_TLSA_Test, toWire) { - this->obuffer.clear(); - rdata_tlsa.toWire(this->obuffer); - - EXPECT_EQ(sizeof (rdata_tlsa_wiredata), - this->obuffer.getLength()); - - matchWireData(rdata_tlsa_wiredata, sizeof(rdata_tlsa_wiredata), - obuffer.getData(), obuffer.getLength()); -} - -TEST_F(Rdata_TLSA_Test, compare) { - const generic::TLSA rdata_tlsa2("0 0 0 d2abde240d7cd3ee6b4b28c54df034b9" - "7983a1d16e8a410e4561cb106618e971"); - EXPECT_EQ(-1, rdata_tlsa2.compare(rdata_tlsa)); - EXPECT_EQ(1, rdata_tlsa.compare(rdata_tlsa2)); -} - -TEST_F(Rdata_TLSA_Test, getCertificateUsage) { - EXPECT_EQ(0, rdata_tlsa.getCertificateUsage()); -} - -TEST_F(Rdata_TLSA_Test, getSelector) { - EXPECT_EQ(0, rdata_tlsa.getSelector()); -} - -TEST_F(Rdata_TLSA_Test, getMatchingType) { - EXPECT_EQ(1, rdata_tlsa.getMatchingType()); -} - -TEST_F(Rdata_TLSA_Test, getDataLength) { - EXPECT_EQ(32, rdata_tlsa.getDataLength()); -} -} diff --git a/src/lib/dns/tests/rdata_tsig_unittest.cc b/src/lib/dns/tests/rdata_tsig_unittest.cc index 9d3bd89662..8b13789179 100644 --- a/src/lib/dns/tests/rdata_tsig_unittest.cc +++ b/src/lib/dns/tests/rdata_tsig_unittest.cc @@ -1,423 +1 @@ -// Copyright (C) 2010-2023 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. -#include <config.h> - -#include <string> - -#include <exceptions/exceptions.h> - -#include <util/buffer.h> -#include <dns/exceptions.h> -#include <dns/messagerenderer.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> -#include <dns/rrclass.h> -#include <dns/rrtype.h> -#include <dns/tsigerror.h> - -#include <gtest/gtest.h> - -#include <dns/tests/unittest_util.h> -#include <dns/tests/rdata_unittest.h> -#include <util/unittests/wiredata.h> - -using namespace std; -using namespace isc; -using namespace isc::dns; -using namespace isc::util; -using namespace isc::dns::rdata; -using namespace isc::dns::rdata::any; -using isc::UnitTestUtil; -using isc::util::unittests::matchWireData; - -namespace { - -class Rdata_TSIG_Test : public RdataTest { -protected: - Rdata_TSIG_Test() : - // no MAC or Other Data - valid_text1("hmac-md5.sig-alg.reg.int. 1286779327 300 " - "0 16020 BADKEY 0"), - // MAC but no Other Data - valid_text2("hmac-sha256. 1286779327 300 12 " - "FAKEFAKEFAKEFAKE 16020 BADSIG 0"), - // 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) - valid_text4("hmac-sha1. 1286779327 300 12 " - "FAKEFAKEFAKEFAKE 16020 BADSIG 6 FAKEFAKE"), - // numeric error code - valid_text5("hmac-sha256. 1286779327 300 12 " - "FAKEFAKEFAKEFAKE 16020 2845 0"), - rdata_tsig(valid_text1) - {} - - void checkFromText_None(const string& rdata_str) { - checkFromText<TSIG, isc::Exception, isc::Exception>( - rdata_str, rdata_tsig, false, false); - } - - void checkFromText_InvalidText(const string& rdata_str) { - checkFromText<TSIG, InvalidRdataText, InvalidRdataText>( - rdata_str, rdata_tsig, true, true); - } - - void checkFromText_BadValue(const string& rdata_str) { - checkFromText<TSIG, BadValue, BadValue>( - rdata_str, rdata_tsig, true, true); - } - - void checkFromText_LexerError(const string& rdata_str) { - checkFromText - <TSIG, InvalidRdataText, MasterLexer::LexerError>( - rdata_str, rdata_tsig, true, true); - } - - void checkFromText_TooLongLabel(const string& rdata_str) { - checkFromText<TSIG, TooLongLabel, TooLongLabel>( - rdata_str, rdata_tsig, true, true); - } - - void checkFromText_EmptyLabel(const string& rdata_str) { - checkFromText<TSIG, EmptyLabel, EmptyLabel>( - rdata_str, rdata_tsig, true, true); - } - - void checkFromText_BadString(const string& rdata_str) { - checkFromText - <TSIG, InvalidRdataText, isc::Exception>( - rdata_str, rdata_tsig, true, false); - } - - template <typename Output> - void toWireCommonChecks(Output& output) const; - - const string valid_text1; - const string valid_text2; - const string valid_text3; - const string valid_text4; - const string valid_text5; - vector<uint8_t> expect_data; - const TSIG rdata_tsig; // commonly used test RDATA -}; - -TEST_F(Rdata_TSIG_Test, fromText) { - // normal case. it also tests getter methods. - EXPECT_EQ(Name("hmac-md5.sig-alg.reg.int"), rdata_tsig.getAlgorithm()); - EXPECT_EQ(1286779327, rdata_tsig.getTimeSigned()); - EXPECT_EQ(300, rdata_tsig.getFudge()); - EXPECT_EQ(0, rdata_tsig.getMACSize()); - EXPECT_EQ(static_cast<void*>(NULL), rdata_tsig.getMAC()); - EXPECT_EQ(16020, rdata_tsig.getOriginalID()); - EXPECT_EQ(TSIGError::BAD_KEY_CODE, rdata_tsig.getError()); - EXPECT_EQ(0, rdata_tsig.getOtherLen()); - EXPECT_EQ(static_cast<void*>(NULL), rdata_tsig.getOtherData()); - - TSIG tsig2(valid_text2); - EXPECT_EQ(12, tsig2.getMACSize()); - EXPECT_EQ(TSIGError::BAD_SIG_CODE, tsig2.getError()); - - TSIG tsig3(valid_text3); - EXPECT_EQ(6, tsig3.getOtherLen()); - - // The other data is unusual, but we don't reject it. - EXPECT_NO_THROW(TSIG tsig4(valid_text4)); - - // numeric representation of TSIG error - TSIG tsig5(valid_text5); - EXPECT_EQ(2845, tsig5.getError()); - - // not fully qualified algorithm name - TSIG tsig1("hmac-md5.sig-alg.reg.int 1286779327 300 0 16020 BADKEY 0"); - EXPECT_EQ(0, tsig1.compare(rdata_tsig)); - - // multi-line rdata - checkFromText_None("hmac-md5.sig-alg.reg.int. ( 1286779327 300 \n" - "0 16020 BADKEY 0 )"); - - // short-form HMAC-MD5 name - const TSIG tsig6("hmac-md5. 1286779327 300 0 16020 BADKEY 0"); - EXPECT_EQ(0, tsig6.compare(rdata_tsig)); -}; - -TEST_F(Rdata_TSIG_Test, badText) { - // too many fields - checkFromText_BadString(valid_text1 + " 0 0"); - // not enough fields - checkFromText_LexerError("foo 0 0 0 0 BADKEY"); - // bad domain name - checkFromText_TooLongLabel( - "0123456789012345678901234567890123456789012345678901234567890123" - " 0 0 0 0 BADKEY 0"); - checkFromText_EmptyLabel("foo..bar 0 0 0 0 BADKEY"); - // time is too large (2814...6 is 2^48) - checkFromText_InvalidText("foo 281474976710656 0 0 0 BADKEY 0"); - // invalid time (negative) - checkFromText_InvalidText("foo -1 0 0 0 BADKEY 0"); - // invalid time (not a number) - checkFromText_InvalidText("foo TIME 0 0 0 BADKEY 0"); - // fudge is too large - checkFromText_InvalidText("foo 0 65536 0 0 BADKEY 0"); - // invalid fudge (negative) - checkFromText_LexerError("foo 0 -1 0 0 BADKEY 0"); - // invalid fudge (not a number) - checkFromText_LexerError("foo 0 FUDGE 0 0 BADKEY 0"); - // MAC size is too large - checkFromText_InvalidText("foo 0 0 65536 0 BADKEY 0"); - // invalid MAC size (negative) - checkFromText_LexerError("foo 0 0 -1 0 BADKEY 0"); - // invalid MAC size (not a number) - checkFromText_LexerError("foo 0 0 MACSIZE 0 BADKEY 0"); - // MAC size and MAC mismatch - checkFromText_InvalidText("foo 0 0 9 FAKE 0 BADKEY 0"); - // MAC is bad base64 - checkFromText_BadValue("foo 0 0 3 FAK= 0 BADKEY 0"); - // Unknown error code - checkFromText_InvalidText("foo 0 0 0 0 TEST 0"); - // Numeric error code is too large - checkFromText_InvalidText("foo 0 0 0 0 65536 0"); - // Numeric error code is negative - checkFromText_InvalidText("foo 0 0 0 0 -1 0"); - // Other len is too large - checkFromText_InvalidText("foo 0 0 0 0 NOERROR 65536 FAKE"); - // Other len is negative - checkFromText_LexerError("foo 0 0 0 0 NOERROR -1 FAKE"); - // invalid Other len - checkFromText_LexerError("foo 0 0 0 0 NOERROR LEN FAKE"); - // Other len and data mismatch - checkFromText_InvalidText("foo 0 0 0 0 NOERROR 9 FAKE"); -} - -void -fromWireCommonChecks(const TSIG& tsig) { - EXPECT_EQ(Name("hmac-sha256"), tsig.getAlgorithm()); - EXPECT_EQ(1286978795, tsig.getTimeSigned()); - EXPECT_EQ(300, tsig.getFudge()); - - vector<uint8_t> expect_mac(32, 'x'); - matchWireData(&expect_mac[0], expect_mac.size(), - tsig.getMAC(), tsig.getMACSize()); - - EXPECT_EQ(2845, tsig.getOriginalID()); - - EXPECT_EQ(0, tsig.getOtherLen()); - EXPECT_EQ(static_cast<const void*>(NULL), tsig.getOtherData()); -} - -TEST_F(Rdata_TSIG_Test, createFromWire) { - RdataPtr rdata(rdataFactoryFromFile(RRType::TSIG(), RRClass::ANY(), - "rdata_tsig_fromWire1.wire")); - fromWireCommonChecks(dynamic_cast<TSIG&>(*rdata)); -} - -TEST_F(Rdata_TSIG_Test, createFromWireWithOtherData) { - RdataPtr rdata(rdataFactoryFromFile(RRType::TSIG(), RRClass::ANY(), - "rdata_tsig_fromWire2.wire")); - const TSIG& tsig(dynamic_cast<TSIG&>(*rdata)); - - EXPECT_EQ(18, tsig.getError()); - const uint64_t otherdata = 1286978795 + 300 + 1; // time-signed + fudge + 1 - expect_data.resize(6); - expect_data[0] = (otherdata >> 40); - expect_data[1] = ((otherdata >> 32) & 0xff); - expect_data[2] = ((otherdata >> 24) & 0xff); - expect_data[3] = ((otherdata >> 16) & 0xff); - expect_data[4] = ((otherdata >> 8) & 0xff); - expect_data[5] = (otherdata & 0xff); - matchWireData(&expect_data[0], expect_data.size(), - tsig.getOtherData(), tsig.getOtherLen()); -} - -TEST_F(Rdata_TSIG_Test, createFromWireWithoutMAC) { - RdataPtr rdata(rdataFactoryFromFile(RRType::TSIG(), RRClass::ANY(), - "rdata_tsig_fromWire3.wire")); - const TSIG& tsig(dynamic_cast<TSIG&>(*rdata)); - EXPECT_EQ(16, tsig.getError()); - EXPECT_EQ(0, tsig.getMACSize()); - EXPECT_EQ(static_cast<const void*>(NULL), tsig.getMAC()); -} - -TEST_F(Rdata_TSIG_Test, createFromWireWithCompression) { - RdataPtr rdata(rdataFactoryFromFile(RRType::TSIG(), RRClass::ANY(), - "rdata_tsig_fromWire4.wire", - // we need to skip the dummy name: - Name("hmac-sha256").getLength())); - fromWireCommonChecks(dynamic_cast<TSIG&>(*rdata)); -} - -TEST_F(Rdata_TSIG_Test, badFromWire) { - // RDLENGTH is too short: - EXPECT_THROW(rdataFactoryFromFile(RRType::TSIG(), RRClass::ANY(), - "rdata_tsig_fromWire5.wire"), - InvalidRdataLength); - // RDLENGTH is too long: - EXPECT_THROW(rdataFactoryFromFile(RRType::TSIG(), RRClass::ANY(), - "rdata_tsig_fromWire6.wire"), - InvalidRdataLength); - // Algorithm name is broken: - EXPECT_THROW(rdataFactoryFromFile(RRType::TSIG(), RRClass::ANY(), - "rdata_tsig_fromWire7.wire"), - DNSMessageFORMERR); - // MAC size is bogus: - EXPECT_THROW(rdataFactoryFromFile(RRType::TSIG(), RRClass::ANY(), - "rdata_tsig_fromWire8.wire"), - InvalidBufferPosition); - // Other-data length is bogus: - EXPECT_THROW(rdataFactoryFromFile(RRType::TSIG(), RRClass::ANY(), - "rdata_tsig_fromWire9.wire"), - InvalidBufferPosition); -} - -TEST_F(Rdata_TSIG_Test, copyConstruct) { - const TSIG copy(rdata_tsig); - EXPECT_EQ(0, copy.compare(rdata_tsig)); - - // Check the copied data is valid even after the original is deleted - TSIG* copy2 = new TSIG(rdata_tsig); - TSIG copy3(*copy2); - delete copy2; - EXPECT_EQ(0, copy3.compare(rdata_tsig)); -} - -TEST_F(Rdata_TSIG_Test, createFromParams) { - EXPECT_EQ(0, rdata_tsig.compare(TSIG(Name("hmac-md5.sig-alg.reg.int"), - 1286779327, 300, 0, NULL, 16020, 17, 0, NULL))); - - const uint8_t fake_data[] = { 0x14, 0x02, 0x84, 0x14, 0x02, 0x84, - 0x14, 0x02, 0x84, 0x14, 0x02, 0x84 }; - EXPECT_EQ(0, TSIG(valid_text2).compare(TSIG(Name("hmac-sha256"), 1286779327, 300, 12, - fake_data, 16020, 16, 0, NULL))); - - const uint8_t fake_data2[] = { 0x14, 0x02, 0x84, 0x14, 0x02, 0x84 }; - EXPECT_EQ(0, TSIG(valid_text3).compare(TSIG(Name("hmac-sha1"), 1286779327, 300, 12, - fake_data, 16020, 18, 6, fake_data2))); - - EXPECT_THROW(TSIG(Name("hmac-sha256"), 1ULL << 48, 300, 12, fake_data, 16020, 18, 6, fake_data2), - isc::OutOfRange); - EXPECT_THROW(TSIG(Name("hmac-sha256"), 0, 300, 0, fake_data, 16020, 18, 0, NULL), - isc::InvalidParameter); - EXPECT_THROW(TSIG(Name("hmac-sha256"), 0, 300, 12, NULL, 16020, 18, 0, NULL), - isc::InvalidParameter); - EXPECT_THROW(TSIG(Name("hmac-sha256"), 0, 300, 0, NULL, 16020, 18, 0, fake_data), - isc::InvalidParameter); - EXPECT_THROW(TSIG(Name("hmac-sha256"), 0, 300, 0, NULL, 16020, 18, 6, NULL), - isc::InvalidParameter); -} - -TEST_F(Rdata_TSIG_Test, assignment) { - TSIG copy(valid_text2); - copy = rdata_tsig; - EXPECT_EQ(0, copy.compare(rdata_tsig)); - - // Check if the copied data is valid even after the original is deleted - TSIG* copy2 = new TSIG(rdata_tsig); - TSIG copy3(valid_text2); - copy3 = *copy2; - delete copy2; - EXPECT_EQ(0, copy3.compare(rdata_tsig)); - - // Self assignment - copy = *© - EXPECT_EQ(0, copy.compare(rdata_tsig)); -} - -template <typename Output> -void -Rdata_TSIG_Test::toWireCommonChecks(Output& output) const { - vector<uint8_t> expect_data; - - output.clear(); - expect_data.clear(); - rdata_tsig.toWire(output); - // 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); - matchWireData(&expect_data[0], expect_data.size(), - output.getData(), output.getLength()); - - expect_data.clear(); - output.clear(); - TSIG(valid_text2).toWire(output); - UnitTestUtil::readWireData("rdata_tsig_toWire2.wire", expect_data); - expect_data.erase(expect_data.begin(), expect_data.begin() + 2); - matchWireData(&expect_data[0], expect_data.size(), - output.getData(), output.getLength()); - - expect_data.clear(); - output.clear(); - TSIG(valid_text3).toWire(output); - UnitTestUtil::readWireData("rdata_tsig_toWire3.wire", expect_data); - expect_data.erase(expect_data.begin(), expect_data.begin() + 2); - matchWireData(&expect_data[0], expect_data.size(), - output.getData(), output.getLength()); -} - -TEST_F(Rdata_TSIG_Test, toWireBuffer) { - toWireCommonChecks<OutputBuffer>(obuffer); -} - -TEST_F(Rdata_TSIG_Test, toWireRenderer) { - toWireCommonChecks<MessageRenderer>(renderer); - - // check algorithm name won't compressed when it would otherwise. - expect_data.clear(); - renderer.clear(); - renderer.writeName(Name("hmac-md5.sig-alg.reg.int")); - renderer.writeUint16(42); // RDLEN - rdata_tsig.toWire(renderer); - UnitTestUtil::readWireData("rdata_tsig_toWire4.wire", expect_data); - matchWireData(&expect_data[0], expect_data.size(), - renderer.getData(), renderer.getLength()); - - // check algorithm can be used as a compression target. - expect_data.clear(); - renderer.clear(); - renderer.writeUint16(42); - rdata_tsig.toWire(renderer); - renderer.writeName(Name("hmac-md5.sig-alg.reg.int")); - UnitTestUtil::readWireData("rdata_tsig_toWire5.wire", expect_data); - matchWireData(&expect_data[0], expect_data.size(), - renderer.getData(), renderer.getLength()); -} - -TEST_F(Rdata_TSIG_Test, toText) { - EXPECT_EQ(valid_text1, rdata_tsig.toText()); - EXPECT_EQ(valid_text2, TSIG(valid_text2).toText()); - EXPECT_EQ(valid_text3, TSIG(valid_text3).toText()); - EXPECT_EQ(valid_text5, TSIG(valid_text5).toText()); -} - -TEST_F(Rdata_TSIG_Test, compare) { - // test RDATAs, sorted in the ascending order. - // "AAAA" encoded in BASE64 corresponds to 0x000000, so it should be the - // smallest data of the same length. - vector<TSIG> compare_set; - compare_set.push_back(TSIG("a.example 0 300 0 16020 0 0")); - compare_set.push_back(TSIG("example 0 300 0 16020 0 0")); - compare_set.push_back(TSIG("example 1 300 0 16020 0 0")); - compare_set.push_back(TSIG("example 1 600 0 16020 0 0")); - compare_set.push_back(TSIG("example 1 600 3 AAAA 16020 0 0")); - compare_set.push_back(TSIG("example 1 600 3 FAKE 16020 0 0")); - compare_set.push_back(TSIG("example 1 600 3 FAKE 16021 0 0")); - compare_set.push_back(TSIG("example 1 600 3 FAKE 16021 1 0")); - compare_set.push_back(TSIG("example 1 600 3 FAKE 16021 1 3 AAAA")); - compare_set.push_back(TSIG("example 1 600 3 FAKE 16021 1 3 FAKE")); - - EXPECT_EQ(0, compare_set[0].compare(TSIG("A.EXAMPLE 0 300 0 16020 0 0"))); - - vector<TSIG>::const_iterator it; - vector<TSIG>::const_iterator it_end = compare_set.end(); - for (it = compare_set.begin(); it != it_end - 1; ++it) { - EXPECT_GT(0, (*it).compare(*(it + 1))); - EXPECT_LT(0, (*(it + 1)).compare(*it)); - } - - // comparison attempt between incompatible RR types should be rejected - EXPECT_THROW(rdata_tsig.compare(*RdataTest::rdata_nomatch), bad_cast); -} -} diff --git a/src/lib/dns/tests/rdata_txt_like_unittest.cc b/src/lib/dns/tests/rdata_txt_like_unittest.cc index 52097dc60e..8b13789179 100644 --- a/src/lib/dns/tests/rdata_txt_like_unittest.cc +++ b/src/lib/dns/tests/rdata_txt_like_unittest.cc @@ -1,395 +1 @@ -// Copyright (C) 2011-2024 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. -// This is the common code for TXT and SPF tests. - -#include <config.h> - -#include <util/buffer.h> -#include <dns/exceptions.h> -#include <dns/rdataclass.h> - -#include <dns/tests/unittest_util.h> -#include <dns/tests/rdata_unittest.h> - -#include <util/unittests/wiredata.h> - -#include <gtest/gtest.h> - -#include <string> -#include <sstream> -#include <vector> - -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 { - -template<class T> -class RRTYPE : public RRType { -public: - RRTYPE(); -}; - -template<> RRTYPE<generic::TXT>::RRTYPE() : RRType(RRType::TXT()) {} -template<> RRTYPE<generic::SPF>::RRTYPE() : RRType(RRType::SPF()) {} - -const uint8_t wiredata_txt_like[] = { - sizeof("Test-String") - 1, - 'T', 'e', 's', 't', '-', 'S', 't', 'r', 'i', 'n', 'g' -}; - -const uint8_t wiredata_nulltxt[] = { 0 }; - -template<class TXT_LIKE> -class Rdata_TXT_LIKE_Test : public RdataTest { -protected: - Rdata_TXT_LIKE_Test() : - wiredata_longesttxt(256, 'a'), - rdata_txt_like("Test-String"), - rdata_txt_like_empty("\"\""), - rdata_txt_like_quoted("\"Test-String\"") - { - wiredata_longesttxt[0] = 255; // adjust length - } - -protected: - vector<uint8_t> wiredata_longesttxt; - const TXT_LIKE rdata_txt_like; - const TXT_LIKE rdata_txt_like_empty; - const TXT_LIKE rdata_txt_like_quoted; -}; - -// The list of types we want to test. -typedef testing::Types<generic::TXT, generic::SPF> Implementations; - -#ifdef TYPED_TEST_SUITE -TYPED_TEST_SUITE(Rdata_TXT_LIKE_Test, Implementations); -#else -TYPED_TEST_CASE(Rdata_TXT_LIKE_Test, Implementations); -#endif - -TYPED_TEST(Rdata_TXT_LIKE_Test, createFromText) { - // Below we check the behavior for the "from text" constructors, both - // from std::string and with MasterLexer. The underlying implementation - // is the same, so both should work exactly same, but we confirm both - // cases. - - const std::string multi_line = "(\n \"Test-String\" )"; - const std::string escaped_txt = "Test\\045Strin\\g"; - - // test input for the lexer version - std::stringstream ss; - ss << "Test-String\n"; - ss << "\"Test-String\"\n"; // explicitly surrounded by '"'s - ss << multi_line << "\n"; // multi-line text with () - ss << escaped_txt << "\n"; // using the two types of escape with '\' - ss << "\"\"\n"; // empty string (note: still valid char-str) - ss << string(255, 'a') << "\n"; // Longest possible character-string. - ss << string(256, 'a') << "\n"; // char-string too long - ss << "\"Test-String\\\"\n"; // unbalanced quote - ss << "\"Test-String\\\"\"\n"; - this->lexer.pushSource(ss); - - // commonly used Rdata to compare below, created from wire - ConstRdataPtr const rdata = - this->rdataFactoryFromFile(RRTYPE<TypeParam>(), - RRClass("IN"), "rdata_txt_fromWire1"); - - // normal case is covered in toWireBuffer. First check the std::string - // case, then with MasterLexer. For the latter, we need to read and skip - // '\n'. These apply to most of the other cases below. - EXPECT_EQ(0, this->rdata_txt_like.compare(*rdata)); - EXPECT_EQ(0, TypeParam(this->lexer, NULL, MasterLoader::MANY_ERRORS, - this->loader_cb).compare(*rdata)); - EXPECT_EQ(MasterToken::END_OF_LINE, this->lexer.getNextToken().getType()); - - // surrounding double-quotes shouldn't change the result. - EXPECT_EQ(0, this->rdata_txt_like_quoted.compare(*rdata)); - EXPECT_EQ(0, TypeParam(this->lexer, NULL, MasterLoader::MANY_ERRORS, - this->loader_cb).compare(*rdata)); - EXPECT_EQ(MasterToken::END_OF_LINE, this->lexer.getNextToken().getType()); - - // multi-line input with () - EXPECT_EQ(0, TypeParam(multi_line).compare(*rdata)); - EXPECT_EQ(0, TypeParam(this->lexer, NULL, MasterLoader::MANY_ERRORS, - this->loader_cb).compare(*rdata)); - EXPECT_EQ(MasterToken::END_OF_LINE, this->lexer.getNextToken().getType()); - - // for the same data using escape - EXPECT_EQ(0, TypeParam(escaped_txt).compare(*rdata)); - EXPECT_EQ(0, TypeParam(this->lexer, NULL, MasterLoader::MANY_ERRORS, - this->loader_cb).compare(*rdata)); - EXPECT_EQ(MasterToken::END_OF_LINE, this->lexer.getNextToken().getType()); - - // Null character-string. - this->obuffer.clear(); - TypeParam(string("\"\"")).toWire(this->obuffer); - 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); - 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); - 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); - 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. - EXPECT_THROW(TypeParam(string(256, 'a')), CharStringTooLong); - EXPECT_THROW(TypeParam(this->lexer, NULL, MasterLoader::MANY_ERRORS, - this->loader_cb), CharStringTooLong); - EXPECT_EQ(MasterToken::END_OF_LINE, this->lexer.getNextToken().getType()); - - // The escape character makes the double quote a part of character-string, - // so this is invalid input and should be rejected. - EXPECT_THROW(TypeParam("\"Test-String\\\""), InvalidRdataText); - EXPECT_THROW(TypeParam(this->lexer, NULL, MasterLoader::MANY_ERRORS, - this->loader_cb), MasterLexer::LexerError); - EXPECT_EQ(MasterToken::END_OF_LINE, this->lexer.getNextToken().getType()); -} - -TYPED_TEST(Rdata_TXT_LIKE_Test, createMultiStringsFromText) { - // Tests for "from text" variants construction with various forms of - // multi character-strings. - - std::vector<std::string > texts; - texts.push_back("\"Test-String\" \"Test-String\""); // most common form - texts.push_back("\"Test-String\"\"Test-String\""); // no space between'em - texts.push_back("\"Test-String\" Test-String"); // no '"' for one - texts.push_back("\"Test-String\"Test-String"); // and no space either - texts.push_back("Test-String \"Test-String\""); // no '"' for the other - texts.push_back("Test-String\"Test-String\""); // and no space either - - std::stringstream ss; - for (auto const& it : texts) { - ss << it << "\n"; - } - this->lexer.pushSource(ss); - - // The corresponding Rdata built from wire to compare in the checks below. - ConstRdataPtr const rdata = - this->rdataFactoryFromFile(RRTYPE<TypeParam>(), - RRClass("IN"), "rdata_txt_fromWire3.wire"); - - // Confirm we can construct the Rdata from the test text, both from - // std::string and with lexer, and that matches the from-wire data. - for (auto const& it : texts) { - SCOPED_TRACE(it); - EXPECT_EQ(0, TypeParam(it).compare(*rdata)); - - EXPECT_EQ(0, TypeParam(this->lexer, NULL, MasterLoader::MANY_ERRORS, - this->loader_cb).compare(*rdata)); - EXPECT_EQ(MasterToken::END_OF_LINE, - this->lexer.getNextToken().getType()); - } -} - -TYPED_TEST(Rdata_TXT_LIKE_Test, createFromTextExtra) { - // This is for the std::string version only: the input must end with EOF; - // an extra new-line will result in an exception. - EXPECT_THROW(TypeParam("\"Test-String\"\n"), InvalidRdataText); - // Same if there's a space before '\n' - EXPECT_THROW(TypeParam("\"Test-String\" \n"), InvalidRdataText); -} - -TYPED_TEST(Rdata_TXT_LIKE_Test, fromTextEmpty) { - // If the input text doesn't contain any character-string, it should be - // rejected - EXPECT_THROW(TypeParam(""), InvalidRdataText); - EXPECT_THROW(TypeParam(" "), InvalidRdataText); // even with a space - EXPECT_THROW(TypeParam("(\n)"), InvalidRdataText); // or multi-line with () -} - -void -makeLargest(vector<uint8_t>& data) { - uint8_t ch = 0; - - // create 255 sets of character-strings, each of which has the longest - // length (255bytes string + 1-byte length field) - for (int i = 0; i < 255; ++i, ++ch) { - data.push_back(255); - data.insert(data.end(), 255, ch); - } - // the last character-string should be 255 bytes (including the one-byte - // length field) in length so that the total length should be in the range - // of 16-bit integers. - data.push_back(254); - data.insert(data.end(), 254, ch); - - assert(data.size() == 65535); -} - -TYPED_TEST(Rdata_TXT_LIKE_Test, createFromWire) { - EXPECT_EQ(0, this->rdata_txt_like.compare( - *this->rdataFactoryFromFile(RRTYPE<TypeParam>(), - RRClass("IN"), - "rdata_txt_fromWire1"))); - - // Empty character string - EXPECT_EQ(0, this->rdata_txt_like_empty.compare( - *this->rdataFactoryFromFile(RRTYPE<TypeParam>(), - RRClass("IN"), - "rdata_txt_fromWire2.wire"))); - - // Multiple character strings - this->obuffer.clear(); - this->rdataFactoryFromFile(RRTYPE<TypeParam>(), RRClass("IN"), - "rdata_txt_fromWire3.wire")->toWire(this->obuffer); - // the result should be 'wiredata_txt' repeated twice - vector<uint8_t> expected_data(wiredata_txt_like, wiredata_txt_like + - sizeof(wiredata_txt_like)); - expected_data.insert(expected_data.end(), wiredata_txt_like, - wiredata_txt_like + sizeof(wiredata_txt_like)); - 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 - // data. - vector<uint8_t> largest_txt_like_data; - makeLargest(largest_txt_like_data); - InputBuffer ibuffer(&largest_txt_like_data[0], - largest_txt_like_data.size()); - TypeParam largest_txt_like(ibuffer, largest_txt_like_data.size()); - this->obuffer.clear(); - largest_txt_like.toWire(this->obuffer); - 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 - // length is validated. But this should be checked explicitly. - InputBuffer ibuffer2(&largest_txt_like_data[0], - largest_txt_like_data.size()); - EXPECT_THROW(TypeParam(ibuffer2, 65536), InvalidRdataLength); - - // RDATA is empty, which is invalid for TXT_LIKE. - EXPECT_THROW(this->rdataFactoryFromFile(RRTYPE<TypeParam>(), RRClass("IN"), - "rdata_txt_fromWire4.wire"), - DNSMessageFORMERR); - - // character-string length is too large, which could cause overrun. - EXPECT_THROW(this->rdataFactoryFromFile(RRTYPE<TypeParam>(), RRClass("IN"), - "rdata_txt_fromWire5.wire"), - DNSMessageFORMERR); -} - -TYPED_TEST(Rdata_TXT_LIKE_Test, createFromLexer) { - EXPECT_EQ(0, this->rdata_txt_like.compare( - *test::createRdataUsingLexer(RRTYPE<TypeParam>(), RRClass::IN(), - "Test-String"))); -} - -TYPED_TEST(Rdata_TXT_LIKE_Test, toWireBuffer) { - this->rdata_txt_like.toWire(this->obuffer); - 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); - matchWireData(wiredata_txt_like, sizeof(wiredata_txt_like), - this->renderer.getData(), this->renderer.getLength()); -} - -TYPED_TEST(Rdata_TXT_LIKE_Test, toText) { - EXPECT_EQ("\"Test-String\"", this->rdata_txt_like.toText()); - EXPECT_EQ("\"\"", this->rdata_txt_like_empty.toText()); - EXPECT_EQ("\"Test-String\"", this->rdata_txt_like_quoted.toText()); - - // Check escape behavior - const TypeParam double_quotes("Test-String\"Test-String\""); - EXPECT_EQ("\"Test-String\" \"Test-String\"", double_quotes.toText()); - const TypeParam semicolon("Test-String\\;Test-String"); - EXPECT_EQ("\"Test-String\\;Test-String\"", semicolon.toText()); - const TypeParam backslash("Test-String\\\\Test-String"); - EXPECT_EQ("\"Test-String\\\\Test-String\"", backslash.toText()); - const TypeParam before_x20("Test-String\\031Test-String"); - EXPECT_EQ("\"Test-String\\031Test-String\"", before_x20.toText()); - const TypeParam from_x20_to_x7e("\"Test-String ~ Test-String\""); - EXPECT_EQ("\"Test-String ~ Test-String\"", from_x20_to_x7e.toText()); - const TypeParam from_x20_to_x7e_2("Test-String\\032\\126\\032Test-String"); - EXPECT_EQ("\"Test-String ~ Test-String\"", from_x20_to_x7e_2.toText()); - const TypeParam after_x7e("Test-String\\127Test-String"); - EXPECT_EQ("\"Test-String\\127Test-String\"", after_x7e.toText()); -} - -TYPED_TEST(Rdata_TXT_LIKE_Test, assignment) { - TypeParam rdata1("assignment1"); - TypeParam rdata2("assignment2"); - rdata1 = rdata2; - EXPECT_EQ(0, rdata2.compare(rdata1)); - - // Check if the copied data is valid even after the original is deleted - TypeParam* rdata3 = new TypeParam(rdata1); - TypeParam rdata4("assignment3"); - rdata4 = *rdata3; - delete rdata3; - EXPECT_EQ(0, rdata4.compare(rdata1)); - - // Self assignment - rdata2 = *&rdata2; - EXPECT_EQ(0, rdata2.compare(rdata1)); -} - -TYPED_TEST(Rdata_TXT_LIKE_Test, compare) { - string const txt1("aaaaaaaa"); - string const txt2("aaaaaaaaaa"); - string const txt3("bbbbbbbb"); - string const txt4(129, 'a'); - string const txt5(128, 'b'); - - EXPECT_EQ(TypeParam(txt1).compare(TypeParam(txt1)), 0); - - EXPECT_LT(TypeParam("\"\"").compare(TypeParam(txt1)), 0); - EXPECT_GT(TypeParam(txt1).compare(TypeParam("\"\"")), 0); - - EXPECT_LT(TypeParam(txt1).compare(TypeParam(txt2)), 0); - EXPECT_GT(TypeParam(txt2).compare(TypeParam(txt1)), 0); - - EXPECT_LT(TypeParam(txt1).compare(TypeParam(txt3)), 0); - EXPECT_GT(TypeParam(txt3).compare(TypeParam(txt1)), 0); - - // we're comparing the data raw, starting at the length octet, so a shorter - // string sorts before a longer one no matter the lexicopraphical order - EXPECT_LT(TypeParam(txt3).compare(TypeParam(txt2)), 0); - EXPECT_GT(TypeParam(txt2).compare(TypeParam(txt3)), 0); - - // to make sure the length octet compares unsigned - EXPECT_LT(TypeParam(txt1).compare(TypeParam(txt4)), 0); - EXPECT_GT(TypeParam(txt4).compare(TypeParam(txt1)), 0); - - EXPECT_LT(TypeParam(txt5).compare(TypeParam(txt4)), 0); - EXPECT_GT(TypeParam(txt4).compare(TypeParam(txt5)), 0); - - // comparison attempt between incompatible RR types should be rejected - EXPECT_THROW(TypeParam(txt1).compare(*this->rdata_nomatch), - bad_cast); -} - -} diff --git a/src/lib/dns/tests/rdata_unittest.cc b/src/lib/dns/tests/rdata_unittest.cc index afc16a1986..8b13789179 100644 --- a/src/lib/dns/tests/rdata_unittest.cc +++ b/src/lib/dns/tests/rdata_unittest.cc @@ -1,467 +1 @@ -// Copyright (C) 2010-2023 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. -#include <config.h> - -#include <functional> -#include <iomanip> -#include <vector> -#include <string> -#include <sstream> - -#include <util/buffer.h> -#include <dns/messagerenderer.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> -#include <dns/rrclass.h> -#include <dns/rrtype.h> - -#include <gtest/gtest.h> - -#include <dns/tests/unittest_util.h> -#include <dns/tests/rdata_unittest.h> - -#include <util/unittests/wiredata.h> - -#include <boost/lexical_cast.hpp> - -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 ph = std::placeholders; - -namespace isc { -namespace dns { -namespace rdata { -RdataTest::RdataTest() : - obuffer(0), rdata_nomatch(createRdata(RRType(0), RRClass(1), "\\# 0")), - loader_cb(MasterLoaderCallbacks::getNullCallbacks()) -{} - -RdataPtr -RdataTest::rdataFactoryFromFile(const RRType& rrtype, const RRClass& rrclass, - const char* datafile, size_t position) -{ - std::vector<unsigned char> data; - UnitTestUtil::readWireData(datafile, data); - - InputBuffer buffer(&data[0], data.size()); - buffer.setPosition(position); - - uint16_t rdlen = buffer.readUint16(); - return (createRdata(rrtype, rrclass, buffer, rdlen)); -} - -namespace test { - -RdataPtr -createRdataUsingLexer(const RRType& rrtype, const RRClass& rrclass, - const std::string& str) -{ - std::stringstream ss(str); - MasterLexer lexer; - lexer.pushSource(ss); - - MasterLoaderCallbacks callbacks = - MasterLoaderCallbacks::getNullCallbacks(); - const Name origin("example.org."); - - return (createRdata(rrtype, rrclass, lexer, &origin, - MasterLoader::MANY_ERRORS, callbacks)); -} - -} // end of namespace isc::dns::rdata::test - -// A mock class to check parameters passed via loader callbacks. Its callback -// records the passed parameters, allowing the test to check them later via -// the check() method. -class CreateRdataCallback { -public: - enum CallbackType { NONE, ERROR, WARN }; - CreateRdataCallback() : type_(NONE), line_(0) {} - void callback(CallbackType type, const string& source, size_t line, - const string& reason_txt) { - type_ = type; - source_ = source; - line_ = line; - reason_txt_ = reason_txt; - } - - void clear() { - type_ = NONE; - source_.clear(); - line_ = 0; - reason_txt_.clear(); - } - - // Return if callback is called since the previous call to clear(). - bool isCalled() const { return (type_ != NONE); } - - void check(const string& expected_srcname, size_t expected_line, - CallbackType expected_type, const string& expected_reason) - const - { - EXPECT_EQ(expected_srcname, source_); - EXPECT_EQ(expected_line, line_); - EXPECT_EQ(expected_type, type_); - EXPECT_EQ(expected_reason, reason_txt_); - } - -private: - CallbackType type_; - string source_; - size_t line_; - string reason_txt_; -}; - -// Test class/type-independent behavior of createRdata(). -TEST_F(RdataTest, createRdataWithLexer) { - const in::AAAA aaaa_rdata("2001:db8::1"); - - stringstream ss; - const string src_name = "stream-" + boost::lexical_cast<string>(&ss); - ss << aaaa_rdata.toText() << "\n"; // valid case - ss << aaaa_rdata.toText() << "; comment, should be ignored\n"; - ss << aaaa_rdata.toText() << " extra-token\n"; // extra token - ss << aaaa_rdata.toText() << " extra token\n"; // 2 extra tokens - ss << ")\n"; // causing lexer error in parsing the RDATA text - ss << "192.0.2.1\n"; // semantics error: IPv4 address is given for AAAA - ss << aaaa_rdata.toText(); // valid, but end with EOF, not EOL - lexer.pushSource(ss); - - CreateRdataCallback callback; - MasterLoaderCallbacks callbacks( - std::bind(&CreateRdataCallback::callback, &callback, - CreateRdataCallback::ERROR, ph::_1, ph::_2, ph::_3), - std::bind(&CreateRdataCallback::callback, &callback, - CreateRdataCallback::WARN, ph::_1, ph::_2, ph::_3)); - - size_t line = 0; - - // Valid case. - ++line; - ConstRdataPtr rdata = createRdata(RRType::AAAA(), RRClass::IN(), lexer, - NULL, MasterLoader::MANY_ERRORS, - callbacks); - EXPECT_EQ(0, aaaa_rdata.compare(*rdata)); - EXPECT_FALSE(callback.isCalled()); - - // Similar to the previous case, but RDATA is followed by a comment. - // It should cause any confusion. - ++line; - callback.clear(); - rdata = createRdata(RRType::AAAA(), RRClass::IN(), lexer, NULL, - MasterLoader::MANY_ERRORS, callbacks); - EXPECT_EQ(0, aaaa_rdata.compare(*rdata)); - EXPECT_FALSE(callback.isCalled()); - - // Broken RDATA text: extra token. createRdata() returns NULL, error - // callback is called. - ++line; - callback.clear(); - EXPECT_FALSE(createRdata(RRType::AAAA(), RRClass::IN(), lexer, NULL, - MasterLoader::MANY_ERRORS, callbacks)); - callback.check(src_name, line, CreateRdataCallback::ERROR, - "createRdata from text failed near 'extra-token': " - "extra input text"); - - // Similar to the previous case, but only the first extra token triggers - // callback. - ++line; - callback.clear(); - EXPECT_FALSE(createRdata(RRType::AAAA(), RRClass::IN(), lexer, NULL, - MasterLoader::MANY_ERRORS, callbacks)); - callback.check(src_name, line, CreateRdataCallback::ERROR, - "createRdata from text failed near 'extra': " - "extra input text"); - - // Lexer error will happen, corresponding error callback will be triggered. - ++line; - callback.clear(); - EXPECT_FALSE(createRdata(RRType::AAAA(), RRClass::IN(), lexer, NULL, - MasterLoader::MANY_ERRORS, callbacks)); - callback.check(src_name, line, CreateRdataCallback::ERROR, - "createRdata from text failed: unbalanced parentheses"); - - // Semantics level error will happen, corresponding error callback will be - // triggered. - ++line; - callback.clear(); - EXPECT_FALSE(createRdata(RRType::AAAA(), RRClass::IN(), lexer, NULL, - MasterLoader::MANY_ERRORS, callbacks)); - callback.check(src_name, line, CreateRdataCallback::ERROR, - "createRdata from text failed: Bad IN/AAAA RDATA text: " - "'192.0.2.1'"); - - // Input is valid and parse will succeed, but with a warning that the - // file is not ended with a newline. - ++line; - callback.clear(); - rdata = createRdata(RRType::AAAA(), RRClass::IN(), lexer, NULL, - MasterLoader::MANY_ERRORS, callbacks); - EXPECT_EQ(0, aaaa_rdata.compare(*rdata)); - callback.check(src_name, line, CreateRdataCallback::WARN, - "file does not end with newline"); -} - -TEST_F(RdataTest, getLength) { - const in::AAAA aaaa_rdata("2001:db8::1"); - EXPECT_EQ(16, aaaa_rdata.getLength()); - - const generic::TXT txt_rdata("Hello World"); - EXPECT_EQ(12, txt_rdata.getLength()); -} - -} -} -} - -namespace { - -// Wire-format data correspond to rdata_unknown. Note that it doesn't -// include RDLENGTH. -const uint8_t wiredata_unknown[] = { 0xa1, 0xb2, 0xc3, 0x0d }; - -class Rdata_Unknown_Test : public RdataTest { -public: - Rdata_Unknown_Test() : - // "Unknown" RR Type used for the test cases below. If/when we - // use this type number as a "well-known" (probably - // experimental) type, we'll need to renumber it. - unknown_rrtype(RRType(65000)), - rdata_unknowntxt("\\# 4 a1b2c30d"), - rdata_unknown(rdata_unknowntxt) - {} -protected: - static string getLongestRdataTxt(); - static void getLongestRdataWire(vector<uint8_t>& v); - - const RRType unknown_rrtype; - const std::string rdata_unknowntxt; - const generic::Generic rdata_unknown; -}; - -string -Rdata_Unknown_Test::getLongestRdataTxt() { - ostringstream oss; - - oss << "\\# " << MAX_RDLENGTH << " "; - oss.fill('0'); - oss << right << hex; - for (int i = 0; i < MAX_RDLENGTH; i++) { - oss << setw(2) << (i & 0xff); - } - - return (oss.str()); -} - -void -Rdata_Unknown_Test::getLongestRdataWire(vector<uint8_t>& v) { - unsigned char ch = 0; - for (int i = 0; i < MAX_RDLENGTH; ++i, ++ch) { - v.push_back(ch); - } -} - -TEST_F(Rdata_Unknown_Test, createFromText) { - // valid construction. This also tests a normal case of "FromWire". - EXPECT_EQ(0, generic::Generic("\\# 4 a1b2c30d").compare( - *rdataFactoryFromFile(unknown_rrtype, RRClass::IN(), - "rdata_unknown_fromWire"))); - // upper case hexadecimal digits should also be okay. - EXPECT_EQ(0, generic::Generic("\\# 4 A1B2C30D").compare( - *rdataFactoryFromFile(unknown_rrtype, RRClass::IN(), - "rdata_unknown_fromWire"))); - // 0-length RDATA should be accepted - EXPECT_EQ(0, generic::Generic("\\# 0").compare( - *rdataFactoryFromFile(unknown_rrtype, RRClass::IN(), - "rdata_unknown_fromWire", 6))); - // hex encoding can be space-separated - EXPECT_EQ(0, generic::Generic("\\# 4 a1 b2c30d").compare(rdata_unknown)); - EXPECT_EQ(0, generic::Generic("\\# 4 a1b2 c30d").compare(rdata_unknown)); - EXPECT_EQ(0, generic::Generic("\\# 4 a1 b2 c3 0d").compare(rdata_unknown)); - EXPECT_EQ(0, generic::Generic("\\# 4 a1\tb2c3 0d").compare(rdata_unknown)); - - // Max-length RDATA - vector<uint8_t> v; - getLongestRdataWire(v); - InputBuffer ibuffer(&v[0], v.size()); - EXPECT_EQ(0, generic::Generic(getLongestRdataTxt()).compare( - generic::Generic(ibuffer, v.size()))); - - // the length field must match the encoding data length. - EXPECT_THROW(generic::Generic("\\# 4 1080c0ff00"), InvalidRdataLength); - EXPECT_THROW(generic::Generic("\\# 5 1080c0ff"), InvalidRdataLength); - // RDATA encoding part must consist of an even number of hex digits. - EXPECT_THROW(generic::Generic("\\# 1 1"), InvalidRdataText); - EXPECT_THROW(generic::Generic("\\# 1 ax"), InvalidRdataText); - // 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"), InvalidRdataLength); - EXPECT_THROW(generic::Generic("\\# 0a 00010203040506070809"), - 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"), InvalidRdataLength); -} - -TEST_F(Rdata_Unknown_Test, createFromWire) { - // normal case (including 0-length data) is covered in createFromText. - - // buffer too short. the error should be detected in buffer read - EXPECT_THROW(rdataFactoryFromFile(unknown_rrtype, RRClass::IN(), - "rdata_unknown_fromWire", 8), - InvalidBufferPosition); - - // too large data - vector<uint8_t> v; - getLongestRdataWire(v); - v.push_back(0); // making it too long - InputBuffer ibuffer(&v[0], v.size()); - EXPECT_THROW(generic::Generic(ibuffer, v.size()), InvalidRdataLength); -} - -// The following 3 sets of tests check the behavior of createRdata() variants -// with the "unknown" RRtype. The result should be RRclass independent. -TEST_F(Rdata_Unknown_Test, createRdataFromString) { - EXPECT_EQ(0, rdata_unknown.compare( - *createRdata(unknown_rrtype, RRClass::IN(), - rdata_unknowntxt))); - EXPECT_EQ(0, rdata_unknown.compare( - *createRdata(unknown_rrtype, RRClass::CH(), - rdata_unknowntxt))); - EXPECT_EQ(0, rdata_unknown.compare( - *createRdata(unknown_rrtype, RRClass("CLASS65000"), - rdata_unknowntxt))); -} - -TEST_F(Rdata_Unknown_Test, createRdataFromWire) { - InputBuffer ibuffer(wiredata_unknown, sizeof(wiredata_unknown)); - EXPECT_EQ(0, rdata_unknown.compare( - *createRdata(unknown_rrtype, RRClass::IN(), - ibuffer, sizeof(wiredata_unknown)))); - - InputBuffer ibuffer2(wiredata_unknown, sizeof(wiredata_unknown)); - EXPECT_EQ(0, rdata_unknown.compare( - *createRdata(unknown_rrtype, RRClass::CH(), - ibuffer2, sizeof(wiredata_unknown)))); - - InputBuffer ibuffer3(wiredata_unknown, sizeof(wiredata_unknown)); - EXPECT_EQ(0, rdata_unknown.compare( - *createRdata(unknown_rrtype, RRClass(65000), - ibuffer3, sizeof(wiredata_unknown)))); -} - -TEST_F(Rdata_Unknown_Test, createRdataByCopy) { - EXPECT_EQ(0, rdata_unknown.compare( - *createRdata(unknown_rrtype, RRClass::IN(), rdata_unknown))); - EXPECT_EQ(0, rdata_unknown.compare( - *createRdata(unknown_rrtype, RRClass::CH(), rdata_unknown))); - EXPECT_EQ(0, rdata_unknown.compare( - *createRdata(unknown_rrtype, RRClass(65000), - rdata_unknown))); -} - -TEST_F(Rdata_Unknown_Test, copyConstruct) { - generic::Generic copy(rdata_unknown); - EXPECT_EQ(0, copy.compare(rdata_unknown)); - - // Check the copied data is valid even after the original is deleted - generic::Generic* copy2 = new generic::Generic(rdata_unknown); - generic::Generic copy3(*copy2); - delete copy2; - EXPECT_EQ(0, copy3.compare(rdata_unknown)); -} - -TEST_F(Rdata_Unknown_Test, assignment) { - generic::Generic copy("\\# 1 10"); - copy = rdata_unknown; - EXPECT_EQ(0, copy.compare(rdata_unknown)); - - // Check if the copied data is valid even after the original is deleted - generic::Generic* copy2 = new generic::Generic(rdata_unknown); - generic::Generic copy3("\\# 1 10"); - copy3 = *copy2; - delete copy2; - EXPECT_EQ(0, copy3.compare(rdata_unknown)); - - // Self assignment - copy = *© - EXPECT_EQ(0, copy.compare(rdata_unknown)); -} - -TEST_F(Rdata_Unknown_Test, toText) { - EXPECT_EQ(rdata_unknowntxt, rdata_unknown.toText()); - EXPECT_EQ(getLongestRdataTxt(), - generic::Generic(getLongestRdataTxt()).toText()); -} - -TEST_F(Rdata_Unknown_Test, toWireBuffer) { - rdata_unknown.toWire(obuffer); - matchWireData(wiredata_unknown, sizeof(wiredata_unknown), - obuffer.getData(), obuffer.getLength()); -} - -TEST_F(Rdata_Unknown_Test, toWireRenderer) { - rdata_unknown.toWire(renderer); - matchWireData(wiredata_unknown, sizeof(wiredata_unknown), - renderer.getData(), renderer.getLength()); -} - -TEST_F(Rdata_Unknown_Test, compare) { - // comparison as left-justified unsigned octet sequences: - // cppcheck-suppress uselessCallsCompare - EXPECT_EQ(0, rdata_unknown.compare(rdata_unknown)); - - generic::Generic rdata_unknown_small("\\# 4 00b2c3ff"); - EXPECT_GT(0, rdata_unknown_small.compare(rdata_unknown)); - EXPECT_LT(0, rdata_unknown.compare(rdata_unknown_small)); - - generic::Generic rdata_unknown_large("\\# 4 ffb2c300"); - EXPECT_LT(0, rdata_unknown_large.compare(rdata_unknown)); - EXPECT_GT(0, rdata_unknown.compare(rdata_unknown_large)); - - // the absence of an octet sorts before a zero octet. - generic::Generic rdata_unknown_short("\\# 3 a1b2c3"); - EXPECT_GT(0, rdata_unknown_short.compare(rdata_unknown)); - EXPECT_LT(0, rdata_unknown.compare(rdata_unknown_short)); -} - -TEST_F(Rdata_Unknown_Test, LeftShiftOperator) { - ostringstream oss; - oss << rdata_unknown; - EXPECT_EQ(rdata_unknown.toText(), oss.str()); -} - -// -// Tests for global utility functions -// -TEST_F(RdataTest, compareNames) { - Name small("a.example"); - Name large("example"); - - // Check the case where the order is different from the owner name - // comparison: - EXPECT_TRUE(small > large); - EXPECT_EQ(-1, compareNames(small, large)); - EXPECT_EQ(1, compareNames(large, small)); - - // Check case insensitive comparison: - Name small_upper("A.EXAMPLE"); - EXPECT_EQ(0, compareNames(small, small_upper)); - - // the absence of an octet sorts before a zero octet. - Name large2("a.example2"); - EXPECT_EQ(-1, compareNames(small, large2)); - EXPECT_EQ(1, compareNames(large2, small)); -} -} diff --git a/src/lib/dns/tests/rdata_unittest.h b/src/lib/dns/tests/rdata_unittest.h index 0c9178e17c..8b13789179 100644 --- a/src/lib/dns/tests/rdata_unittest.h +++ b/src/lib/dns/tests/rdata_unittest.h @@ -1,92 +1 @@ -// Copyright (C) 2010-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. -#ifndef RDATA_UNITTEST_H -#define RDATA_UNITTEST_H 1 - -#include <util/buffer.h> -#include <dns/messagerenderer.h> -#include <dns/rrclass.h> -#include <dns/rrtype.h> -#include <dns/rdata.h> -#include <dns/master_lexer.h> - -#include <gtest/gtest.h> - -#include <string> -#include <sstream> - -namespace isc { -namespace dns { -namespace rdata { -class RdataTest : public ::testing::Test { -protected: - RdataTest(); - static RdataPtr rdataFactoryFromFile(const RRType& rrtype, - const RRClass& rrclass, - const char* datafile, - size_t position = 0); - - // Common check to see the result of Rdata construction of given type - // (template parameter RdataType) either from std::string or with - // MasterLexer object. If it's expected to succeed the result should be - // identical to the commonly used test data (rdata_expected); otherwise it - // should result in the exception specified as the template parameter: - // ExForString for the string version, and ExForLexer for the lexer - // version. throw_str_version and throw_lexer_version are set to true - // iff the string/lexer version is expected to throw, respectively. - // Parameter origin can be set to non NULL for the origin parameter of - // the lexer version of Rdata constructor. - template <typename RdataType, typename ExForString, typename ExForLexer> - void checkFromText(const std::string& rdata_txt, - const RdataType& rdata_expected, - bool throw_str_version = true, - bool throw_lexer_version = true, - const Name* origin = NULL) - { - SCOPED_TRACE(rdata_txt); - - if (throw_str_version) { - EXPECT_THROW(RdataType rdata(rdata_txt), ExForString); - } else { - EXPECT_EQ(0, RdataType(rdata_txt).compare(rdata_expected)); - } - - std::stringstream ss(rdata_txt); - MasterLexer lexer; - lexer.pushSource(ss); - if (throw_lexer_version) { - EXPECT_THROW(RdataType rdata(lexer, origin, MasterLoader::DEFAULT, - loader_cb), ExForLexer); - } else { - EXPECT_EQ(0, RdataType(lexer, origin, MasterLoader::DEFAULT, - loader_cb).compare(rdata_expected)); - } - } - - 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. - RdataPtr rdata_nomatch; - MasterLexer lexer; - MasterLoaderCallbacks loader_cb; -}; - -namespace test { -RdataPtr -createRdataUsingLexer(const RRType& rrtype, const RRClass& rrclass, - const std::string& str); -} - -} -} -} -#endif // RDATA_UNITTEST_H - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/tests/rdatafields_unittest.cc b/src/lib/dns/tests/rdatafields_unittest.cc index 0531439574..8b13789179 100644 --- a/src/lib/dns/tests/rdatafields_unittest.cc +++ b/src/lib/dns/tests/rdatafields_unittest.cc @@ -1,366 +1 @@ -// Copyright (C) 2010-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. -#include <config.h> - -#include <vector> - -#include <exceptions/exceptions.h> - -#include <util/buffer.h> -#include <dns/messagerenderer.h> -#include <dns/name.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> -#include <dns/rdatafields.h> -#include <dns/tests/unittest_util.h> - -#include <util/unittests/wiredata.h> - -#include <gtest/gtest.h> - -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 { -protected: - RdataFieldsTest() : obuffer(0), ns_name("example.com"), - other_name("www.example.com") - {} - void constructCommonTests(const RdataFields& fields, - const uint8_t* const expected_data, - const size_t expected_data_len); - void constructCommonTestsNS(const RdataFields& fields); - void constructCommonTestsTXT(const RdataFields& fields); - void constructCommonTestsRRSIG(const RdataFields& fields); - void constructCommonTestsOPT(const RdataFields& fields); - OutputBuffer obuffer; - MessageRenderer renderer; - const Name ns_name; - const Name other_name; - vector<unsigned char> expected_wire; - vector<unsigned char> fields_wire; -}; - -const uint8_t in_a_data[] = { 192, 0, 2, 1 }; -// binary representation of example.com. -const uint8_t ns_data[] = { 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, - 0x03, 0x63, 0x6f, 0x6d, 0x00 }; - -// -// IN/A RDATA: fixed length, single data field -// -void -RdataFieldsTest::constructCommonTests(const RdataFields& fields, - const uint8_t* const expected_data, - const size_t expected_data_len) -{ - 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); - matchWireData(expected_data, expected_data_len, - obuffer.getData(), obuffer.getLength()); - - fields.toWire(renderer); - matchWireData(expected_data, expected_data_len, - renderer.getData(), renderer.getLength()); -} - -TEST_F(RdataFieldsTest, constructFromRdata) { - const RdataFields fields(in::A("192.0.2.1")); - constructCommonTests(fields, in_a_data, sizeof(in_a_data)); -} - -TEST_F(RdataFieldsTest, constructFromParams) { - const RdataFields::FieldSpec spec(RdataFields::DATA, 4); - const RdataFields fields(&spec, sizeof(spec), in_a_data, - sizeof(in_a_data)); - constructCommonTests(fields, in_a_data, sizeof(in_a_data)); -} - -// -// NS RDATA: containing a compressible name. -// -void -RdataFieldsTest::constructCommonTestsNS(const RdataFields& fields) { - EXPECT_EQ(sizeof(RdataFields::FieldSpec), fields.getFieldSpecDataSize()); - EXPECT_EQ(1, fields.getFieldCount()); - EXPECT_EQ(RdataFields::COMPRESSIBLE_NAME, fields.getFieldSpec(0).type); - EXPECT_EQ(ns_name.getLength(), fields.getFieldSpec(0).len); - - expected_wire.clear(); - UnitTestUtil::readWireData("rdatafields1.wire", expected_wire); - other_name.toWire(obuffer); - fields.toWire(obuffer); - 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); - matchWireData(&expected_wire[0], expected_wire.size(), - renderer.getData(), renderer.getLength()); -} - -TEST_F(RdataFieldsTest, constructFromRdataNS) { - const RdataFields fields_ns((generic::NS(ns_name))); - constructCommonTestsNS(fields_ns); -} - -TEST_F(RdataFieldsTest, constructFromParamsNS) { - const RdataFields::FieldSpec spec(RdataFields::COMPRESSIBLE_NAME, - sizeof(ns_data)); - const RdataFields fields_ns(&spec, sizeof(spec), ns_data, sizeof(ns_data)); - constructCommonTestsNS(fields_ns); -} - -// -// TXT RDATA: multiple fields, lengths vary -// -void -RdataFieldsTest::constructCommonTestsTXT(const RdataFields& fields) { - // Since all fields are plain data, they are handled as a single data - // field. - EXPECT_EQ(sizeof(RdataFields::FieldSpec), fields.getFieldSpecDataSize()); - EXPECT_EQ(1, fields.getFieldCount()); - EXPECT_EQ(RdataFields::DATA, fields.getFieldSpec(0).type); - EXPECT_EQ(expected_wire.size(), fields.getFieldSpec(0).len); - - fields.toWire(obuffer); - matchWireData(&expected_wire[0], expected_wire.size(), - obuffer.getData(), obuffer.getLength()); - - fields.toWire(renderer); - matchWireData(&expected_wire[0], expected_wire.size(), - renderer.getData(), renderer.getLength()); -} - -TEST_F(RdataFieldsTest, constructFromRdataTXT) { - UnitTestUtil::readWireData("rdatafields3.wire", expected_wire); - InputBuffer ibuffer(&expected_wire[0], expected_wire.size()); - const uint16_t rdlen = ibuffer.readUint16(); - const RdataFields fields(generic::TXT(ibuffer, rdlen)); - - // drop the RDLEN part - expected_wire.erase(expected_wire.begin(), expected_wire.begin() + 2); - - constructCommonTestsTXT(fields); -} - -TEST_F(RdataFieldsTest, constructFromParamsTXT) { - UnitTestUtil::readWireData("rdatafields3.wire", expected_wire); - expected_wire.erase(expected_wire.begin(), expected_wire.begin() + 2); - const RdataFields::FieldSpec spec(RdataFields::DATA, expected_wire.size()); - const RdataFields fields(&spec, sizeof(spec), &expected_wire[0], - expected_wire.size()); - constructCommonTestsTXT(fields); -} - -// -// RRSIG: multiple fields, with an incompressible name -// -void -RdataFieldsTest::constructCommonTestsRRSIG(const RdataFields& fields) { - // In terms of RdataFields RRSIG RDATA consists of 3 fields: - // - 18-byte data field (from the "type covered" field to "key tag" field) - // - an incompressible name field (for the signer's name field). - // this is a variable length field. In this test it's a 13-byte field. - // - a variable-length data field for the signature. In this tests - // it's a 15-byte field. - EXPECT_EQ(3 * sizeof(RdataFields::FieldSpec), - fields.getFieldSpecDataSize()); - EXPECT_EQ(3, fields.getFieldCount()); - EXPECT_EQ(RdataFields::DATA, fields.getFieldSpec(0).type); - EXPECT_EQ(18, fields.getFieldSpec(0).len); - EXPECT_EQ(RdataFields::INCOMPRESSIBLE_NAME, fields.getFieldSpec(1).type); - EXPECT_EQ(13, fields.getFieldSpec(1).len); - EXPECT_EQ(RdataFields::DATA, fields.getFieldSpec(2).type); - EXPECT_EQ(15, fields.getFieldSpec(2).len); - - expected_wire.clear(); - UnitTestUtil::readWireData("rdatafields5.wire", expected_wire); - Name("com").toWire(obuffer); - obuffer.writeUint16(fields.getDataLength()); - fields.toWire(obuffer); - other_name.toWire(obuffer); - matchWireData(&expected_wire[0], expected_wire.size(), - obuffer.getData(), obuffer.getLength()); - - expected_wire.clear(); - UnitTestUtil::readWireData("rdatafields6.wire", expected_wire); - Name("com").toWire(renderer); - 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 - matchWireData(&expected_wire[0], expected_wire.size(), - renderer.getData(), renderer.getLength()); -} - -TEST_F(RdataFieldsTest, constructFromRdataRRSIG) { - UnitTestUtil::readWireData("rdatafields4.wire", expected_wire); - InputBuffer ibuffer(&expected_wire[0], expected_wire.size()); - const uint16_t rdlen = ibuffer.readUint16(); - const RdataFields fields(generic::RRSIG(ibuffer, rdlen)); - - // drop the RDLEN part - expected_wire.erase(expected_wire.begin(), expected_wire.begin() + 2); - - constructCommonTestsRRSIG(fields); -} - -TEST_F(RdataFieldsTest, constructFromParamsRRSIG) { - UnitTestUtil::readWireData("rdatafields4.wire", fields_wire); - fields_wire.erase(fields_wire.begin(), fields_wire.begin() + 2); - - const RdataFields::FieldSpec specs[] = { - RdataFields::FieldSpec(RdataFields::DATA, 18), - RdataFields::FieldSpec(RdataFields::INCOMPRESSIBLE_NAME, 13), - RdataFields::FieldSpec(RdataFields::DATA, 15) - }; - const RdataFields fields(specs, sizeof(specs), &fields_wire[0], - fields_wire.size()); - constructCommonTestsRRSIG(fields); -} - -TEST_F(RdataFieldsTest, convertRdatatoParams) { - // Confirm we can restore the original data from the serialized data. - // We use RRSIG as a relatively complicated field structure. - UnitTestUtil::readWireData("rdatafields4.wire", expected_wire); - InputBuffer ibuffer(&expected_wire[0], expected_wire.size()); - const uint16_t rdlen = ibuffer.readUint16(); - const RdataFields fields(generic::RRSIG(ibuffer, rdlen)); - - expected_wire.erase(expected_wire.begin(), expected_wire.begin() + 2); - - // Copy the data in separate storage - vector<uint8_t> spec_store(fields.getFieldSpecDataSize()); - void* cp_spec = &spec_store[0]; - memcpy(cp_spec, fields.getFieldSpecData(), spec_store.size()); - vector<uint8_t> data_store(fields.getDataLength()); - memcpy(&data_store[0], fields.getData(), fields.getDataLength()); - - // Restore the data in the form of RdataFields - const RdataFields fields_byparams(cp_spec, fields.getFieldSpecDataSize(), - &data_store[0], fields.getDataLength()); - - // Check it's valid - constructCommonTestsRRSIG(fields_byparams); -} - -// -// OPT: an empty RDATA -// -void -RdataFieldsTest::constructCommonTestsOPT(const RdataFields& fields) { - EXPECT_EQ(0, fields.getFieldSpecDataSize()); - EXPECT_EQ(0, fields.getFieldCount()); - EXPECT_EQ(0, fields.getDataLength()); - EXPECT_EQ((const uint8_t*) NULL, fields.getData()); - fields.toWire(obuffer); - EXPECT_EQ(0, obuffer.getLength()); - fields.toWire(renderer); - EXPECT_EQ(0, renderer.getLength()); -} - -TEST_F(RdataFieldsTest, constructFromRdataOPT) { - InputBuffer ibuffer(NULL, 0); - const RdataFields fields(generic::OPT(ibuffer, 0)); - constructCommonTestsOPT(fields); -} - -TEST_F(RdataFieldsTest, constructFromParamsOPT) { - const RdataFields fields(NULL, 0, NULL, 0); - constructCommonTestsOPT(fields); -} - -// Invalid input to the "from parameter" constructor: sum of the field lengths -// is not equal to the data length. -TEST_F(RdataFieldsTest, invalidFieldLength) { - UnitTestUtil::readWireData("rdatafields4.wire", fields_wire); - fields_wire.erase(fields_wire.begin(), fields_wire.begin() + 2); - - const RdataFields::FieldSpec specs[] = { - RdataFields::FieldSpec(RdataFields::DATA, 18), - RdataFields::FieldSpec(RdataFields::INCOMPRESSIBLE_NAME, 13), - RdataFields::FieldSpec(RdataFields::DATA, 14) - }; - // sum of field len < data len - EXPECT_THROW(RdataFields(specs, 3, &fields_wire[0], fields_wire.size()), - isc::InvalidParameter); - // sum of field len > data len - EXPECT_THROW(RdataFields(specs, 3, &fields_wire[0], - fields_wire.size() - 2), - isc::InvalidParameter); -} - -// Invalid input to the "from parameter" constructor: NULL vs length mismatch -TEST_F(RdataFieldsTest, mismatchFieldLengthAndData) { - const unsigned char dummy_data = 0; - const RdataFields::FieldSpec dummy_spec(RdataFields::DATA, 1); - - EXPECT_THROW(RdataFields(NULL, 1, &dummy_data, 1), isc::InvalidParameter); - EXPECT_THROW(RdataFields(&dummy_spec, 0, NULL, 0), isc::InvalidParameter); - EXPECT_THROW(RdataFields(&dummy_spec, 1, NULL, 1), isc::InvalidParameter); - EXPECT_THROW(RdataFields(NULL, 0, &dummy_data, 0), isc::InvalidParameter); -} - -// Bogus input to getFieldSpec() -TEST_F(RdataFieldsTest, getFieldSpecWithBadFieldId) { - const RdataFields fields_in_a(in::A("192.0.2.1")); - EXPECT_THROW(fields_in_a.getFieldSpec(1), isc::OutOfRange); -} - -// Tests for unexpected methods in RdataFieldComposerTest. Confirm -// a call to these methods triggers an exception. Expected methods are -// tested via other tests above. -class DummyRdata : public Rdata { -public: - enum Mode { CLEAR, SKIP, TRIM }; - explicit DummyRdata(Mode mode) : mode_(mode) {} - DummyRdata(const DummyRdata& source) : Rdata(), mode_(source.mode_) {} - virtual ~DummyRdata() {} - virtual void toWire(AbstractMessageRenderer& renderer) const { - // call the unexpected method corresponding to the test mode. - // method parameters don't matter. - switch (mode_) { - case CLEAR: - renderer.clear(); - break; - case SKIP: - renderer.skip(2); - break; - case TRIM: - renderer.trim(2); - break; - } - } - - // These are defined only to make the compiler happy. We don't use them - // for the test. - virtual string toText() const { return (""); } - virtual void toWire(OutputBuffer&) const {} - virtual int compare(const Rdata&) const { return (0); } -private: - const int mode_; -}; - -TEST(RdataFieldComposerTest, unusedMethods) { - EXPECT_THROW(RdataFields(DummyRdata(DummyRdata::CLEAR)), isc::Unexpected); -} -} diff --git a/src/lib/dns/tests/rrclass_unittest.cc b/src/lib/dns/tests/rrclass_unittest.cc index ae85f01be4..8b13789179 100644 --- a/src/lib/dns/tests/rrclass_unittest.cc +++ b/src/lib/dns/tests/rrclass_unittest.cc @@ -1,174 +1 @@ -// Copyright (C) 2010-2017 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. -#include <config.h> - -#include <gtest/gtest.h> - -#include <util/buffer.h> -#include <dns/messagerenderer.h> -#include <dns/rrclass.h> - -#include <dns/tests/unittest_util.h> -#include <util/unittests/wiredata.h> - -#include <boost/scoped_ptr.hpp> - -using namespace std; -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 { -protected: - RRClassTest() : obuffer(0) {} - - OutputBuffer obuffer; - MessageRenderer renderer; - - static RRClass rrclassFactoryFromWire(const char* datafile); - static const RRClass rrclass_1, rrclass_0x80, rrclass_0x800, - rrclass_0x8000, rrclass_max; - static const uint8_t wiredata[]; -}; - -const RRClass RRClassTest::rrclass_1(1); -const RRClass RRClassTest::rrclass_0x80(0x80); -const RRClass RRClassTest::rrclass_0x800(0x800); -const RRClass RRClassTest::rrclass_0x8000(0x8000); -const RRClass RRClassTest::rrclass_max(0xffff); -// This is wire-format data for the above sample RRClass rendered in the -// appearing order. -const uint8_t RRClassTest::wiredata[] = { 0x00, 0x01, 0x00, 0x80, 0x08, - 0x00, 0x80, 0x00, 0xff, 0xff }; - -RRClass -RRClassTest::rrclassFactoryFromWire(const char* datafile) { - std::vector<unsigned char> data; - UnitTestUtil::readWireData(datafile, data); - - InputBuffer buffer(&data[0], data.size()); - - return (RRClass(buffer)); -} - -TEST_F(RRClassTest, fromTextConstructor) { - EXPECT_EQ("IN", RRClass("IN").toText()); - EXPECT_EQ("CH", RRClass("CH").toText()); - - EXPECT_EQ("CLASS65535", RRClass("CLASS65535").toText()); - - // some uncommon cases: see the corresponding RRType tests. - EXPECT_EQ(53, RRClass("CLASS00053").getCode()); - EXPECT_THROW(RRClass("CLASS000053"), InvalidRRClass); - - // bogus CLASSnnn representations: should trigger an exception - EXPECT_THROW(RRClass("CLASS"), InvalidRRClass); - EXPECT_THROW(RRClass("CLASS-1"), InvalidRRClass); - EXPECT_THROW(RRClass("CLASSxxx"), InvalidRRClass); - EXPECT_THROW(RRClass("CLASS65536"), InvalidRRClass); - EXPECT_THROW(RRClass("CLASS6500x"), InvalidRRClass); - EXPECT_THROW(RRClass("CLASS65000 "), InvalidRRClass); -} - -TEST_F(RRClassTest, fromWire) { - EXPECT_EQ(0x1234, - rrclassFactoryFromWire("rrcode16_fromWire1").getCode()); - EXPECT_THROW(rrclassFactoryFromWire("rrcode16_fromWire2"), - IncompleteRRClass); -} - -TEST_F(RRClassTest, caseConstruct) { - EXPECT_EQ("IN", RRClass("in").toText()); - EXPECT_EQ("CH", RRClass("ch").toText()); - EXPECT_EQ("CLASS65535", RRClass("class65535").toText()); -} - -TEST_F(RRClassTest, toText) { - EXPECT_EQ("IN", RRClass(1).toText()); - EXPECT_EQ("CLASS65000", RRClass(65000).toText()); -} - -TEST_F(RRClassTest, createFromText) { - scoped_ptr<RRClass> chclass(RRClass::createFromText("CH")); - EXPECT_TRUE(chclass); - EXPECT_EQ("CH", chclass->toText()); - - scoped_ptr<RRClass> zzclass(RRClass::createFromText("ZZ")); - EXPECT_FALSE(zzclass); -} - -TEST_F(RRClassTest, toWireBuffer) { - rrclass_1.toWire(obuffer); - rrclass_0x80.toWire(obuffer); - rrclass_0x800.toWire(obuffer); - rrclass_0x8000.toWire(obuffer); - rrclass_max.toWire(obuffer); - - matchWireData(wiredata, sizeof (wiredata), - obuffer.getData(), obuffer.getLength()); -} - -TEST_F(RRClassTest, toWireRenderer) { - rrclass_1.toWire(renderer); - rrclass_0x80.toWire(renderer); - rrclass_0x800.toWire(renderer); - rrclass_0x8000.toWire(renderer); - rrclass_max.toWire(renderer); - - matchWireData(wiredata, sizeof (wiredata), - renderer.getData(), renderer.getLength()); -} - -TEST_F(RRClassTest, wellKnownClass) { - EXPECT_EQ(1, RRClass::IN().getCode()); - EXPECT_EQ("IN", RRClass::IN().toText()); -} - -TEST_F(RRClassTest, compare) { - EXPECT_TRUE(RRClass(1) == RRClass("IN")); - EXPECT_TRUE(RRClass(1).equals(RRClass("IN"))); - EXPECT_TRUE(RRClass(0).nequals(RRClass("IN"))); - - EXPECT_TRUE(RRClass("IN") < RRClass("CH")); - EXPECT_TRUE(RRClass(100) < RRClass(65535)); -} - -// test operator<<. We simply confirm it appends the result of toText(). -TEST_F(RRClassTest, LeftShiftOperator) { - ostringstream oss; - oss << RRClass::IN(); - EXPECT_EQ(RRClass::IN().toText(), oss.str()); -} - -// Below, we'll check definitions for all well-known RR classes; whether they -// are defined and have the correct parameter values. Test data are generated -// from the list available at: -// http://www.iana.org/assignments/dns-parameters/dns-parameters.xml -struct ClassParam { - const char* const txt; // "IN", "CH", etc - const uint16_t code; // 1, 3, - const RRClass& (*obj)(); // RRClass::IN(), etc -} known_classes[] = { - {"IN", 1, RRClass::IN}, {"CH", 3, RRClass::CH}, {"HS", 4, RRClass::HS}, - {"NONE", 254, RRClass::NONE}, {"ANY", 255, RRClass::ANY}, - {NULL, 0, NULL} -}; - -TEST(RRClassConstTest, wellKnowns) { - for (int i = 0; known_classes[i].txt; ++i) { - SCOPED_TRACE("Checking well known RRClass: " + - string(known_classes[i].txt)); - EXPECT_EQ(known_classes[i].code, - RRClass(known_classes[i].txt).getCode()); - EXPECT_EQ(known_classes[i].code, - (*known_classes[i].obj)().getCode()); - } -} -} diff --git a/src/lib/dns/tests/rrcollator_unittest.cc b/src/lib/dns/tests/rrcollator_unittest.cc index 4247911d35..8b13789179 100644 --- a/src/lib/dns/tests/rrcollator_unittest.cc +++ b/src/lib/dns/tests/rrcollator_unittest.cc @@ -1,208 +1 @@ -// Copyright (C) 2012-2020 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. -#include <config.h> - -#include <exceptions/exceptions.h> - -#include <dns/name.h> -#include <dns/master_loader.h> -#include <dns/master_loader_callbacks.h> -#include <dns/rrclass.h> -#include <dns/rrcollator.h> -#include <dns/rdata.h> -#include <dns/rrset.h> -#include <dns/rrttl.h> - -#include <gtest/gtest.h> - -#include <functional> -#include <sstream> -#include <vector> - -using std::vector; -using namespace isc::dns; -using namespace isc::dns::rdata; -namespace ph = std::placeholders; - -namespace { - -typedef RRCollator::AddRRsetCallback AddRRsetCallback; - -void -addRRset(const RRsetPtr& rrset, vector<ConstRRsetPtr>* to_append, - const bool* do_throw) { - if (*do_throw) { - isc_throw(isc::Unexpected, "faked failure"); - } - to_append->push_back(rrset); -} - -class RRCollatorTest : public ::testing::Test { -protected: - RRCollatorTest() : - origin_("example.com"), rrclass_(RRClass::IN()), rrttl_(3600), - throw_from_callback_(false), - collator_(std::bind(addRRset, ph::_1, &rrsets_, &throw_from_callback_)), - rr_callback_(collator_.getCallback()), - a_rdata1_(createRdata(RRType::A(), rrclass_, "192.0.2.1")), - a_rdata2_(createRdata(RRType::A(), rrclass_, "192.0.2.2")), - txt_rdata_(createRdata(RRType::TXT(), rrclass_, "test")), - sig_rdata1_(createRdata(RRType::RRSIG(), rrclass_, - "A 5 3 3600 20000101000000 20000201000000 " - "12345 example.com. FAKE")), - sig_rdata2_(createRdata(RRType::RRSIG(), rrclass_, - "NS 5 3 3600 20000101000000 20000201000000 " - "12345 example.com. FAKE")) - {} - - void checkRRset(const Name& expected_name, const RRClass& expected_class, - const RRType& expected_type, const RRTTL& expected_ttl, - const vector<ConstRdataPtr>& expected_rdatas) { - SCOPED_TRACE(expected_name.toText(true) + "/" + - expected_class.toText() + "/" + expected_type.toText()); - - // This test always clears rrsets_ to confirm RRsets are added - // one-by-one - ASSERT_EQ(1, rrsets_.size()); - - ConstRRsetPtr actual = rrsets_[0]; - EXPECT_EQ(expected_name, actual->getName()); - EXPECT_EQ(expected_class, actual->getClass()); - EXPECT_EQ(expected_type, actual->getType()); - EXPECT_EQ(expected_ttl, actual->getTTL()); - ASSERT_EQ(expected_rdatas.size(), actual->getRdataCount()); - vector<ConstRdataPtr>::const_iterator it = expected_rdatas.begin(); - for (RdataIteratorPtr rit = actual->getRdataIterator(); - !rit->isLast(); - rit->next()) { - EXPECT_EQ(0, rit->getCurrent().compare(**it)); - ++it; - } - - rrsets_.clear(); - } - - const Name origin_; - const RRClass rrclass_; - const RRTTL rrttl_; - vector<ConstRRsetPtr> rrsets_; - bool throw_from_callback_; - RRCollator collator_; - AddRRCallback rr_callback_; - const RdataPtr a_rdata1_, a_rdata2_, txt_rdata_, sig_rdata1_, sig_rdata2_; - vector<ConstRdataPtr> rdatas_; // placeholder for expected data -}; - -TEST_F(RRCollatorTest, basicCases) { - // Add two RRs belonging to the same RRset. These will be buffered. - rr_callback_(origin_, rrclass_, RRType::A(), rrttl_, a_rdata1_); - EXPECT_TRUE(rrsets_.empty()); // not yet given as an RRset - rr_callback_(origin_, rrclass_, RRType::A(), rrttl_, a_rdata2_); - EXPECT_TRUE(rrsets_.empty()); // still not given - - // Add another type of RR. This completes the construction of the A RRset, - // which will be given via the callback. - rr_callback_(origin_, rrclass_, RRType::TXT(), rrttl_, txt_rdata_); - rdatas_.push_back(a_rdata1_); - rdatas_.push_back(a_rdata2_); - checkRRset(origin_, rrclass_, RRType::A(), rrttl_, rdatas_); - - // Add the same type of RR but of different name. This should make another - // callback for the previous TXT RR. - rr_callback_(Name("txt.example.com"), rrclass_, RRType::TXT(), rrttl_, - txt_rdata_); - rdatas_.clear(); - rdatas_.push_back(txt_rdata_); - checkRRset(origin_, rrclass_, RRType::TXT(), rrttl_, rdatas_); - - // Add the same type and name of RR but of different class (rare case - // in practice) - rr_callback_(Name("txt.example.com"), RRClass::CH(), RRType::TXT(), rrttl_, - txt_rdata_); - rdatas_.clear(); - rdatas_.push_back(txt_rdata_); - checkRRset(Name("txt.example.com"), rrclass_, RRType::TXT(), rrttl_, - rdatas_); - - // Tell the collator we are done, then we'll see the last RR as an RRset. - collator_.flush(); - checkRRset(Name("txt.example.com"), RRClass::CH(), RRType::TXT(), rrttl_, - rdatas_); - - // Redundant flush() will be no-op. - collator_.flush(); - EXPECT_TRUE(rrsets_.empty()); -} - -TEST_F(RRCollatorTest, minTTLFirst) { - // RRs of the same RRset but has different TTLs. The first RR has - // the smaller TTL, which should be used for the TTL of the RRset. - rr_callback_(origin_, rrclass_, RRType::A(), RRTTL(10), a_rdata1_); - rr_callback_(origin_, rrclass_, RRType::A(), RRTTL(20), a_rdata2_); - rdatas_.push_back(a_rdata1_); - rdatas_.push_back(a_rdata2_); - collator_.flush(); - checkRRset(origin_, rrclass_, RRType::A(), RRTTL(10), rdatas_); -} - -TEST_F(RRCollatorTest, maxTTLFirst) { - // RRs of the same RRset but has different TTLs. The second RR has - // the smaller TTL, which should be used for the TTL of the RRset. - rr_callback_(origin_, rrclass_, RRType::A(), RRTTL(20), a_rdata1_); - rr_callback_(origin_, rrclass_, RRType::A(), RRTTL(10), a_rdata2_); - rdatas_.push_back(a_rdata1_); - rdatas_.push_back(a_rdata2_); - collator_.flush(); - checkRRset(origin_, rrclass_, RRType::A(), RRTTL(10), rdatas_); -} - -TEST_F(RRCollatorTest, addRRSIGs) { - // RRSIG is special; they are also distinguished by their covered types. - rr_callback_(origin_, rrclass_, RRType::RRSIG(), rrttl_, sig_rdata1_); - rr_callback_(origin_, rrclass_, RRType::RRSIG(), rrttl_, sig_rdata2_); - - rdatas_.push_back(sig_rdata1_); - checkRRset(origin_, rrclass_, RRType::RRSIG(), rrttl_, rdatas_); -} - -TEST_F(RRCollatorTest, emptyFlush) { - collator_.flush(); - EXPECT_TRUE(rrsets_.empty()); -} - -TEST_F(RRCollatorTest, throwFromCallback) { - // Adding an A RR - rr_callback_(origin_, rrclass_, RRType::A(), rrttl_, a_rdata1_); - - // Adding a TXT RR, which would trigger RRset callback, but in this test - // it throws. The added TXT RR will be effectively lost. - throw_from_callback_ = true; - EXPECT_THROW(rr_callback_(origin_, rrclass_, RRType::TXT(), rrttl_, - txt_rdata_), isc::Unexpected); - - // We'll only see the A RR. - throw_from_callback_ = false; - collator_.flush(); - rdatas_.push_back(a_rdata1_); - checkRRset(origin_, rrclass_, RRType::A(), rrttl_, rdatas_); -} - -TEST_F(RRCollatorTest, withMasterLoader) { - // Test a simple case with MasterLoader. There shouldn't be anything - // special, but that's the mainly intended usage of the collator, so we - // check it explicitly. - std::istringstream ss("example.com. 3600 IN A 192.0.2.1\n"); - MasterLoader loader(ss, origin_, rrclass_, - MasterLoaderCallbacks::getNullCallbacks(), - collator_.getCallback()); - loader.load(); - collator_.flush(); - rdatas_.push_back(a_rdata1_); - checkRRset(origin_, rrclass_, RRType::A(), rrttl_, rdatas_); -} - -} diff --git a/src/lib/dns/tests/rrparamregistry_unittest.cc b/src/lib/dns/tests/rrparamregistry_unittest.cc index cd14d14180..b928cc603f 100644 --- a/src/lib/dns/tests/rrparamregistry_unittest.cc +++ b/src/lib/dns/tests/rrparamregistry_unittest.cc @@ -1,9 +1,3 @@ -// Copyright (C) 2010-2020 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - #include <config.h> #include <string> diff --git a/src/lib/dns/tests/rrset_collection_unittest.cc b/src/lib/dns/tests/rrset_collection_unittest.cc index cc0dc20ee6..8b13789179 100644 --- a/src/lib/dns/tests/rrset_collection_unittest.cc +++ b/src/lib/dns/tests/rrset_collection_unittest.cc @@ -1,239 +1 @@ -// Copyright (C) 2012-2024 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. -#include <config.h> - -#include <dns/rrset_collection.h> -#include <dns/rrttl.h> -#include <dns/rdataclass.h> - -#include <gtest/gtest.h> - -#include <list> -#include <fstream> - -using namespace isc::dns; -using namespace isc::dns::rdata; -using namespace std; - -namespace { - -class RRsetCollectionTest : public ::testing::Test { -public: - RRsetCollectionTest() : - rrclass("IN"), - origin("example.org"), - collection(TEST_DATA_SRCDIR "/example.org", origin, rrclass) - {} - - const RRClass rrclass; - const Name origin; - RRsetCollection collection; -}; - -TEST_F(RRsetCollectionTest, istreamConstructor) { - std::ifstream fs(TEST_DATA_SRCDIR "/example.org"); - RRsetCollection collection2(fs, origin, rrclass); - - RRsetCollectionBase::Iterator iter = collection.begin(); - RRsetCollectionBase::Iterator iter2 = collection2.begin(); - while (iter != collection.end()) { - ASSERT_TRUE(iter2 != collection2.end()); - EXPECT_EQ((*iter).toText(), (*iter2).toText()); - ++iter; - ++iter2; - } - ASSERT_TRUE(iter2 == collection2.end()); -} - -template <typename T, typename TP> -void doFind(T& collection, const RRClass& rrclass) { - // Test the find() that returns ConstRRsetPtr - TP rrset = collection.find(Name("www.example.org"), rrclass, RRType::A()); - EXPECT_TRUE(rrset); - EXPECT_EQ(RRType::A(), rrset->getType()); - EXPECT_EQ(RRTTL(3600), rrset->getTTL()); - EXPECT_EQ(RRClass("IN"), rrset->getClass()); - EXPECT_EQ(Name("www.example.org"), rrset->getName()); - - // foo.example.org doesn't exist - rrset = collection.find(Name("foo.example.org"), rrclass, RRType::A()); - EXPECT_FALSE(rrset); - - // www.example.org exists, but not with MX - rrset = collection.find(Name("www.example.org"), rrclass, RRType::MX()); - EXPECT_FALSE(rrset); - - // www.example.org exists, with AAAA - rrset = collection.find(Name("www.example.org"), rrclass, RRType::AAAA()); - EXPECT_TRUE(rrset); - - // www.example.org with AAAA does not exist in RRClass::CH() - rrset = collection.find(Name("www.example.org"), RRClass::CH(), - RRType::AAAA()); - EXPECT_FALSE(rrset); -} - -TEST_F(RRsetCollectionTest, findConst) { - // Test the find() that returns ConstRRsetPtr - const RRsetCollection& ccln = collection; - doFind<const RRsetCollection, ConstRRsetPtr>(ccln, rrclass); -} - -TEST_F(RRsetCollectionTest, find) { - // Test the find() that returns RRsetPtr - doFind<RRsetCollection, RRsetPtr>(collection, rrclass); -} - -void -doAddAndRemove(RRsetCollection& collection, const RRClass& rrclass) { - // foo.example.org/A doesn't exist - RRsetPtr rrset_found = collection.find(Name("foo.example.org"), rrclass, - RRType::A()); - EXPECT_FALSE(rrset_found); - - // Add foo.example.org/A - RRsetPtr rrset(new BasicRRset(Name("foo.example.org"), rrclass, RRType::A(), - RRTTL(7200))); - rrset->addRdata(in::A("192.0.2.1")); - collection.addRRset(rrset); - - // foo.example.org/A should now exist - rrset_found = collection.find(Name("foo.example.org"), rrclass, - RRType::A()); - EXPECT_TRUE(rrset_found); - EXPECT_EQ(RRType::A(), rrset_found->getType()); - EXPECT_EQ(RRTTL(7200), rrset_found->getTTL()); - EXPECT_EQ(RRClass("IN"), rrset_found->getClass()); - EXPECT_EQ(Name("foo.example.org"), rrset_found->getName()); - - // The collection must not be empty. - EXPECT_TRUE(collection.end() != collection.begin()); - - // Adding a duplicate RRset must throw. - EXPECT_THROW({ - collection.addRRset(rrset); - }, isc::InvalidParameter); - - // Remove foo.example.org/A, which should pass - EXPECT_TRUE(collection.removeRRset(Name("foo.example.org"), - rrclass, RRType::A())); - // foo.example.org/A should not exist now - rrset_found = collection.find(Name("foo.example.org"), rrclass, - RRType::A()); - EXPECT_FALSE(rrset_found); - - // Removing foo.example.org/A should fail now - EXPECT_FALSE(collection.removeRRset(Name("foo.example.org"), - rrclass, RRType::A())); -} - -TEST_F(RRsetCollectionTest, addAndRemove) { - doAddAndRemove(collection, rrclass); -} - -TEST_F(RRsetCollectionTest, empty) { - RRsetCollection cln; - - // Here, cln is empty. - EXPECT_TRUE(cln.end() == cln.begin()); - - doAddAndRemove(cln, rrclass); - - // cln should be empty again here, after the add and remove - // operations. - EXPECT_TRUE(cln.end() == cln.begin()); -} - -TEST_F(RRsetCollectionTest, iteratorTest) { - // The collection must not be empty. - EXPECT_TRUE(collection.end() != collection.begin()); - - // Here, we just count the records and do some basic tests on them. - size_t count = 0; - for (auto const& it : collection) { - ++count; - const AbstractRRset& rrset = it; - EXPECT_EQ(rrclass, rrset.getClass()); - EXPECT_EQ(RRTTL(3600), rrset.getTTL()); - } - - // example.org master file has SOA, NS, A, AAAA - EXPECT_EQ(4, count); -} - -// This is a dummy class which is used in iteratorCompareDifferent test -// to compare iterators from different RRsetCollectionBase -// implementations. -class MyRRsetCollection : public RRsetCollectionBase { -public: - MyRRsetCollection() - {} - - virtual isc::dns::ConstRRsetPtr find(const isc::dns::Name&, - const isc::dns::RRClass&, - const isc::dns::RRType&) const { - return (ConstRRsetPtr()); - } - - typedef std::list<isc::dns::RRset> MyCollection; - -protected: - class MyIter : public RRsetCollectionBase::Iter { - public: - MyIter(MyCollection::iterator& iter) : - iter_(iter) - {} - - virtual const isc::dns::AbstractRRset& getValue() { - return (*iter_); - } - - virtual IterPtr getNext() { - MyCollection::iterator it = iter_; - ++it; - return (RRsetCollectionBase::IterPtr(new MyIter(it))); - } - - virtual bool equals(Iter& other) { - const MyIter* other_real = dynamic_cast<MyIter*>(&other); - if (other_real == NULL) { - return (false); - } - return (iter_ == other_real->iter_); - } - - private: - MyCollection::iterator iter_; - }; - - virtual RRsetCollectionBase::IterPtr getBeginning() { - MyCollection::iterator it = dummy_list_.begin(); - return (RRsetCollectionBase::IterPtr(new MyIter(it))); - } - - virtual RRsetCollectionBase::IterPtr getEnd() { - MyCollection::iterator it = dummy_list_.end(); - return (RRsetCollectionBase::IterPtr(new MyIter(it))); - } - -private: - MyCollection dummy_list_; -}; - -TEST_F(RRsetCollectionTest, iteratorCompareDifferent) { - // Create objects of two different RRsetCollectionBase - // implementations. - RRsetCollection cln1; - MyRRsetCollection cln2; - - // Comparing two iterators from different RRsetCollectionBase - // implementations must not throw. - EXPECT_TRUE(cln2.begin() != cln1.begin()); - EXPECT_TRUE(cln1.end() != cln2.end()); -} - -} // namespace diff --git a/src/lib/dns/tests/rrset_unittest.cc b/src/lib/dns/tests/rrset_unittest.cc index 04258126a5..8b13789179 100644 --- a/src/lib/dns/tests/rrset_unittest.cc +++ b/src/lib/dns/tests/rrset_unittest.cc @@ -1,442 +1 @@ -// Copyright (C) 2010-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. -#include <config.h> - -#include <util/buffer.h> -#include <dns/messagerenderer.h> -#include <dns/name.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> -#include <dns/rrclass.h> -#include <dns/rrtype.h> -#include <dns/rrttl.h> -#include <dns/rrset.h> - -#include <dns/tests/unittest_util.h> -#include <util/unittests/wiredata.h> - -#include <gtest/gtest.h> - -#include <stdexcept> -#include <sstream> - -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 { -protected: - RRsetTest() : buffer(0), - test_name("test.example.com"), - test_domain("example.com"), - test_nsname("ns.example.com"), - rrset_a(test_name, RRClass::IN(), RRType::A(), RRTTL(3600)), - rrset_a_empty(test_name, RRClass::IN(), RRType::A(), - RRTTL(3600)), - rrset_any_a_empty(test_name, RRClass::ANY(), RRType::A(), - RRTTL(3600)), - rrset_none_a_empty(test_name, RRClass::NONE(), RRType::A(), - RRTTL(3600)), - rrset_ns(test_domain, RRClass::IN(), RRType::NS(), - RRTTL(86400)), - rrset_ch_txt(test_domain, RRClass::CH(), RRType::TXT(), - RRTTL(0)) - { - rrset_a.addRdata(in::A("192.0.2.1")); - rrset_a.addRdata(in::A("192.0.2.2")); - } - - OutputBuffer buffer; - MessageRenderer renderer; - Name test_name; - Name test_domain; - Name test_nsname; - RRset rrset_a; - RRset rrset_a_empty; - RRset rrset_any_a_empty; - RRset rrset_none_a_empty; - RRset rrset_ns; - RRset rrset_ch_txt; - std::vector<unsigned char> wiredata; - - // max number of Rdata objects added to a test RRset object. - // this is an arbitrary chosen limit, but should be sufficiently large - // in practice and reasonable even as an extreme test case. - static const int MAX_RDATA_COUNT = 100; -}; - -TEST_F(RRsetTest, getRdataCount) { - for (int i = 0; i < MAX_RDATA_COUNT; ++i) { - EXPECT_EQ(i, rrset_a_empty.getRdataCount()); - rrset_a_empty.addRdata(in::A("192.0.2.1")); - } -} - -TEST_F(RRsetTest, getName) { - EXPECT_EQ(test_name, rrset_a.getName()); - EXPECT_EQ(test_domain, rrset_ns.getName()); -} - -TEST_F(RRsetTest, getClass) { - EXPECT_EQ(RRClass("IN"), rrset_a.getClass()); - EXPECT_EQ(RRClass("CH"), rrset_ch_txt.getClass()); -} - -TEST_F(RRsetTest, getType) { - EXPECT_EQ(RRType("A"), rrset_a.getType()); - EXPECT_EQ(RRType("NS"), rrset_ns.getType()); - EXPECT_EQ(RRType("TXT"), rrset_ch_txt.getType()); -} - -TEST_F(RRsetTest, getTTL) { - EXPECT_EQ(RRTTL(3600), rrset_a.getTTL()); - EXPECT_EQ(RRTTL(86400), rrset_ns.getTTL()); - EXPECT_EQ(RRTTL(0), rrset_ch_txt.getTTL()); -} - -TEST_F(RRsetTest, setTTL) { - rrset_a.setTTL(RRTTL(86400)); - EXPECT_EQ(RRTTL(86400), rrset_a.getTTL()); - rrset_a.setTTL(RRTTL(0)); - EXPECT_EQ(RRTTL(0), rrset_a.getTTL()); -} - -TEST_F(RRsetTest, isSameKind) { - RRset rrset_w(test_name, RRClass::IN(), RRType::A(), RRTTL(3600)); - RRset rrset_x(test_name, RRClass::IN(), RRType::A(), RRTTL(3600)); - RRset rrset_y(test_name, RRClass::IN(), RRType::NS(), RRTTL(3600)); - RRset rrset_z(test_name, RRClass::CH(), RRType::A(), RRTTL(3600)); - RRset rrset_p(test_nsname, RRClass::IN(), RRType::A(), RRTTL(3600)); - - EXPECT_TRUE(rrset_w.isSameKind(rrset_w)); - EXPECT_TRUE(rrset_w.isSameKind(rrset_x)); - EXPECT_FALSE(rrset_w.isSameKind(rrset_y)); - EXPECT_FALSE(rrset_w.isSameKind(rrset_z)); - EXPECT_FALSE(rrset_w.isSameKind(rrset_p)); -} - -void -addRdataTestCommon(const RRset& rrset) { - ASSERT_EQ(2, rrset.getRdataCount()); - - RdataIteratorPtr it = rrset.getRdataIterator(); // cursor is set to the 1st - EXPECT_FALSE(it->isLast()); - EXPECT_EQ(0, it->getCurrent().compare(in::A("192.0.2.1"))); - it->next(); - EXPECT_FALSE(it->isLast()); - EXPECT_EQ(0, it->getCurrent().compare(in::A("192.0.2.2"))); - it->next(); - EXPECT_TRUE(it->isLast()); -} - -TEST_F(RRsetTest, addRdata) { - addRdataTestCommon(rrset_a); - - // Reference version of addRdata() doesn't allow to add a different - // type of Rdata. - EXPECT_THROW(rrset_a.addRdata(generic::NS(test_nsname)), std::bad_cast); -} - -TEST_F(RRsetTest, addRdataPtr) { - rrset_a_empty.addRdata(createRdata(rrset_a_empty.getType(), - rrset_a_empty.getClass(), - "192.0.2.1")); - rrset_a_empty.addRdata(createRdata(rrset_a_empty.getType(), - rrset_a_empty.getClass(), - "192.0.2.2")); - addRdataTestCommon(rrset_a_empty); -} - -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(1, rrset_a_empty.getRdataCount()); - - // Class mismatch - rrset_ch_txt.addRdata(createRdata(RRType::TXT(), RRClass::IN(), - "Test String")); - EXPECT_EQ(1, rrset_ch_txt.getRdataCount()); -} - -TEST_F(RRsetTest, addRdataString) { - rrset_a_empty.addRdata("192.0.2.1"); - rrset_a_empty.addRdata("192.0.2.2"); - - addRdataTestCommon(rrset_a_empty); - - // String version of addRdata() will throw for bad RDATA for - // RRType::A(). - EXPECT_THROW(rrset_a_empty.addRdata("ns.example.com."), InvalidRdataText); - addRdataTestCommon(rrset_a_empty); -} - -TEST_F(RRsetTest, iterator) { - // Iterator for an empty RRset. - RdataIteratorPtr it = rrset_a_empty.getRdataIterator(); - EXPECT_TRUE(it->isLast()); - - // Normal case (already tested, but do it again just in case) - rrset_a_empty.addRdata(in::A("192.0.2.1")); - rrset_a_empty.addRdata(in::A("192.0.2.2")); - addRdataTestCommon(rrset_a_empty); - - // Rewind test: should be repeat the iteration by calling first(). - for (int i = 0; i < 2; ++i) { - it = rrset_a_empty.getRdataIterator(); - it->first(); - EXPECT_FALSE(it->isLast()); - it->next(); - EXPECT_FALSE(it->isLast()); - it->next(); - EXPECT_TRUE(it->isLast()); - } -} - -TEST_F(RRsetTest, toText) { - EXPECT_EQ("test.example.com. 3600 IN A 192.0.2.1\n" - "test.example.com. 3600 IN A 192.0.2.2\n", - rrset_a.toText()); - - // toText() cannot be performed for an empty RRset - EXPECT_THROW(rrset_a_empty.toText(), EmptyRRset); - - // Unless it is type ANY or NONE - EXPECT_EQ("test.example.com. 3600 ANY A\n", - rrset_any_a_empty.toText()); - EXPECT_EQ("test.example.com. 3600 NONE A\n", - rrset_none_a_empty.toText()); -} - -TEST_F(RRsetTest, getLength) { - // Empty RRset should throw - EXPECT_THROW(rrset_a_empty.getLength(), EmptyRRset); - - // Unless it is type ANY or NONE: - // test.example.com = 1 + 4 + 1 + 7 + 1 + 3 + 1 = 18 octets - // TYPE field = 2 octets - // CLASS field = 2 octets - // TTL field = 4 octets - // RDLENGTH field = 2 octets - // Total = 18 + 2 + 2 + 4 + 2 = 28 octets - EXPECT_EQ(28, rrset_any_a_empty.getLength()); - EXPECT_EQ(28, rrset_none_a_empty.getLength()); - - // RRset with single RDATA - // 28 (above) + 4 octets (A RDATA) = 32 octets - rrset_a_empty.addRdata(in::A("192.0.2.1")); - EXPECT_EQ(32, rrset_a_empty.getLength()); - - // 2 A RRs - rrset_a_empty.addRdata(in::A("192.0.2.2")); - EXPECT_EQ(32 + 32, rrset_a_empty.getLength()); -} - -TEST_F(RRsetTest, toWireBuffer) { - rrset_a.toWire(buffer); - - UnitTestUtil::readWireData("rrset_toWire1", wiredata); - matchWireData(&wiredata[0], wiredata.size(), - buffer.getData(), buffer.getLength()); - - // toWire() cannot be performed for an empty RRset except when - // class=ANY or class=NONE. - buffer.clear(); - EXPECT_THROW(rrset_a_empty.toWire(buffer), EmptyRRset); - - // When class=ANY or class=NONE, toWire() can also be performed for - // an empty RRset. - buffer.clear(); - rrset_any_a_empty.toWire(buffer); - wiredata.clear(); - UnitTestUtil::readWireData("rrset_toWire3", wiredata); - matchWireData(&wiredata[0], wiredata.size(), - buffer.getData(), buffer.getLength()); - - buffer.clear(); - rrset_none_a_empty.toWire(buffer); - wiredata.clear(); - UnitTestUtil::readWireData("rrset_toWire4", wiredata); - matchWireData(&wiredata[0], wiredata.size(), - buffer.getData(), buffer.getLength()); -} - -TEST_F(RRsetTest, toWireRenderer) { - rrset_ns.addRdata(generic::NS(test_nsname)); - - rrset_a.toWire(renderer); - rrset_ns.toWire(renderer); - - UnitTestUtil::readWireData("rrset_toWire2", wiredata); - matchWireData(&wiredata[0], wiredata.size(), - renderer.getData(), renderer.getLength()); - - // toWire() cannot be performed for an empty RRset except when - // class=ANY or class=NONE. - renderer.clear(); - EXPECT_THROW(rrset_a_empty.toWire(renderer), EmptyRRset); - - // When class=ANY or class=NONE, toWire() can also be performed for - // an empty RRset. - renderer.clear(); - rrset_any_a_empty.toWire(renderer); - wiredata.clear(); - UnitTestUtil::readWireData("rrset_toWire3", wiredata); - matchWireData(&wiredata[0], wiredata.size(), - renderer.getData(), renderer.getLength()); - - renderer.clear(); - rrset_none_a_empty.toWire(renderer); - wiredata.clear(); - UnitTestUtil::readWireData("rrset_toWire4", wiredata); - matchWireData(&wiredata[0], wiredata.size(), - renderer.getData(), renderer.getLength()); -} - -// test operator<<. We simply confirm it appends the result of toText(). -TEST_F(RRsetTest, LeftShiftOperator) { - ostringstream oss; - oss << rrset_a; - EXPECT_EQ(rrset_a.toText(), oss.str()); -} - -class RRsetRRSIGTest : public ::testing::Test { -protected: - RRsetRRSIGTest() : test_name("test.example.com") - { - rrset_a = RRsetPtr(new RRset(test_name, RRClass::IN(), - RRType::A(), RRTTL(3600))); - rrset_a->addRdata(in::A("192.0.2.1")); - rrset_a->addRdata(in::A("192.0.2.2")); - - rrset_aaaa = RRsetPtr(new RRset(test_name, RRClass::IN(), - RRType::AAAA(), RRTTL(3600))); - rrset_aaaa->addRdata(in::AAAA("2001:db8::1234")); - - rrset_rrsig = RRsetPtr(new RRset(test_name, RRClass::IN(), - RRType::RRSIG(), RRTTL(3600))); - rrset_rrsig->addRdata(generic::RRSIG("AAAA 5 3 7200 20100322084538 " - "20100220084538 1 example.com. " - "FAKEFAKEFAKEFAKE")); - rrset_aaaa->addRRsig(rrset_rrsig); - } - - const Name test_name; - RRsetPtr rrset_a; // A RRset with two RDATAs - RRsetPtr rrset_aaaa; // AAAA RRset with one RDATA with RRSIG - RRsetPtr rrset_rrsig; // RRSIG for the AAAA RRset -}; - -TEST_F(RRsetRRSIGTest, getRRsig) { - RRsetPtr sp = rrset_a->getRRsig(); - EXPECT_EQ(static_cast<void*>(NULL), sp.get()); - - sp = rrset_aaaa->getRRsig(); - EXPECT_NE(static_cast<void*>(NULL), sp.get()); -} - -TEST_F(RRsetRRSIGTest, addRRsig) { - RRsetPtr sp = rrset_a->getRRsig(); - EXPECT_EQ(static_cast<void*>(NULL), sp.get()); - - rrset_rrsig = RRsetPtr(new RRset(test_name, RRClass::IN(), - RRType::RRSIG(), RRTTL(3600))); - // one signature algorithm (5 = RSA/SHA-1) - rrset_rrsig->addRdata(generic::RRSIG("A 5 3 3600 " - "20000101000000 20000201000000 " - "12345 example.com. FAKEFAKEFAKE")); - // another signature algorithm (3 = DSA/SHA-1) - rrset_rrsig->addRdata(generic::RRSIG("A 3 3 3600 " - "20000101000000 20000201000000 " - "12345 example.com. FAKEFAKEFAKE")); - rrset_a->addRRsig(rrset_rrsig); - - sp = rrset_a->getRRsig(); - EXPECT_NE(static_cast<void*>(NULL), sp.get()); - EXPECT_EQ(2, sp->getRdataCount()); - - // add to existing RRSIG - rrset_rrsig = RRsetPtr(new RRset(test_name, RRClass::IN(), - RRType::RRSIG(), RRTTL(3600))); - // another signature algorithm (4 = ECC) - rrset_rrsig->addRdata(generic::RRSIG("A 4 3 3600 " - "20000101000000 20000201000000 " - "12345 example.com. FAKEFAKEFAKE")); - rrset_a->addRRsig(rrset_rrsig); - EXPECT_EQ(3, sp->getRdataCount()); -} - -TEST_F(RRsetRRSIGTest, getRRsigDataCount) { - EXPECT_EQ(1, rrset_aaaa->getRRsigDataCount()); - EXPECT_EQ(0, rrset_a->getRRsigDataCount()); - - rrset_rrsig = RRsetPtr(new RRset(test_name, RRClass::IN(), - RRType::RRSIG(), RRTTL(3600))); - // one signature algorithm (5 = RSA/SHA-1) - rrset_rrsig->addRdata(generic::RRSIG("A 5 3 3600 " - "20000101000000 20000201000000 " - "12345 example.com. FAKEFAKEFAKE")); - // another signature algorithm (3 = DSA/SHA-1) - rrset_rrsig->addRdata(generic::RRSIG("A 3 3 3600 " - "20000101000000 20000201000000 " - "12345 example.com. FAKEFAKEFAKE")); - rrset_a->addRRsig(rrset_rrsig); - EXPECT_EQ(2, rrset_a->getRRsigDataCount()); - - rrset_a->removeRRsig(); - EXPECT_EQ(0, rrset_a->getRRsigDataCount()); -} - -TEST_F(RRsetRRSIGTest, toText) { - // toText() should also return the associated RRSIG. - EXPECT_EQ("test.example.com. 3600 IN AAAA 2001:db8::1234\n" - "test.example.com. 3600 IN RRSIG AAAA 5 3 7200 " - "20100322084538 20100220084538 1 example.com. FAKEFAKEFAKEFAKE\n", - rrset_aaaa->toText()); -} - -TEST_F(RRsetRRSIGTest, getLength) { - // A RR - // test.example.com = 1 + 4 + 1 + 7 + 1 + 3 + 1 = 18 octets - // TYPE field = 2 octets - // CLASS field = 2 octets - // TTL field = 4 octets - // RDLENGTH field = 2 octets - // A RDATA = 4 octets - // Total = 18 + 2 + 2 + 4 + 2 + 4 = 32 octets - - // 2 A RRs - EXPECT_EQ(32 + 32, rrset_a->getLength()); - - // RRSIG - // test.example.com = 1 + 4 + 1 + 7 + 1 + 3 + 1 = 18 octets - // TYPE field = 2 octets - // CLASS field = 2 octets - // TTL field = 4 octets - // RDLENGTH field = 2 octets - // RRSIG RDATA = 40 octets - // Total = 18 + 2 + 2 + 4 + 2 + 40 = 68 octets - RRsetPtr my_rrsig(new RRset(test_name, RRClass::IN(), - RRType::RRSIG(), RRTTL(3600))); - my_rrsig->addRdata(generic::RRSIG("A 4 3 3600 " - "20000101000000 20000201000000 " - "12345 example.com. FAKEFAKEFAKE")); - EXPECT_EQ(68, my_rrsig->getLength()); - - // RRset with attached RRSIG - rrset_a->addRRsig(my_rrsig); - - EXPECT_EQ(32 + 32 + 68, rrset_a->getLength()); -} -} diff --git a/src/lib/dns/tests/rrttl_unittest.cc b/src/lib/dns/tests/rrttl_unittest.cc index 3cada14cbc..8b13789179 100644 --- a/src/lib/dns/tests/rrttl_unittest.cc +++ b/src/lib/dns/tests/rrttl_unittest.cc @@ -1,279 +1 @@ -// Copyright (C) 2010-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. -#include <config.h> - -#include <gtest/gtest.h> - -#include <util/buffer.h> -#include <dns/messagerenderer.h> -#include <dns/rrttl.h> - -#include <dns/tests/unittest_util.h> -#include <util/unittests/wiredata.h> - -#include <boost/scoped_ptr.hpp> - -using namespace std; -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 { -protected: - RRTTLTest() : obuffer(0) {} - - OutputBuffer obuffer; - MessageRenderer renderer; - - static RRTTL rrttlFactoryFromWire(const char* datafile); - static const RRTTL ttl_0, ttl_1h, ttl_1d, ttl_32bit, ttl_max; - static const RRTTL ttl_small, ttl_large; - static const uint8_t wiredata[20]; -}; - -const RRTTL RRTTLTest::ttl_0(0); -const RRTTL RRTTLTest::ttl_1h(3600); -const RRTTL RRTTLTest::ttl_1d(86400); -const RRTTL RRTTLTest::ttl_32bit(0x12345678); -const RRTTL RRTTLTest::ttl_max(0xffffffff); - -const RRTTL RRTTLTest::ttl_small(1); -const RRTTL RRTTLTest::ttl_large(0x80000001); -// This is wire-format data for the above sample RRTTLs rendered in the -// appearing order. -const uint8_t RRTTLTest::wiredata[20] = { 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x0e, 0x10, - 0x00, 0x01, 0x51, 0x80, - 0x12, 0x34, 0x56, 0x78, - 0xff, 0xff, 0xff, 0xff }; - -RRTTL -RRTTLTest::rrttlFactoryFromWire(const char* datafile) { - std::vector<unsigned char> data; - UnitTestUtil::readWireData(datafile, data); - - InputBuffer buffer(&data[0], data.size()); - - return (RRTTL(buffer)); -} - -TEST_F(RRTTLTest, getValue) { - EXPECT_EQ(0, ttl_0.getValue()); - EXPECT_EQ(3600, ttl_1h.getValue()); - EXPECT_EQ(86400, ttl_1d.getValue()); - EXPECT_EQ(0x12345678, ttl_32bit.getValue()); - EXPECT_EQ(0xffffffff, ttl_max.getValue()); -} - -TEST_F(RRTTLTest, copyConstruct) { - const RRTTL ttl1(3600); - const RRTTL ttl2(ttl1); - EXPECT_EQ(ttl1.getValue(), ttl2.getValue()); -} - -TEST_F(RRTTLTest, fromText) { - // Border cases - EXPECT_EQ(0, RRTTL("0").getValue()); - EXPECT_EQ(4294967295U, RRTTL("4294967295").getValue()); - - // Invalid cases - EXPECT_THROW(RRTTL("0xdeadbeef"), InvalidRRTTL); // must be decimal - EXPECT_THROW(RRTTL("-1"), InvalidRRTTL); // must be positive - EXPECT_THROW(RRTTL("1.1"), InvalidRRTTL); // must be integer - EXPECT_THROW(RRTTL("4294967296"), InvalidRRTTL); // must be 32-bit -} - -TEST_F(RRTTLTest, createFromText) { - // It returns an actual RRTTL iff the given text is recognized as a - // valid RR TTL. - scoped_ptr<RRTTL> good_ttl(RRTTL::createFromText("3600")); - EXPECT_TRUE(good_ttl); - EXPECT_EQ(RRTTL(3600), *good_ttl); - - scoped_ptr<RRTTL> bad_ttl(RRTTL::createFromText("bad")); - EXPECT_FALSE(bad_ttl); -} - -void -checkUnit(unsigned multiply, char suffix) { - SCOPED_TRACE(string("Unit check with suffix ") + suffix); - const uint32_t value = 10 * multiply; - const string num = "10"; - // Check both lower and upper version of the suffix - EXPECT_EQ(value, - RRTTL(num + static_cast<char>(tolower(suffix))).getValue()); - EXPECT_EQ(value, - RRTTL(num + static_cast<char>(toupper(suffix))).getValue()); -} - -// Check parsing the unit form (1D, etc) -TEST_F(RRTTLTest, fromTextUnit) { - // Check each of the units separately - checkUnit(1, 'S'); - checkUnit(60, 'M'); - checkUnit(60 * 60, 'H'); - checkUnit(24 * 60 * 60, 'D'); - checkUnit(7 * 24 * 60 * 60, 'W'); - - // Some border cases (with units) - EXPECT_EQ(4294967295U, RRTTL("4294967295S").getValue()); - EXPECT_EQ(0, RRTTL("0W0D0H0M0S").getValue()); - EXPECT_EQ(4294967295U, RRTTL("1193046H1695S").getValue()); - // Leading zeroes are accepted - EXPECT_EQ(4294967295U, RRTTL("0000000000000004294967295S").getValue()); - - // Now some compound ones. We allow any order (it would be much work to - // check the order anyway). - EXPECT_EQ(60 * 60 + 3, RRTTL("1H3S").getValue()); - - // Awkward, but allowed case - the same unit used twice. - EXPECT_EQ(20 * 3600, RRTTL("12H8H").getValue()); - - // Negative number in part of the expression, but the total is positive. - // Rejected. - EXPECT_THROW(RRTTL("-1S1H"), InvalidRRTTL); - - // Some things out of range in the ttl, but it wraps to number in range - // in int64_t. Should still not get fooled and reject it. - - // First part out of range - EXPECT_THROW(RRTTL("9223372036854775807S9223372036854775807S2S"), - InvalidRRTTL); - // Second part out of range, but it immediately wraps (2S+2^64-2S) - EXPECT_THROW(RRTTL("2S18446744073709551614S"), InvalidRRTTL); - // The whole thing wraps right away (2^64S) - EXPECT_THROW(RRTTL("18446744073709551616S"), InvalidRRTTL); - // Second part out of range, and will become negative with the unit, - EXPECT_THROW(RRTTL("256S307445734561825856M"), InvalidRRTTL); - - // Missing before unit. - EXPECT_THROW(RRTTL("W5H"), InvalidRRTTL); - EXPECT_THROW(RRTTL("5hW"), InvalidRRTTL); - - // Empty string is not allowed - EXPECT_THROW(RRTTL(""), InvalidRRTTL); - // Missing the last unit is not allowed - EXPECT_THROW(RRTTL("3D5"), InvalidRRTTL); - - // There are some wrong units - EXPECT_THROW(RRTTL("13X"), InvalidRRTTL); - EXPECT_THROW(RRTTL("3D5F"), InvalidRRTTL); -} - -TEST_F(RRTTLTest, fromWire) { - EXPECT_EQ(0x12345678, - rrttlFactoryFromWire("rrcode32_fromWire1").getValue()); - EXPECT_THROW(rrttlFactoryFromWire("rrcode32_fromWire2"), - IncompleteRRTTL); -} - -TEST_F(RRTTLTest, toText) { - EXPECT_EQ("0", ttl_0.toText()); - EXPECT_EQ("3600", ttl_1h.toText()); - EXPECT_EQ("86400", ttl_1d.toText()); - EXPECT_EQ("305419896", ttl_32bit.toText()); - EXPECT_EQ("4294967295", ttl_max.toText()); -} - -TEST_F(RRTTLTest, toWireBuffer) { - ttl_0.toWire(obuffer); - ttl_1h.toWire(obuffer); - ttl_1d.toWire(obuffer); - ttl_32bit.toWire(obuffer); - ttl_max.toWire(obuffer); - - matchWireData(wiredata, sizeof(wiredata), - obuffer.getData(), obuffer.getLength()); -} - -TEST_F(RRTTLTest, toWireRenderer) { - ttl_0.toWire(renderer); - ttl_1h.toWire(renderer); - ttl_1d.toWire(renderer); - ttl_32bit.toWire(renderer); - ttl_max.toWire(renderer); - - matchWireData(wiredata, sizeof(wiredata), - renderer.getData(), renderer.getLength()); -} - -TEST_F(RRTTLTest, equal) { - EXPECT_TRUE(RRTTL("3600") == ttl_1h); - EXPECT_TRUE(RRTTL("86400").equals(ttl_1d)); - - EXPECT_TRUE(ttl_1d != ttl_1h); - EXPECT_TRUE(ttl_1d.nequals(ttl_max)); -} - -// -// The following set of tests confirm the result of <=, <, >=, > -// The test logic is simple, and all tests are just straightforward variations -// of the first one. -// -TEST_F(RRTTLTest, leq) { - // small <= large is true - EXPECT_TRUE(ttl_small.leq(ttl_large)); - EXPECT_TRUE(ttl_small <= ttl_large); - - // small <= small is true - EXPECT_TRUE(ttl_small.leq(ttl_small)); - EXPECT_LE(ttl_small, ttl_small); - - // large <= small is false - EXPECT_FALSE(ttl_large.leq(ttl_small)); - EXPECT_FALSE(ttl_large <= ttl_small); -} - -TEST_F(RRTTLTest, geq) { - EXPECT_TRUE(ttl_large.geq(ttl_small)); - EXPECT_TRUE(ttl_large >= ttl_small); - - EXPECT_TRUE(ttl_large.geq(ttl_large)); - EXPECT_GE(ttl_large, ttl_large); - - EXPECT_FALSE(ttl_small.geq(ttl_large)); - EXPECT_FALSE(ttl_small >= ttl_large); -} - -TEST_F(RRTTLTest, lthan) { - EXPECT_TRUE(ttl_small.lthan(ttl_large)); - EXPECT_TRUE(ttl_small < ttl_large); - - EXPECT_FALSE(ttl_small.lthan(ttl_small)); - // cppcheck-suppress duplicateExpression - EXPECT_FALSE(ttl_small < ttl_small); - - EXPECT_FALSE(ttl_large.lthan(ttl_small)); - EXPECT_FALSE(ttl_large < ttl_small); -} - -TEST_F(RRTTLTest, gthan) { - EXPECT_TRUE(ttl_large.gthan(ttl_small)); - EXPECT_TRUE(ttl_large > ttl_small); - - EXPECT_FALSE(ttl_large.gthan(ttl_large)); - // cppcheck-suppress duplicateExpression - EXPECT_FALSE(ttl_large > ttl_large); - - EXPECT_FALSE(ttl_small.gthan(ttl_large)); - EXPECT_FALSE(ttl_small > ttl_large); -} - -TEST_F(RRTTLTest, maxTTL) { - EXPECT_EQ((1u << 31) - 1, RRTTL::MAX_TTL().getValue()); -} - -// test operator<<. We simply confirm it appends the result of toText(). -TEST_F(RRTTLTest, LeftShiftOperator) { - ostringstream oss; - oss << ttl_1h; - EXPECT_EQ(ttl_1h.toText(), oss.str()); -} -} diff --git a/src/lib/dns/tests/rrtype_unittest.cc b/src/lib/dns/tests/rrtype_unittest.cc index a2f8ba556d..8b13789179 100644 --- a/src/lib/dns/tests/rrtype_unittest.cc +++ b/src/lib/dns/tests/rrtype_unittest.cc @@ -1,195 +1 @@ -// Copyright (C) 2010-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. -#include <config.h> - -#include <gtest/gtest.h> - -#include <util/buffer.h> -#include <dns/messagerenderer.h> -#include <dns/rrtype.h> - -#include <dns/tests/unittest_util.h> -#include <util/unittests/wiredata.h> - -using namespace std; -using namespace isc; -using namespace isc::dns; -using namespace isc::util; -using isc::util::unittests::matchWireData; - -namespace { -class RRTypeTest : public ::testing::Test { -protected: - RRTypeTest() : obuffer(0) {} - - OutputBuffer obuffer; - MessageRenderer renderer; - - static RRType rrtypeFactoryFromWire(const char* datafile); - static const RRType rrtype_1, rrtype_0x80, rrtype_0x800, rrtype_0x8000, - rrtype_max; - static const uint8_t wiredata[]; -}; - -const RRType RRTypeTest::rrtype_1(1); -const RRType RRTypeTest::rrtype_0x80(0x80); -const RRType RRTypeTest::rrtype_0x800(0x800); -const RRType RRTypeTest::rrtype_0x8000(0x8000); -const RRType RRTypeTest::rrtype_max(0xffff); -// This is wire-format data for the above sample RRTypes rendered in the -// appearing order. -const uint8_t RRTypeTest::wiredata[] = { 0x00, 0x01, 0x00, 0x80, 0x08, - 0x00, 0x80, 0x00, 0xff, 0xff }; - -RRType -RRTypeTest::rrtypeFactoryFromWire(const char* datafile) { - std::vector<unsigned char> data; - UnitTestUtil::readWireData(datafile, data); - - InputBuffer buffer(&data[0], data.size()); - - return (RRType(buffer)); -} - -TEST_F(RRTypeTest, fromText) { - EXPECT_EQ("A", RRType("A").toText()); - EXPECT_EQ("NS", RRType("NS").toText()); - - EXPECT_EQ("TYPE65535", RRType("TYPE65535").toText()); - - // something unusual, but existing implementations accept this form, - // so do we. - EXPECT_EQ(53, RRType("TYPE00053").getCode()); - // again, unusual, and the majority of other implementations reject it. - // In any case, there should be no reasonable reason to accept such a - // ridiculously long input. - EXPECT_THROW(RRType("TYPE000053"), InvalidRRType); - - // bogus TYPEnnn representations: should trigger an exception - EXPECT_THROW(RRType("TYPE"), InvalidRRType); - EXPECT_THROW(RRType("TYPE-1"), InvalidRRType); - EXPECT_THROW(RRType("TYPExxx"), InvalidRRType); - EXPECT_THROW(RRType("TYPE65536"), InvalidRRType); - EXPECT_THROW(RRType("TYPE6500x"), InvalidRRType); - EXPECT_THROW(RRType("TYPE65000 "), InvalidRRType); -} - -TEST_F(RRTypeTest, fromWire) { - EXPECT_EQ(0x1234, - rrtypeFactoryFromWire("rrcode16_fromWire1").getCode()); - EXPECT_THROW(rrtypeFactoryFromWire("rrcode16_fromWire2"), IncompleteRRType); -} - -// from string, lower case -TEST_F(RRTypeTest, caseConstruct) { - EXPECT_EQ("A", RRType("a").toText()); - EXPECT_EQ("NS", RRType("ns").toText()); - EXPECT_EQ("TYPE65535", RRType("type65535").toText()); -} - -TEST_F(RRTypeTest, toText) { - EXPECT_EQ("A", RRType(1).toText()); - EXPECT_EQ("TYPE65000", RRType(65000).toText()); -} - -TEST_F(RRTypeTest, toWireBuffer) { - rrtype_1.toWire(obuffer); - rrtype_0x80.toWire(obuffer); - rrtype_0x800.toWire(obuffer); - rrtype_0x8000.toWire(obuffer); - rrtype_max.toWire(obuffer); - - matchWireData(wiredata, sizeof(wiredata), - obuffer.getData(), obuffer.getLength()); -} - -TEST_F(RRTypeTest, toWireRenderer) { - rrtype_1.toWire(renderer); - rrtype_0x80.toWire(renderer); - rrtype_0x800.toWire(renderer); - rrtype_0x8000.toWire(renderer); - rrtype_max.toWire(renderer); - - matchWireData(wiredata, sizeof(wiredata), - renderer.getData(), renderer.getLength()); -} - -TEST_F(RRTypeTest, wellKnownTypes) { - EXPECT_EQ(1, RRType::A().getCode()); - EXPECT_EQ("A", RRType::A().toText()); -} - -TEST_F(RRTypeTest, compare) { - EXPECT_TRUE(RRType(1) == RRType("A")); - EXPECT_TRUE(RRType(1).equals(RRType("A"))); - EXPECT_TRUE(RRType(0) != RRType("A")); - EXPECT_TRUE(RRType(0).nequals(RRType("A"))); - - EXPECT_TRUE(RRType("A") < RRType("NS")); - EXPECT_TRUE(RRType(100) < RRType(65535)); -} - -// test operator<<. We simply confirm it appends the result of toText(). -TEST_F(RRTypeTest, LeftShiftOperator) { - ostringstream oss; - oss << RRType::A(); - EXPECT_EQ(RRType::A().toText(), oss.str()); -} - -// Below, we'll check definitions for all well-known RR types; whether they -// are defined and have the correct parameter values. Test data are generated -// from the list available at: -// http://www.iana.org/assignments/dns-parameters/dns-parameters.xml -struct TypeParam { - const char* const txt; // "A", "AAAA", "NS", etc - const uint16_t code; // 1, 28, 2, etc - const RRType& (*obj)(); // RRType::A(), etc -} known_types[] = { - {"A", 1, RRType::A}, {"NS", 2, RRType::NS}, {"MD", 3, RRType::MD}, - {"MF", 4, RRType::MF}, {"CNAME", 5, RRType::CNAME}, - {"SOA", 6, RRType::SOA}, {"MB", 7, RRType::MB}, {"MG", 8, RRType::MG}, - {"MR", 9, RRType::MR}, {"NULL", 10, RRType::Null}, - {"WKS", 11, RRType::WKS}, {"PTR", 12, RRType::PTR}, - {"HINFO", 13, RRType::HINFO}, {"MINFO", 14, RRType::MINFO}, - {"MX", 15, RRType::MX}, {"TXT", 16, RRType::TXT}, {"RP", 17, RRType::RP}, - {"AFSDB", 18, RRType::AFSDB}, {"X25", 19, RRType::X25}, - {"ISDN", 20, RRType::ISDN}, {"RT", 21, RRType::RT}, - {"NSAP", 22, RRType::NSAP}, {"NSAP-PTR", 23, RRType::NSAP_PTR}, - {"SIG", 24, RRType::SIG}, {"KEY", 25, RRType::KEY}, - {"PX", 26, RRType::PX}, {"GPOS", 27, RRType::GPOS}, - {"AAAA", 28, RRType::AAAA}, {"LOC", 29, RRType::LOC}, - {"NXT", 30, RRType::NXT}, {"SRV", 33, RRType::SRV}, - {"NAPTR", 35, RRType::NAPTR}, {"KX", 36, RRType::KX}, - {"CERT", 37, RRType::CERT}, {"A6", 38, RRType::A6}, - {"DNAME", 39, RRType::DNAME}, {"OPT", 41, RRType::OPT}, - {"APL", 42, RRType::APL}, {"DS", 43, RRType::DS}, - {"SSHFP", 44, RRType::SSHFP}, {"IPSECKEY", 45, RRType::IPSECKEY}, - {"RRSIG", 46, RRType::RRSIG}, {"NSEC", 47, RRType::NSEC}, - {"DNSKEY", 48, RRType::DNSKEY}, {"DHCID", 49, RRType::DHCID}, - {"NSEC3", 50, RRType::NSEC3}, {"NSEC3PARAM", 51, RRType::NSEC3PARAM}, - {"TLSA", 52, RRType::TLSA}, {"HIP", 55, RRType::HIP}, - {"SPF", 99, RRType::SPF}, {"UNSPEC", 103, RRType::UNSPEC}, - {"NID", 104, RRType::NID}, {"L32", 105, RRType::L32}, - {"L64", 106, RRType::L64}, {"LP", 107, RRType::LP}, - {"TKEY", 249, RRType::TKEY}, {"TSIG", 250, RRType::TSIG}, - {"IXFR", 251, RRType::IXFR}, {"AXFR", 252, RRType::AXFR}, - {"MAILB", 253, RRType::MAILB}, {"MAILA", 254, RRType::MAILA}, - {"ANY", 255, RRType::ANY}, {"URI", 256, RRType::URI}, - {"CAA", 257, RRType::CAA}, {"DLV", 32769, RRType::DLV}, - {NULL, 0, NULL} -}; - -TEST(RRTypeConstTest, wellKnowns) { - for (int i = 0; known_types[i].txt; ++i) { - SCOPED_TRACE("Checking well known RRType: " + - string(known_types[i].txt)); - EXPECT_EQ(known_types[i].code, RRType(known_types[i].txt).getCode()); - EXPECT_EQ(known_types[i].code, - (*known_types[i].obj)().getCode()); - } -} -} diff --git a/src/lib/dns/tests/serial_unittest.cc b/src/lib/dns/tests/serial_unittest.cc index 305b0b0d79..8b13789179 100644 --- a/src/lib/dns/tests/serial_unittest.cc +++ b/src/lib/dns/tests/serial_unittest.cc @@ -1,173 +1 @@ -// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. -#include <config.h> - -#include <gtest/gtest.h> - -#include <dns/serial.h> - -using namespace isc::dns; - -class SerialTest : public ::testing::Test { -public: - SerialTest() : one(1), one_2(1), two(2), - date_zero(1980120100), date_one(1980120101), - min(0), max(4294967295u), - number_low(12345), - number_medium(2000000000), - number_high(4000000000u) - {} - Serial one, one_2, two, date_zero, date_one, min, max, number_low, number_medium, number_high; -}; - -// -// Basic tests -// - -TEST_F(SerialTest, get_value) { - EXPECT_EQ(1, one.getValue()); - EXPECT_NE(2, one.getValue()); - EXPECT_EQ(2, two.getValue()); - EXPECT_EQ(1980120100, date_zero.getValue()); - EXPECT_EQ(1980120101, date_one.getValue()); - EXPECT_EQ(0, min.getValue()); - EXPECT_EQ(4294967295u, max.getValue()); - EXPECT_EQ(12345, number_low.getValue()); - EXPECT_EQ(2000000000, number_medium.getValue()); - EXPECT_EQ(4000000000u, number_high.getValue()); -} - -TEST_F(SerialTest, equals) { - EXPECT_EQ(one, one); - EXPECT_EQ(one, one_2); - EXPECT_NE(one, two); - EXPECT_NE(two, one); - EXPECT_EQ(Serial(12345), number_low); - EXPECT_NE(Serial(12346), number_low); -} - -TEST_F(SerialTest, comparison) { - // These should be true/false even without serial arithmetic - EXPECT_LE(one, one); - EXPECT_LE(one, one_2); - EXPECT_LT(one, two); - EXPECT_LE(one, two); - EXPECT_GE(two, two); - EXPECT_GT(two, one); - EXPECT_GE(two, one); - EXPECT_LT(one, number_low); - EXPECT_LT(number_low, number_medium); - EXPECT_LT(number_medium, number_high); - - // now let's try some that 'wrap', as it were - EXPECT_GT(min, max); - EXPECT_LT(max, min); - EXPECT_LT(number_high, number_low); -} - -// -// RFC 1982 Section 3.1 -// -TEST_F(SerialTest, addition) { - EXPECT_EQ(two, one + one); - EXPECT_EQ(two, one + one_2); - EXPECT_EQ(max, max + min); - EXPECT_EQ(min, max + one); - EXPECT_EQ(one, max + two); - EXPECT_EQ(one, max + one + one); - - EXPECT_EQ(one + 100, max + 102); - EXPECT_EQ(min + 2147483645, max + 2147483646); - EXPECT_EQ(min + 2147483646, max + MAX_SERIAL_INCREMENT); -} - -// -// RFC 1982 Section 3.2 has been checked by the basic tests above -// - -// -// RFC 1982 Section 4.1 -// - -// Helper function for addition_always_larger test, add some numbers -// and check that the result is always larger than the original -void do_addition_larger_test(const Serial& number) { - EXPECT_GE(number + 0, number); - EXPECT_EQ(number + 0, number); - EXPECT_GT(number + 1, number); - EXPECT_GT(number + 2, number); - EXPECT_GT(number + 100, number); - EXPECT_GT(number + 1111111, number); - EXPECT_GT(number + 2147483646, number); - EXPECT_GT(number + MAX_SERIAL_INCREMENT, number); - // Try MAX_SERIAL_INCREMENT as a hardcoded number as well - EXPECT_GT(number + 2147483647, number); -} - -TEST_F(SerialTest, addition_always_larger) { - do_addition_larger_test(one); - do_addition_larger_test(two); - do_addition_larger_test(date_zero); - do_addition_larger_test(date_one); - do_addition_larger_test(min); - do_addition_larger_test(max); - do_addition_larger_test(number_low); - do_addition_larger_test(number_medium); - do_addition_larger_test(number_high); -} - -// -// RFC 1982 Section 4.2 -// - -// Helper function to do the second addition -void -do_two_additions_test_second(const Serial &original, - const Serial &number) -{ - EXPECT_NE(original, number); - EXPECT_NE(original, number + 0); - EXPECT_NE(original, number + 1); - EXPECT_NE(original, number + 2); - EXPECT_NE(original, number + 100); - EXPECT_NE(original, number + 1111111); - EXPECT_NE(original, number + 2147483646); - EXPECT_NE(original, number + MAX_SERIAL_INCREMENT); - EXPECT_NE(original, number + 2147483647); -} - -void do_two_additions_test_first(const Serial &number) { - do_two_additions_test_second(number, number + 1); - do_two_additions_test_second(number, number + 2); - do_two_additions_test_second(number, number + 100); - do_two_additions_test_second(number, number + 1111111); - do_two_additions_test_second(number, number + 2147483646); - do_two_additions_test_second(number, number + MAX_SERIAL_INCREMENT); - do_two_additions_test_second(number, number + 2147483647); -} - -TEST_F(SerialTest, two_additions_never_equal) { - do_two_additions_test_first(one); - do_two_additions_test_first(two); - do_two_additions_test_first(date_zero); - do_two_additions_test_first(date_one); - do_two_additions_test_first(min); - do_two_additions_test_first(max); - do_two_additions_test_first(number_low); - do_two_additions_test_first(number_medium); - do_two_additions_test_first(number_high); -} - -// -// RFC 1982 Section 4.3 and 4.4 have nothing to test -// - -// -// Tests from RFC 1982 examples -// -TEST(SerialTextRFCExamples, rfc_example_tests) { -} diff --git a/src/lib/dns/tests/tsig_unittest.cc b/src/lib/dns/tests/tsig_unittest.cc index 9b40d80d94..8b13789179 100644 --- a/src/lib/dns/tests/tsig_unittest.cc +++ b/src/lib/dns/tests/tsig_unittest.cc @@ -1,1185 +1 @@ -// Copyright (C) 2011-2024 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. -#include <config.h> - -#include <time.h> -#include <string> -#include <stdexcept> -#include <vector> - -#include <boost/scoped_ptr.hpp> - -#include <gtest/gtest.h> - -#include <exceptions/exceptions.h> - -#include <util/buffer.h> -#include <util/encode/encode.h> -#include <util/unittests/newhook.h> -#include <util/time_utilities.h> - -#include <dns/message.h> -#include <dns/messagerenderer.h> -#include <dns/question.h> -#include <dns/opcode.h> -#include <dns/rcode.h> -#include <dns/rrclass.h> -#include <dns/rrtype.h> -#include <dns/tsig.h> -#include <dns/tsigkey.h> -#include <dns/tsigrecord.h> - -#include <dns/tests/unittest_util.h> -#include <util/unittests/wiredata.h> - -using namespace std; -using namespace isc; -using namespace isc::dns; -using namespace isc::util; -using namespace isc::util::encode; -using namespace isc::dns::rdata; -using namespace isc::dns::rdata::any; -using isc::UnitTestUtil; -using isc::util::unittests::matchWireData; - -// @note: blocks and SCOPED_TRACE can make buggy cppchecks raise -// a spurious syntax error... - -// See dnssectime.cc -namespace isc { -namespace util { -namespace detail { -extern int64_t (*gettimeFunction)(); -} -} -} - -namespace { -// See dnssectime_unittest.cc -template <int64_t NOW> -int64_t -testGetTime() { - return (NOW); -} - -// Thin wrapper around TSIGContext to allow access to the -// update method. -class TestTSIGContext : public TSIGContext { -public: - TestTSIGContext(const TSIGKey& key) : - TSIGContext(key) - {} - TestTSIGContext(const Name& key_name, const Name& algorithm_name, - const TSIGKeyRing& keyring) : - TSIGContext(key_name, algorithm_name, keyring) - {} - void update(const void* const data, size_t len) { - TSIGContext::update(data, len); - } -}; - -class TSIGTest : public ::testing::Test { -protected: - TSIGTest() : - tsig_ctx(NULL), qid(0x2d65), test_name("www.example.com"), - badkey_name("badkey.example.com"), test_class(RRClass::IN()), - test_ttl(86400), message(Message::RENDER), - dummy_data(1024, 0xdd), // should be sufficiently large for all tests - dummy_record(badkey_name, TSIG(TSIGKey::HMACMD5_NAME(), 0x4da8877a, - TSIGContext::DEFAULT_FUDGE, 0, NULL, qid, 0, 0, NULL)) - { - // Make sure we use the system time by default so that we won't be - // confused due to other tests that tweak the time. - isc::util::detail::gettimeFunction = NULL; - - decodeBase64("SFuWd/q99SzF8Yzd1QbB9g==", secret); - tsig_ctx.reset(new TestTSIGContext(TSIGKey(test_name, - TSIGKey::HMACMD5_NAME(), - &secret[0], - secret.size()))); - tsig_verify_ctx.reset(new TSIGContext(TSIGKey(test_name, - TSIGKey::HMACMD5_NAME(), - &secret[0], - secret.size()))); - } - ~TSIGTest() { - isc::util::detail::gettimeFunction = NULL; - } - - // Many of the tests below create some DNS message and sign it under - // some specific TSIG context. This helper method unifies the common - // logic with slightly different parameters. - ConstTSIGRecordPtr createMessageAndSign(uint16_t qid, const Name& qname, - TSIGContext* ctx, - unsigned int message_flags = - RD_FLAG, - RRType qtype = RRType::A(), - const char* answer_data = NULL, - const RRType* answer_type = NULL, - bool add_question = true, - Rcode rcode = Rcode::NOERROR()); - - void createMessageFromFile(const char* datafile); - - // bit-wise constant flags to configure DNS header flags for test - // messages. - static const unsigned int QR_FLAG = 0x1; - static const unsigned int AA_FLAG = 0x2; - static const unsigned int RD_FLAG = 0x4; - - boost::scoped_ptr<TestTSIGContext> tsig_ctx; - boost::scoped_ptr<TSIGContext> tsig_verify_ctx; - TSIGKeyRing keyring; - const uint16_t qid; - const Name test_name; - const Name badkey_name; - const RRClass test_class; - const RRTTL test_ttl; - Message message; - MessageRenderer renderer; - vector<uint8_t> secret; - vector<uint8_t> dummy_data; - const TSIGRecord dummy_record; - vector<uint8_t> received_data; -}; - -ConstTSIGRecordPtr -TSIGTest::createMessageAndSign(uint16_t id, const Name& qname, - TSIGContext* ctx, unsigned int message_flags, - RRType qtype, const char* answer_data, - const RRType* answer_type, bool add_question, - Rcode rcode) -{ - message.clear(Message::RENDER); - message.setQid(id); - message.setOpcode(Opcode::QUERY()); - message.setRcode(rcode); - if ((message_flags & QR_FLAG) != 0) { - message.setHeaderFlag(Message::HEADERFLAG_QR); - } - if ((message_flags & AA_FLAG) != 0) { - message.setHeaderFlag(Message::HEADERFLAG_AA); - } - if ((message_flags & RD_FLAG) != 0) { - message.setHeaderFlag(Message::HEADERFLAG_RD); - } - if (add_question) { - message.addQuestion(Question(qname, test_class, qtype)); - } - if (answer_data != NULL) { - if (answer_type == NULL) { - answer_type = &qtype; - } - RRsetPtr answer_rrset(new RRset(qname, test_class, *answer_type, - test_ttl)); - answer_rrset->addRdata(createRdata(*answer_type, test_class, - answer_data)); - message.addRRset(Message::SECTION_ANSWER, answer_rrset); - } - renderer.clear(); - - TSIGContext::State expected_new_state = - (ctx->getState() == TSIGContext::INIT) ? - TSIGContext::SENT_REQUEST : TSIGContext::SENT_RESPONSE; - - message.toWire(renderer, ctx); - - message.clear(Message::PARSE); - InputBuffer buffer(renderer.getData(), renderer.getLength()); - message.fromWire(buffer); - - EXPECT_EQ(expected_new_state, ctx->getState()); - - return (ConstTSIGRecordPtr(new TSIGRecord(*message.getTSIGRecord()))); -} - -void -TSIGTest::createMessageFromFile(const char* datafile) { - message.clear(Message::PARSE); - received_data.clear(); - UnitTestUtil::readWireData(datafile, received_data); - InputBuffer buffer(&received_data[0], received_data.size()); - message.fromWire(buffer); -} - -void -commonSignChecks(ConstTSIGRecordPtr tsig, uint16_t expected_qid, - uint64_t expected_timesigned, - const uint8_t* expected_mac, size_t expected_maclen, - uint16_t expected_error = 0, - uint16_t expected_otherlen = 0, - const uint8_t* expected_otherdata = NULL, - const Name& expected_algorithm = TSIGKey::HMACMD5_NAME()) -{ - ASSERT_TRUE(tsig != NULL); - const TSIG& tsig_rdata = tsig->getRdata(); - - EXPECT_EQ(expected_algorithm, tsig_rdata.getAlgorithm()); - EXPECT_EQ(expected_timesigned, tsig_rdata.getTimeSigned()); - EXPECT_EQ(300, tsig_rdata.getFudge()); - EXPECT_EQ(expected_maclen, tsig_rdata.getMACSize()); - 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()); - matchWireData(expected_otherdata, expected_otherlen, - tsig_rdata.getOtherData(), tsig_rdata.getOtherLen()); -} - -void -commonVerifyChecks(TSIGContext& ctx, const TSIGRecord* record, - const void* data, size_t data_len, TSIGError expected_error, - TSIGContext::State expected_new_state = - TSIGContext::VERIFIED_RESPONSE, - bool last_should_throw = false) -{ - EXPECT_EQ(expected_error, ctx.verify(record, data, data_len)); - EXPECT_EQ(expected_error, ctx.getError()); - EXPECT_EQ(expected_new_state, ctx.getState()); - if (last_should_throw) { - EXPECT_THROW(ctx.lastHadSignature(), TSIGContextError); - } else { - EXPECT_EQ(record != NULL, ctx.lastHadSignature()); - } -} - -TEST_F(TSIGTest, initialState) { - // Until signing or verifying, the state should be INIT - EXPECT_EQ(TSIGContext::INIT, tsig_ctx->getState()); - - // And there should be no error code. - EXPECT_EQ(TSIGError(Rcode::NOERROR()), tsig_ctx->getError()); - - // Nothing verified yet - EXPECT_THROW(tsig_ctx->lastHadSignature(), TSIGContextError); -} - -TEST_F(TSIGTest, constructFromKeyRing) { - // Construct a TSIG context with an empty key ring. Key shouldn't be - // found, and the BAD_KEY error should be recorded. - TSIGContext ctx1(test_name, TSIGKey::HMACMD5_NAME(), keyring); - EXPECT_EQ(TSIGContext::INIT, ctx1.getState()); - EXPECT_EQ(TSIGError::BAD_KEY(), ctx1.getError()); - - // Add a matching key (we don't use the secret so leave it empty), and - // construct it again. This time it should be constructed with a valid - // key. - keyring.add(TSIGKey(test_name, TSIGKey::HMACMD5_NAME(), NULL, 0)); - TSIGContext ctx2(test_name, TSIGKey::HMACMD5_NAME(), keyring); - EXPECT_EQ(TSIGContext::INIT, ctx2.getState()); - EXPECT_EQ(TSIGError::NOERROR(), ctx2.getError()); - - // Similar to the first case except that the key ring isn't empty but - // it doesn't contain a matching key. - TSIGContext ctx3(test_name, TSIGKey::HMACSHA1_NAME(), keyring); - EXPECT_EQ(TSIGContext::INIT, ctx3.getState()); - EXPECT_EQ(TSIGError::BAD_KEY(), ctx3.getError()); - - TSIGContext ctx4(Name("different-key.example"), TSIGKey::HMACMD5_NAME(), - keyring); - EXPECT_EQ(TSIGContext::INIT, ctx4.getState()); - EXPECT_EQ(TSIGError::BAD_KEY(), ctx4.getError()); - - // "Unknown" algorithm name will result in BADKEY, too. - TSIGContext ctx5(test_name, Name("unknown.algorithm"), keyring); - EXPECT_EQ(TSIGContext::INIT, ctx5.getState()); - EXPECT_EQ(TSIGError::BAD_KEY(), ctx5.getError()); -} - -// Example output generated by -// "dig -y www.example.com:SFuWd/q99SzF8Yzd1QbB9g== www.example.com -// QID: 0x2d65 -// Time Signed: 0x00004da8877a -// MAC: 227026ad297beee721ce6c6fff1e9ef3 -const uint8_t common_expected_mac[] = { - 0x22, 0x70, 0x26, 0xad, 0x29, 0x7b, 0xee, 0xe7, - 0x21, 0xce, 0x6c, 0x6f, 0xff, 0x1e, 0x9e, 0xf3 -}; -TEST_F(TSIGTest, sign) { - isc::util::detail::gettimeFunction = testGetTime<0x4da8877a>; - - { - SCOPED_TRACE("Sign test for query"); - commonSignChecks(createMessageAndSign(qid, test_name, tsig_ctx.get()), - qid, 0x4da8877a, common_expected_mac, - sizeof(common_expected_mac)); - } -} - -// Same test as sign, but specifying the key name with upper-case (i.e. -// non canonical) characters. The digest must be the same. It should actually -// be ensured at the level of TSIGKey, but we confirm that at this level, too. -TEST_F(TSIGTest, signUsingUpperCasedKeyName) { - isc::util::detail::gettimeFunction = testGetTime<0x4da8877a>; - - TSIGContext cap_ctx(TSIGKey(Name("WWW.EXAMPLE.COM"), - TSIGKey::HMACMD5_NAME(), - &secret[0], secret.size())); - - { - SCOPED_TRACE("Sign test for query using non canonical key name"); - commonSignChecks(createMessageAndSign(qid, test_name, &cap_ctx), qid, - 0x4da8877a, common_expected_mac, - sizeof(common_expected_mac)); - } -} - -// Same as the previous test, but for the algorithm name. -TEST_F(TSIGTest, signUsingUpperCasedAlgorithmName) { - isc::util::detail::gettimeFunction = testGetTime<0x4da8877a>; - - TSIGContext cap_ctx(TSIGKey(test_name, - Name("HMAC-md5.SIG-alg.REG.int"), - &secret[0], secret.size())); - - { - SCOPED_TRACE("Sign test for query using non canonical algorithm name"); - commonSignChecks(createMessageAndSign(qid, test_name, &cap_ctx), qid, - 0x4da8877a, common_expected_mac, - sizeof(common_expected_mac)); - } -} - -TEST_F(TSIGTest, signAtActualTime) { - // Sign the message using the actual time, and check the accuracy of it. - // We cannot reasonably predict the expected MAC, so don't bother to - // check it. - const uint64_t now = static_cast<uint64_t>(time(NULL)); - - { - SCOPED_TRACE("Sign test for query at actual time"); - ConstTSIGRecordPtr tsig = createMessageAndSign(qid, test_name, - tsig_ctx.get()); - const TSIG& tsig_rdata = tsig->getRdata(); - - // Check the resulted time signed is in the range of [now, now + 5] - // (5 is an arbitrary choice). Note that due to the order of the call - // to time() and sign(), time signed must not be smaller than the - // current time. - EXPECT_LE(now, tsig_rdata.getTimeSigned()); - EXPECT_GE(now + 5, tsig_rdata.getTimeSigned()); - } -} - -TEST_F(TSIGTest, signBadData) { - // some specific bad data should be rejected proactively. - const unsigned char dummy_data = 0; - EXPECT_THROW(tsig_ctx->sign(0, NULL, 10), InvalidParameter); - EXPECT_THROW(tsig_ctx->sign(0, &dummy_data, 0), InvalidParameter); -} - -TEST_F(TSIGTest, verifyBadData) { - // the data must at least hold the DNS message header and the specified - // TSIG. - EXPECT_THROW(tsig_ctx->verify(&dummy_record, &dummy_data[0], - 12 + dummy_record.getLength() - 1), - InvalidParameter); - - // Still nothing verified - EXPECT_THROW(tsig_ctx->lastHadSignature(), TSIGContextError); - - // And the data must not be NULL. - EXPECT_THROW(tsig_ctx->verify(&dummy_record, NULL, - 12 + dummy_record.getLength()), - InvalidParameter); - - // Still nothing verified - EXPECT_THROW(tsig_ctx->lastHadSignature(), TSIGContextError); - -} - -#ifdef ENABLE_CUSTOM_OPERATOR_NEW -// We enable this test only when we enable custom new/delete at build time -// We could enable/disable the test runtime using the gtest filter, but -// we'd basically like to minimize the number of disabled tests (they -// should generally be considered tests that temporarily fail and should -// be fixed). -TEST_F(TSIGTest, signExceptionSafety) { - // Check sign() provides the strong exception guarantee for the simpler - // case (with a key error and empty MAC). The general case is more - // complicated and involves more memory allocation, so the test result - // won't be reliable. - - commonVerifyChecks(*tsig_verify_ctx, &dummy_record, &dummy_data[0], - dummy_data.size(), TSIGError::BAD_KEY(), - TSIGContext::RECEIVED_REQUEST); - - try { - int dummydata; - isc::util::unittests::force_throw_on_new = true; - isc::util::unittests::throw_size_on_new = sizeof(TSIGRecord); - tsig_verify_ctx->sign(0, &dummydata, sizeof(dummydata)); - isc::util::unittests::force_throw_on_new = false; - ASSERT_FALSE(true) << "Expected throw on new, but it didn't happen"; - } catch (const std::bad_alloc&) { - isc::util::unittests::force_throw_on_new = false; - - // sign() threw, so the state should still be RECEIVED_REQUEST - EXPECT_EQ(TSIGContext::RECEIVED_REQUEST, tsig_verify_ctx->getState()); - } - isc::util::unittests::force_throw_on_new = false; -} -#endif // ENABLE_CUSTOM_OPERATOR_NEW - -// Same test as "sign" but use a different algorithm just to confirm we don't -// naively hardcode constants specific to a particular algorithm. -// Test data generated by -// "dig -y hmac-sha1:www.example.com:MA+QDhXbyqUak+qnMFyTyEirzng= www.example.com" -// QID: 0x0967, RDflag -// Current Time: 00004da8be86 -// Time Signed: 00004dae7d5f -// HMAC Size: 20 -// HMAC: 415340c7daf824ed684ee586f7b5a67a2febc0d3 -TEST_F(TSIGTest, signUsingHMACSHA1) { - isc::util::detail::gettimeFunction = testGetTime<0x4dae7d5f>; - - secret.clear(); - decodeBase64("MA+QDhXbyqUak+qnMFyTyEirzng=", secret); - TSIGContext sha1_ctx(TSIGKey(test_name, TSIGKey::HMACSHA1_NAME(), - &secret[0], secret.size())); - - const uint16_t sha1_qid = 0x0967; - const uint8_t expected_mac[] = { - 0x41, 0x53, 0x40, 0xc7, 0xda, 0xf8, 0x24, 0xed, 0x68, 0x4e, - 0xe5, 0x86, 0xf7, 0xb5, 0xa6, 0x7a, 0x2f, 0xeb, 0xc0, 0xd3 - }; - { - SCOPED_TRACE("Sign test using HMAC-SHA1"); - commonSignChecks(createMessageAndSign(sha1_qid, test_name, &sha1_ctx), - sha1_qid, 0x4dae7d5f, expected_mac, - sizeof(expected_mac), 0, 0, NULL, - TSIGKey::HMACSHA1_NAME()); - } -} - -TEST_F(TSIGTest, signUsingHMACSHA224) { - isc::util::detail::gettimeFunction = testGetTime<0x4dae7d5f>; - - secret.clear(); - decodeBase64("MA+QDhXbyqUak+qnMFyTyEirzng=", secret); - TSIGContext sha1_ctx(TSIGKey(test_name, TSIGKey::HMACSHA224_NAME(), - &secret[0], secret.size())); - - const uint16_t sha1_qid = 0x0967; - const uint8_t expected_mac[] = { - 0x3b, 0x93, 0xd3, 0xc5, 0xf9, 0x64, 0xb9, 0xc5, 0x00, 0x35, - 0x02, 0x69, 0x9f, 0xfc, 0x44, 0xd6, 0xe2, 0x66, 0xf4, 0x08, - 0xef, 0x33, 0xa2, 0xda, 0xa1, 0x48, 0x71, 0xd3 - }; - { - SCOPED_TRACE("Sign test using HMAC-SHA224"); - commonSignChecks(createMessageAndSign(sha1_qid, test_name, &sha1_ctx), - sha1_qid, 0x4dae7d5f, expected_mac, - sizeof(expected_mac), 0, 0, NULL, - TSIGKey::HMACSHA224_NAME()); - } -} - -// The first part of this test checks verifying the signed query used for -// the "sign" test. -// The second part of this test generates a signed response to the signed -// query as follows: -// Answer: www.example.com. 86400 IN A 192.0.2.1 -// MAC: 8fcda66a7cd1a3b9948eb1869d384a9f -TEST_F(TSIGTest, verifyThenSignResponse) { - isc::util::detail::gettimeFunction = testGetTime<0x4da8877a>; - - // This test data for the message test has the same wire format data - // as the message used in the "sign" test. - createMessageFromFile("message_toWire2.wire"); - { - SCOPED_TRACE("Verify test for request"); - commonVerifyChecks(*tsig_verify_ctx, message.getTSIGRecord(), - &received_data[0], received_data.size(), - TSIGError::NOERROR(), TSIGContext::RECEIVED_REQUEST); - } - - // Transform the original message to a response, then sign the response - // with the context of "verified state". - ConstTSIGRecordPtr tsig = createMessageAndSign(qid, test_name, - tsig_verify_ctx.get(), - QR_FLAG|AA_FLAG|RD_FLAG, - RRType::A(), "192.0.2.1"); - const uint8_t expected_mac[] = { - 0x8f, 0xcd, 0xa6, 0x6a, 0x7c, 0xd1, 0xa3, 0xb9, - 0x94, 0x8e, 0xb1, 0x86, 0x9d, 0x38, 0x4a, 0x9f - }; - { - SCOPED_TRACE("Sign test for response"); - commonSignChecks(tsig, qid, 0x4da8877a, expected_mac, - sizeof(expected_mac)); - } -} - -TEST_F(TSIGTest, verifyUpperCaseNames) { - isc::util::detail::gettimeFunction = testGetTime<0x4da8877a>; - - // This test data for the message test has the same wire format data - // as the message used in the "sign" test. - createMessageFromFile("tsig_verify9.wire"); - { - SCOPED_TRACE("Verify test for request"); - commonVerifyChecks(*tsig_verify_ctx, message.getTSIGRecord(), - &received_data[0], received_data.size(), - TSIGError::NOERROR(), TSIGContext::RECEIVED_REQUEST); - } -} - -TEST_F(TSIGTest, verifyForwardedMessage) { - // Similar to the first part of the previous test, but this test emulates - // the "forward" case, where the ID of the Header and the original ID in - // TSIG is different. - isc::util::detail::gettimeFunction = testGetTime<0x4da8877a>; - - createMessageFromFile("tsig_verify6.wire"); - { - SCOPED_TRACE("Verify test for forwarded request"); - commonVerifyChecks(*tsig_verify_ctx, message.getTSIGRecord(), - &received_data[0], received_data.size(), - TSIGError::NOERROR(), TSIGContext::RECEIVED_REQUEST); - } -} - -// Example of signing multiple messages in a single TCP stream, -// taken from data using BIND 9's "one-answer" transfer-format. -// Request: -// QID: 0x3410, flags (none) -// Question: example.com/IN/AXFR -// Time Signed: 0x4da8e951 -// MAC: 35b2fd08268781634400c7c8a5533b13 -// First message: -// QID: 0x3410, flags QR, AA -// Question: example.com/IN/AXFR -// Answer: example.com. 86400 IN SOA ns.example.com. root.example.com. ( -// 2011041503 7200 3600 2592000 1200) -// MAC: bdd612cd2c7f9e0648bd6dc23713e83c -// Second message: -// Answer: example.com. 86400 IN NS ns.example.com. -// MAC: 102458f7f62ddd7d638d746034130968 -TEST_F(TSIGTest, signContinuation) { - isc::util::detail::gettimeFunction = testGetTime<0x4da8e951>; - - const uint16_t axfr_qid = 0x3410; - const Name zone_name("example.com"); - - // Create and sign the AXFR request - ConstTSIGRecordPtr tsig = createMessageAndSign(axfr_qid, zone_name, - tsig_ctx.get(), 0, - RRType::AXFR()); - // Then verify it (the wire format test data should contain the same - // message data, and verification should succeed). - received_data.clear(); - UnitTestUtil::readWireData("tsig_verify1.wire", received_data); - { - SCOPED_TRACE("Verify AXFR query"); - commonVerifyChecks(*tsig_verify_ctx, tsig.get(), &received_data[0], - received_data.size(), TSIGError::NOERROR(), - TSIGContext::RECEIVED_REQUEST); - } - - // Create and sign the first response message - tsig = createMessageAndSign(axfr_qid, zone_name, tsig_verify_ctx.get(), - AA_FLAG|QR_FLAG, RRType::AXFR(), - "ns.example.com. root.example.com. " - "2011041503 7200 3600 2592000 1200", - &RRType::SOA()); - - // Then verify it at the requester side. - received_data.clear(); - UnitTestUtil::readWireData("tsig_verify2.wire", received_data); - { - SCOPED_TRACE("Verify first AXFR response"); - commonVerifyChecks(*tsig_ctx, tsig.get(), &received_data[0], - received_data.size(), TSIGError::NOERROR()); - } - - // Create and sign the second response message - const uint8_t expected_mac[] = { - 0x10, 0x24, 0x58, 0xf7, 0xf6, 0x2d, 0xdd, 0x7d, - 0x63, 0x8d, 0x74, 0x60, 0x34, 0x13, 0x09, 0x68 - }; - { - SCOPED_TRACE("Sign test for continued response in TCP stream"); - tsig = createMessageAndSign(axfr_qid, zone_name, tsig_verify_ctx.get(), - AA_FLAG|QR_FLAG, RRType::AXFR(), - "ns.example.com.", &RRType::NS(), false); - commonSignChecks(tsig, axfr_qid, 0x4da8e951, expected_mac, - sizeof(expected_mac)); - } - - // Then verify it at the requester side. - received_data.clear(); - UnitTestUtil::readWireData("tsig_verify3.wire", received_data); - { - SCOPED_TRACE("Verify second AXFR response"); - commonVerifyChecks(*tsig_ctx, tsig.get(), &received_data[0], - received_data.size(), TSIGError::NOERROR()); - } -} - -// BADTIME example, taken from data using specially hacked BIND 9's nsupdate -// Query: -// QID: 0x1830, RD flag -// Current Time: 00004da8be86 -// Time Signed: 00004da8b9d6 -// Question: www.example.com/IN/SOA -//(mac) 8406 7d50 b8e7 d054 3d50 5bd9 de2a bb68 -// Response: -// QRbit, RCODE=9(NOTAUTH) -// Time Signed: 00004da8b9d6 (the one in the query) -// MAC: d4b043f6f44495ec8a01260e39159d76 -// Error: 0x12 (BADTIME), Other Len: 6 -// Other data: 00004da8be86 -TEST_F(TSIGTest, badtimeResponse) { - isc::util::detail::gettimeFunction = testGetTime<0x4da8b9d6>; - - const uint16_t test_qid = 0x7fc4; - ConstTSIGRecordPtr tsig = createMessageAndSign(test_qid, test_name, - tsig_ctx.get(), 0, - RRType::SOA()); - - // "advance the clock" and try validating, which should fail due to BADTIME - isc::util::detail::gettimeFunction = testGetTime<0x4da8be86>; - { - SCOPED_TRACE("Verify resulting in BADTIME due to expired SIG"); - commonVerifyChecks(*tsig_verify_ctx, tsig.get(), &dummy_data[0], - dummy_data.size(), TSIGError::BAD_TIME(), - TSIGContext::RECEIVED_REQUEST); - } - - // make and sign a response in the context of TSIG error. - tsig = createMessageAndSign(test_qid, test_name, tsig_verify_ctx.get(), - QR_FLAG, RRType::SOA(), NULL, NULL, - true, Rcode::NOTAUTH()); - const uint8_t expected_otherdata[] = { 0, 0, 0x4d, 0xa8, 0xbe, 0x86 }; - const uint8_t expected_mac[] = { - 0xd4, 0xb0, 0x43, 0xf6, 0xf4, 0x44, 0x95, 0xec, - 0x8a, 0x01, 0x26, 0x0e, 0x39, 0x15, 0x9d, 0x76 - }; - { - SCOPED_TRACE("Sign test for response with BADTIME"); - commonSignChecks(tsig, message.getQid(), 0x4da8b9d6, - expected_mac, sizeof(expected_mac), - 18, // error: BADTIME - sizeof(expected_otherdata), - expected_otherdata); - } -} - -TEST_F(TSIGTest, badtimeResponse2) { - isc::util::detail::gettimeFunction = testGetTime<0x4da8b9d6>; - - ConstTSIGRecordPtr tsig = createMessageAndSign(qid, test_name, - tsig_ctx.get(), 0, - RRType::SOA()); - - // "rewind the clock" and try validating, which should fail due to BADTIME - isc::util::detail::gettimeFunction = testGetTime<0x4da8b9d6 - 600>; - { - SCOPED_TRACE("Verify resulting in BADTIME due to too future SIG"); - commonVerifyChecks(*tsig_verify_ctx, tsig.get(), &dummy_data[0], - dummy_data.size(), TSIGError::BAD_TIME(), - TSIGContext::RECEIVED_REQUEST); - } -} - -TEST_F(TSIGTest, badtimeBoundaries) { - isc::util::detail::gettimeFunction = testGetTime<0x4da8b9d6>; - - // Test various boundary conditions. We intentionally use the magic - // number of 300 instead of the constant variable for testing. - // In the okay cases, signature is not correct, but it's sufficient to - // check the error code isn't BADTIME for the purpose of this test. - ConstTSIGRecordPtr tsig = createMessageAndSign(qid, test_name, - tsig_ctx.get(), 0, - RRType::SOA()); - isc::util::detail::gettimeFunction = testGetTime<0x4da8b9d6 + 301>; - EXPECT_EQ(TSIGError::BAD_TIME(), - tsig_verify_ctx->verify(tsig.get(), &dummy_data[0], - dummy_data.size())); - isc::util::detail::gettimeFunction = testGetTime<0x4da8b9d6 + 300>; - EXPECT_NE(TSIGError::BAD_TIME(), - tsig_verify_ctx->verify(tsig.get(), &dummy_data[0], - dummy_data.size())); - isc::util::detail::gettimeFunction = testGetTime<0x4da8b9d6 - 301>; - EXPECT_EQ(TSIGError::BAD_TIME(), - tsig_verify_ctx->verify(tsig.get(), &dummy_data[0], - dummy_data.size())); - isc::util::detail::gettimeFunction = testGetTime<0x4da8b9d6 - 300>; - EXPECT_NE(TSIGError::BAD_TIME(), - tsig_verify_ctx->verify(tsig.get(), &dummy_data[0], - dummy_data.size())); -} - -TEST_F(TSIGTest, badtimeOverflow) { - isc::util::detail::gettimeFunction = testGetTime<200>; - ConstTSIGRecordPtr tsig = createMessageAndSign(qid, test_name, - tsig_ctx.get(), 0, - RRType::SOA()); - - // This should be in the okay range, but since "200 - fudge" overflows - // and we compare them as 64-bit unsigned integers, it results in a false - // positive (we intentionally accept that). - isc::util::detail::gettimeFunction = testGetTime<100>; - EXPECT_EQ(TSIGError::BAD_TIME(), - tsig_verify_ctx->verify(tsig.get(), &dummy_data[0], - dummy_data.size())); -} - -TEST_F(TSIGTest, badsigResponse) { - isc::util::detail::gettimeFunction = testGetTime<0x4da8877a>; - - // Try to sign a simple message with bogus secret. It should fail - // with BADSIG. - createMessageFromFile("message_toWire2.wire"); - TSIGContext bad_ctx(TSIGKey(test_name, TSIGKey::HMACMD5_NAME(), - &dummy_data[0], dummy_data.size())); - { - SCOPED_TRACE("Verify resulting in BADSIG"); - commonVerifyChecks(bad_ctx, message.getTSIGRecord(), - &received_data[0], received_data.size(), - TSIGError::BAD_SIG(), TSIGContext::RECEIVED_REQUEST); - } - - // Sign the same message (which doesn't matter for this test) with the - // context of "checked state". - { - SCOPED_TRACE("Sign test for response with BADSIG error"); - commonSignChecks(createMessageAndSign(qid, test_name, &bad_ctx), - message.getQid(), 0x4da8877a, NULL, 0, - 16); // 16: BADSIG - } -} - -TEST_F(TSIGTest, badkeyResponse) { - // A similar test as badsigResponse but for BADKEY - isc::util::detail::gettimeFunction = testGetTime<0x4da8877a>; - tsig_ctx.reset(new TestTSIGContext(badkey_name, TSIGKey::HMACMD5_NAME(), - keyring)); - { - SCOPED_TRACE("Verify resulting in BADKEY"); - commonVerifyChecks(*tsig_ctx, &dummy_record, &dummy_data[0], - dummy_data.size(), TSIGError::BAD_KEY(), - TSIGContext::RECEIVED_REQUEST); - } - - { - SCOPED_TRACE("Sign test for response with BADKEY error"); - ConstTSIGRecordPtr sig = createMessageAndSign(qid, test_name, - tsig_ctx.get()); - EXPECT_EQ(badkey_name, sig->getName()); - commonSignChecks(sig, qid, 0x4da8877a, NULL, 0, 17); // 17: BADKEY - } -} - -TEST_F(TSIGTest, badkeyForResponse) { - // "BADKEY" case for a response to a signed message - createMessageAndSign(qid, test_name, tsig_ctx.get()); - { - SCOPED_TRACE("Verify a response resulting in BADKEY"); - commonVerifyChecks(*tsig_ctx, &dummy_record, &dummy_data[0], - dummy_data.size(), TSIGError::BAD_KEY(), - TSIGContext::SENT_REQUEST); - } - - // A similar case with a different algorithm - const TSIGRecord dummy_record2(test_name, TSIG(TSIGKey::HMACSHA1_NAME(), - 0x4da8877a, - TSIGContext::DEFAULT_FUDGE, - 0, NULL, qid, 0, 0, NULL)); - { - SCOPED_TRACE("Verify a response resulting in BADKEY due to bad alg"); - commonVerifyChecks(*tsig_ctx, &dummy_record2, &dummy_data[0], - dummy_data.size(), TSIGError::BAD_KEY(), - TSIGContext::SENT_REQUEST); - } -} - -TEST_F(TSIGTest, badsigThenValidate) { - // According to RFC2845 4.6, if TSIG verification fails the client - // should discard that message and wait for another signed response. - // This test emulates that situation. - - isc::util::detail::gettimeFunction = testGetTime<0x4da8877a>; - - createMessageAndSign(qid, test_name, tsig_ctx.get()); - - createMessageFromFile("tsig_verify4.wire"); - { - SCOPED_TRACE("Verify a response that should fail due to BADSIG"); - commonVerifyChecks(*tsig_ctx, message.getTSIGRecord(), - &received_data[0], received_data.size(), - TSIGError::BAD_SIG(), TSIGContext::SENT_REQUEST); - } - - createMessageFromFile("tsig_verify5.wire"); - { - SCOPED_TRACE("Verify a response after a BADSIG failure"); - commonVerifyChecks(*tsig_ctx, message.getTSIGRecord(), - &received_data[0], received_data.size(), - TSIGError::NOERROR(), - TSIGContext::VERIFIED_RESPONSE); - } -} - -TEST_F(TSIGTest, nosigThenValidate) { - // Similar to the previous test, but the first response doesn't contain - // TSIG. - isc::util::detail::gettimeFunction = testGetTime<0x4da8877a>; - - createMessageAndSign(qid, test_name, tsig_ctx.get()); - - { - SCOPED_TRACE("Verify a response without TSIG that should exist"); - commonVerifyChecks(*tsig_ctx, NULL, &dummy_data[0], - dummy_data.size(), TSIGError::FORMERR(), - TSIGContext::SENT_REQUEST, true); - } - - createMessageFromFile("tsig_verify5.wire"); - { - SCOPED_TRACE("Verify a response after a FORMERR failure"); - commonVerifyChecks(*tsig_ctx, message.getTSIGRecord(), - &received_data[0], received_data.size(), - TSIGError::NOERROR(), - TSIGContext::VERIFIED_RESPONSE); - } -} - -TEST_F(TSIGTest, badtimeThenValidate) { - // Similar to the previous test, but the first response results in BADTIME. - isc::util::detail::gettimeFunction = testGetTime<0x4da8877a>; - - ConstTSIGRecordPtr tsig = createMessageAndSign(qid, test_name, - tsig_ctx.get()); - - // "advance the clock" and try validating, which should fail due to BADTIME - isc::util::detail::gettimeFunction = testGetTime<0x4da8877a + 600>; - { - SCOPED_TRACE("Verify resulting in BADTIME due to expired SIG"); - commonVerifyChecks(*tsig_ctx, tsig.get(), &dummy_data[0], - dummy_data.size(), TSIGError::BAD_TIME(), - TSIGContext::SENT_REQUEST); - } - - // revert the clock again. - isc::util::detail::gettimeFunction = testGetTime<0x4da8877a>; - createMessageFromFile("tsig_verify5.wire"); - { - SCOPED_TRACE("Verify a response after a BADTIME failure"); - commonVerifyChecks(*tsig_ctx, message.getTSIGRecord(), - &received_data[0], received_data.size(), - TSIGError::NOERROR(), - TSIGContext::VERIFIED_RESPONSE); - } -} - -TEST_F(TSIGTest, emptyMAC) { - isc::util::detail::gettimeFunction = testGetTime<0x4da8877a>; - - // We don't allow empty MAC unless the TSIG error is BADSIG or BADKEY. - createMessageFromFile("tsig_verify7.wire"); - { - SCOPED_TRACE("Verify test for request"); - commonVerifyChecks(*tsig_verify_ctx, message.getTSIGRecord(), - &received_data[0], received_data.size(), - TSIGError::BAD_SIG(), TSIGContext::RECEIVED_REQUEST); - } - - // If the empty MAC comes with a BADKEY error, the error is passed - // transparently. - createMessageFromFile("tsig_verify8.wire"); - { - SCOPED_TRACE("Verify test for request"); - commonVerifyChecks(*tsig_verify_ctx, message.getTSIGRecord(), - &received_data[0], received_data.size(), - TSIGError::BAD_KEY(), TSIGContext::RECEIVED_REQUEST); - } -} - -TEST_F(TSIGTest, verifyAfterSendResponse) { - // Once the context is used for sending a signed response, it shouldn't - // be used for further verification. - - // The following are essentially the same as what verifyThenSignResponse - // does with simplification. - isc::util::detail::gettimeFunction = testGetTime<0x4da8877a>; - createMessageFromFile("message_toWire2.wire"); - tsig_verify_ctx->verify(message.getTSIGRecord(), &received_data[0], - received_data.size()); - EXPECT_EQ(TSIGContext::RECEIVED_REQUEST, tsig_verify_ctx->getState()); - createMessageAndSign(qid, test_name, tsig_verify_ctx.get(), - QR_FLAG|AA_FLAG|RD_FLAG, RRType::A(), "192.0.2.1"); - EXPECT_EQ(TSIGContext::SENT_RESPONSE, tsig_verify_ctx->getState()); - - // Now trying further verification. - createMessageFromFile("message_toWire2.wire"); - EXPECT_THROW(tsig_verify_ctx->verify(message.getTSIGRecord(), - &received_data[0], - received_data.size()), - TSIGContextError); -} - -TEST_F(TSIGTest, signAfterVerified) { - // Likewise, once the context verifies a response, it shouldn't for - // signing any more. - - // The following are borrowed from badsigThenValidate (without the - // intermediate failure) - isc::util::detail::gettimeFunction = testGetTime<0x4da8877a>; - createMessageAndSign(qid, test_name, tsig_ctx.get()); - createMessageFromFile("tsig_verify5.wire"); - tsig_ctx->verify(message.getTSIGRecord(), &received_data[0], - received_data.size()); - EXPECT_EQ(TSIGContext::VERIFIED_RESPONSE, tsig_ctx->getState()); - - // Now trying further signing. - EXPECT_THROW(createMessageAndSign(qid, test_name, tsig_ctx.get()), - TSIGContextError); -} - -TEST_F(TSIGTest, tooShortMAC) { - // Too short MAC should be rejected. - - isc::util::detail::gettimeFunction = testGetTime<0x4da8877a>; - createMessageFromFile("tsig_verify10.wire"); - { - SCOPED_TRACE("Verify test for request"); - commonVerifyChecks(*tsig_verify_ctx, message.getTSIGRecord(), - &received_data[0], received_data.size(), - TSIGError::FORMERR(), TSIGContext::RECEIVED_REQUEST); - } -} - -TEST_F(TSIGTest, truncatedMAC) { - // Check truncated MAC support with HMAC-SHA512-256 - isc::util::detail::gettimeFunction = testGetTime<0x4da8877a>; - - secret.clear(); - decodeBase64("jI/Pa4qRu96t76Pns5Z/Ndxbn3QCkwcxLOgt9vgvnJw5wqTRvNyk3FtD6yIMd1dWVlqZ+Y4fe6Uasc0ckctEmg==", secret); - TSIGContext sha_ctx(TSIGKey(test_name, TSIGKey::HMACSHA512_NAME(), - &secret[0], secret.size(), 256)); - - createMessageFromFile("tsig_verify11.wire"); - { - SCOPED_TRACE("Verify test for request"); - commonVerifyChecks(sha_ctx, message.getTSIGRecord(), - &received_data[0], received_data.size(), - TSIGError::NOERROR(), TSIGContext::RECEIVED_REQUEST); - } - - // Try with HMAC-SHA512-264 (should fail) - TSIGContext bad_sha_ctx(TSIGKey(test_name, TSIGKey::HMACSHA512_NAME(), - &secret[0], secret.size(), 264)); - { - SCOPED_TRACE("Verify test for request"); - commonVerifyChecks(bad_sha_ctx, message.getTSIGRecord(), - &received_data[0], received_data.size(), - TSIGError::BAD_TRUNC(), TSIGContext::RECEIVED_REQUEST); - } -} - -TEST_F(TSIGTest, getTSIGLength) { - // Check for the most common case with various algorithms - // See the comment in TSIGContext::getTSIGLength() for calculation and - // parameter notation. - // The key name (www.example.com) is the same for most cases, where n1=17 - - // hmac-md5.sig-alg.reg.int.: n2=26, x=16 - EXPECT_EQ(85, tsig_ctx->getTSIGLength()); - - // hmac-md5-80: n2=26, x=10 - tsig_ctx.reset(new TestTSIGContext(TSIGKey(test_name, - TSIGKey::HMACMD5_NAME(), - &dummy_data[0], 10, 80))); - EXPECT_EQ(79, tsig_ctx->getTSIGLength()); - - // hmac-sha1: n2=11, x=20 - tsig_ctx.reset(new TestTSIGContext(TSIGKey(test_name, - TSIGKey::HMACSHA1_NAME(), - &dummy_data[0], 20))); - EXPECT_EQ(74, tsig_ctx->getTSIGLength()); - - // hmac-sha256: n2=13, x=32 - tsig_ctx.reset(new TestTSIGContext(TSIGKey(test_name, - TSIGKey::HMACSHA256_NAME(), - &dummy_data[0], 32))); - EXPECT_EQ(88, tsig_ctx->getTSIGLength()); - - // hmac-sha224: n2=13, x=28 - tsig_ctx.reset(new TestTSIGContext(TSIGKey(test_name, - TSIGKey::HMACSHA224_NAME(), - &dummy_data[0], 28))); - EXPECT_EQ(84, tsig_ctx->getTSIGLength()); - - // hmac-sha384: n2=13, x=48 - tsig_ctx.reset(new TestTSIGContext(TSIGKey(test_name, - TSIGKey::HMACSHA384_NAME(), - &dummy_data[0], 48))); - EXPECT_EQ(104, tsig_ctx->getTSIGLength()); - - // hmac-sha512: n2=13, x=64 - tsig_ctx.reset(new TestTSIGContext(TSIGKey(test_name, - TSIGKey::HMACSHA512_NAME(), - &dummy_data[0], 64))); - EXPECT_EQ(120, tsig_ctx->getTSIGLength()); - - // hmac-sha512-256: n2=13, x=32 - tsig_ctx.reset(new TestTSIGContext(TSIGKey(test_name, - TSIGKey::HMACSHA512_NAME(), - &dummy_data[0], 32, 256))); - EXPECT_EQ(88, tsig_ctx->getTSIGLength()); - - // bad key case: n1=len(badkey.example.com)=20, n2=26, x=0 - tsig_ctx.reset(new TestTSIGContext(badkey_name, TSIGKey::HMACMD5_NAME(), - keyring)); - EXPECT_EQ(72, tsig_ctx->getTSIGLength()); - - // bad sig case: n1=17, n2=26, x=0 - isc::util::detail::gettimeFunction = testGetTime<0x4da8877a>; - createMessageFromFile("message_toWire2.wire"); - tsig_ctx.reset(new TestTSIGContext(TSIGKey(test_name, - TSIGKey::HMACMD5_NAME(), - &dummy_data[0], - dummy_data.size()))); - { - SCOPED_TRACE("Verify resulting in BADSIG"); - commonVerifyChecks(*tsig_ctx, message.getTSIGRecord(), - &received_data[0], received_data.size(), - TSIGError::BAD_SIG(), TSIGContext::RECEIVED_REQUEST); - } - EXPECT_EQ(69, tsig_ctx->getTSIGLength()); - - // bad time case: n1=17, n2=26, x=16, y=6 - isc::util::detail::gettimeFunction = testGetTime<0x4da8877a - 1000>; - tsig_ctx.reset(new TestTSIGContext(TSIGKey(test_name, - TSIGKey::HMACMD5_NAME(), - &dummy_data[0], - dummy_data.size()))); - { - SCOPED_TRACE("Verify resulting in BADTIME"); - commonVerifyChecks(*tsig_ctx, message.getTSIGRecord(), - &received_data[0], received_data.size(), - TSIGError::BAD_TIME(), - TSIGContext::RECEIVED_REQUEST); - } - EXPECT_EQ(91, tsig_ctx->getTSIGLength()); -} - -// Verify a stream of multiple messages. Some of them have a signature omitted. -// -// We have two contexts, one that signs, another that verifies. -TEST_F(TSIGTest, verifyMulti) { - isc::util::detail::gettimeFunction = testGetTime<0x4da8877a>; - - // First, send query from the verify one to the normal one, so - // we initialize something like AXFR - { - SCOPED_TRACE("Query"); - ConstTSIGRecordPtr tsig = createMessageAndSign(1234, test_name, - tsig_verify_ctx.get()); - commonVerifyChecks(*tsig_ctx, tsig.get(), - renderer.getData(), renderer.getLength(), - TSIGError(Rcode::NOERROR()), - TSIGContext::RECEIVED_REQUEST); - } - - { - SCOPED_TRACE("First message"); - ConstTSIGRecordPtr tsig = createMessageAndSign(1234, test_name, - tsig_ctx.get()); - commonVerifyChecks(*tsig_verify_ctx, tsig.get(), - renderer.getData(), renderer.getLength(), - TSIGError(Rcode::NOERROR()), - TSIGContext::VERIFIED_RESPONSE); - EXPECT_TRUE(tsig_verify_ctx->lastHadSignature()); - } - - { - SCOPED_TRACE("Second message"); - ConstTSIGRecordPtr tsig = createMessageAndSign(1234, test_name, - tsig_ctx.get()); - commonVerifyChecks(*tsig_verify_ctx, tsig.get(), - renderer.getData(), renderer.getLength(), - TSIGError(Rcode::NOERROR()), - TSIGContext::VERIFIED_RESPONSE); - EXPECT_TRUE(tsig_verify_ctx->lastHadSignature()); - } - - { - SCOPED_TRACE("Third message. Unsigned."); - // Another message does not carry the TSIG on it. But it should - // be OK, it's in the middle of stream. - message.clear(Message::RENDER); - message.setQid(1234); - message.setOpcode(Opcode::QUERY()); - message.setRcode(Rcode::NOERROR()); - RRsetPtr answer_rrset(new RRset(test_name, test_class, RRType::A(), - test_ttl)); - answer_rrset->addRdata(createRdata(RRType::A(), test_class, - "192.0.2.1")); - message.addRRset(Message::SECTION_ANSWER, answer_rrset); - message.toWire(renderer); - // Update the internal state. We abuse the knowledge of - // internals here a little bit to generate correct test data - tsig_ctx->update(renderer.getData(), renderer.getLength()); - - commonVerifyChecks(*tsig_verify_ctx, NULL, - renderer.getData(), renderer.getLength(), - TSIGError(Rcode::NOERROR()), - TSIGContext::VERIFIED_RESPONSE); - - EXPECT_FALSE(tsig_verify_ctx->lastHadSignature()); - } - - { - SCOPED_TRACE("Fourth message. Signed again."); - ConstTSIGRecordPtr tsig = createMessageAndSign(1234, test_name, - tsig_ctx.get()); - commonVerifyChecks(*tsig_verify_ctx, tsig.get(), - renderer.getData(), renderer.getLength(), - TSIGError(Rcode::NOERROR()), - TSIGContext::VERIFIED_RESPONSE); - EXPECT_TRUE(tsig_verify_ctx->lastHadSignature()); - } - - { - SCOPED_TRACE("Filling in bunch of unsigned messages"); - for (size_t i = 0; i < 100; ++i) { - SCOPED_TRACE(i); - // Another message does not carry the TSIG on it. But it should - // be OK, it's in the middle of stream. - message.clear(Message::RENDER); - message.setQid(1234); - message.setOpcode(Opcode::QUERY()); - message.setRcode(Rcode::NOERROR()); - RRsetPtr answer_rrset(new RRset(test_name, test_class, RRType::A(), - test_ttl)); - answer_rrset->addRdata(createRdata(RRType::A(), test_class, - "192.0.2.1")); - message.addRRset(Message::SECTION_ANSWER, answer_rrset); - message.toWire(renderer); - // Update the internal state. We abuse the knowledge of - // internals here a little bit to generate correct test data - tsig_ctx->update(renderer.getData(), renderer.getLength()); - - // 99 unsigned messages is OK. But the 100th must be signed, according - // to the RFC2845, section 4.4 - commonVerifyChecks(*tsig_verify_ctx, NULL, - renderer.getData(), renderer.getLength(), - i == 99 ? TSIGError::FORMERR() : - TSIGError(Rcode::NOERROR()), - TSIGContext::VERIFIED_RESPONSE); - - EXPECT_FALSE(tsig_verify_ctx->lastHadSignature()); - } - } -} - -} // end namespace diff --git a/src/lib/dns/tests/tsigerror_unittest.cc b/src/lib/dns/tests/tsigerror_unittest.cc index e50f0763d3..8b13789179 100644 --- a/src/lib/dns/tests/tsigerror_unittest.cc +++ b/src/lib/dns/tests/tsigerror_unittest.cc @@ -1,126 +1 @@ -// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. -#include <config.h> - -#include <string> -#include <ostream> - -#include <gtest/gtest.h> - -#include <exceptions/exceptions.h> - -#include <dns/rcode.h> -#include <dns/tsigerror.h> - -using namespace std; -using namespace isc; -using namespace isc::dns; - -namespace { -TEST(TSIGErrorTest, constructFromErrorCode) { - // These are pretty trivial, and also test getCode(); - EXPECT_EQ(0, TSIGError(0).getCode()); - EXPECT_EQ(18, TSIGError(18).getCode()); - EXPECT_EQ(65535, TSIGError(65535).getCode()); -} - -TEST(TSIGErrorTest, constructFromRcode) { - // We use RCODE for code values from 0-15. - EXPECT_EQ(0, TSIGError(Rcode::NOERROR()).getCode()); - EXPECT_EQ(15, TSIGError(Rcode(15)).getCode()); - - // From error code 16 TSIG errors define a separate space, so passing - // corresponding RCODE for such code values should be prohibited. - EXPECT_THROW(TSIGError(Rcode(16)).getCode(), OutOfRange); -} - -TEST(TSIGErrorTest, constants) { - // We'll only test arbitrarily chosen subsets of the codes. - // This class is quite simple, so it should be suffice. - - EXPECT_EQ(TSIGError::BAD_SIG_CODE, TSIGError(16).getCode()); - EXPECT_EQ(TSIGError::BAD_KEY_CODE, TSIGError(17).getCode()); - EXPECT_EQ(TSIGError::BAD_TIME_CODE, TSIGError(18).getCode()); - EXPECT_EQ(TSIGError::BAD_MODE_CODE, TSIGError(19).getCode()); - EXPECT_EQ(TSIGError::BAD_NAME_CODE, TSIGError(20).getCode()); - EXPECT_EQ(TSIGError::BAD_ALG_CODE, TSIGError(21).getCode()); - EXPECT_EQ(TSIGError::BAD_TRUNC_CODE, TSIGError(22).getCode()); - - EXPECT_EQ(0, TSIGError::NOERROR().getCode()); - EXPECT_EQ(9, TSIGError::NOTAUTH().getCode()); - EXPECT_EQ(14, TSIGError::RESERVED14().getCode()); - EXPECT_EQ(TSIGError::BAD_SIG_CODE, TSIGError::BAD_SIG().getCode()); - EXPECT_EQ(TSIGError::BAD_KEY_CODE, TSIGError::BAD_KEY().getCode()); - EXPECT_EQ(TSIGError::BAD_TIME_CODE, TSIGError::BAD_TIME().getCode()); - EXPECT_EQ(TSIGError::BAD_MODE_CODE, TSIGError::BAD_MODE().getCode()); - EXPECT_EQ(TSIGError::BAD_NAME_CODE, TSIGError::BAD_NAME().getCode()); - EXPECT_EQ(TSIGError::BAD_ALG_CODE, TSIGError::BAD_ALG().getCode()); - EXPECT_EQ(TSIGError::BAD_TRUNC_CODE, TSIGError::BAD_TRUNC().getCode()); -} - -TEST(TSIGErrorTest, equal) { - EXPECT_TRUE(TSIGError::NOERROR() == TSIGError(Rcode::NOERROR())); - EXPECT_TRUE(TSIGError(Rcode::NOERROR()) == TSIGError::NOERROR()); - EXPECT_TRUE(TSIGError::NOERROR().equals(TSIGError(Rcode::NOERROR()))); - EXPECT_TRUE(TSIGError::NOERROR().equals(TSIGError(Rcode::NOERROR()))); - - EXPECT_TRUE(TSIGError::BAD_SIG() == TSIGError(16)); - EXPECT_TRUE(TSIGError(16) == TSIGError::BAD_SIG()); - EXPECT_TRUE(TSIGError::BAD_SIG().equals(TSIGError(16))); - EXPECT_TRUE(TSIGError(16).equals(TSIGError::BAD_SIG())); -} - -TEST(TSIGErrorTest, nequal) { - EXPECT_TRUE(TSIGError::BAD_KEY() != TSIGError(Rcode::NOERROR())); - EXPECT_TRUE(TSIGError(Rcode::NOERROR()) != TSIGError::BAD_KEY()); - EXPECT_TRUE(TSIGError::BAD_KEY().nequals(TSIGError(Rcode::NOERROR()))); - EXPECT_TRUE(TSIGError(Rcode::NOERROR()).nequals(TSIGError::BAD_KEY())); -} - -TEST(TSIGErrorTest, toText) { - // TSIGError derived from the standard Rcode - EXPECT_EQ("NOERROR", TSIGError(Rcode::NOERROR()).toText()); - - // Well known TSIG errors - EXPECT_EQ("BADSIG", TSIGError::BAD_SIG().toText()); - EXPECT_EQ("BADKEY", TSIGError::BAD_KEY().toText()); - EXPECT_EQ("BADTIME", TSIGError::BAD_TIME().toText()); - EXPECT_EQ("BADMODE", TSIGError::BAD_MODE().toText()); - EXPECT_EQ("BADNAME", TSIGError::BAD_NAME().toText()); - EXPECT_EQ("BADALG", TSIGError::BAD_ALG().toText()); - EXPECT_EQ("BADTRUNC", TSIGError::BAD_TRUNC().toText()); - - // Unknown (or not yet supported) codes. Simply converted as numeric. - EXPECT_EQ("23", TSIGError(23).toText()); - EXPECT_EQ("65535", TSIGError(65535).toText()); -} - -TEST(TSIGErrorTest, toRcode) { - // TSIGError derived from the standard Rcode - EXPECT_EQ(Rcode::NOERROR(), TSIGError(Rcode::NOERROR()).toRcode()); - - // Well known TSIG errors - EXPECT_EQ(Rcode::NOTAUTH(), TSIGError::BAD_SIG().toRcode()); - EXPECT_EQ(Rcode::NOTAUTH(), TSIGError::BAD_KEY().toRcode()); - EXPECT_EQ(Rcode::NOTAUTH(), TSIGError::BAD_TIME().toRcode()); - EXPECT_EQ(Rcode::NOTAUTH(), TSIGError::BAD_MODE().toRcode()); - EXPECT_EQ(Rcode::NOTAUTH(), TSIGError::BAD_NAME().toRcode()); - EXPECT_EQ(Rcode::NOTAUTH(), TSIGError::BAD_ALG().toRcode()); - EXPECT_EQ(Rcode::NOTAUTH(), TSIGError::BAD_TRUNC().toRcode()); - - // Unknown (or not yet supported) codes are treated as SERVFAIL. - EXPECT_EQ(Rcode::SERVFAIL(), TSIGError(23).toRcode()); - EXPECT_EQ(Rcode::SERVFAIL(), TSIGError(65535).toRcode()); -} - -// test operator<<. We simply confirm it appends the result of toText(). -TEST(TSIGErrorTest, LeftShiftOperator) { - ostringstream oss; - oss << TSIGError::BAD_KEY(); - EXPECT_EQ(TSIGError::BAD_KEY().toText(), oss.str()); -} -} // end namespace diff --git a/src/lib/dns/tests/tsigkey_unittest.cc b/src/lib/dns/tests/tsigkey_unittest.cc index 90c59ac112..8b13789179 100644 --- a/src/lib/dns/tests/tsigkey_unittest.cc +++ b/src/lib/dns/tests/tsigkey_unittest.cc @@ -1,350 +1 @@ -// Copyright (C) 2021-2019 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. -#include <config.h> - -#include <string> - -#include <gtest/gtest.h> - -#include <exceptions/exceptions.h> - -#include <cryptolink/cryptolink.h> - -#include <dns/tsigkey.h> - -#include <dns/tests/unittest_util.h> -#include <util/unittests/wiredata.h> - -using namespace std; -using namespace isc::dns; -using isc::UnitTestUtil; -using isc::util::unittests::matchWireData; - -namespace { -class TSIGKeyTest : public ::testing::Test { -protected: - TSIGKeyTest() : secret("someRandomData"), key_name("example.com") {} - string secret; - const Name key_name; -}; - -TEST_F(TSIGKeyTest, algorithmNames) { - EXPECT_EQ(Name("hmac-md5.sig-alg.reg.int"), TSIGKey::HMACMD5_NAME()); - EXPECT_EQ(Name("hmac-md5"), TSIGKey::HMACMD5_SHORT_NAME()); - EXPECT_EQ(Name("hmac-sha1"), TSIGKey::HMACSHA1_NAME()); - EXPECT_EQ(Name("hmac-sha256"), TSIGKey::HMACSHA256_NAME()); - EXPECT_EQ(Name("hmac-sha224"), TSIGKey::HMACSHA224_NAME()); - EXPECT_EQ(Name("hmac-sha384"), TSIGKey::HMACSHA384_NAME()); - EXPECT_EQ(Name("hmac-sha512"), TSIGKey::HMACSHA512_NAME()); - EXPECT_EQ(Name("gss-tsig"), TSIGKey::GSSTSIG_NAME()); - - // Also check conversion to cryptolink definitions - EXPECT_EQ(isc::cryptolink::MD5, TSIGKey(key_name, TSIGKey::HMACMD5_NAME(), - NULL, 0).getAlgorithm()); - EXPECT_EQ(isc::cryptolink::MD5, - TSIGKey(key_name, TSIGKey::HMACMD5_SHORT_NAME(), - NULL, 0).getAlgorithm()); - EXPECT_EQ(isc::cryptolink::SHA1, TSIGKey(key_name, TSIGKey::HMACSHA1_NAME(), - NULL, 0).getAlgorithm()); - EXPECT_EQ(isc::cryptolink::SHA256, TSIGKey(key_name, - TSIGKey::HMACSHA256_NAME(), - NULL, 0).getAlgorithm()); - EXPECT_EQ(isc::cryptolink::SHA224, TSIGKey(key_name, - TSIGKey::HMACSHA224_NAME(), - NULL, 0).getAlgorithm()); - EXPECT_EQ(isc::cryptolink::SHA384, TSIGKey(key_name, - TSIGKey::HMACSHA384_NAME(), - NULL, 0).getAlgorithm()); - EXPECT_EQ(isc::cryptolink::SHA512, TSIGKey(key_name, - TSIGKey::HMACSHA512_NAME(), - NULL, 0).getAlgorithm()); -} - -TEST_F(TSIGKeyTest, construct) { - TSIGKey key(key_name, TSIGKey::HMACMD5_NAME(), - secret.c_str(), secret.size()); - EXPECT_EQ(key_name, key.getKeyName()); - EXPECT_EQ(Name("hmac-md5.sig-alg.reg.int"), key.getAlgorithmName()); - 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_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"), - secret.c_str(), secret.size()), - isc::InvalidParameter); - TSIGKey key2(key_name, Name("unknown-alg"), NULL, 0); - EXPECT_EQ(key_name, key2.getKeyName()); - EXPECT_EQ(Name("unknown-alg"), key2.getAlgorithmName()); - - // The algorithm name should be converted to the canonical form. - EXPECT_EQ("hmac-sha1.", - TSIGKey(key_name, Name("HMAC-sha1"), - secret.c_str(), - secret.size()).getAlgorithmName().toText()); - - // Same for key name - EXPECT_EQ("example.com.", - TSIGKey(Name("EXAMPLE.CoM."), TSIGKey::HMACSHA256_NAME(), - secret.c_str(), - secret.size()).getKeyName().toText()); - - // Check digestbits - EXPECT_EQ(key.getDigestbits(), 0); - TSIGKey key_trunc(key_name, TSIGKey::HMACMD5_NAME(), - secret.c_str(), secret.size(), 120); - EXPECT_EQ(key_trunc.getDigestbits(), 120); - - // Invalid combinations of secret and secret_len: - EXPECT_THROW(TSIGKey(key_name, TSIGKey::HMACSHA1_NAME(), secret.c_str(), 0), - isc::InvalidParameter); - EXPECT_THROW(TSIGKey(key_name, TSIGKey::HMACSHA256_NAME(), NULL, 16), - isc::InvalidParameter); - - // Empty secret - TSIGKey keye = TSIGKey(key_name, TSIGKey::HMACSHA256_NAME(), NULL, 0); - EXPECT_EQ(keye.getSecretLength(), 0); - EXPECT_EQ(keye.getSecret(), (const void*)0); -} - -void -compareTSIGKeys(const TSIGKey& expect, const TSIGKey& actual) { - EXPECT_EQ(expect.getKeyName(), actual.getKeyName()); - EXPECT_EQ(expect.getAlgorithmName(), actual.getAlgorithmName()); - EXPECT_EQ(expect.getDigestbits(), actual.getDigestbits()); - matchWireData(expect.getSecret(), expect.getSecretLength(), - actual.getSecret(), actual.getSecretLength()); -} - -TEST_F(TSIGKeyTest, copyConstruct) { - const TSIGKey original(key_name, TSIGKey::HMACSHA256_NAME(), - secret.c_str(), secret.size(), 128); - const TSIGKey copy(original); - compareTSIGKeys(original, copy); - - // Check the copied data is valid even after the original is deleted - TSIGKey* copy2 = new TSIGKey(original); - TSIGKey copy3(*copy2); - delete copy2; - compareTSIGKeys(original, copy3); -} - -TEST_F(TSIGKeyTest, assignment) { - const TSIGKey original(key_name, TSIGKey::HMACSHA256_NAME(), - secret.c_str(), secret.size(), 200); - TSIGKey copy = original; - compareTSIGKeys(original, copy); - - // Check if the copied data is valid even after the original is deleted - TSIGKey* copy2 = new TSIGKey(original); - TSIGKey copy3(original); - copy3 = *copy2; - delete copy2; - compareTSIGKeys(original, copy3); - - // Self assignment - copy = *© - compareTSIGKeys(original, copy); -} - -class TSIGKeyRingTest : public ::testing::Test { -protected: - TSIGKeyRingTest() : - key_name("example.com"), - md5_name("hmac-md5.sig-alg.reg.int"), - sha1_name("hmac-sha1"), - sha256_name("hmac-sha256"), - secretstring("anotherRandomData"), - secret(secretstring.c_str()), - secret_len(secretstring.size()) - {} - TSIGKeyRing keyring; - const Name key_name; - const Name md5_name; - const Name sha1_name; - const Name sha256_name; -private: - const string secretstring; -protected: - const char* secret; - size_t secret_len; -}; - -TEST_F(TSIGKeyRingTest, init) { - EXPECT_EQ(0, keyring.size()); -} - -TEST_F(TSIGKeyRingTest, add) { - EXPECT_EQ(TSIGKeyRing::SUCCESS, keyring.add( - TSIGKey(key_name, TSIGKey::HMACSHA256_NAME(), - secret, secret_len))); - EXPECT_EQ(1, keyring.size()); - EXPECT_EQ(TSIGKeyRing::EXIST, keyring.add( - TSIGKey(key_name, TSIGKey::HMACSHA256_NAME(), - secret, secret_len))); - // keys are identified by their names, the same name of key with a - // different algorithm would be considered a duplicate. - EXPECT_EQ(TSIGKeyRing::EXIST, keyring.add( - TSIGKey(Name("example.com"), TSIGKey::HMACSHA1_NAME(), - secret, secret_len))); - // names are compared in a case insensitive manner. - EXPECT_EQ(TSIGKeyRing::EXIST, keyring.add( - TSIGKey(Name("EXAMPLE.COM"), TSIGKey::HMACSHA1_NAME(), - secret, secret_len))); - EXPECT_EQ(1, keyring.size()); -} - -TEST_F(TSIGKeyRingTest, addMore) { - // essentially the same test, but try adding more than 1 - EXPECT_EQ(TSIGKeyRing::SUCCESS, keyring.add( - TSIGKey(key_name, TSIGKey::HMACSHA256_NAME(), - secret, secret_len))); - EXPECT_EQ(TSIGKeyRing::SUCCESS, keyring.add( - TSIGKey(Name("another.example"), TSIGKey::HMACMD5_NAME(), - secret, secret_len))); - EXPECT_EQ(TSIGKeyRing::SUCCESS, keyring.add( - TSIGKey(Name("more.example"), TSIGKey::HMACSHA1_NAME(), - secret, secret_len))); - EXPECT_EQ(3, keyring.size()); -} - -TEST_F(TSIGKeyRingTest, remove) { - EXPECT_EQ(TSIGKeyRing::SUCCESS, keyring.add( - TSIGKey(key_name, TSIGKey::HMACSHA256_NAME(), - secret, secret_len))); - EXPECT_EQ(TSIGKeyRing::SUCCESS, keyring.remove(key_name)); - EXPECT_EQ(TSIGKeyRing::NOTFOUND, keyring.remove(key_name)); -} - -TEST_F(TSIGKeyRingTest, removeFromSome) { - // essentially the same test, but try removing from a larger set - - EXPECT_EQ(TSIGKeyRing::SUCCESS, keyring.add( - TSIGKey(key_name, TSIGKey::HMACSHA256_NAME(), - secret, secret_len))); - EXPECT_EQ(TSIGKeyRing::SUCCESS, keyring.add( - TSIGKey(Name("another.example"), TSIGKey::HMACMD5_NAME(), - secret, secret_len))); - EXPECT_EQ(TSIGKeyRing::SUCCESS, keyring.add( - TSIGKey(Name("more.example"), TSIGKey::HMACSHA1_NAME(), - secret, secret_len))); - - EXPECT_EQ(TSIGKeyRing::SUCCESS, keyring.remove(Name("another.example"))); - EXPECT_EQ(TSIGKeyRing::NOTFOUND, keyring.remove(Name("noexist.example"))); - EXPECT_EQ(2, keyring.size()); -} - -TEST_F(TSIGKeyRingTest, find) { - // If the keyring is empty the search should fail. - EXPECT_EQ(TSIGKeyRing::NOTFOUND, keyring.find(key_name, md5_name).code); - EXPECT_EQ(static_cast<const TSIGKey*>(NULL), - keyring.find(key_name, md5_name).key); - - // Add a key and try to find it. Should succeed. - EXPECT_EQ(TSIGKeyRing::SUCCESS, keyring.add(TSIGKey(key_name, sha256_name, - secret, secret_len))); - const TSIGKeyRing::FindResult result1(keyring.find(key_name, sha256_name)); - EXPECT_EQ(TSIGKeyRing::SUCCESS, result1.code); - EXPECT_EQ(key_name, result1.key->getKeyName()); - EXPECT_EQ(TSIGKey::HMACSHA256_NAME(), result1.key->getAlgorithmName()); - 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 = - keyring.find(Name("different-key.example"), sha256_name); - EXPECT_EQ(TSIGKeyRing::NOTFOUND, result2.code); - EXPECT_EQ(static_cast<const TSIGKey*>(NULL), result2.key); - - const TSIGKeyRing::FindResult result3 = keyring.find(key_name, md5_name); - EXPECT_EQ(TSIGKeyRing::NOTFOUND, result3.code); - EXPECT_EQ(static_cast<const TSIGKey*>(NULL), result3.key); - - // But with just the name it should work - const TSIGKeyRing::FindResult result4(keyring.find(key_name)); - EXPECT_EQ(TSIGKeyRing::SUCCESS, result4.code); - EXPECT_EQ(key_name, result4.key->getKeyName()); - EXPECT_EQ(TSIGKey::HMACSHA256_NAME(), result4.key->getAlgorithmName()); - matchWireData(secret, secret_len, - result4.key->getSecret(), result4.key->getSecretLength()); -} - -TEST_F(TSIGKeyRingTest, findFromSome) { - // essentially the same test, but search a larger set - - EXPECT_EQ(TSIGKeyRing::SUCCESS, keyring.add(TSIGKey(key_name, sha256_name, - secret, secret_len))); - EXPECT_EQ(TSIGKeyRing::SUCCESS, keyring.add(TSIGKey(Name("another.example"), - md5_name, - secret, secret_len))); - EXPECT_EQ(TSIGKeyRing::SUCCESS, keyring.add(TSIGKey(Name("more.example"), - sha1_name, - secret, secret_len))); - - const TSIGKeyRing::FindResult result( - keyring.find(Name("another.example"), md5_name)); - EXPECT_EQ(TSIGKeyRing::SUCCESS, result.code); - EXPECT_EQ(Name("another.example"), result.key->getKeyName()); - EXPECT_EQ(TSIGKey::HMACMD5_NAME(), result.key->getAlgorithmName()); - - EXPECT_EQ(TSIGKeyRing::NOTFOUND, - keyring.find(Name("noexist.example"), sha1_name).code); - EXPECT_EQ(static_cast<const TSIGKey*>(NULL), - keyring.find(Name("noexist.example"), sha256_name).key); - - EXPECT_EQ(TSIGKeyRing::NOTFOUND, - keyring.find(Name("another.example"), sha1_name).code); - EXPECT_EQ(static_cast<const TSIGKey*>(NULL), - keyring.find(Name("another.example"), sha256_name).key); -} - -TEST(TSIGStringTest, TSIGKeyFromToString) { - TSIGKey k1 = TSIGKey("test.example:MSG6Ng==:hmac-md5.sig-alg.reg.int"); - TSIGKey k2 = TSIGKey("test.example.:MSG6Ng==:hmac-md5.sig-alg.reg.int."); - TSIGKey k3 = TSIGKey("test.example:MSG6Ng=="); - TSIGKey k4 = TSIGKey("test.example.:MSG6Ng==:hmac-md5.sig-alg.reg.int.:120"); - TSIGKey k5 = TSIGKey(Name("test.example."), Name("hmac-sha1."), NULL, 0); - // "Unknown" key with empty secret is okay - TSIGKey k6 = TSIGKey("test.example.::unknown"); - - EXPECT_EQ("test.example.:MSG6Ng==:hmac-md5.sig-alg.reg.int.", - k1.toText()); - EXPECT_EQ("test.example.:MSG6Ng==:hmac-md5.sig-alg.reg.int.", - k2.toText()); - EXPECT_EQ("test.example.:MSG6Ng==:hmac-md5.sig-alg.reg.int.", - k3.toText()); - EXPECT_EQ("test.example.:MSG6Ng==:hmac-md5.sig-alg.reg.int.:120", - k4.toText()); - EXPECT_EQ(120, k4.getDigestbits()); - EXPECT_EQ("test.example.::hmac-sha1.", k5.toText()); - EXPECT_EQ(Name("test.example."), k6.getKeyName()); - EXPECT_EQ(Name("unknown"), k6.getAlgorithmName()); - - EXPECT_THROW(TSIGKey(""), isc::InvalidParameter); - EXPECT_THROW(TSIGKey(":"), isc::InvalidParameter); - EXPECT_THROW(TSIGKey("::"), isc::InvalidParameter); - EXPECT_THROW(TSIGKey("..:aa:"), isc::InvalidParameter); - EXPECT_THROW(TSIGKey("test.example:xxxx:"), isc::InvalidParameter); - EXPECT_THROW(TSIGKey("test.example.::"), isc::InvalidParameter); - EXPECT_THROW(TSIGKey("test.example.:"), isc::InvalidParameter); - EXPECT_THROW(TSIGKey("test.example.:MSG6Ng==:"), isc::InvalidParameter); - EXPECT_THROW(TSIGKey("test.example.:MSG6Ng==:unknown"), isc::InvalidParameter); - EXPECT_THROW(TSIGKey("test.example.:MSG6Ng==:hmac-md5.sig-alg.reg.int.:"), - isc::InvalidParameter); - EXPECT_THROW(TSIGKey("test.example.:MSG6Ng==:hmac-md5.sig-alg.reg.int.:xxx"), - isc::InvalidParameter); -} - - -} // end namespace diff --git a/src/lib/dns/tests/tsigrecord_unittest.cc b/src/lib/dns/tests/tsigrecord_unittest.cc index 624f03b85e..8b13789179 100644 --- a/src/lib/dns/tests/tsigrecord_unittest.cc +++ b/src/lib/dns/tests/tsigrecord_unittest.cc @@ -1,158 +1 @@ -// Copyright (C) 2011-2023 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. -#include <config.h> - -#include <vector> -#include <sstream> - -#include <gtest/gtest.h> - -#include <util/buffer.h> - -#include <dns/exceptions.h> -#include <dns/messagerenderer.h> -#include <dns/name.h> -#include <dns/rdata.h> -#include <dns/rdataclass.h> -#include <dns/tsig.h> -#include <dns/tsigkey.h> -#include <dns/tsigrecord.h> - -#include <dns/tests/unittest_util.h> -#include <util/unittests/wiredata.h> - -using namespace std; -using namespace isc::util; -using namespace isc::dns; -using namespace isc::dns::rdata; -using namespace isc::dns::rdata::any; -using isc::UnitTestUtil; -using isc::util::unittests::matchWireData; - -namespace { -class TSIGRecordTest : public ::testing::Test { -protected: - TSIGRecordTest() : - test_name("www.example.com"), test_mac(16, 0xda), - test_rdata(TSIG(TSIGKey::HMACMD5_NAME(), 0x4da8877a, TSIGContext::DEFAULT_FUDGE, - test_mac.size(), &test_mac[0], 0x2d65, 0, 0, NULL)), - test_record(test_name, test_rdata), - buffer(0) { - } - - const Name test_name; - - vector<unsigned char> test_mac; - - const TSIG test_rdata; - - const TSIGRecord test_record; - - OutputBuffer buffer; - - MessageRenderer renderer; - - vector<unsigned char> data; -}; - -TEST_F(TSIGRecordTest, getName) { - EXPECT_EQ(test_name, test_record.getName()); -} - -TEST_F(TSIGRecordTest, getLength) { - // 85 = 17 + 26 + 16 + 26 - // len(www.example.com) = 17 - // len(hmac-md5.sig-alg.reg.int) = 26 - // len(MAC) = 16 - // the rest are fixed length fields (26 in total) - EXPECT_EQ(85, test_record.getLength()); -} - -TEST_F(TSIGRecordTest, fromParams) { - // Construct the same TSIG RR as test_record from parameters. - // See the getLength test for the magic number of 85 (although it - // actually doesn't matter) - const TSIGRecord record(test_name, TSIGRecord::getClass(), - TSIGRecord::getTTL(), test_rdata, 85); - // Perform straight sanity checks - EXPECT_EQ(test_name, record.getName()); - EXPECT_EQ(85, record.getLength()); - EXPECT_EQ(0, test_rdata.compare(record.getRdata())); - - // The constructor doesn't check the length... - EXPECT_NO_THROW(TSIGRecord(test_name, TSIGRecord::getClass(), - TSIGRecord::getTTL(), test_rdata, 82)); - // ...even for impossibly small values... - EXPECT_NO_THROW(TSIGRecord(test_name, TSIGRecord::getClass(), - TSIGRecord::getTTL(), test_rdata, 1)); - // ...or too large values. - EXPECT_NO_THROW(TSIGRecord(test_name, TSIGRecord::getClass(), - TSIGRecord::getTTL(), test_rdata, 65536)); - - // RDATA must indeed be TSIG - EXPECT_THROW(TSIGRecord(test_name, TSIGRecord::getClass(), - TSIGRecord::getTTL(), in::A("192.0.2.1"), 85), - DNSMessageFORMERR); - - // Unexpected class - EXPECT_THROW(TSIGRecord(test_name, RRClass::IN(), TSIGRecord::getTTL(), - test_rdata, 85), DNSMessageFORMERR); - - // Unexpected TTL - EXPECT_THROW(TSIGRecord(test_name, TSIGRecord::getClass(), - RRTTL(3600), test_rdata, 85), DNSMessageFORMERR); -} - -TEST_F(TSIGRecordTest, recordToWire) { - UnitTestUtil::readWireData("tsigrecord_toWire1.wire", data); - EXPECT_EQ(1, test_record.toWire(renderer)); - matchWireData(&data[0], data.size(), - renderer.getData(), renderer.getLength()); - - // Same test for a dumb buffer - buffer.clear(); - EXPECT_EQ(1, test_record.toWire(buffer)); - matchWireData(&data[0], data.size(), - buffer.getData(), buffer.getLength()); -} - -TEST_F(TSIGRecordTest, recordToOLongToWire) { - // By setting the limit to "record length - 1", it will fail, and the - // renderer will be marked as "truncated". - renderer.setLengthLimit(test_record.getLength() - 1); - EXPECT_FALSE(renderer.isTruncated()); // not marked before render attempt - EXPECT_EQ(0, test_record.toWire(renderer)); - EXPECT_TRUE(renderer.isTruncated()); -} - -TEST_F(TSIGRecordTest, recordToWireAfterNames) { - // A similar test but the TSIG RR follows some domain names that could - // cause name compression inside TSIG. Our implementation shouldn't - // compress either owner (key) name or the algorithm name. This test - // confirms that. - - UnitTestUtil::readWireData("tsigrecord_toWire2.wire", data); - renderer.writeName(TSIGKey::HMACMD5_NAME()); - renderer.writeName(Name("foo.example.com")); - EXPECT_EQ(1, test_record.toWire(renderer)); - matchWireData(&data[0], data.size(), - renderer.getData(), renderer.getLength()); -} - -TEST_F(TSIGRecordTest, toText) { - EXPECT_EQ("www.example.com. 0 ANY TSIG hmac-md5.sig-alg.reg.int. " - "1302890362 300 16 2tra2tra2tra2tra2tra2g== 11621 NOERROR 0\n", - test_record.toText()); -} - -// test operator<<. We simply confirm it appends the result of toText(). -TEST_F(TSIGRecordTest, LeftShiftOperator) { - ostringstream oss; - oss << test_record; - EXPECT_EQ(test_record.toText(), oss.str()); -} -} // end namespace diff --git a/src/lib/dns/tests/unittest_util.cc b/src/lib/dns/tests/unittest_util.cc index b234c1cf9d..a86203d3dc 100644 --- a/src/lib/dns/tests/unittest_util.cc +++ b/src/lib/dns/tests/unittest_util.cc @@ -21,7 +21,7 @@ #include <dns/tests/unittest_util.h> using namespace std; -using namespace isc::dns; +//using namespace isc::dns; using isc::UnitTestUtil; @@ -94,8 +94,7 @@ UnitTestUtil::addDataPath(const string& directory) { void UnitTestUtil::readWireData(const string& datastr, - vector<unsigned char>& data) -{ + vector<unsigned char>& data) { istringstream iss(datastr); do { @@ -122,55 +121,3 @@ UnitTestUtil::readWireData(const string& datastr, } } while (!iss.eof()); } - -::testing::AssertionResult -UnitTestUtil::matchName(const char*, const char*, - const isc::dns::Name& name1, - const isc::dns::Name& name2) -{ - ::testing::Message msg; - - NameComparisonResult cmpresult = name1.compare(name2); - if (cmpresult.getOrder() != 0 || - cmpresult.getRelation() != NameComparisonResult::EQUAL) { - msg << "Two names are expected to be equal but not:\n" - << " One: " << name1 << "\n" - << "Other: " << name2 << "\n"; - return (::testing::AssertionFailure(msg)); - } - return (::testing::AssertionSuccess()); -} - -void -UnitTestUtil::createRequestMessage(Message& message, - const Opcode& opcode, - const uint16_t qid, - const Name& name, - const RRClass& rrclass, - const RRType& rrtype) -{ - message.clear(Message::RENDER); - message.setOpcode(opcode); - message.setRcode(Rcode::NOERROR()); - message.setQid(qid); - message.addQuestion(Question(name, rrclass, rrtype)); -} - -void -UnitTestUtil::createDNSSECRequestMessage(Message& message, - const Opcode& opcode, - const uint16_t qid, - const Name& name, - const RRClass& rrclass, - const RRType& rrtype) -{ - message.clear(Message::RENDER); - message.setOpcode(opcode); - message.setRcode(Rcode::NOERROR()); - message.setQid(qid); - message.addQuestion(Question(name, rrclass, rrtype)); - EDNSPtr edns(new EDNS()); - edns->setUDPSize(4096); - edns->setDNSSECAwareness(true); - message.setEDNS(edns); -} diff --git a/src/lib/dns/tests/unittest_util.h b/src/lib/dns/tests/unittest_util.h index 8c6b8f56cd..f1af813de0 100644 --- a/src/lib/dns/tests/unittest_util.h +++ b/src/lib/dns/tests/unittest_util.h @@ -37,48 +37,6 @@ public: static void readWireData(const std::string& datastr, std::vector<unsigned char>& data); - /// - /// Compare two names. - /// - /// This check method uses \c Name::compare() for comparison, which performs - /// deeper checks including the equality of offsets, and should be better - /// than EXPECT_EQ, which uses operator==. Like the \c matchWireData() - /// method, the usage is a bit awkward; the caller should use - /// \c EXPECT_PRED_FORMAT2. - /// - static ::testing::AssertionResult - matchName(const char* nameexp1, const char* nameexp2, - const isc::dns::Name& name1, const isc::dns::Name& name2); - - /// - /// Populate a request message - /// - /// Create a request message in 'request_message' using the - /// opcode 'opcode' and the name/class/type query tuple specified in - /// 'name', 'rrclass' and 'rrtype. - static void - createRequestMessage(isc::dns::Message& request_message, - const isc::dns::Opcode& opcode, - const uint16_t qid, - const isc::dns::Name& name, - const isc::dns::RRClass& rrclass, - const isc::dns::RRType& rrtype); - - /// - /// Populate a DNSSEC request message - /// - /// Create a request message in 'request_message' using the - /// opcode 'opcode' and the name/class/type query tuple specified in - /// 'name', 'rrclass' and 'rrtype. - /// EDNS will be added with DO=1 and bufsize 4096 - static void - createDNSSECRequestMessage(isc::dns::Message& request_message, - const isc::dns::Opcode& opcode, - const uint16_t qid, - const isc::dns::Name& name, - const isc::dns::RRClass& rrclass, - const isc::dns::RRType& rrtype); - }; } #endif // UNITTEST_UTIL_H diff --git a/src/lib/dns/tests/zone_checker_unittest.cc b/src/lib/dns/tests/zone_checker_unittest.cc index 863b439eb4..8b13789179 100644 --- a/src/lib/dns/tests/zone_checker_unittest.cc +++ b/src/lib/dns/tests/zone_checker_unittest.cc @@ -1,349 +1 @@ -// Copyright (C) 2012-2020 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. -#include <config.h> - -#include <dns/zone_checker.h> - -#include <exceptions/exceptions.h> - -#include <dns/name.h> -#include <dns/rrclass.h> -#include <dns/rrset.h> -#include <dns/rrtype.h> -#include <dns/rrttl.h> -#include <dns/rdataclass.h> -#include <dns/rrset_collection.h> - -#include <gtest/gtest.h> - -#include <boost/scoped_ptr.hpp> - -#include <algorithm> -#include <functional> -#include <string> -#include <sstream> -#include <vector> - -using isc::Unexpected; -using namespace isc::dns; -using namespace isc::dns::rdata; -namespace ph = std::placeholders; - -namespace { - -const char* const soa_txt = "ns.example.com. root.example.com. 0 0 0 0 0"; -const char* const ns_txt1 = "ns.example.com."; -const char* const ns_a_txt1 = "192.0.2.1"; -const char* const ns_txt2 = "ns2.example.com."; -const char* const ns_a_txt2 = "192.0.2.2"; - -class ZoneCheckerTest : public ::testing::Test { -protected: - ZoneCheckerTest() : - zname_("example.com"), zclass_(RRClass::IN()), - soa_(new RRset(zname_, zclass_, RRType::SOA(), RRTTL(60))), - ns_(new RRset(zname_, zclass_, RRType::NS(), RRTTL(60))), - callbacks_(std::bind(&ZoneCheckerTest::callback, this, ph::_1, true), - std::bind(&ZoneCheckerTest::callback, this, ph::_1, false)) - { - std::stringstream ss; - ss << "example.com. 60 IN SOA " << soa_txt << "\n"; - ss << "example.com. 60 IN NS " << ns_txt1 << "\n"; - ss << "ns.example.com. 60 IN A " << ns_a_txt1 << "\n"; - ss << "ns2.example.com. 60 IN A " << ns_a_txt2 << "\n"; - rrsets_.reset(new RRsetCollection(ss, zname_, zclass_)); - } - -public: - // This one is passed to std::bind. Some compilers seem to require - // it be public. - void callback(const std::string& reason, bool is_error) { - if (is_error) { - errors_.push_back(reason); - } else { - warns_.push_back(reason); - } - } - -protected: - // Check stored issue messages with expected ones. Clear vectors so - // the caller can check other cases. - void checkIssues() { - EXPECT_EQ(expected_errors_.size(), errors_.size()); - for (size_t i = 0; - i < std::min(expected_errors_.size(), errors_.size()); - ++i) { - // The actual message should begin with the expected message. - EXPECT_EQ(0, errors_[0].find(expected_errors_[0])) - << "actual message: " << errors_[0] << " expected: " << - expected_errors_[0]; - } - EXPECT_EQ(expected_warns_.size(), warns_.size()); - for (size_t i = 0; - i < std::min(expected_warns_.size(), warns_.size()); - ++i) { - EXPECT_EQ(0, warns_[0].find(expected_warns_[0])) - << "actual message: " << warns_[0] << " expected: " << - expected_warns_[0]; - } - - errors_.clear(); - expected_errors_.clear(); - warns_.clear(); - expected_warns_.clear(); - } - - const Name zname_; - const RRClass zclass_; - boost::scoped_ptr<RRsetCollection> rrsets_; - RRsetPtr soa_; - RRsetPtr ns_; - std::vector<std::string> errors_; - std::vector<std::string> warns_; - std::vector<std::string> expected_errors_; - std::vector<std::string> expected_warns_; - ZoneCheckerCallbacks callbacks_; -}; - -TEST_F(ZoneCheckerTest, checkGood) { - // Checking a valid case. No errors or warnings should be reported. - EXPECT_TRUE(checkZone(zname_, zclass_, *rrsets_, callbacks_)); - checkIssues(); - - // Multiple NS RRs are okay. - rrsets_->removeRRset(zname_, zclass_, RRType::NS()); - ns_->addRdata(generic::NS(ns_txt1)); - ns_->addRdata(generic::NS(ns_txt2)); - rrsets_->addRRset(ns_); - EXPECT_TRUE(checkZone(zname_, zclass_, *rrsets_, callbacks_)); - checkIssues(); -} - -TEST_F(ZoneCheckerTest, checkSOA) { - // If the zone has no SOA it triggers an error. - rrsets_->removeRRset(zname_, zclass_, RRType::SOA()); - EXPECT_FALSE(checkZone(zname_, zclass_, *rrsets_, callbacks_)); - expected_errors_.push_back("zone example.com/IN: has 0 SOA records"); - checkIssues(); - - // If null callback is specified, checkZone() only returns the final - // result. - ZoneCheckerCallbacks noerror_callbacks( - 0, std::bind(&ZoneCheckerTest::callback, this, ph::_1, false)); - EXPECT_FALSE(checkZone(zname_, zclass_, *rrsets_, noerror_callbacks)); - checkIssues(); - - // If there are more than 1 SOA RR, it's also an error. - errors_.clear(); - soa_->addRdata(generic::SOA(soa_txt)); - soa_->addRdata(generic::SOA("ns2.example.com. . 0 0 0 0 0")); - rrsets_->addRRset(soa_); - EXPECT_FALSE(checkZone(zname_, zclass_, *rrsets_, callbacks_)); - expected_errors_.push_back("zone example.com/IN: has 2 SOA records"); - checkIssues(); - - // If the SOA RRset is "empty", it's treated as an implementation - // (rather than operational) error and results in an exception. - rrsets_->removeRRset(zname_, zclass_, RRType::SOA()); - soa_.reset(new RRset(zname_, zclass_, RRType::SOA(), RRTTL(60))); - rrsets_->addRRset(soa_); - EXPECT_THROW(checkZone(zname_, zclass_, *rrsets_, callbacks_), Unexpected); - checkIssues(); // no error/warning should be reported - - // Likewise, if the SOA RRset contains non SOA Rdata, it should be a bug. - rrsets_->removeRRset(zname_, zclass_, RRType::SOA()); - soa_.reset(new RRset(zname_, zclass_, RRType::SOA(), RRTTL(60))); - soa_->addRdata(createRdata(RRType::NS(), zclass_, "ns.example.com.")); - rrsets_->addRRset(soa_); - EXPECT_THROW(checkZone(zname_, zclass_, *rrsets_, callbacks_), Unexpected); - checkIssues(); // no error/warning should be reported -} - -TEST_F(ZoneCheckerTest, checkNS) { - // If the zone has no NS at origin it triggers an error. - rrsets_->removeRRset(zname_, zclass_, RRType::NS()); - EXPECT_FALSE(checkZone(zname_, zclass_, *rrsets_, callbacks_)); - expected_errors_.push_back("zone example.com/IN: has no NS records"); - checkIssues(); - - // Check two buggy cases like the SOA tests - ns_.reset(new RRset(zname_, zclass_, RRType::NS(), RRTTL(60))); - rrsets_->addRRset(ns_); - EXPECT_THROW(checkZone(zname_, zclass_, *rrsets_, callbacks_), Unexpected); - checkIssues(); // no error/warning should be reported - - rrsets_->removeRRset(zname_, zclass_, RRType::NS()); - ns_.reset(new RRset(zname_, zclass_, RRType::NS(), RRTTL(60))); - ns_->addRdata(createRdata(RRType::TXT(), zclass_, "ns.example.com")); - rrsets_->addRRset(ns_); - EXPECT_THROW(checkZone(zname_, zclass_, *rrsets_, callbacks_), Unexpected); - checkIssues(); // no error/warning should be reported -} - -TEST_F(ZoneCheckerTest, checkNSData) { - const Name ns_name("ns.example.com"); - - // If a ("in-bailiwick") NS name doesn't have an address record, it's - // reported as a warning. - rrsets_->removeRRset(ns_name, zclass_, RRType::A()); - EXPECT_TRUE(checkZone(zname_, zclass_, *rrsets_, callbacks_)); - expected_warns_.push_back("zone example.com/IN: NS has no address"); - checkIssues(); - - // Same check, but disabling warning callback. Same result, but without - // the warning. - ZoneCheckerCallbacks nowarn_callbacks( - std::bind(&ZoneCheckerTest::callback, this, ph::_1, true), 0); - EXPECT_TRUE(checkZone(zname_, zclass_, *rrsets_, nowarn_callbacks)); - checkIssues(); - - // A tricky case: if the name matches a wildcard, it should technically - // be considered valid, but this checker doesn't check that far and still - // warns. - RRsetPtr wild(new RRset(Name("*.example.com"), zclass_, RRType::A(), - RRTTL(0))); - wild->addRdata(in::A("192.0.2.255")); - rrsets_->addRRset(wild); - EXPECT_TRUE(checkZone(zname_, zclass_, *rrsets_, callbacks_)); - expected_warns_.push_back("zone example.com/IN: NS has no address"); - checkIssues(); - - // If there's a CNAME at the name instead, it's an error. - rrsets_->removeRRset(Name("*.example.com"), zclass_, RRType::A()); - RRsetPtr cname(new RRset(ns_name, zclass_, RRType::CNAME(), RRTTL(60))); - cname->addRdata(generic::CNAME("cname.example.com.")); - rrsets_->addRRset(cname); - EXPECT_FALSE(checkZone(zname_, zclass_, *rrsets_, callbacks_)); - expected_errors_.push_back("zone example.com/IN: NS 'ns.example.com' is " - "a CNAME (illegal per RFC2181)"); - checkIssues(); - - // It doesn't have to be A. An AAAA is enough. - rrsets_->removeRRset(ns_name, zclass_, RRType::CNAME()); - RRsetPtr aaaa(new RRset(ns_name, zclass_, RRType::AAAA(), RRTTL(60))); - aaaa->addRdata(in::AAAA("2001:db8::1")); - rrsets_->addRRset(aaaa); - EXPECT_TRUE(checkZone(zname_, zclass_, *rrsets_, callbacks_)); - checkIssues(); - - // Coexisting CNAME makes it error (CNAME with other record is itself - // invalid, but it's a different issue in this context) - rrsets_->addRRset(cname); - EXPECT_FALSE(checkZone(zname_, zclass_, *rrsets_, callbacks_)); - expected_errors_.push_back("zone example.com/IN: NS 'ns.example.com' is " - "a CNAME (illegal per RFC2181)"); - checkIssues(); - - // It doesn't matter if the NS name is "out of bailiwick". - rrsets_->removeRRset(ns_name, zclass_, RRType::CNAME()); - rrsets_->removeRRset(zname_, zclass_, RRType::NS()); - ns_.reset(new RRset(zname_, zclass_, RRType::NS(), RRTTL(60))); - ns_->addRdata(generic::NS("ns.example.org.")); - rrsets_->addRRset(ns_); - EXPECT_TRUE(checkZone(zname_, zclass_, *rrsets_, callbacks_)); - checkIssues(); - - // Note that if the NS name is the origin name, it should be checked - rrsets_->removeRRset(zname_, zclass_, RRType::NS()); - ns_.reset(new RRset(zname_, zclass_, RRType::NS(), RRTTL(60))); - ns_->addRdata(generic::NS(zname_)); - rrsets_->addRRset(ns_); - EXPECT_TRUE(checkZone(zname_, zclass_, *rrsets_, callbacks_)); - expected_warns_.push_back("zone example.com/IN: NS has no address"); - checkIssues(); -} - -TEST_F(ZoneCheckerTest, checkNSWithDelegation) { - // Tests various cases where there's a zone cut due to delegation between - // the zone origin and the NS name. In each case the NS name doesn't have - // an address record. - const Name ns_name("ns.child.example.com"); - - // Zone cut due to delegation in the middle; the check for the address - // record should be skipped. - rrsets_->removeRRset(zname_, zclass_, RRType::NS()); - ns_.reset(new RRset(zname_, zclass_, RRType::NS(), RRTTL(60))); - ns_->addRdata(generic::NS(ns_name)); - rrsets_->addRRset(ns_); - RRsetPtr child_ns(new RRset(Name("child.example.com"), zclass_, - RRType::NS(), RRTTL(60))); - child_ns->addRdata(generic::NS("ns.example.org.")); - rrsets_->addRRset(child_ns); - EXPECT_TRUE(checkZone(zname_, zclass_, *rrsets_, callbacks_)); - checkIssues(); - - // Zone cut at the NS name. Same result. - rrsets_->removeRRset(child_ns->getName(), zclass_, RRType::NS()); - child_ns.reset(new RRset(ns_name, zclass_, RRType::NS(), RRTTL(60))); - child_ns->addRdata(generic::NS("ns.example.org.")); - rrsets_->addRRset(child_ns); - EXPECT_TRUE(checkZone(zname_, zclass_, *rrsets_, callbacks_)); - checkIssues(); - - // Zone cut below the NS name. The check applies. - rrsets_->removeRRset(child_ns->getName(), zclass_, RRType::NS()); - child_ns.reset(new RRset(Name("another.ns.child.example.com"), zclass_, - RRType::NS(), RRTTL(60))); - child_ns->addRdata(generic::NS("ns.example.org.")); - rrsets_->addRRset(child_ns); - EXPECT_TRUE(checkZone(zname_, zclass_, *rrsets_, callbacks_)); - expected_warns_.push_back("zone example.com/IN: NS has no address"); - checkIssues(); -} - -TEST_F(ZoneCheckerTest, checkNSWithDNAME) { - // Similar to the above case, but the zone cut is due to DNAME. This is - // an invalid configuration. - const Name ns_name("ns.child.example.com"); - - // Zone cut due to DNAME at the zone origin. This is an invalid case. - rrsets_->removeRRset(zname_, zclass_, RRType::NS()); - ns_.reset(new RRset(zname_, zclass_, RRType::NS(), RRTTL(60))); - ns_->addRdata(generic::NS(ns_name)); - rrsets_->addRRset(ns_); - RRsetPtr dname(new RRset(zname_, zclass_, RRType::DNAME(), RRTTL(60))); - dname->addRdata(generic::DNAME("example.org.")); - rrsets_->addRRset(dname); - EXPECT_FALSE(checkZone(zname_, zclass_, *rrsets_, callbacks_)); - expected_errors_.push_back("zone example.com/IN: NS 'ns.child.example.com'" - " is below a DNAME 'example.com'"); - checkIssues(); - - // Zone cut due to DNAME in the middle. Same result. - rrsets_->removeRRset(zname_, zclass_, RRType::DNAME()); - dname.reset(new RRset(Name("child.example.com"), zclass_, RRType::DNAME(), - RRTTL(60))); - dname->addRdata(generic::DNAME("example.org.")); - rrsets_->addRRset(dname); - EXPECT_FALSE(checkZone(zname_, zclass_, *rrsets_, callbacks_)); - expected_errors_.push_back("zone example.com/IN: NS 'ns.child.example.com'" - " is below a DNAME 'child.example.com'"); - checkIssues(); - - // A tricky case: there's also an NS at the name that has DNAME. It's - // prohibited per RFC6672 so we could say it's "undefined". Nevertheless, - // this implementation prefers the NS and skips further checks. - ns_.reset(new RRset(Name("child.example.com"), zclass_, RRType::NS(), - RRTTL(60))); - ns_->addRdata(generic::NS("ns.example.org.")); - rrsets_->addRRset(ns_); - EXPECT_TRUE(checkZone(zname_, zclass_, *rrsets_, callbacks_)); - checkIssues(); - - // Zone cut due to DNAME at the NS name. In this case DNAME doesn't - // affect the NS name, so it should result in "no address record" warning. - rrsets_->removeRRset(dname->getName(), zclass_, RRType::DNAME()); - rrsets_->removeRRset(ns_->getName(), zclass_, RRType::NS()); - dname.reset(new RRset(ns_name, zclass_, RRType::DNAME(), RRTTL(60))); - dname->addRdata(generic::DNAME("example.org.")); - rrsets_->addRRset(dname); - EXPECT_TRUE(checkZone(zname_, zclass_, *rrsets_, callbacks_)); - expected_warns_.push_back("zone example.com/IN: NS has no address"); - checkIssues(); -} - -} diff --git a/src/lib/dns/tsig.cc b/src/lib/dns/tsig.cc index d7c85de4d1..ee5ba98e3c 100644 --- a/src/lib/dns/tsig.cc +++ b/src/lib/dns/tsig.cc @@ -98,8 +98,7 @@ struct TSIGContext::TSIGContextImpl { // the caller of verify(), so that verify() can call this method within // its 'return' statement. TSIGError postVerifyUpdate(TSIGError error, const void* digest, - uint16_t digest_len) - { + uint16_t digest_len) { if (state_ == INIT) { state_ = RECEIVED_REQUEST; } else if (state_ == SENT_REQUEST && error == TSIGError::NOERROR()) { @@ -276,15 +275,14 @@ TSIGContext::TSIGContext(const Name& key_name, const Name& algorithm_name, // parameters and empty secret. In the common scenario this will // be used in subsequent response with a TSIG indicating a BADKEY // error. - impl_ = new TSIGContextImpl(TSIGKey(key_name, algorithm_name, - NULL, 0), TSIGError::BAD_KEY()); + impl_.reset(new TSIGContextImpl(TSIGKey(key_name, algorithm_name, + NULL, 0), TSIGError::BAD_KEY())); } else { - impl_ = new TSIGContextImpl(*result.key); + impl_.reset(new TSIGContextImpl(*result.key)); } } TSIGContext::~TSIGContext() { - delete impl_; } size_t diff --git a/src/lib/dns/tsig.h b/src/lib/dns/tsig.h index ed74e77c9a..cc5b42adc1 100644 --- a/src/lib/dns/tsig.h +++ b/src/lib/dns/tsig.h @@ -8,7 +8,7 @@ // it was fixed, cf RFC 8945. Note that Kea uses only the client side. #ifndef TSIG_H -#define TSIG_H 1 +#define TSIG_H #include <boost/noncopyable.hpp> #include <boost/shared_ptr.hpp> @@ -429,7 +429,7 @@ protected: private: struct TSIGContextImpl; - TSIGContextImpl* impl_; + boost::shared_ptr<TSIGContextImpl> impl_; }; typedef boost::shared_ptr<TSIGContext> TSIGContextPtr; @@ -439,7 +439,3 @@ typedef boost::shared_ptr<TSIGKey> TSIGKeyPtr; } #endif // TSIG_H - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/tsigerror.h b/src/lib/dns/tsigerror.h index f7727d71ae..693aea61e3 100644 --- a/src/lib/dns/tsigerror.h +++ b/src/lib/dns/tsigerror.h @@ -5,7 +5,7 @@ // file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef TSIGERROR_H -#define TSIGERROR_H 1 +#define TSIGERROR_H #include <ostream> #include <string> @@ -70,7 +70,9 @@ public: /// \exception None /// /// \return The underlying code value corresponding to the \c TSIGError. - uint16_t getCode() const { return (code_); } + uint16_t getCode() const { + return (code_); + } /// \brief Return true iff two \c TSIGError objects are equal. /// @@ -80,11 +82,14 @@ public: /// /// \param other the \c TSIGError object to compare against. /// \return true if the two TSIGError are equal; otherwise false. - bool equals(const TSIGError& other) const - { return (code_ == other.code_); } + bool equals(const TSIGError& other) const { + return (code_ == other.code_); + } /// \brief Same as \c equals(). - bool operator==(const TSIGError& other) const { return (equals(other)); } + bool operator==(const TSIGError& other) const { + return (equals(other)); + } /// \brief Return true iff two \c TSIGError objects are not equal. /// @@ -93,11 +98,14 @@ public: /// \param other the \c TSIGError object to compare against. /// \return true if the two TSIGError objects are not equal; /// otherwise false. - bool nequals(const TSIGError& other) const - { return (code_ != other.code_); } + bool nequals(const TSIGError& other) const { + return (code_ != other.code_); + } /// \brief Same as \c nequals(). - bool operator!=(const TSIGError& other) const { return (nequals(other)); } + bool operator!=(const TSIGError& other) const { + return (nequals(other)); + } /// \brief Convert the \c TSIGError to a string. /// @@ -368,7 +376,3 @@ std::ostream& operator<<(std::ostream& os, const TSIGError& tsig_error); } #endif // TSIGERROR_H - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/tsigkey.cc b/src/lib/dns/tsigkey.cc index f80d0b86b3..a29c1db581 100644 --- a/src/lib/dns/tsigkey.cc +++ b/src/lib/dns/tsigkey.cc @@ -60,11 +60,9 @@ TSIGKey::TSIGKeyImpl { TSIGKeyImpl(const Name& key_name, const Name& algorithm_name, isc::cryptolink::HashAlgorithm algorithm, size_t digestbits) : - key_name_(key_name), algorithm_name_(algorithm_name), algorithm_(algorithm), digestbits_(digestbits), - secret_() - { + secret_() { // Convert the key and algorithm names to the canonical form. key_name_.downcase(); if (algorithm == isc::cryptolink::MD5) { @@ -76,12 +74,10 @@ TSIGKey::TSIGKeyImpl { isc::cryptolink::HashAlgorithm algorithm, size_t digestbits, const void* secret, size_t secret_len) : - key_name_(key_name), algorithm_name_(algorithm_name), algorithm_(algorithm), digestbits_(digestbits), secret_(static_cast<const uint8_t*>(secret), - static_cast<const uint8_t*>(secret) + secret_len) - { + static_cast<const uint8_t*>(secret) + secret_len) { // Convert the key and algorithm names to the canonical form. key_name_.downcase(); if (algorithm == isc::cryptolink::MD5) { @@ -112,11 +108,11 @@ TSIGKey::TSIGKey(const Name& key_name, const Name& algorithm_name, key_name << ":" << algorithm_name); } if (secret == NULL) { - impl_ = new TSIGKeyImpl(key_name, algorithm_name, algorithm, - digestbits); + impl_.reset(new TSIGKey::TSIGKeyImpl(key_name, algorithm_name, algorithm, + digestbits)); } else { - impl_ = new TSIGKeyImpl(key_name, algorithm_name, algorithm, - digestbits, secret, secret_len); + impl_.reset(new TSIGKey::TSIGKeyImpl(key_name, algorithm_name, algorithm, + digestbits, secret, secret_len)); } } @@ -175,11 +171,11 @@ TSIGKey::TSIGKey(const std::string& str) : impl_(NULL) { } if (secret.empty()) { - impl_ = new TSIGKeyImpl(Name(keyname_str), algo_name, algorithm, - digestbits); + impl_.reset(new TSIGKey::TSIGKeyImpl(Name(keyname_str), algo_name, algorithm, + digestbits)); } else { - impl_ = new TSIGKeyImpl(Name(keyname_str), algo_name, algorithm, - digestbits, &secret[0], secret.size()); + impl_.reset(new TSIGKey::TSIGKeyImpl(Name(keyname_str), algo_name, algorithm, + digestbits, &secret[0], secret.size())); } } catch (const isc::Exception& e) { // 'reduce' the several types of exceptions name parsing and @@ -188,7 +184,6 @@ TSIGKey::TSIGKey(const std::string& str) : impl_(NULL) { } } - TSIGKey::TSIGKey(const TSIGKey& source) : impl_(new TSIGKeyImpl(*source.impl_)) { } @@ -198,15 +193,11 @@ TSIGKey::operator=(const TSIGKey& source) { return (*this); } - TSIGKeyImpl* newimpl = new TSIGKeyImpl(*source.impl_); - delete impl_; - impl_ = newimpl; - + impl_.reset(new TSIGKey::TSIGKeyImpl(*source.impl_)); return (*this); } TSIGKey::~TSIGKey() { - delete impl_; } const Name& @@ -315,7 +306,6 @@ TSIGKeyRing::TSIGKeyRing() : impl_(new TSIGKeyRingImpl()) { } TSIGKeyRing::~TSIGKeyRing() { - delete impl_; } unsigned int diff --git a/src/lib/dns/tsigkey.h b/src/lib/dns/tsigkey.h index ead33e1463..c9850b08cb 100644 --- a/src/lib/dns/tsigkey.h +++ b/src/lib/dns/tsigkey.h @@ -5,7 +5,7 @@ // file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef TSIGKEY_H -#define TSIGKEY_H 1 +#define TSIGKEY_H #include <cryptolink/cryptolink.h> @@ -221,7 +221,7 @@ public: private: struct TSIGKeyImpl; - const TSIGKeyImpl* impl_; + boost::shared_ptr<TSIGKeyImpl> impl_; }; /// \brief A simple repository of a set of \c TSIGKey objects. @@ -269,8 +269,8 @@ public: /// variables. struct FindResult { FindResult(Result param_code, const TSIGKey* param_key) : - code(param_code), key(param_key) - {} + code(param_code), key(param_key) { + } const Result code; const TSIGKey* const key; }; @@ -379,13 +379,9 @@ public: private: struct TSIGKeyRingImpl; - TSIGKeyRingImpl* impl_; + boost::shared_ptr<TSIGKeyRingImpl> impl_; }; } } #endif // TSIGKEY_H - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/tsigrecord.cc b/src/lib/dns/tsigrecord.cc index 483296ded6..13b7e9acdd 100644 --- a/src/lib/dns/tsigrecord.cc +++ b/src/lib/dns/tsigrecord.cc @@ -43,8 +43,8 @@ TSIGRecord::TSIGRecord(const Name& key_name, key_name_(key_name), rdata_(tsig_rdata), length_(RR_COMMON_LEN + RDATA_COMMON_LEN + key_name_.getLength() + rdata_.getAlgorithm().getLength() + - rdata_.getMACSize() + rdata_.getOtherLen()) -{} + rdata_.getMACSize() + rdata_.getOtherLen()) { +} namespace { // This is a straightforward wrapper of dynamic_cast<const any::TSIG&>. @@ -67,8 +67,7 @@ castToTSIGRdata(const rdata::Rdata& rdata) { TSIGRecord::TSIGRecord(const Name& name, const RRClass& rrclass, const RRTTL& ttl, const rdata::Rdata& rdata, size_t length) : - key_name_(name), rdata_(castToTSIGRdata(rdata)), length_(length) -{ + key_name_(name), rdata_(castToTSIGRdata(rdata)), length_(length) { if (rrclass != getClass()) { isc_throw(DNSMessageFORMERR, "Unexpected TSIG RR class: " << rrclass); } diff --git a/src/lib/dns/tsigrecord.h b/src/lib/dns/tsigrecord.h index 0d5a37593f..f754b2f69e 100644 --- a/src/lib/dns/tsigrecord.h +++ b/src/lib/dns/tsigrecord.h @@ -5,7 +5,7 @@ // file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef TSIGRECORD_H -#define TSIGRECORD_H 1 +#define TSIGRECORD_H #include <ostream> #include <string> @@ -18,9 +18,6 @@ #include <dns/rdataclass.h> namespace isc { -namespace util { -class OutputBuffer; -} namespace dns { class AbstractMessageRenderer; @@ -168,12 +165,16 @@ public: /// Return the owner name of the TSIG RR, which is the TSIG key name /// /// \exception None - const Name& getName() const { return (key_name_); } + const Name& getName() const { + return (key_name_); + } /// Return the RDATA of the TSIG RR /// /// \exception None - const rdata::any::TSIG& getRdata() const { return (rdata_); } + const rdata::any::TSIG& getRdata() const { + return (rdata_); + } /// \name Protocol constants and defaults /// @@ -207,7 +208,9 @@ public: /// to verify the message once parse is completed. /// /// \exception None - size_t getLength() const { return (length_); } + size_t getLength() const { + return (length_); + } /// \brief Render the \c TSIG RR in the wire format. /// @@ -294,7 +297,3 @@ std::ostream& operator<<(std::ostream& os, const TSIGRecord& record); } #endif // TSIGRECORD_H - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/dns/zone_checker.cc b/src/lib/dns/zone_checker.cc deleted file mode 100644 index f0a132ae84..0000000000 --- a/src/lib/dns/zone_checker.cc +++ /dev/null @@ -1,189 +0,0 @@ -// Copyright (C) 2012-2024 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#include <config.h> - -#include <dns/zone_checker.h> - -#include <dns/name.h> -#include <dns/rdataclass.h> -#include <dns/rrclass.h> -#include <dns/rrtype.h> -#include <dns/rrset.h> -#include <dns/rrset_collection_base.h> - -#include <boost/lexical_cast.hpp> - -#include <functional> -#include <string> - -using boost::lexical_cast; -using std::string; -namespace ph = std::placeholders; - -namespace isc { -namespace dns { - -namespace { -std::string -zoneText(const Name& zone_name, const RRClass& zone_class) { - return (zone_name.toText(true) + "/" + zone_class.toText()); -} - -void -checkSOA(const Name& zone_name, const RRClass& zone_class, - const RRsetCollectionBase& zone_rrsets, - ZoneCheckerCallbacks& callback) { - ConstRRsetPtr rrset = - zone_rrsets.find(zone_name, zone_class, RRType::SOA()); - size_t count = 0; - if (rrset) { - for (RdataIteratorPtr rit = rrset->getRdataIterator(); - !rit->isLast(); rit->next(), ++count) { - if (dynamic_cast<const rdata::generic::SOA*>(&rit->getCurrent()) == - NULL) { - isc_throw(Unexpected, "Zone checker found bad RDATA in SOA"); - } - } - if (count == 0) { - // this should be an implementation bug, not an operational error. - isc_throw(Unexpected, "Zone checker found an empty SOA RRset"); - } - } - if (count != 1) { - callback.error("zone " + zoneText(zone_name, zone_class) + ": has " + - lexical_cast<string>(count) + " SOA records"); - } -} - -// Check if a target name is beyond zone cut, either due to delegation or -// DNAME. Note that DNAME works on the origin but not on the name itself, -// while delegation works on the name itself (but the NS at the origin is not -// delegation). -ConstRRsetPtr -findZoneCut(const Name& zone_name, const RRClass& zone_class, - const RRsetCollectionBase& zone_rrsets, const Name& target_name) { - const unsigned int origin_count = zone_name.getLabelCount(); - const unsigned int target_count = target_name.getLabelCount(); - assert(origin_count <= target_count); - - for (unsigned int l = origin_count; l <= target_count; ++l) { - const Name& mid_name = (l == target_count) ? target_name : - target_name.split(target_count - l); - - ConstRRsetPtr found; - if (l != origin_count && - (found = zone_rrsets.find(mid_name, zone_class, RRType::NS())) != - NULL) { - return (found); - } - if (l != target_count && - (found = zone_rrsets.find(mid_name, zone_class, RRType::DNAME())) - != NULL) { - return (found); - } - } - return (ConstRRsetPtr()); -} - -// Check if each "in-zone" NS name has an address record, identifying some -// error cases. -void -checkNSNames(const Name& zone_name, const RRClass& zone_class, - const RRsetCollectionBase& zone_rrsets, - ConstRRsetPtr ns_rrset, ZoneCheckerCallbacks& callbacks) { - if (ns_rrset->getRdataCount() == 0) { - // this should be an implementation bug, not an operational error. - isc_throw(Unexpected, "Zone checker found an empty NS RRset"); - } - - for (RdataIteratorPtr rit = ns_rrset->getRdataIterator(); - !rit->isLast(); rit->next()) { - const rdata::generic::NS* ns_data = - dynamic_cast<const rdata::generic::NS*>(&rit->getCurrent()); - if (ns_data == NULL) { - isc_throw(Unexpected, "Zone checker found bad RDATA in NS"); - } - const Name& ns_name = ns_data->getNSName(); - const NameComparisonResult::NameRelation reln = - ns_name.compare(zone_name).getRelation(); - if (reln != NameComparisonResult::EQUAL && - reln != NameComparisonResult::SUBDOMAIN) { - continue; // not in the zone. we can ignore it. - } - - // Check if there's a zone cut between the origin and the NS name. - ConstRRsetPtr cut_rrset = findZoneCut(zone_name, zone_class, - zone_rrsets, ns_name); - if (cut_rrset) { - if (cut_rrset->getType() == RRType::NS()) { - continue; // delegation; making the NS name "out of zone". - } else if (cut_rrset->getType() == RRType::DNAME()) { - callbacks.error("zone " + zoneText(zone_name, zone_class) + - ": NS '" + ns_name.toText(true) + "' is " + - "below a DNAME '" + - cut_rrset->getName().toText(true) + - "' (illegal per RFC6672)"); - continue; - } else { - assert(false); - } - } - if (zone_rrsets.find(ns_name, zone_class, RRType::CNAME()) != NULL) { - callbacks.error("zone " + zoneText(zone_name, zone_class) + - ": NS '" + ns_name.toText(true) + "' is a CNAME " + - "(illegal per RFC2181)"); - continue; - } - if (zone_rrsets.find(ns_name, zone_class, RRType::A()) == NULL && - zone_rrsets.find(ns_name, zone_class, RRType::AAAA()) == NULL) { - callbacks.warn("zone " + zoneText(zone_name, zone_class) + - ": NS has no address records (A or AAAA)"); - } - } -} - -void -checkNS(const Name& zone_name, const RRClass& zone_class, - const RRsetCollectionBase& zone_rrsets, - ZoneCheckerCallbacks& callbacks) { - ConstRRsetPtr rrset = - zone_rrsets.find(zone_name, zone_class, RRType::NS()); - if (rrset == NULL) { - callbacks.error("zone " + zoneText(zone_name, zone_class) + - ": has no NS records"); - return; - } - checkNSNames(zone_name, zone_class, zone_rrsets, rrset, callbacks); -} - -// The following is a simple wrapper of checker callback so checkZone() -// can also remember any critical errors. -void -errorWrapper(const string& reason, const ZoneCheckerCallbacks* callbacks, - bool* had_error) { - *had_error = true; - callbacks->error(reason); -} -} - -bool -checkZone(const Name& zone_name, const RRClass& zone_class, - const RRsetCollectionBase& zone_rrsets, - const ZoneCheckerCallbacks& callbacks) { - bool had_error = false; - ZoneCheckerCallbacks my_callbacks( - std::bind(errorWrapper, ph::_1, &callbacks, &had_error), - std::bind(&ZoneCheckerCallbacks::warn, &callbacks, ph::_1)); - - checkSOA(zone_name, zone_class, zone_rrsets, my_callbacks); - checkNS(zone_name, zone_class, zone_rrsets, my_callbacks); - - return (!had_error); -} - -} // end namespace dns -} // end namespace isc diff --git a/src/lib/dns/zone_checker.h b/src/lib/dns/zone_checker.h deleted file mode 100644 index be36a32417..0000000000 --- a/src/lib/dns/zone_checker.h +++ /dev/null @@ -1,153 +0,0 @@ -// Copyright (C) 2012-2020 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef ZONE_CHECKER_H -#define ZONE_CHECKER_H 1 - -#include <dns/dns_fwd.h> - -#include <functional> -#include <string> - -namespace isc { -namespace dns { - -/// \brief Set of callbacks used in zone checks. -/// -/// Objects of this class are expected to be passed to \c checkZone(). -class ZoneCheckerCallbacks { -public: - /// \brief Functor type of the callback on some issue (error or warning). - /// - /// Its parameter indicates the reason for the corresponding issue. - typedef std::function<void(const std::string& reason)> IssueCallback; - - /// \brief Constructor. - /// - /// Either or both of the callbacks can be empty, in which case the - /// corresponding callback will be effectively no-operation. This can be - /// used, for example, when the caller of \c checkZone() is only - /// interested in the final result. Note that a \c NULL pointer will be - /// implicitly converted to an empty functor object, so passing \c NULL - /// suffices. - /// - /// \throw none - /// - /// \param error_callback Callback functor to be called on critical errors. - /// \param warn_callback Callback functor to be called on non critical - /// issues. - ZoneCheckerCallbacks(const IssueCallback& error_callback, - const IssueCallback& warn_callback) : - error_callback_(error_callback), warn_callback_(warn_callback) - {} - - /// \brief Call the callback for a critical error. - /// - /// This method itself is exception free, but propagates any exception - /// thrown from the callback. - /// - /// \param reason Textual representation of the reason for the error. - void error(const std::string& reason) const { - if (error_callback_) { - error_callback_(reason); - } - } - - /// \brief Call the callback for a non critical issue. - /// - /// This method itself is exception free, but propagates any exception - /// thrown from the callback. - /// - /// \param reason Textual representation of the reason for the issue. - void warn(const std::string& reason) const { - if (warn_callback_) - warn_callback_(reason); - } - -private: - IssueCallback error_callback_; - IssueCallback warn_callback_; -}; - -/// \brief Perform basic integrity checks on zone RRsets. -/// -/// This function performs some lightweight checks on zone's SOA and (apex) -/// NS records. Here, lightweight means it doesn't require traversing -/// the entire zone, and should be expected to complete reasonably quickly -/// regardless of the size of the zone. -/// -/// It distinguishes "critical" errors and other undesirable issues: -/// the former should be interpreted as the resulting zone shouldn't be used -/// further, e.g, by an authoritative server implementation; the latter means -/// the issues are better to be addressed but are not necessarily considered -/// to make the zone invalid. Critical errors are reported via the -/// \c error() method of \c callbacks, and non critical issues are reported -/// via its \c warn() method. -/// -/// Specific checks performed by this function is as follows. Failure of -/// a check is considered a critical error unless noted otherwise: -/// - There is exactly one SOA RR at the zone apex. -/// - There is at least one NS RR at the zone apex. -/// - For each apex NS record, if the NS name (the RDATA of the record) is -/// in the zone (i.e., it's a subdomain of the zone origin and above any -/// zone cut due to delegation), check the following: -/// - the NS name should have an address record (AAAA or A). Failure of -/// this check is considered a non critical issue. -/// - the NS name does not have a CNAME. This is prohibited by Section -/// 10.3 of RFC 2181. -/// - the NS name is not subject to DNAME substitution. This is prohibited -/// by Section 4 of RFC 6672. -/// . -/// -/// In addition, when the check is completed without any critical error, this -/// function guarantees that RRsets for the SOA and (apex) NS stored in the -/// passed RRset collection have the expected type of Rdata objects, -/// i.e., generic::SOA and generic::NS, respectively. (This is normally -/// expected to be the case, but not guaranteed by the API). -/// -/// As for the check on the existence of AAAA or A records for NS names, -/// it should be noted that BIND 9 treats this as a critical error. -/// It's not clear whether it's an implementation dependent behavior or -/// based on the protocol standard (it looks like the former), but to make -/// it sure we need to confirm there is even no wildcard match for the names. -/// This should be a very rare configuration, and more expensive to detect, -/// so we do not check this condition, and treat this case as a non critical -/// issue. -/// -/// This function indicates the result of the checks (whether there is a -/// critical error) via the return value: It returns \c true if there is no -/// critical error and returns \c false otherwise. It doesn't throw an -/// exception on encountering an error so that it can report as many errors -/// as possible in a single call. If an exception is a better way to signal -/// the error, the caller can pass a callback object that throws from its -/// \c error() method. -/// -/// This function can still throw an exception if it finds a really bogus -/// condition that is most likely to be an implementation bug of the caller. -/// Such cases include when an RRset contained in the RRset collection is -/// empty. -/// -/// \throw Unexpected Conditions that suggest a caller's bug (see the -/// description) -/// -/// \param zone_name The name of the zone to be checked -/// \param zone_class The RR class of the zone to be checked -/// \param zone_rrsets The collection of RRsets of the zone -/// \param callbacks Callback object used to report errors and issues -/// -/// \return \c true if no critical errors are found; \c false otherwise. -bool -checkZone(const Name& zone_name, const RRClass& zone_class, - const RRsetCollectionBase& zone_rrsets, - const ZoneCheckerCallbacks& callbacks); - -} // namespace dns -} // namespace isc -#endif // ZONE_CHECKER_H - -// Local Variables: -// mode: c++ -// End: |