summaryrefslogtreecommitdiffstats
path: root/src/lib/dns/rdata
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/lib/dns/rdata.cc408
-rw-r--r--src/lib/dns/rdata.h582
-rw-r--r--src/lib/dns/rdata/any_255/tsig_250.cc567
-rw-r--r--src/lib/dns/rdata/any_255/tsig_250.h148
-rw-r--r--src/lib/dns/rdata/ch_3/a_1.cc64
-rw-r--r--src/lib/dns/rdata/ch_3/a_1.h32
-rw-r--r--src/lib/dns/rdata/generic/afsdb_18.cc201
-rw-r--r--src/lib/dns/rdata/generic/afsdb_18.h68
-rw-r--r--src/lib/dns/rdata/generic/caa_257.cc298
-rw-r--r--src/lib/dns/rdata/generic/caa_257.h64
-rw-r--r--src/lib/dns/rdata/generic/cname_5.cc125
-rw-r--r--src/lib/dns/rdata/generic/cname_5.h39
-rw-r--r--src/lib/dns/rdata/generic/detail/char_string.cc264
-rw-r--r--src/lib/dns/rdata/generic/detail/char_string.h140
-rw-r--r--src/lib/dns/rdata/generic/detail/ds_like.h277
-rw-r--r--src/lib/dns/rdata/generic/detail/lexer_util.h62
-rw-r--r--src/lib/dns/rdata/generic/detail/nsec3param_common.cc115
-rw-r--r--src/lib/dns/rdata/generic/detail/nsec3param_common.h123
-rw-r--r--src/lib/dns/rdata/generic/detail/nsec_bitmap.cc169
-rw-r--r--src/lib/dns/rdata/generic/detail/nsec_bitmap.h103
-rw-r--r--src/lib/dns/rdata/generic/detail/txt_like.h237
-rw-r--r--src/lib/dns/rdata/generic/dlv_32769.cc120
-rw-r--r--src/lib/dns/rdata/generic/dlv_32769.h69
-rw-r--r--src/lib/dns/rdata/generic/dname_39.cc127
-rw-r--r--src/lib/dns/rdata/generic/dname_39.h39
-rw-r--r--src/lib/dns/rdata/generic/dnskey_48.cc316
-rw-r--r--src/lib/dns/rdata/generic/dnskey_48.h60
-rw-r--r--src/lib/dns/rdata/generic/ds_43.cc90
-rw-r--r--src/lib/dns/rdata/generic/ds_43.h69
-rw-r--r--src/lib/dns/rdata/generic/hinfo_13.cc151
-rw-r--r--src/lib/dns/rdata/generic/hinfo_13.h64
-rw-r--r--src/lib/dns/rdata/generic/minfo_14.cc173
-rw-r--r--src/lib/dns/rdata/generic/minfo_14.h74
-rw-r--r--src/lib/dns/rdata/generic/mx_15.cc160
-rw-r--r--src/lib/dns/rdata/generic/mx_15.h52
-rw-r--r--src/lib/dns/rdata/generic/naptr_35.cc256
-rw-r--r--src/lib/dns/rdata/generic/naptr_35.h64
-rw-r--r--src/lib/dns/rdata/generic/ns_2.cc121
-rw-r--r--src/lib/dns/rdata/generic/ns_2.h43
-rw-r--r--src/lib/dns/rdata/generic/nsec3_50.cc343
-rw-r--r--src/lib/dns/rdata/generic/nsec3_50.h54
-rw-r--r--src/lib/dns/rdata/generic/nsec3param_51.cc232
-rw-r--r--src/lib/dns/rdata/generic/nsec3param_51.h56
-rw-r--r--src/lib/dns/rdata/generic/nsec_47.cc216
-rw-r--r--src/lib/dns/rdata/generic/nsec_47.h53
-rw-r--r--src/lib/dns/rdata/generic/opt_41.cc219
-rw-r--r--src/lib/dns/rdata/generic/opt_41.h90
-rw-r--r--src/lib/dns/rdata/generic/ptr_12.cc123
-rw-r--r--src/lib/dns/rdata/generic/ptr_12.h44
-rw-r--r--src/lib/dns/rdata/generic/rp_17.cc160
-rw-r--r--src/lib/dns/rdata/generic/rp_17.h78
-rw-r--r--src/lib/dns/rdata/generic/rrsig_46.cc334
-rw-r--r--src/lib/dns/rdata/generic/rrsig_46.h54
-rw-r--r--src/lib/dns/rdata/generic/soa_6.cc210
-rw-r--r--src/lib/dns/rdata/generic/soa_6.h51
-rw-r--r--src/lib/dns/rdata/generic/spf_99.cc139
-rw-r--r--src/lib/dns/rdata/generic/spf_99.h72
-rw-r--r--src/lib/dns/rdata/generic/sshfp_44.cc298
-rw-r--r--src/lib/dns/rdata/generic/sshfp_44.h56
-rw-r--r--src/lib/dns/rdata/generic/tkey_249.cc613
-rw-r--r--src/lib/dns/rdata/generic/tkey_249.h142
-rw-r--r--src/lib/dns/rdata/generic/tlsa_52.cc342
-rw-r--r--src/lib/dns/rdata/generic/tlsa_52.h57
-rw-r--r--src/lib/dns/rdata/generic/txt_16.cc95
-rw-r--r--src/lib/dns/rdata/generic/txt_16.h46
-rw-r--r--src/lib/dns/rdata/hs_4/a_1.cc64
-rw-r--r--src/lib/dns/rdata/hs_4/a_1.h32
-rw-r--r--src/lib/dns/rdata/in_1/a_1.cc174
-rw-r--r--src/lib/dns/rdata/in_1/a_1.h38
-rw-r--r--src/lib/dns/rdata/in_1/aaaa_28.cc153
-rw-r--r--src/lib/dns/rdata/in_1/aaaa_28.h38
-rw-r--r--src/lib/dns/rdata/in_1/dhcid_49.cc161
-rw-r--r--src/lib/dns/rdata/in_1/dhcid_49.h53
-rw-r--r--src/lib/dns/rdata/in_1/srv_33.cc298
-rw-r--r--src/lib/dns/rdata/in_1/srv_33.h85
-rw-r--r--src/lib/dns/rdata/template.cc67
-rw-r--r--src/lib/dns/rdata/template.h54
-rw-r--r--src/lib/dns/rdata_pimpl_holder.h52
-rw-r--r--src/lib/dns/rdataclass.cc7078
-rw-r--r--src/lib/dns/rdataclass.h2746
-rw-r--r--src/lib/dns/rdatafields.cc216
-rw-r--r--src/lib/dns/rdatafields.h419
82 files changed, 22039 insertions, 0 deletions
diff --git a/src/lib/dns/rdata.cc b/src/lib/dns/rdata.cc
new file mode 100644
index 0000000..357ccc7
--- /dev/null
+++ b/src/lib/dns/rdata.cc
@@ -0,0 +1,408 @@
+// Copyright (C) 2010-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 <exceptions/exceptions.h>
+
+#include <util/buffer.h>
+#include <util/encode/hex.h>
+
+#include <dns/name.h>
+#include <dns/messagerenderer.h>
+#include <dns/master_lexer.h>
+#include <dns/rdata.h>
+#include <dns/rrparamregistry.h>
+#include <dns/rrtype.h>
+
+#include <boost/lexical_cast.hpp>
+#include <boost/shared_ptr.hpp>
+
+#include <algorithm>
+#include <cctype>
+#include <string>
+#include <sstream>
+#include <iomanip>
+#include <ios>
+#include <ostream>
+#include <vector>
+
+#include <stdint.h>
+#include <string.h>
+
+using namespace std;
+using boost::lexical_cast;
+using namespace isc::util;
+
+namespace isc {
+namespace dns {
+namespace rdata {
+
+uint16_t
+Rdata::getLength() const {
+ OutputBuffer obuffer(0);
+
+ toWire(obuffer);
+
+ return (obuffer.getLength());
+}
+
+// XXX: we need to specify std:: for string to help doxygen match the
+// function signature with that given in the header file.
+RdataPtr
+createRdata(const RRType& rrtype, const RRClass& rrclass,
+ 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)
+{
+ if (len > MAX_RDLENGTH) {
+ isc_throw(InvalidRdataLength, "RDLENGTH too large");
+ }
+
+ size_t old_pos = buffer.getPosition();
+
+ RdataPtr rdata =
+ RRParamRegistry::getRegistry().createRdata(rrtype, rrclass, buffer,
+ len);
+
+ if (buffer.getPosition() - old_pos != len) {
+ isc_throw(InvalidRdataLength, "RDLENGTH mismatch: " <<
+ buffer.getPosition() - old_pos << " != " << len);
+ }
+
+ return (rdata);
+}
+
+RdataPtr
+createRdata(const RRType& rrtype, const RRClass& rrclass, const Rdata& source)
+{
+ return (RRParamRegistry::getRegistry().createRdata(rrtype, rrclass,
+ source));
+}
+
+namespace {
+void
+fromtextError(bool& error_issued, const MasterLexer& lexer,
+ MasterLoaderCallbacks& callbacks,
+ const MasterToken* token, const char* reason)
+{
+ // Don't be too noisy if there are many issues for single RDATA
+ if (error_issued) {
+ return;
+ }
+ error_issued = true;
+
+ if (token == NULL) {
+ callbacks.error(lexer.getSourceName(), lexer.getSourceLine(),
+ "createRdata from text failed: " + string(reason));
+ return;
+ }
+
+ switch (token->getType()) {
+ case MasterToken::STRING:
+ case MasterToken::QSTRING:
+ callbacks.error(lexer.getSourceName(), lexer.getSourceLine(),
+ "createRdata from text failed near '" +
+ token->getString() + "': " + string(reason));
+ break;
+ case MasterToken::ERROR:
+ callbacks.error(lexer.getSourceName(), lexer.getSourceLine(),
+ "createRdata from text failed: " +
+ token->getErrorText());
+ break;
+ default:
+ // This case shouldn't happen based on how we use MasterLexer in
+ // createRdata(), so we could assert() that here. But since it
+ // depends on detailed behavior of other classes, we treat the case
+ // in a bit less harsh way.
+ isc_throw(Unexpected, "bug: createRdata() saw unexpected token type");
+ }
+}
+}
+
+RdataPtr
+createRdata(const RRType& rrtype, const RRClass& rrclass,
+ MasterLexer& lexer, const Name* origin,
+ MasterLoader::Options options,
+ MasterLoaderCallbacks& callbacks)
+{
+ RdataPtr rdata;
+
+ bool error_issued = false;
+ try {
+ rdata = RRParamRegistry::getRegistry().createRdata(
+ rrtype, rrclass, lexer, origin, options, callbacks);
+ } catch (const MasterLexer::LexerError& error) {
+ fromtextError(error_issued, lexer, callbacks, &error.token_, "");
+ } catch (const Exception& ex) {
+ // Catching all isc::Exception is too broad, but right now we don't
+ // have better granularity. When we complete #2518 we can make this
+ // finer.
+ fromtextError(error_issued, lexer, callbacks, NULL, ex.what());
+ }
+ // Other exceptions mean a serious implementation bug or fatal system
+ // error; it doesn't make sense to catch and try to recover from them
+ // here. Just propagate.
+
+ // Consume to end of line / file.
+ // Call callback via fromtextError once if there was an error.
+ do {
+ const MasterToken& token = lexer.getNextToken();
+ switch (token.getType()) {
+ case MasterToken::END_OF_LINE:
+ return (rdata);
+ case MasterToken::END_OF_FILE:
+ callbacks.warning(lexer.getSourceName(), lexer.getSourceLine(),
+ "file does not end with newline");
+ return (rdata);
+ default:
+ rdata.reset(); // we'll return NULL
+ fromtextError(error_issued, lexer, callbacks, &token,
+ "extra input text");
+ // Continue until we see EOL or EOF
+ }
+ } while (true);
+
+ // We shouldn't reach here
+ assert(false);
+ return (RdataPtr()); // add explicit return to silence some compilers
+}
+
+int
+compareNames(const Name& n1, const Name& n2) {
+ size_t len1 = n1.getLength();
+ size_t len2 = n2.getLength();
+ size_t cmplen = min(len1, len2);
+
+ for (size_t i = 0; i < cmplen; ++i) {
+ uint8_t c1 = tolower(n1.at(i));
+ uint8_t c2 = tolower(n2.at(i));
+ if (c1 < c2) {
+ return (-1);
+ } else if (c1 > c2) {
+ return (1);
+ }
+ }
+
+ return ((len1 == len2) ? 0 : (len1 < len2) ? -1 : 1);
+}
+
+namespace generic {
+struct GenericImpl {
+ GenericImpl(const vector<uint8_t>& data) : data_(data) {}
+ vector<uint8_t> data_;
+};
+
+Generic::Generic(isc::util::InputBuffer& buffer, size_t rdata_len) {
+ if (rdata_len > MAX_RDLENGTH) {
+ isc_throw(InvalidRdataLength, "RDLENGTH too large");
+ }
+
+ vector<uint8_t> data(rdata_len);
+ if (rdata_len > 0) {
+ buffer.readData(&data[0], rdata_len);
+ }
+
+ impl_ = new GenericImpl(data);
+}
+
+GenericImpl*
+Generic::constructFromLexer(MasterLexer& lexer) {
+ const MasterToken& token = lexer.getNextToken(MasterToken::STRING);
+ if (token.getString() != "\\#") {
+ isc_throw(InvalidRdataText,
+ "Missing the special token (\\#) for "
+ "unknown RDATA encoding");
+ }
+
+ // Initialize with an absurd value.
+ uint32_t rdlen = 65536;
+
+ try {
+ rdlen = lexer.getNextToken(MasterToken::NUMBER).getNumber();
+ } catch (const MasterLexer::LexerError&) {
+ isc_throw(InvalidRdataLength,
+ "Unknown RDATA length is invalid");
+ }
+
+ if (rdlen > 65535) {
+ isc_throw(InvalidRdataLength,
+ "Unknown RDATA length is out of range: " << rdlen);
+ }
+
+ vector<uint8_t> data;
+
+ if (rdlen > 0) {
+ string hex_txt;
+ string hex_part;
+ // Whitespace is allowed within hex data, so read to the end of input.
+ while (true) {
+ const MasterToken& token =
+ lexer.getNextToken(MasterToken::STRING, true);
+ if ((token.getType() == MasterToken::END_OF_FILE) ||
+ (token.getType() == MasterToken::END_OF_LINE)) {
+ // Unget the last read token as createRdata() expects us
+ // to leave it at the end-of-line or end-of-file when we
+ // return.
+ lexer.ungetToken();
+ break;
+ }
+ token.getString(hex_part);
+ hex_txt.append(hex_part);
+ }
+
+ try {
+ isc::util::encode::decodeHex(hex_txt, data);
+ } catch (const isc::BadValue& ex) {
+ isc_throw(InvalidRdataText,
+ "Invalid hex encoding of generic RDATA: " << ex.what());
+ }
+ }
+
+ if (data.size() != rdlen) {
+ isc_throw(InvalidRdataLength,
+ "Size of unknown RDATA hex data doesn't match RDLENGTH: "
+ << data.size() << " vs. " << rdlen);
+ }
+
+ return (new GenericImpl(data));
+}
+
+Generic::Generic(const std::string& rdata_string) :
+ 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;
+
+ try {
+ std::istringstream ss(rdata_string);
+ 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 unknown RDATA: "
+ << rdata_string);
+ }
+ } catch (const MasterLexer::LexerError& ex) {
+ isc_throw(InvalidRdataText, "Failed to construct unknown RDATA "
+ "from '" << rdata_string << "': " << ex.what());
+ }
+
+ impl_ = impl_ptr.release();
+}
+
+Generic::Generic(MasterLexer& lexer, const Name*,
+ MasterLoader::Options,
+ MasterLoaderCallbacks&) :
+ impl_(constructFromLexer(lexer))
+{
+}
+
+Generic::~Generic() {
+ delete impl_;
+}
+
+Generic::Generic(const Generic& source) :
+ Rdata(), impl_(new GenericImpl(*source.impl_))
+{}
+
+Generic&
+// Our check is better than the usual if (this == &source),
+// but cppcheck doesn't recognize it.
+// cppcheck-suppress operatorEqToSelf
+Generic::operator=(const Generic& source) {
+ if (impl_ == source.impl_) {
+ return (*this);
+ }
+
+ GenericImpl* newimpl = new GenericImpl(*source.impl_);
+ delete impl_;
+ impl_ = newimpl;
+
+ return (*this);
+}
+
+namespace {
+class UnknownRdataDumper {
+public:
+ UnknownRdataDumper(ostringstream& oss) : oss_(&oss) {}
+ void operator()(const unsigned char d)
+ {
+ *oss_ << setw(2) << static_cast<unsigned int>(d);
+ }
+private:
+ ostringstream* oss_;
+};
+}
+
+string
+Generic::toText() const {
+ ostringstream oss;
+
+ oss << "\\# " << impl_->data_.size() << " ";
+ oss.fill('0');
+ oss << right << hex;
+ for_each(impl_->data_.begin(), impl_->data_.end(), UnknownRdataDumper(oss));
+
+ return (oss.str());
+}
+
+void
+Generic::toWire(isc::util::OutputBuffer& buffer) const {
+ buffer.writeData(&impl_->data_[0], impl_->data_.size());
+}
+
+void
+Generic::toWire(AbstractMessageRenderer& renderer) const {
+ renderer.writeData(&impl_->data_[0], impl_->data_.size());
+}
+
+namespace {
+inline int
+compare_internal(const GenericImpl& lhs, const GenericImpl& rhs) {
+ size_t this_len = lhs.data_.size();
+ size_t other_len = rhs.data_.size();
+ size_t len = (this_len < other_len) ? this_len : other_len;
+ int cmp;
+
+ // TODO: is there a need to check len - should we just assert?
+ // (Depends if it is possible for rdata to have zero length)
+ if ((len != 0) &&
+ ((cmp = memcmp(&lhs.data_[0], &rhs.data_[0], len)) != 0)) {
+ return (cmp);
+ } else {
+ return ((this_len == other_len) ? 0 :
+ (this_len < other_len) ? -1 : 1);
+ }
+}
+}
+
+int
+Generic::compare(const Rdata& other) const {
+ const Generic& other_rdata = dynamic_cast<const Generic&>(other);
+
+ return (compare_internal(*impl_, *other_rdata.impl_));
+}
+
+std::ostream&
+operator<<(std::ostream& os, const Generic& rdata) {
+ return (os << rdata.toText());
+}
+} // end of namespace generic
+
+} // end of namespace rdata
+}
+}
diff --git a/src/lib/dns/rdata.h b/src/lib/dns/rdata.h
new file mode 100644
index 0000000..a6515ef
--- /dev/null
+++ b/src/lib/dns/rdata.h
@@ -0,0 +1,582 @@
+// 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_H
+#define RDATA_H 1
+
+#include <dns/master_lexer.h>
+#include <dns/master_loader.h>
+#include <dns/master_loader_callbacks.h>
+
+#include <dns/exceptions.h>
+
+#include <boost/shared_ptr.hpp>
+
+#include <stdint.h>
+
+namespace isc {
+namespace util {
+class InputBuffer;
+class OutputBuffer;
+}
+namespace dns {
+class AbstractMessageRenderer;
+class RRType;
+class RRClass;
+class Name;
+
+namespace rdata {
+
+///
+/// \brief A standard DNS module exception that is thrown if RDATA parser
+/// encounters an invalid or inconsistent data length.
+///
+class InvalidRdataLength : public DNSTextError {
+public:
+ InvalidRdataLength(const char* file, size_t line, const char* what) :
+ DNSTextError(file, line, what) {}
+};
+
+///
+/// \brief A standard DNS module exception that is thrown if RDATA parser
+/// fails to recognize a given textual representation.
+///
+class InvalidRdataText : public DNSTextError {
+public:
+ InvalidRdataText(const char* file, size_t line, const char* what) :
+ DNSTextError(file, line, what) {}
+};
+
+///
+/// \brief A standard DNS module exception that is thrown if RDATA parser
+/// encounters a character-string (as defined in RFC1035) exceeding
+/// the maximum allowable length (\c MAX_CHARSTRING_LEN).
+///
+class CharStringTooLong : public DNSTextError {
+public:
+ CharStringTooLong(const char* file, size_t line, const char* what) :
+ DNSTextError(file, line, what) {}
+};
+
+// Forward declaration to define RdataPtr.
+class Rdata;
+
+///
+/// The \c RdataPtr type is a pointer-like type, pointing to an
+/// object of some concrete derived class of \c Rdata.
+///
+typedef boost::shared_ptr<Rdata> RdataPtr;
+typedef boost::shared_ptr<const Rdata> ConstRdataPtr;
+
+/// \brief Possible maximum length of RDATA, which is the maximum unsigned
+/// 16 bit value.
+const size_t MAX_RDLENGTH = 65535;
+
+/// \brief The maximum allowable length of character-string containing in
+/// RDATA as defined in RFC1035, not including the 1-byte length field.
+const unsigned int MAX_CHARSTRING_LEN = 255;
+
+/// \brief The \c Rdata class is an abstract base class that provides
+/// a set of common interfaces to manipulate concrete RDATA objects.
+///
+/// Generally, a separate derived class directly inherited from the base
+/// \c Rdata class is defined for each well known RDATA.
+/// Each of such classes will define the common logic based on the
+/// corresponding protocol standard.
+///
+/// Since some types of RRs are class specific and the corresponding RDATA
+/// may have different semantics (e.g. type A for class IN and type A for
+/// class CH have different representations and semantics), we separate
+/// \c Rdata derived classes for such RR types in different namespaces.
+/// The namespace of types specific to a class is named the lower-cased class
+/// name; for example, RDATA of class IN-specific types are defined in the
+/// \c in namespace, and RDATA of class CH-specific types are defined in
+/// the \c ch namespace, and so on.
+/// The derived classes are named using the RR type name (upper cased) such as
+/// \c A or \c AAAA.
+/// Thus RDATA of type A RR for class IN and CH are defined as \c in::A and
+/// \c ch::A, respectively.
+/// Many other RR types are class independent; the derived \c Rdata classes
+/// for such RR types are defined in the \c generic namespace. Examples are
+/// \c generic::NS and \c generic::SOA.
+///
+/// If applications need to refer to these derived classes, it is generally
+/// recommended to prepend at least some part of the namespace because the
+/// same class name can be used in different namespaces.
+/// So, instead of doing
+/// \code using namespace isc::dns::rdata::in;
+/// A& rdata_type_a; \endcode
+/// it is advisable to prepend at least \c in from the namespace:
+/// \code using namespace isc::dns::rdata;
+/// in::A& rdata_type_a; \endcode
+///
+/// In many cases, however, an application doesn't have to care about such
+/// derived classes.
+/// For instance, to parse an incoming DNS message an application wouldn't
+/// have to perform type specific operation unless the application is
+/// specifically concerned about a particular type.
+/// So, this API generally handles \c Rdata in a polymorphic way through
+/// a pointer or reference to this base abstract class.
+class Rdata {
+ ///
+ /// \name Constructors and Destructor
+ ///
+ /// Note: The copy constructor and the assignment operator are intentionally
+ /// defined as private. Concrete classes should generally specialize their
+ /// own versions of these methods.
+ //@{
+protected:
+ /// The default constructor.
+ ///
+ /// This is intentionally defined as \c protected as this base class should
+ /// never be instantiated (except as part of a derived class). In many
+ /// cases, the derived class wouldn't define a public default constructor
+ /// either, because an \c Rdata object without concrete data isn't
+ /// meaningful.
+ Rdata() {}
+private:
+ Rdata(const Rdata& source);
+ void operator=(const Rdata& source);
+public:
+ /// The destructor.
+ virtual ~Rdata() {};
+ //@}
+
+ ///
+ /// \name Converter methods
+ ///
+ //@{
+ /// \brief Convert an \c Rdata to a string.
+ ///
+ /// This method returns a \c std::string object representing the \c Rdata.
+ ///
+ /// This is a pure virtual method without the definition; the actual
+ /// representation is specific to each derived concrete class and
+ /// should be explicitly defined in the derived class.
+ ///
+ /// \return A string representation of \c Rdata.
+ virtual std::string toText() const = 0;
+
+ /// \brief Render the \c Rdata in the wire format into a buffer.
+ ///
+ /// This is a pure virtual method without the definition; the actual
+ /// conversion is specific to each derived concrete class and
+ /// should be explicitly defined in the derived class.
+ ///
+ /// \param buffer An output buffer to store the wire data.
+ virtual void toWire(isc::util::OutputBuffer& buffer) const = 0;
+
+ /// \brief Render the \c Rdata in the wire format into a
+ /// \c MessageRenderer object.
+ ///
+ /// This is a pure virtual method without the definition; the actual
+ /// conversion is specific to each derived concrete class and
+ /// should be explicitly defined in the derived class.
+ ///
+ /// \param renderer DNS message rendering context that encapsulates the
+ /// output buffer in which the \c Rdata is to be stored.
+ virtual void toWire(AbstractMessageRenderer& renderer) const = 0;
+ //@}
+
+ ///
+ /// \name Comparison method
+ ///
+ //@{
+ /// \brief Compare two instances of \c Rdata.
+ ///
+ /// This method compares \c this and the \c other Rdata objects
+ /// in terms of the DNSSEC sorting order as defined in RFC4034, and returns
+ /// the result as an integer.
+ ///
+ /// This is a pure virtual method without the definition; the actual
+ /// comparison logic is specific to each derived concrete class and
+ /// should be explicitly defined in the derived class.
+ ///
+ /// Specific implementations of this method must confirm that \c this
+ /// and the \c other are objects of the same concrete derived class of
+ /// \c Rdata. This is normally done by \c dynamic_cast in the
+ /// implementation. It also means if the assumption isn't met
+ /// an exception of class \c std::bad_cast will be thrown.
+ ///
+ /// Here is an implementation choice: instead of relying on
+ /// \c dynamic_cast, we could first convert the data into wire-format
+ /// and compare the pair as opaque data. This would be more polymorphic,
+ /// but might involve significant overhead, especially for a large size
+ /// of RDATA.
+ ///
+ /// \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.
+ virtual int compare(const Rdata& other) const = 0;
+ //@}
+
+ /// \brief Get the wire format length of an Rdata.
+ ///
+ /// IMPLEMENTATION NOTE: Currently this base class implementation is
+ /// non-optimal as it renders the wire data to a buffer and returns
+ /// the buffer's length. What would perform better is to add
+ /// implementations of \c getLength() method to every RDATA
+ /// type. This is why this method is virtual. Once all Rdata types
+ /// have \c getLength() implementations, this base class
+ /// implementation must be removed and the method should become a
+ /// pure interface.
+ ///
+ /// \return The length of the wire format representation of the
+ /// RDATA.
+ virtual uint16_t getLength() const;
+};
+
+namespace generic {
+
+/// \brief The \c GenericImpl class is the actual implementation of the
+/// \c generic::Generic class.
+///
+/// The implementation is hidden from applications. This approach requires
+/// dynamic memory allocation on construction, copy, or assignment, but
+/// we believe it should be acceptable as "unknown" RDATA should be pretty
+/// rare.
+struct GenericImpl;
+
+/// \brief The \c generic::Generic class represents generic "unknown" RDATA.
+///
+/// This class is used as a placeholder for all non well-known type of RDATA.
+/// By definition, the stored data is regarded as opaque binary without
+/// assuming any structure.
+class Generic : public Rdata {
+public:
+ ///
+ /// \name Constructors, Assignment Operator and Destructor.
+ ///
+ //@{
+ /// \brief Constructor from a string.
+ ///
+ /// This method constructs a \c generic::Generic object from a textual
+ /// representation as defined in RFC3597.
+ ///
+ /// If \c rdata_string isn't a valid textual representation of this type
+ /// of RDATA, an exception of class \c InvalidRdataText or
+ /// \c InvalidRdataLength will be thrown.
+ /// If resource allocation to store the data fails, a corresponding standard
+ /// exception will be thrown.
+ ///
+ /// \param rdata_string A string of textual representation of generic
+ /// RDATA.
+ explicit Generic(const std::string& rdata_string);
+
+ ///
+ /// \brief Constructor from wire-format data.
+ ///
+ /// The \c buffer parameter normally stores a complete DNS message
+ /// containing the generic RDATA to be constructed.
+ /// The current read position of the buffer points to the head of the
+ /// data.
+ ///
+ /// This method reads \c rdata_len bytes from the \c buffer, and internally
+ /// stores the data as an opaque byte sequence.
+ ///
+ /// \c rdata_len must not exceed \c MAX_RDLENGTH; otherwise, an exception
+ /// of class \c InvalidRdataLength will be thrown.
+ /// If resource allocation to hold the data fails, a corresponding standard
+ /// exception will be thrown; if the \c buffer doesn't contain \c rdata_len
+ /// bytes of unread data, an exception of class \c InvalidBufferPosition
+ /// will be thrown.
+ ///
+ /// \param buffer A reference to an \c InputBuffer object storing the
+ /// \c Rdata to parse.
+ /// \param rdata_len The length in buffer of the \c Rdata. In bytes.
+ Generic(isc::util::InputBuffer& buffer, size_t rdata_len);
+
+ /// \brief Constructor from master lexer.
+ ///
+ Generic(MasterLexer& lexer, const Name* name,
+ MasterLoader::Options options, MasterLoaderCallbacks& callbacks);
+
+ ///
+ /// \brief The destructor.
+ virtual ~Generic();
+ ///
+ /// \brief The copy constructor.
+ ///
+ /// If resource allocation to copy the data fails, a corresponding standard
+ /// exception will be thrown.
+ ///
+ /// \param source A reference to a \c generic::Generic object to copy from.
+ Generic(const Generic& source);
+
+ ///
+ /// \brief The assignment operator.
+ ///
+ /// If resource allocation to copy the data fails, a corresponding standard
+ /// exception will be thrown.
+ ///
+ /// \param source A reference to a \c generic::Generic object to copy from.
+ Generic& operator=(const Generic& source);
+ //@}
+
+ ///
+ /// \name Converter methods
+ ///
+ //@{
+ /// \brief Convert an \c generic::Generic object to a string.
+ ///
+ /// This method converts a generic "unknown" RDATA object into a textual
+ /// representation of such unknown data as defined in RFC3597.
+ ///
+ /// If resource allocation to copy the data fails, a corresponding standard
+ /// exception will be thrown.
+ ///
+ /// \return A string representation of \c generic::Generic.
+ virtual std::string toText() const;
+
+ ///
+ /// \brief Render the \c generic::Generic in the wire format into a buffer.
+ ///
+ /// This will require \c rdata_len bytes of remaining capacity in the
+ /// \c buffer. If this is not the case and resource allocation for the
+ /// necessary memory space fails, a corresponding standard exception will
+ /// be thrown.
+ ///
+ /// \param buffer An output buffer to store the wire data.
+ virtual void toWire(isc::util::OutputBuffer& buffer) const;
+
+ /// \brief Render the \c generic::Generic in the wire format into a
+ /// \c MessageRenderer object.
+ ///
+ /// This will require \c rdata_len bytes of remaining capacity in the
+ /// \c buffer. If this is not the case and resource allocation for the
+ /// necessary memory space fails, a corresponding standard exception will
+ /// be thrown.
+ ///
+ /// \param renderer DNS message rendering context that encapsulates the
+ /// output buffer in which the \c Generic object is to be stored.
+ virtual void toWire(AbstractMessageRenderer& renderer) const;
+ //@}
+
+ ///
+ /// \name Comparison method
+ ///
+ //@{
+ /// \brief Compare two instances of \c generic::Generic objects.
+ ///
+ /// As defined in RFC4034, this method simply compares the wire-format
+ /// representations of the two objects as left-justified unsigned octet
+ /// sequences.
+ ///
+ /// The object referenced by \c other must have been instantiated as
+ /// a c generic::Generic class object; otherwise, an exception of class
+ /// \c std::bad_cast will be thrown.
+ /// Note that the comparison is RR type/class agnostic: this method doesn't
+ /// check whether the two \c Rdata objects to compare are of the comparable
+ /// RR type/class. For example, \c this object may come from an \c RRset
+ /// of \c RRType x, and the \c other may come from a different \c RRset
+ /// of \c RRType y (where x != y). This situation would be considered a
+ /// bug, but this method cannot detect this type of error.
+ /// The caller must ensure this condition.
+ ///
+ /// \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.
+ virtual int compare(const Rdata& other) const;
+ //@}
+
+private:
+ GenericImpl* constructFromLexer(MasterLexer& lexer);
+
+ GenericImpl* impl_;
+};
+
+///
+/// \brief Insert the name as a string into stream.
+///
+/// This method convert the \c rdata into a string and inserts it into the
+/// output stream \c os.
+///
+/// This function overloads the global \c operator<< to behave as described in
+/// \c ostream::operator<< but applied to \c generic::Generic Rdata objects.
+///
+/// \param os A \c std::ostream object on which the insertion operation is
+/// performed.
+/// \param rdata The \c Generic 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 Generic& rdata);
+} // end of namespace "generic"
+
+//
+// Non class-member functions related to Rdata
+//
+
+///
+/// \name Parameterized Polymorphic RDATA Factories
+///
+/// This set of global functions provide a unified interface to create an
+/// \c Rdata object in a parameterized polymorphic way,
+/// that is, these functions take a pair of \c RRType and \c RRClass
+/// objects and data specific to that pair, and create an object of
+/// the corresponding concrete derived class of \c Rdata.
+///
+/// These will be useful when parsing/constructing a DNS message or
+/// parsing a master file, where information for a specific type of RDATA
+/// is given but the resulting object, once created, should better be used
+/// in a polymorphic way.
+///
+/// For example, if a master file parser encounters an NS RR
+/// \verbatim example.com. 3600 IN NS ns.example.com.\endverbatim
+/// it stores the text fragments "IN", "NS", and "ns.example.com." in
+/// \c std::string objects \c class_txt, \c type_txt, and \c nsname_txt,
+/// respectively, then it would create a new \c RdataPtr object as follows:
+/// \code RdataPtr rdata = createRdata(RRType(type_txt), RRClass(class_txt),
+/// nsname_txt); \endcode
+/// On success, \c rdata will point to an object of the \c generic::NS class
+/// that internally holds a domain name of "ns.example.com."
+///
+/// Internally, these functions uses the corresponding
+/// \c RRParamRegistry::createRdata methods of the \c RRParamRegistry.
+/// See also the description on these methods for related notes.
+//@{
+/// \brief Create RDATA of a given pair of RR type and class from a string.
+///
+/// This method creates from a string an \c Rdata object of the given pair
+/// of RR type and class.
+///
+/// \param rrtype An \c RRType object specifying the type/class pair.
+/// \param rrclass An \c RRClass object specifying the type/class pair.
+/// \param rdata_string A string of textual representation of the \c Rdata.
+/// \return An \c RdataPtr object pointing to the created \c Rdata
+/// object.
+RdataPtr createRdata(const RRType& rrtype, const RRClass& rrclass,
+ const std::string& rdata_string);
+
+/// \brief Create RDATA of a given pair of RR type and class from
+/// wire-format data.
+///
+/// This method creates from wire-format binary data an \c Rdata object
+/// of the given pair of RR type and class.
+///
+/// \c len must not exceed the protocol defined maximum value, \c MAX_RDLENGTH;
+/// otherwise, an exception of class \c InvalidRdataLength will be thrown.
+///
+/// In some cases, the length of the RDATA is determined without the
+/// information of \c len. For example, the RDATA length of an IN/A RR
+/// must always be 4. If \c len is not equal to the actual length in such
+/// cases, an exception of class InvalidRdataLength will be thrown.
+///
+/// \param rrtype An \c RRType object specifying the type/class pair.
+/// \param rrclass An \c RRClass object specifying the type/class pair.
+/// \param buffer A reference to an \c InputBuffer object storing the
+/// \c Rdata to parse.
+/// \param len The length in buffer of the \c Rdata. In bytes.
+/// \return An \c RdataPtr object pointing to the created \c Rdata
+/// object.
+RdataPtr createRdata(const RRType& rrtype, const RRClass& rrclass,
+ isc::util::InputBuffer& buffer, size_t len);
+
+/// \brief Create RDATA of a given pair of RR type and class, copying
+/// of another RDATA of same kind.
+///
+/// This method creates an \c Rdata object of the given pair of
+/// RR type and class, copying the content of the given \c Rdata,
+/// \c source.
+///
+/// \param rrtype An \c RRType object specifying the type/class pair.
+/// \param rrclass An \c RRClass object specifying the type/class pair.
+/// \param source A reference to an \c Rdata object whose content
+/// is to be copied to the created \c Rdata object.
+/// \return An \c RdataPtr object pointing to the created
+/// \c Rdata object.
+RdataPtr createRdata(const RRType& rrtype, const RRClass& rrclass,
+ const Rdata& source);
+
+/// \brief Create RDATA of a given pair of RR type and class using the
+/// master lexer.
+///
+/// This is a more generic form of factory from textual RDATA, and is mainly
+/// intended to be used internally by the master file parser (\c MasterLoader)
+/// of this library.
+///
+/// The \c lexer is expected to be at the beginning of textual RDATA of the
+/// specified type and class. This function (and its underlying Rdata
+/// implementations) extracts necessary tokens from the lexer and constructs
+/// the RDATA from them.
+///
+/// Due to the intended usage of this version, this function handles error
+/// cases quite differently from other versions. It internally catches
+/// most of syntax and semantics errors of the input (reported as exceptions),
+/// calls the corresponding callback specified by the \c callbacks parameters,
+/// and returns a NULL smart pointer. If the caller rather wants to get
+/// an exception in these cases, it can pass a callback that internally
+/// throws on error. Some critical exceptions such as \c std::bad_alloc are
+/// still propagated to the upper layer as it doesn't make sense to try
+/// recovery from such a situation within this function.
+///
+/// Whether or not the creation succeeds, this function updates the lexer
+/// until it reaches either the end of line or file, starting from the end of
+/// the RDATA text (or the point of failure if the parsing fails in the
+/// middle of it). The caller can therefore assume it's ready for reading
+/// the next data (which is normally a subsequent RR in the zone file) on
+/// return, whether or not this function succeeds.
+///
+/// \param rrtype An \c RRType object specifying the type/class pair.
+/// \param rrclass An \c RRClass object specifying the type/class pair.
+/// \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 any domain name fields
+/// of the RDATA that are non absolute.
+/// \param options Master loader options controlling how to deal with errors
+/// or non critical issues in the parsed RDATA.
+/// \param callbacks Callback to be called when an error or non critical issue
+/// is found.
+/// \return An \c RdataPtr object pointing to the created
+/// \c Rdata object. Will be NULL if parsing fails.
+RdataPtr createRdata(const RRType& rrtype, const RRClass& rrclass,
+ MasterLexer& lexer, const Name* origin,
+ MasterLoader::Options options,
+ MasterLoaderCallbacks& callbacks);
+
+//@}
+
+///
+/// \brief Gives relative ordering of two names in terms of DNSSEC RDATA
+/// ordering.
+///
+/// This method compares two names as defined in Sections 6.2 and 6.3 of
+/// RFC4034: Comparing two names in their canonical form
+/// (i.e., converting upper case ASCII characters to lower ones) and
+/// as a left-justified unsigned octet sequence. Note that the ordering is
+/// different from that for owner names. For example, "a.example" should be
+/// sorted before "example" as RDATA, but the ordering is the opposite when
+/// compared as owner names.
+///
+/// Normally, applications would not need this function directly.
+/// This is mostly an internal helper function for \c Rdata related classes
+/// to implement their \c compare() method.
+/// This function is publicly open, however, for the convenience of
+/// external developers who want to implement new or experimental RR types.
+///
+/// This function never throws an exception as long as the given names are
+/// valid \c Name objects.
+///
+/// Additional note about applicability: In fact, BIND9's similar function,
+/// \c dns_name_rdatacompare(), is only used in rdata implementations and
+/// for testing purposes.
+///
+/// \param n1,n2 \c Name class objects to compare.
+/// \return -1 if \c n1 would be sorted before \c n2.
+/// \return 0 if \c n1 is identical to \c n2 in terms of sorting order.
+/// \return 1 if \c n1 would be sorted after \c n2.
+///
+int compareNames(const Name& n1, const Name& n2);
+
+} // end of namespace "rdata"
+}
+}
+#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
new file mode 100644
index 0000000..a80d742
--- /dev/null
+++ b/src/lib/dns/rdata/any_255/tsig_250.cc
@@ -0,0 +1,567 @@
+// Copyright (C) 2010-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 <string>
+#include <sstream>
+#include <vector>
+
+#include <boost/lexical_cast.hpp>
+
+#include <util/buffer.h>
+#include <util/encode/base64.h>
+
+#include <dns/messagerenderer.h>
+#include <dns/name.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rcode.h>
+#include <dns/tsigkey.h>
+#include <dns/tsigerror.h>
+#include <dns/rdata/generic/detail/lexer_util.h>
+
+using namespace std;
+using boost::lexical_cast;
+using namespace isc::util;
+using namespace isc::util::encode;
+using namespace isc::dns;
+using isc::dns::rdata::generic::detail::createNameFromLexer;
+
+// BEGIN_ISC_NAMESPACE
+// BEGIN_RDATA_NAMESPACE
+
+// straightforward representation of TSIG RDATA fields
+struct TSIGImpl {
+ TSIGImpl(const Name& algorithm, uint64_t time_signed, uint16_t fudge,
+ vector<uint8_t>& mac, uint16_t original_id, uint16_t error,
+ 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)
+ {}
+ 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) :
+ algorithm_(algorithm), time_signed_(time_signed), fudge_(fudge),
+ mac_(static_cast<const uint8_t*>(mac),
+ 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)
+ {}
+ template <typename Output>
+ void toWireCommon(Output& output) const;
+
+ const Name algorithm_;
+ const uint64_t time_signed_;
+ const uint16_t fudge_;
+ const vector<uint8_t> mac_;
+ const uint16_t original_id_;
+ const uint16_t error_;
+ const vector<uint8_t> other_data_;
+};
+
+// helper function for string and lexer constructors
+TSIGImpl*
+TSIG::constructFromLexer(MasterLexer& lexer, const Name* origin) {
+ const Name& algorithm =
+ createNameFromLexer(lexer, origin ? origin : &Name::ROOT_NAME());
+ const Name& canonical_algorithm_name =
+ (algorithm == TSIGKey::HMACMD5_SHORT_NAME()) ?
+ TSIGKey::HMACMD5_NAME() : algorithm;
+
+ const string& time_txt =
+ lexer.getNextToken(MasterToken::STRING).getString();
+ uint64_t time_signed;
+ try {
+ time_signed = boost::lexical_cast<uint64_t>(time_txt);
+ } catch (const boost::bad_lexical_cast&) {
+ isc_throw(InvalidRdataText, "Invalid TSIG Time");
+ }
+ if ((time_signed >> 48) != 0) {
+ isc_throw(InvalidRdataText, "TSIG Time out of range");
+ }
+
+ const uint32_t fudge = lexer.getNextToken(MasterToken::NUMBER).getNumber();
+ if (fudge > 0xffff) {
+ isc_throw(InvalidRdataText, "TSIG Fudge out of range");
+ }
+ const uint32_t macsize =
+ lexer.getNextToken(MasterToken::NUMBER).getNumber();
+ if (macsize > 0xffff) {
+ isc_throw(InvalidRdataText, "TSIG MAC Size out of range");
+ }
+
+ const string& mac_txt = (macsize > 0) ?
+ lexer.getNextToken(MasterToken::STRING).getString() : "";
+ vector<uint8_t> mac;
+ decodeBase64(mac_txt, mac);
+ if (mac.size() != macsize) {
+ isc_throw(InvalidRdataText, "TSIG MAC Size and data are inconsistent");
+ }
+
+ const uint32_t orig_id =
+ lexer.getNextToken(MasterToken::NUMBER).getNumber();
+ if (orig_id > 0xffff) {
+ isc_throw(InvalidRdataText, "TSIG Original ID out of range");
+ }
+
+ const string& error_txt =
+ lexer.getNextToken(MasterToken::STRING).getString();
+ uint32_t error = 0;
+ // XXX: In the initial implementation we hardcode the mnemonics.
+ // We'll soon generalize this.
+ if (error_txt == "NOERROR") {
+ error = Rcode::NOERROR_CODE;
+ } else if (error_txt == "BADSIG") {
+ error = TSIGError::BAD_SIG_CODE;
+ } else if (error_txt == "BADKEY") {
+ error = TSIGError::BAD_KEY_CODE;
+ } else if (error_txt == "BADTIME") {
+ error = TSIGError::BAD_TIME_CODE;
+ } else if (error_txt == "BADMODE") {
+ error = TSIGError::BAD_MODE_CODE;
+ } else if (error_txt == "BADNAME") {
+ error = TSIGError::BAD_NAME_CODE;
+ } else if (error_txt == "BADALG") {
+ error = TSIGError::BAD_ALG_CODE;
+ } else if (error_txt == "BADTRUNC") {
+ error = TSIGError::BAD_TRUNC_CODE;
+ } else {
+ /// we cast to uint32_t and range-check, because casting directly to
+ /// uint16_t will convert negative numbers to large positive numbers
+ try {
+ error = boost::lexical_cast<uint32_t>(error_txt);
+ } catch (const boost::bad_lexical_cast&) {
+ isc_throw(InvalidRdataText, "Invalid TSIG Error");
+ }
+ if (error > 0xffff) {
+ isc_throw(InvalidRdataText, "TSIG Error out of range");
+ }
+ }
+
+ const uint32_t otherlen =
+ lexer.getNextToken(MasterToken::NUMBER).getNumber();
+ if (otherlen > 0xffff) {
+ isc_throw(InvalidRdataText, "TSIG Other Len out of range");
+ }
+ const string otherdata_txt = (otherlen > 0) ?
+ lexer.getNextToken(MasterToken::STRING).getString() : "";
+ vector<uint8_t> other_data;
+ decodeBase64(otherdata_txt, other_data);
+ if (other_data.size() != otherlen) {
+ isc_throw(InvalidRdataText,
+ "TSIG Other Data length does not match Other Len");
+ }
+ // 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));
+}
+
+/// \brief Constructor from string.
+///
+/// The given string must represent a valid TSIG 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.
+///
+/// \c tsig_str must be formatted as follows:
+/// \code <Algorithm Name> <Time Signed> <Fudge> <MAC Size> [<MAC>]
+/// <Original ID> <Error> <Other Len> [<Other Data>]
+/// \endcode
+///
+/// Note that, since the Algorithm Name field is defined to be "in domain name
+/// syntax", but it is not actually a domain name, it does not have to be
+/// fully qualified.
+///
+/// The Error field is an unsigned 16-bit decimal integer or a valid mnemonic
+/// as specified in RFC2845. Currently, "NOERROR", "BADSIG", "BADKEY", and
+/// "BADTIME" are supported (case sensitive). In future versions other
+/// representations that are compatible with the DNS RCODE may be supported.
+///
+/// The MAC and Other Data fields are base-64 encoded strings that do not
+/// contain space characters.
+/// If the MAC Size field is 0, the MAC field must not appear in \c tsig_str.
+/// If the Other Len field is 0, the Other Data field must not appear in
+/// \c tsig_str.
+/// The decoded data of the MAC field is MAC Size bytes of binary stream.
+/// The decoded data of the Other Data field is Other Len bytes of binary
+/// stream.
+///
+/// An example of valid string is:
+/// \code "hmac-sha256. 853804800 300 3 AAAA 2845 0 0" \endcode
+/// In this example Other Data is missing because Other Len is 0.
+///
+/// Note that RFC2845 does not define the standard presentation format
+/// of %TSIG RR, so the above syntax is implementation specific.
+/// This is, however, compatible with the format acceptable to BIND 9's
+/// RDATA parser.
+///
+/// \throw Others Exception from the Name constructors.
+/// \throw InvalidRdataText if any fields are out of their valid range,
+/// or are incorrect.
+/// \throw BadValue if MAC or Other Data is not validly encoded in base-64.
+///
+/// \param tsig_str A string containing the RDATA to be created
+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;
+
+ try {
+ std::istringstream ss(tsig_str);
+ MasterLexer lexer;
+ lexer.pushSource(ss);
+
+ impl_ptr.reset(constructFromLexer(lexer, NULL));
+
+ if (lexer.getNextToken().getType() != MasterToken::END_OF_FILE) {
+ isc_throw(InvalidRdataText,
+ "Extra input text for TSIG: " << tsig_str);
+ }
+ } catch (const MasterLexer::LexerError& ex) {
+ isc_throw(InvalidRdataText,
+ "Failed to construct TSIG from '" << tsig_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 TSIG RDATA.
+///
+/// See \c TSIG::TSIG(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
+TSIG::TSIG(MasterLexer& lexer, const Name* origin,
+ MasterLoader::Options, MasterLoaderCallbacks&) :
+ impl_(constructFromLexer(lexer, origin))
+{
+}
+
+/// \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 begin 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 RFC3597, the Algorithm field must be a non compressed form
+/// of domain name. But this implementation accepts a %TSIG RR even if that
+/// field is compressed.
+///
+/// \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.
+/// But this constructor does not use this parameter; if necessary, the caller
+/// must check consistency between the length parameter and the actual
+/// RDATA length.
+TSIG::TSIG(InputBuffer& buffer, size_t) :
+ impl_(NULL)
+{
+ Name algorithm(buffer);
+
+ uint8_t time_signed_buf[6];
+ buffer.readData(time_signed_buf, sizeof(time_signed_buf));
+ const uint64_t time_signed =
+ (static_cast<uint64_t>(time_signed_buf[0]) << 40 |
+ static_cast<uint64_t>(time_signed_buf[1]) << 32 |
+ static_cast<uint64_t>(time_signed_buf[2]) << 24 |
+ static_cast<uint64_t>(time_signed_buf[3]) << 16 |
+ static_cast<uint64_t>(time_signed_buf[4]) << 8 |
+ static_cast<uint64_t>(time_signed_buf[5]));
+
+ const uint16_t fudge = buffer.readUint16();
+
+ const uint16_t mac_size = buffer.readUint16();
+ vector<uint8_t> mac(mac_size);
+ if (mac_size > 0) {
+ buffer.readData(&mac[0], mac_size);
+ }
+
+ const uint16_t original_id = buffer.readUint16();
+ const uint16_t error = buffer.readUint16();
+
+ const uint16_t other_len = buffer.readUint16();
+ vector<uint8_t> other_data(other_len);
+ if (other_len > 0) {
+ buffer.readData(&other_data[0], other_len);
+ }
+
+ 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);
+}
+
+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)
+{
+ // Time Signed is a 48-bit value.
+ if ((time_signed >> 48) != 0) {
+ isc_throw(OutOfRange, "TSIG Time Signed is too large: " <<
+ time_signed);
+ }
+ if ((mac_size == 0 && mac != NULL) || (mac_size > 0 && mac == NULL)) {
+ isc_throw(InvalidParameter, "TSIG MAC size and data inconsistent");
+ }
+ if ((other_len == 0 && other_data != NULL) ||
+ (other_len > 0 && other_data == NULL)) {
+ isc_throw(InvalidParameter,
+ "TSIG Other data length and data inconsistent");
+ }
+ 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);
+}
+
+/// \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.
+TSIG::TSIG(const TSIG& source) : Rdata(), impl_(new TSIGImpl(*source.impl_))
+{}
+
+TSIG&
+TSIG::operator=(const TSIG& source) {
+ if (this == &source) {
+ return (*this);
+ }
+
+ TSIGImpl* newimpl = new TSIGImpl(*source.impl_);
+ delete impl_;
+ impl_ = newimpl;
+
+ return (*this);
+}
+
+TSIG::~TSIG() {
+ delete impl_;
+}
+
+/// \brief Convert the \c TSIG to a string.
+///
+/// The output of this method is formatted as described in the "from string"
+/// constructor (\c TSIG(const std::string&))).
+///
+/// If internal resource allocation fails, a corresponding
+/// standard exception will be thrown.
+///
+/// \return A \c string object that represents the \c TSIG object.
+std::string
+TSIG::toText() const {
+ string result;
+
+ result += impl_->algorithm_.toText() + " " +
+ lexical_cast<string>(impl_->time_signed_) + " " +
+ lexical_cast<string>(impl_->fudge_) + " " +
+ lexical_cast<string>(impl_->mac_.size()) + " ";
+ if (!impl_->mac_.empty()) {
+ result += encodeBase64(impl_->mac_) + " ";
+ }
+ result += lexical_cast<string>(impl_->original_id_) + " ";
+ result += TSIGError(impl_->error_).toText() + " ";
+ result += lexical_cast<string>(impl_->other_data_.size());
+ if (!impl_->other_data_.empty()) {
+ result += " " + encodeBase64(impl_->other_data_);
+ }
+
+ return (result);
+}
+
+// Common sequence of toWire() operations used for the two versions of
+// toWire().
+template <typename Output>
+void
+TSIGImpl::toWireCommon(Output& output) const {
+ output.writeUint16(time_signed_ >> 32);
+ output.writeUint32(time_signed_ & 0xffffffff);
+ output.writeUint16(fudge_);
+ const uint16_t mac_size = mac_.size();
+ output.writeUint16(mac_size);
+ if (mac_size > 0) {
+ output.writeData(&mac_[0], mac_size);
+ }
+ output.writeUint16(original_id_);
+ output.writeUint16(error_);
+ const uint16_t other_len = other_data_.size();
+ output.writeUint16(other_len);
+ if (other_len > 0) {
+ output.writeData(&other_data_[0], other_len);
+ }
+}
+
+/// \brief Render the \c TSIG 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
+TSIG::toWire(OutputBuffer& buffer) const {
+ impl_->algorithm_.toWire(buffer);
+ impl_->toWireCommon<OutputBuffer>(buffer);
+}
+
+/// \brief Render the \c TSIG in the wire format with taking into account
+/// compression.
+///
+/// As specified in RFC3597, the Algorithm 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
+TSIG::toWire(AbstractMessageRenderer& renderer) const {
+ renderer.writeName(impl_->algorithm_, false);
+ impl_->toWireCommon<AbstractMessageRenderer>(renderer);
+}
+
+// A helper function commonly used for TSIG::compare().
+int
+vectorComp(const vector<uint8_t>& v1, const vector<uint8_t>& v2) {
+ const size_t this_size = v1.size();
+ const size_t other_size = v2.size();
+ if (this_size != other_size) {
+ return (this_size < other_size ? -1 : 1);
+ }
+ if (this_size > 0) {
+ return (memcmp(&v1[0], &v2[0], this_size));
+ }
+ return (0);
+}
+
+/// \brief Compare two instances of \c TSIG RDATA.
+///
+/// This method compares \c this and the \c other \c TSIG objects
+/// in terms of the DNSSEC sorting order as defined in RFC4034, and returns
+/// the result as an integer.
+///
+/// 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 TSIG object;
+/// otherwise, the standard \c bad_cast exception will be thrown.
+/// This method never throws an exception otherwise.
+///
+/// \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
+TSIG::compare(const Rdata& other) const {
+ const TSIG& other_tsig = dynamic_cast<const TSIG&>(other);
+
+ const int ncmp = compareNames(impl_->algorithm_,
+ other_tsig.impl_->algorithm_);
+ if (ncmp != 0) {
+ return (ncmp);
+ }
+
+ if (impl_->time_signed_ != other_tsig.impl_->time_signed_) {
+ return (impl_->time_signed_ < other_tsig.impl_->time_signed_ ? -1 : 1);
+ }
+ if (impl_->fudge_ != other_tsig.impl_->fudge_) {
+ return (impl_->fudge_ < other_tsig.impl_->fudge_ ? -1 : 1);
+ }
+ const int vcmp = vectorComp(impl_->mac_, other_tsig.impl_->mac_);
+ if (vcmp != 0) {
+ return (vcmp);
+ }
+ if (impl_->original_id_ != other_tsig.impl_->original_id_) {
+ return (impl_->original_id_ < other_tsig.impl_->original_id_ ? -1 : 1);
+ }
+ if (impl_->error_ != other_tsig.impl_->error_) {
+ return (impl_->error_ < other_tsig.impl_->error_ ? -1 : 1);
+ }
+ return (vectorComp(impl_->other_data_, other_tsig.impl_->other_data_));
+}
+
+const Name&
+TSIG::getAlgorithm() const {
+ return (impl_->algorithm_);
+}
+
+uint64_t
+TSIG::getTimeSigned() const {
+ return (impl_->time_signed_);
+}
+
+uint16_t
+TSIG::getFudge() const {
+ return (impl_->fudge_);
+}
+
+uint16_t
+TSIG::getMACSize() const {
+ return (impl_->mac_.size());
+}
+
+const void*
+TSIG::getMAC() const {
+ if (!impl_->mac_.empty()) {
+ return (&impl_->mac_[0]);
+ } else {
+ return (NULL);
+ }
+}
+
+uint16_t
+TSIG::getOriginalID() const {
+ return (impl_->original_id_);
+}
+
+uint16_t
+TSIG::getError() const {
+ return (impl_->error_);
+}
+
+uint16_t
+TSIG::getOtherLen() const {
+ return (impl_->other_data_.size());
+}
+
+const void*
+TSIG::getOtherData() const {
+ if (!impl_->other_data_.empty()) {
+ return (&impl_->other_data_[0]);
+ } else {
+ return (NULL);
+ }
+}
+
+// END_RDATA_NAMESPACE
+// END_ISC_NAMESPACE
diff --git a/src/lib/dns/rdata/any_255/tsig_250.h b/src/lib/dns/rdata/any_255/tsig_250.h
new file mode 100644
index 0000000..63c2234
--- /dev/null
+++ b/src/lib/dns/rdata/any_255/tsig_250.h
@@ -0,0 +1,148 @@
+// 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
+
+struct TSIGImpl;
+
+/// \brief \c rdata::TSIG class represents the TSIG RDATA as defined %in
+/// RFC2845.
+///
+/// This class implements the basic interfaces inherited from the abstract
+/// \c rdata::Rdata class, and provides trivial accessors specific to the
+/// TSIG RDATA.
+class TSIG : public Rdata {
+public:
+ // BEGIN_COMMON_MEMBERS
+ // END_COMMON_MEMBERS
+
+ /// \brief Constructor from RDATA field parameters.
+ ///
+ /// The parameters are a straightforward mapping of %TSIG RDATA
+ /// fields as defined %in RFC2845, but there are some implementation
+ /// specific notes as follows.
+ ///
+ /// \c algorithm is a \c Name object that specifies the algorithm.
+ /// For example, if the algorithm is HMAC-SHA256, \c algorithm would be
+ /// \c Name("hmac-sha256").
+ ///
+ /// \c time_signed corresponds to the Time Signed field, which is of
+ /// 48-bit unsigned integer type, and therefore cannot exceed 2^48-1;
+ /// otherwise, an exception of type \c OutOfRange will be thrown.
+ ///
+ /// \c mac_size and \c mac correspond to the MAC Size and MAC fields,
+ /// respectively. When the MAC field is empty, \c mac must be NULL.
+ /// \c mac_size and \c mac must be consistent %in that \c mac_size is 0 if
+ /// and only if \c mac is NULL; otherwise an exception of type
+ /// InvalidParameter will be thrown.
+ ///
+ /// The same restriction applies to \c other_len and \c other_data,
+ /// which correspond to the Other Len and Other Data fields, respectively.
+ ///
+ /// This constructor internally involves resource allocation, and if
+ /// it fails, a corresponding standard exception will be thrown.
+ 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);
+
+ /// \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.
+ TSIG& operator=(const TSIG& source);
+
+ /// \brief The destructor.
+ ~TSIG();
+
+ /// \brief Return the algorithm name.
+ ///
+ /// This method never throws an exception.
+ const Name& getAlgorithm() const;
+
+ /// \brief Return the value of the Time Signed field.
+ ///
+ /// The returned value does not exceed 2^48-1.
+ ///
+ /// This method never throws an exception.
+ uint64_t getTimeSigned() const;
+
+ /// \brief Return the value of the Fudge field.
+ ///
+ /// This method never throws an exception.
+ uint16_t getFudge() const;
+
+ /// \brief Return the value of the MAC Size field.
+ ///
+ /// This method never throws an exception.
+ uint16_t getMACSize() const;
+
+ /// \brief Return the value of the MAC field.
+ ///
+ /// If the MAC field is empty, it returns NULL.
+ /// Otherwise, the memory region beginning at the address returned by
+ /// this method is valid up to the bytes specified by the return value
+ /// of \c getMACSize().
+ /// The memory region is only valid while the corresponding \c TSIG
+ /// object is valid. The caller must hold the \c TSIG object while
+ /// it needs to refer to the region or it must make a local copy of the
+ /// region.
+ ///
+ /// This method never throws an exception.
+ const void* getMAC() const;
+
+ /// \brief Return the value of the Original ID field.
+ ///
+ /// This method never throws an exception.
+ uint16_t getOriginalID() const;
+
+ /// \brief Return the value of the Error field.
+ ///
+ /// This method never throws an exception.
+ uint16_t getError() const;
+
+ /// \brief Return the value of the Other Len field.
+ ///
+ /// This method never throws an exception.
+ uint16_t getOtherLen() const;
+
+ /// \brief Return the value of the Other Data field.
+ ///
+ /// The same note as \c getMAC() applies.
+ ///
+ /// This method never throws an exception.
+ const void* getOtherData() const;
+private:
+ TSIGImpl* constructFromLexer(MasterLexer& lexer, const Name* origin);
+
+ 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
new file mode 100644
index 0000000..cd4c824
--- /dev/null
+++ b/src/lib/dns/rdata/ch_3/a_1.cc
@@ -0,0 +1,64 @@
+// 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
new file mode 100644
index 0000000..6f319b9
--- /dev/null
+++ b/src/lib/dns/rdata/ch_3/a_1.h
@@ -0,0 +1,32 @@
+// 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
new file mode 100644
index 0000000..5e82b03
--- /dev/null
+++ b/src/lib/dns/rdata/generic/afsdb_18.cc
@@ -0,0 +1,201 @@
+// 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
new file mode 100644
index 0000000..2fd8fba
--- /dev/null
+++ b/src/lib/dns/rdata/generic/afsdb_18.h
@@ -0,0 +1,68 @@
+// 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
new file mode 100644
index 0000000..7f8b455
--- /dev/null
+++ b/src/lib/dns/rdata/generic/caa_257.cc
@@ -0,0 +1,298 @@
+// 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
new file mode 100644
index 0000000..0e81e71
--- /dev/null
+++ b/src/lib/dns/rdata/generic/caa_257.h
@@ -0,0 +1,64 @@
+// 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
new file mode 100644
index 0000000..71cb4dc
--- /dev/null
+++ b/src/lib/dns/rdata/generic/cname_5.cc
@@ -0,0 +1,125 @@
+// 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
new file mode 100644
index 0000000..2149340
--- /dev/null
+++ b/src/lib/dns/rdata/generic/cname_5.h
@@ -0,0 +1,39 @@
+// 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
new file mode 100644
index 0000000..8eee8c0
--- /dev/null
+++ b/src/lib/dns/rdata/generic/detail/char_string.cc
@@ -0,0 +1,264 @@
+// 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/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;
+ for (CharString::const_iterator it = char_string.begin() + 1;
+ it != char_string.end(); ++it) {
+ const uint8_t ch = *it;
+ if ((ch < 0x20) || (ch >= 0x7f)) {
+ // convert to escaped \xxx (decimal) format
+ s.push_back('\\');
+ s.push_back('0' + ((ch / 100) % 10));
+ s.push_back('0' + ((ch / 10) % 10));
+ s.push_back('0' + (ch % 10));
+ continue;
+ }
+ if ((ch == '"') || (ch == ';') || (ch == '\\')) {
+ s.push_back('\\');
+ }
+ s.push_back(ch);
+ }
+
+ return (s);
+}
+
+std::string
+charStringDataToString(const CharStringData& char_string) {
+ std::string s;
+ for (CharString::const_iterator it = char_string.begin();
+ it != char_string.end(); ++it) {
+ const uint8_t ch = *it;
+ if ((ch < 0x20) || (ch >= 0x7f)) {
+ // convert to escaped \xxx (decimal) format
+ s.push_back('\\');
+ s.push_back('0' + ((ch / 100) % 10));
+ s.push_back('0' + ((ch / 10) % 10));
+ s.push_back('0' + (ch % 10));
+ continue;
+ }
+ if ((ch == '"') || (ch == ';') || (ch == '\\')) {
+ s.push_back('\\');
+ }
+ s.push_back(ch);
+ }
+
+ return (s);
+}
+
+int compareCharStrings(const detail::CharString& self,
+ const detail::CharString& other) {
+ if (self.size() == 0 && other.size() == 0) {
+ 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
new file mode 100644
index 0000000..2ad12fb
--- /dev/null
+++ b/src/lib/dns/rdata/generic/detail/char_string.h
@@ -0,0 +1,140 @@
+// 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
new file mode 100644
index 0000000..4d8c2ea
--- /dev/null
+++ b/src/lib/dns/rdata/generic/detail/ds_like.h
@@ -0,0 +1,277 @@
+// 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
new file mode 100644
index 0000000..29b6c31
--- /dev/null
+++ b/src/lib/dns/rdata/generic/detail/lexer_util.h
@@ -0,0 +1,62 @@
+// Copyright (C) 2013-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_LEXER_UTIL_H
+#define DNS_RDATA_LEXER_UTIL_H 1
+
+#include <dns/name.h>
+#include <dns/master_lexer.h>
+
+/// \file lexer_util.h
+/// \brief Utilities for extracting RDATA fields from lexer.
+///
+/// This file intends to define convenient small routines that can be
+/// commonly used in the RDATA implementation to build RDATA fields from
+/// a \c MasterLexer.
+
+namespace isc {
+namespace dns {
+namespace rdata {
+namespace generic {
+namespace detail {
+
+/// \brief Construct a Name object using a master lexer and optional origin.
+///
+/// This is a convenient shortcut of commonly used code pattern that would
+/// be used to build RDATA that contain a domain name field.
+///
+/// Note that this function throws an exception against invalid input.
+/// The (direct or indirect) caller's responsibility needs to expect and
+/// handle exceptions appropriately.
+///
+/// \throw MasterLexer::LexerError The next token from lexer is not string.
+/// \throw Other Exceptions from the \c Name class constructor if the next
+/// string token from the lexer does not represent a valid name.
+///
+/// \param lexer A \c MasterLexer object. Its next token is expected to be
+/// a string that represent a domain name.
+/// \param origin If non NULL, specifies the origin of the name to be
+/// constructed.
+///
+/// \return A new Name object that corresponds to the next string token of
+/// the \c lexer.
+inline Name
+createNameFromLexer(MasterLexer& lexer, const Name* origin) {
+ const MasterToken::StringRegion& str_region =
+ lexer.getNextToken(MasterToken::STRING).getStringRegion();
+ return (Name(str_region.beg, str_region.len, origin));
+}
+
+} // namespace detail
+} // namespace generic
+} // namespace rdata
+} // 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
new file mode 100644
index 0000000..efe488a
--- /dev/null
+++ b/src/lib/dns/rdata/generic/detail/nsec3param_common.cc
@@ -0,0 +1,115 @@
+// 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 <util/encode/hex.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
new file mode 100644
index 0000000..89b2596
--- /dev/null
+++ b/src/lib/dns/rdata/generic/detail/nsec3param_common.h
@@ -0,0 +1,123 @@
+// 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
new file mode 100644
index 0000000..d02c11d
--- /dev/null
+++ b/src/lib/dns/rdata/generic/detail/nsec_bitmap.cc
@@ -0,0 +1,169 @@
+// 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
new file mode 100644
index 0000000..4e073a0
--- /dev/null
+++ b/src/lib/dns/rdata/generic/detail/nsec_bitmap.h
@@ -0,0 +1,103 @@
+// 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
new file mode 100644
index 0000000..5801b09
--- /dev/null
+++ b/src/lib/dns/rdata/generic/detail/txt_like.h
@@ -0,0 +1,237 @@
+// 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
new file mode 100644
index 0000000..66303b7
--- /dev/null
+++ b/src/lib/dns/rdata/generic/dlv_32769.cc
@@ -0,0 +1,120 @@
+// 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 <util/encode/hex.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
new file mode 100644
index 0000000..26523de
--- /dev/null
+++ b/src/lib/dns/rdata/generic/dlv_32769.h
@@ -0,0 +1,69 @@
+// 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
new file mode 100644
index 0000000..9ee669b
--- /dev/null
+++ b/src/lib/dns/rdata/generic/dname_39.cc
@@ -0,0 +1,127 @@
+// 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
new file mode 100644
index 0000000..998fea0
--- /dev/null
+++ b/src/lib/dns/rdata/generic/dname_39.h
@@ -0,0 +1,39 @@
+// 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
new file mode 100644
index 0000000..7bea847
--- /dev/null
+++ b/src/lib/dns/rdata/generic/dnskey_48.cc
@@ -0,0 +1,316 @@
+// Copyright (C) 2010-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 <iostream>
+#include <string>
+#include <sstream>
+#include <vector>
+
+#include <boost/lexical_cast.hpp>
+#include <boost/foreach.hpp>
+
+#include <util/encode/base64.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
new file mode 100644
index 0000000..a5e9efa
--- /dev/null
+++ b/src/lib/dns/rdata/generic/dnskey_48.h
@@ -0,0 +1,60 @@
+// 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
new file mode 100644
index 0000000..48c421c
--- /dev/null
+++ b/src/lib/dns/rdata/generic/ds_43.cc
@@ -0,0 +1,90 @@
+// 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 <util/encode/hex.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
new file mode 100644
index 0000000..a20e349
--- /dev/null
+++ b/src/lib/dns/rdata/generic/ds_43.h
@@ -0,0 +1,69 @@
+// 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
new file mode 100644
index 0000000..3bda219
--- /dev/null
+++ b/src/lib/dns/rdata/generic/hinfo_13.cc
@@ -0,0 +1,151 @@
+// 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
new file mode 100644
index 0000000..acceb14
--- /dev/null
+++ b/src/lib/dns/rdata/generic/hinfo_13.h
@@ -0,0 +1,64 @@
+// 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
new file mode 100644
index 0000000..d3dfd1e
--- /dev/null
+++ b/src/lib/dns/rdata/generic/minfo_14.cc
@@ -0,0 +1,173 @@
+// 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
new file mode 100644
index 0000000..ce9f43d
--- /dev/null
+++ b/src/lib/dns/rdata/generic/minfo_14.h
@@ -0,0 +1,74 @@
+// 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
new file mode 100644
index 0000000..bbe8abc
--- /dev/null
+++ b/src/lib/dns/rdata/generic/mx_15.cc
@@ -0,0 +1,160 @@
+// 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
new file mode 100644
index 0000000..b688f88
--- /dev/null
+++ b/src/lib/dns/rdata/generic/mx_15.h
@@ -0,0 +1,52 @@
+// 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
new file mode 100644
index 0000000..aa2d7f5
--- /dev/null
+++ b/src/lib/dns/rdata/generic/naptr_35.cc
@@ -0,0 +1,256 @@
+// 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
new file mode 100644
index 0000000..c77b95d
--- /dev/null
+++ b/src/lib/dns/rdata/generic/naptr_35.h
@@ -0,0 +1,64 @@
+// 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
new file mode 100644
index 0000000..7c1fd01
--- /dev/null
+++ b/src/lib/dns/rdata/generic/ns_2.cc
@@ -0,0 +1,121 @@
+// 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
new file mode 100644
index 0000000..18c3cf6
--- /dev/null
+++ b/src/lib/dns/rdata/generic/ns_2.h
@@ -0,0 +1,43 @@
+// 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
new file mode 100644
index 0000000..e99c109
--- /dev/null
+++ b/src/lib/dns/rdata/generic/nsec3_50.cc
@@ -0,0 +1,343 @@
+// Copyright (C) 2010-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 <iostream>
+#include <iomanip>
+#include <string>
+#include <sstream>
+#include <vector>
+#include <cassert>
+
+#include <boost/lexical_cast.hpp>
+
+#include <util/encode/base32hex.h>
+#include <util/encode/hex.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
new file mode 100644
index 0000000..cf73624
--- /dev/null
+++ b/src/lib/dns/rdata/generic/nsec3_50.h
@@ -0,0 +1,54 @@
+// 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
new file mode 100644
index 0000000..2d28a69
--- /dev/null
+++ b/src/lib/dns/rdata/generic/nsec3param_51.cc
@@ -0,0 +1,232 @@
+// Copyright (C) 2010-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 <util/buffer.h>
+#include <util/encode/hex.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
new file mode 100644
index 0000000..1c7bf03
--- /dev/null
+++ b/src/lib/dns/rdata/generic/nsec3param_51.h
@@ -0,0 +1,56 @@
+// 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
new file mode 100644
index 0000000..f8af0e0
--- /dev/null
+++ b/src/lib/dns/rdata/generic/nsec_47.cc
@@ -0,0 +1,216 @@
+// 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 <iostream>
+#include <string>
+#include <sstream>
+#include <vector>
+
+#include <util/encode/base64.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
new file mode 100644
index 0000000..299d381
--- /dev/null
+++ b/src/lib/dns/rdata/generic/nsec_47.h
@@ -0,0 +1,53 @@
+// 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
new file mode 100644
index 0000000..40cb1c7
--- /dev/null
+++ b/src/lib/dns/rdata/generic/opt_41.cc
@@ -0,0 +1,219 @@
+// Copyright (C) 2010-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 <util/buffer.h>
+#include <dns/messagerenderer.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+
+#include <boost/foreach.hpp>
+
+#include <string>
+#include <string.h>
+
+using namespace std;
+using namespace isc::util;
+
+// BEGIN_ISC_NAMESPACE
+// BEGIN_RDATA_NAMESPACE
+
+/// \brief Constructor.
+OPT::PseudoRR::PseudoRR(uint16_t code,
+ boost::shared_ptr<std::vector<uint8_t> >& data) :
+ code_(code),
+ data_(data)
+{
+}
+
+uint16_t
+OPT::PseudoRR::getCode() const {
+ return (code_);
+}
+
+const uint8_t*
+OPT::PseudoRR::getData() const {
+ return (&(*data_)[0]);
+}
+
+uint16_t
+OPT::PseudoRR::getLength() const {
+ return (data_->size());
+}
+
+struct OPTImpl {
+ OPTImpl() :
+ rdlength_(0)
+ {}
+
+ uint16_t rdlength_;
+ std::vector<OPT::PseudoRR> pseudo_rrs_;
+};
+
+/// \brief Default constructor.
+OPT::OPT() :
+ impl_(new OPTImpl)
+{
+}
+
+/// \brief Constructor from string.
+///
+/// This constructor cannot be used, and always throws an exception.
+///
+/// \throw InvalidRdataText OPT RR cannot be constructed from text.
+OPT::OPT(const std::string&) :
+ impl_(NULL)
+{
+ isc_throw(InvalidRdataText, "OPT RR cannot be constructed from text");
+}
+
+/// \brief Constructor with a context of MasterLexer.
+///
+/// This constructor cannot be used, and always throws an exception.
+///
+/// \throw InvalidRdataText OPT RR cannot be constructed from text.
+OPT::OPT(MasterLexer&, const Name*,
+ MasterLoader::Options, MasterLoaderCallbacks&) :
+ 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);
+
+ while (true) {
+ if (rdata_len == 0) {
+ break;
+ }
+
+ if (rdata_len < 4) {
+ isc_throw(InvalidRdataLength,
+ "Pseudo OPT RR record too short: "
+ << rdata_len << " bytes");
+ }
+
+ const uint16_t option_code = buffer.readUint16();
+ const uint16_t option_length = buffer.readUint16();
+ rdata_len -= 4;
+
+ if (static_cast<uint16_t>(impl_ptr->rdlength_ + option_length) <
+ impl_ptr->rdlength_)
+ {
+ isc_throw(InvalidRdataText,
+ "Option length " << option_length
+ << " would overflow OPT RR RDLEN (currently "
+ << impl_ptr->rdlength_ << ").");
+ }
+
+ if (rdata_len < option_length) {
+ isc_throw(InvalidRdataLength, "Corrupt pseudo OPT RR record");
+ }
+
+ boost::shared_ptr<std::vector<uint8_t> >
+ option_data(new std::vector<uint8_t>(option_length));
+ buffer.readData(&(*option_data)[0], option_length);
+ impl_ptr->pseudo_rrs_.push_back(PseudoRR(option_code, option_data));
+ impl_ptr->rdlength_ += option_length;
+ rdata_len -= option_length;
+ }
+
+ impl_ = impl_ptr.release();
+}
+
+OPT::OPT(const OPT& other) :
+ Rdata(), impl_(new OPTImpl(*other.impl_))
+{
+}
+
+OPT&
+OPT::operator=(const OPT& source) {
+ if (this == &source) {
+ return (*this);
+ }
+
+ OPTImpl* newimpl = new OPTImpl(*source.impl_);
+ delete impl_;
+ impl_ = newimpl;
+
+ return (*this);
+}
+
+OPT::~OPT() {
+ delete impl_;
+}
+
+std::string
+OPT::toText() const {
+ isc_throw(isc::InvalidOperation,
+ "OPT RRs do not have a presentation format");
+}
+
+void
+OPT::toWire(OutputBuffer& buffer) const {
+ BOOST_FOREACH(const PseudoRR& pseudo_rr, impl_->pseudo_rrs_) {
+ buffer.writeUint16(pseudo_rr.getCode());
+ const uint16_t length = pseudo_rr.getLength();
+ buffer.writeUint16(length);
+ if (length > 0) {
+ buffer.writeData(pseudo_rr.getData(), length);
+ }
+ }
+}
+
+void
+OPT::toWire(AbstractMessageRenderer& renderer) const {
+ BOOST_FOREACH(const PseudoRR& pseudo_rr, impl_->pseudo_rrs_) {
+ renderer.writeUint16(pseudo_rr.getCode());
+ const uint16_t length = pseudo_rr.getLength();
+ renderer.writeUint16(length);
+ if (length > 0) {
+ renderer.writeData(pseudo_rr.getData(), length);
+ }
+ }
+}
+
+int
+OPT::compare(const Rdata&) const {
+ isc_throw(isc::InvalidOperation,
+ "It is meaningless to compare a set of OPT pseudo RRs; "
+ "they have unspecified order");
+ return (0);
+}
+
+void
+OPT::appendPseudoRR(uint16_t code, const uint8_t* data, uint16_t length) {
+ // See if it overflows 16-bit length field. We only worry about the
+ // pseudo-RR length here, not the whole message length (which should
+ // be checked and enforced elsewhere).
+ if (static_cast<uint16_t>(impl_->rdlength_ + length) <
+ impl_->rdlength_)
+ {
+ isc_throw(isc::InvalidParameter,
+ "Option length " << length
+ << " would overflow OPT RR RDLEN (currently "
+ << impl_->rdlength_ << ").");
+ }
+
+ boost::shared_ptr<std::vector<uint8_t> >
+ option_data(new std::vector<uint8_t>(length));
+ if (length != 0) {
+ std::memcpy(&(*option_data)[0], data, length);
+ }
+ impl_->pseudo_rrs_.push_back(PseudoRR(code, option_data));
+ impl_->rdlength_ += length;
+}
+
+const std::vector<OPT::PseudoRR>&
+OPT::getPseudoRRs() const {
+ return (impl_->pseudo_rrs_);
+}
+
+// END_RDATA_NAMESPACE
+// END_ISC_NAMESPACE
diff --git a/src/lib/dns/rdata/generic/opt_41.h b/src/lib/dns/rdata/generic/opt_41.h
new file mode 100644
index 0000000..0c00aed
--- /dev/null
+++ b/src/lib/dns/rdata/generic/opt_41.h
@@ -0,0 +1,90 @@
+// 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>
+
+#include <boost/shared_ptr.hpp>
+
+#include <vector>
+
+// BEGIN_ISC_NAMESPACE
+
+// BEGIN_COMMON_DECLARATIONS
+// END_COMMON_DECLARATIONS
+
+// BEGIN_RDATA_NAMESPACE
+
+struct OPTImpl;
+
+class OPT : public Rdata {
+public:
+ // BEGIN_COMMON_MEMBERS
+ // END_COMMON_MEMBERS
+
+ // The default constructor makes sense for OPT as it can be empty.
+ OPT();
+ OPT& operator=(const OPT& source);
+ ~OPT();
+
+ /// \brief A class representing a pseudo RR (or option) within an
+ /// OPT RR (see RFC 6891).
+ class PseudoRR {
+ public:
+ /// \brief Constructor.
+ /// \param code The OPTION-CODE field of the pseudo RR.
+ /// \param data The OPTION-DATA field of the pseudo
+ /// RR. OPTION-LENGTH is set to the length of this vector.
+ PseudoRR(uint16_t code,
+ boost::shared_ptr<std::vector<uint8_t> >& data);
+
+ /// \brief Return the option code of this pseudo RR.
+ uint16_t getCode() const;
+
+ /// \brief Return the option data of this pseudo RR.
+ const uint8_t* getData() const;
+
+ /// \brief Return the length of the option data of this
+ /// pseudo RR.
+ uint16_t getLength() const;
+
+ private:
+ uint16_t code_;
+ boost::shared_ptr<std::vector<uint8_t> > data_;
+ };
+
+ /// \brief Append a pseudo RR (option) in this OPT RR.
+ ///
+ /// \param code The OPTION-CODE field of the pseudo RR.
+ /// \param data The OPTION-DATA field of the pseudo RR.
+ /// \param length The size of the \c data argument. OPTION-LENGTH is
+ /// set to this size.
+ /// \throw isc::InvalidParameter if this pseudo RR would cause
+ /// the OPT RDATA to overflow its RDLENGTH.
+ void appendPseudoRR(uint16_t code, const uint8_t* data, uint16_t length);
+
+ /// \brief Return a vector of the pseudo RRs (options) in this
+ /// OPT RR.
+ ///
+ /// Note: The returned reference is only valid during the lifetime
+ /// of this \c generic::OPT object. It should not be used
+ /// afterwards.
+ const std::vector<PseudoRR>& getPseudoRRs() const;
+
+private:
+ OPTImpl* impl_;
+};
+
+// END_RDATA_NAMESPACE
+// END_ISC_NAMESPACE
+// END_HEADER_GUARD
+
+// Local Variables:
+// mode: c++
+// End:
diff --git a/src/lib/dns/rdata/generic/ptr_12.cc b/src/lib/dns/rdata/generic/ptr_12.cc
new file mode 100644
index 0000000..b3596e8
--- /dev/null
+++ b/src/lib/dns/rdata/generic/ptr_12.cc
@@ -0,0 +1,123 @@
+// 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 PTR 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 PTRDNAME 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.
+PTR::PTR(const std::string& type_str) :
+ // Fill in dummy name and replace them soon below.
+ ptr_name_(Name::ROOT_NAME())
+{
+ try {
+ std::istringstream ss(type_str);
+ MasterLexer lexer;
+ lexer.pushSource(ss);
+
+ ptr_name_ = createNameFromLexer(lexer, NULL);
+
+ if (lexer.getNextToken().getType() != MasterToken::END_OF_FILE) {
+ isc_throw(InvalidRdataText, "extra input text for PTR: "
+ << type_str);
+ }
+ } catch (const MasterLexer::LexerError& ex) {
+ isc_throw(InvalidRdataText, "Failed to construct PTR from '" <<
+ type_str << "': " << ex.what());
+ }
+}
+
+PTR::PTR(InputBuffer& buffer, size_t) :
+ ptr_name_(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 PTR RDATA. The PTRDNAME 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 PTRDNAME when it
+/// is non-absolute.
+PTR::PTR(MasterLexer& lexer, const Name* origin,
+ MasterLoader::Options, MasterLoaderCallbacks&) :
+ ptr_name_(createNameFromLexer(lexer, origin))
+{}
+
+PTR::PTR(const PTR& source) :
+ Rdata(), ptr_name_(source.ptr_name_)
+{}
+
+std::string
+PTR::toText() const {
+ return (ptr_name_.toText());
+}
+
+void
+PTR::toWire(OutputBuffer& buffer) const {
+ ptr_name_.toWire(buffer);
+}
+
+void
+PTR::toWire(AbstractMessageRenderer& renderer) const {
+ renderer.writeName(ptr_name_);
+}
+
+int
+PTR::compare(const Rdata& other) const {
+ // The compare method normally begins with this dynamic cast.
+ const PTR& other_ptr = dynamic_cast<const PTR&>(other);
+
+ return (compareNames(ptr_name_, other_ptr.ptr_name_));
+
+}
+
+const Name&
+PTR::getPTRName() const {
+ return (ptr_name_);
+}
+
+// END_RDATA_NAMESPACE
+// END_ISC_NAMESPACE
diff --git a/src/lib/dns/rdata/generic/ptr_12.h b/src/lib/dns/rdata/generic/ptr_12.h
new file mode 100644
index 0000000..e562ef7
--- /dev/null
+++ b/src/lib/dns/rdata/generic/ptr_12.h
@@ -0,0 +1,44 @@
+// 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 PTR : public Rdata {
+public:
+ // BEGIN_COMMON_MEMBERS
+ // END_COMMON_MEMBERS
+
+ ///
+ /// Specialized constructor
+ ///
+ explicit PTR(const Name& ptr_name) : ptr_name_(ptr_name) {}
+ ///
+ /// Specialized methods
+ ///
+ const Name& getPTRName() const;
+private:
+ Name ptr_name_;
+};
+
+// 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
new file mode 100644
index 0000000..43bf647
--- /dev/null
+++ b/src/lib/dns/rdata/generic/rp_17.cc
@@ -0,0 +1,160 @@
+// 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
new file mode 100644
index 0000000..9536ee9
--- /dev/null
+++ b/src/lib/dns/rdata/generic/rp_17.h
@@ -0,0 +1,78 @@
+// 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
new file mode 100644
index 0000000..de92c67
--- /dev/null
+++ b/src/lib/dns/rdata/generic/rrsig_46.cc
@@ -0,0 +1,334 @@
+// Copyright (C) 2010-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 <string>
+#include <iomanip>
+#include <iostream>
+#include <sstream>
+#include <vector>
+
+#include <boost/lexical_cast.hpp>
+
+#include <util/encode/base64.h>
+#include <util/buffer.h>
+#include <util/time_utilities.h>
+#include <dns/messagerenderer.h>
+#include <dns/name.h>
+#include <dns/rrtype.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.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 isc::dns::rdata::generic::detail::createNameFromLexer;
+
+// BEGIN_ISC_NAMESPACE
+// BEGIN_RDATA_NAMESPACE
+
+namespace {
+// This is the minimum necessary length of all wire-format RRSIG RDATA:
+// - two 8-bit fields (algorithm and labels)
+// - two 16-bit fields (covered and tag)
+// - three 32-bit fields (original TTL, expire and inception)
+const size_t RRSIG_MINIMUM_LEN = 2 * sizeof(uint8_t) + 2 * sizeof(uint16_t) +
+ 3 * sizeof(uint32_t);
+}
+
+struct RRSIGImpl {
+ // straightforward representation of RRSIG RDATA fields
+ RRSIGImpl(const RRType& covered, uint8_t algorithm, uint8_t labels,
+ uint32_t originalttl, uint32_t timeexpire,
+ uint32_t timeinception, uint16_t tag, const Name& signer,
+ const vector<uint8_t>& signature) :
+ covered_(covered), algorithm_(algorithm), labels_(labels),
+ originalttl_(originalttl), timeexpire_(timeexpire),
+ timeinception_(timeinception), tag_(tag), signer_(signer),
+ signature_(signature)
+ {}
+
+ const RRType covered_;
+ uint8_t algorithm_;
+ uint8_t labels_;
+ uint32_t originalttl_;
+ uint32_t timeexpire_;
+ uint32_t timeinception_;
+ uint16_t tag_;
+ const Name signer_;
+ const vector<uint8_t> signature_;
+};
+
+// helper function for string and lexer constructors
+RRSIGImpl*
+RRSIG::constructFromLexer(MasterLexer& lexer, const Name* origin) {
+ const RRType covered(lexer.getNextToken(MasterToken::STRING).getString());
+ const uint32_t algorithm =
+ lexer.getNextToken(MasterToken::NUMBER).getNumber();
+ if (algorithm > 0xff) {
+ isc_throw(InvalidRdataText, "RRSIG algorithm out of range");
+ }
+ const uint32_t labels =
+ lexer.getNextToken(MasterToken::NUMBER).getNumber();
+ if (labels > 0xff) {
+ isc_throw(InvalidRdataText, "RRSIG labels out of range");
+ }
+ const uint32_t originalttl =
+ lexer.getNextToken(MasterToken::NUMBER).getNumber();
+ const uint32_t timeexpire =
+ timeFromText32(lexer.getNextToken(MasterToken::STRING).getString());
+ const uint32_t timeinception =
+ timeFromText32(lexer.getNextToken(MasterToken::STRING).getString());
+ const uint32_t tag =
+ lexer.getNextToken(MasterToken::NUMBER).getNumber();
+ if (tag > 0xffff) {
+ isc_throw(InvalidRdataText, "RRSIG key tag out of range");
+ }
+ const Name& signer = createNameFromLexer(lexer, origin);
+
+ string signature_txt;
+ string signature_part;
+ // Whitespace is allowed within base64 text, so read to the end of input.
+ while (true) {
+ const MasterToken& token =
+ lexer.getNextToken(MasterToken::STRING, true);
+ if ((token.getType() == MasterToken::END_OF_FILE) ||
+ (token.getType() == MasterToken::END_OF_LINE)) {
+ break;
+ }
+ token.getString(signature_part);
+ signature_txt.append(signature_part);
+ }
+ lexer.ungetToken();
+
+ vector<uint8_t> signature;
+ // missing signature is okay
+ if (signature_txt.size() > 0) {
+ decodeBase64(signature_txt, signature);
+ }
+
+ return (new RRSIGImpl(covered, algorithm, labels,
+ originalttl, timeexpire, timeinception,
+ static_cast<uint16_t>(tag), signer, signature));
+}
+
+/// \brief Constructor from string.
+///
+/// The given string must represent a valid RRSIG 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 Signer's Name must be absolute since there's no parameter that
+/// specifies the origin name; if this is not absolute, \c MissingNameOrigin
+/// exception will be thrown. This must not be represented as a quoted
+/// string.
+///
+/// See the construction that takes \c MasterLexer for other fields.
+///
+/// \throw Others Exception from the Name constructor.
+/// \throw InvalidRdataText Other general syntax errors.
+RRSIG::RRSIG(const std::string& rrsig_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 RRSIGImpl that constructFromLexer() returns.
+ std::unique_ptr<RRSIGImpl> impl_ptr;
+
+ try {
+ std::istringstream iss(rrsig_str);
+ MasterLexer lexer;
+ lexer.pushSource(iss);
+
+ impl_ptr.reset(constructFromLexer(lexer, NULL));
+
+ if (lexer.getNextToken().getType() != MasterToken::END_OF_FILE) {
+ isc_throw(InvalidRdataText, "extra input text for RRSIG: "
+ << rrsig_str);
+ }
+ } catch (const MasterLexer::LexerError& ex) {
+ isc_throw(InvalidRdataText, "Failed to construct RRSIG from '" <<
+ rrsig_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 RRSIG RDATA. The Signer's Name fields can be non absolute if \c
+/// origin is non NULL, in which case \c origin is used to make it absolute.
+/// This must not be represented as a quoted string.
+///
+/// The Original TTL field is a valid decimal representation of an unsigned
+/// 32-bit integer. Note that alternate textual representations of \c RRTTL,
+/// such as "1H" for 3600 seconds, are not allowed here.
+///
+/// \throw MasterLexer::LexerError General parsing error such as missing field.
+/// \throw Other Exceptions from the Name constructor 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 Signer's Name when
+/// it is non absolute.
+RRSIG::RRSIG(MasterLexer& lexer, const Name* origin,
+ MasterLoader::Options, MasterLoaderCallbacks&) :
+ impl_(constructFromLexer(lexer, origin))
+{
+}
+
+RRSIG::RRSIG(InputBuffer& buffer, size_t rdata_len) {
+ size_t pos = buffer.getPosition();
+
+ if (rdata_len < RRSIG_MINIMUM_LEN) {
+ isc_throw(InvalidRdataLength, "RRSIG too short");
+ }
+
+ RRType covered(buffer);
+ uint8_t algorithm = buffer.readUint8();
+ uint8_t labels = buffer.readUint8();
+ uint32_t originalttl = buffer.readUint32();
+ uint32_t timeexpire = buffer.readUint32();
+ uint32_t timeinception = buffer.readUint32();
+ uint16_t tag = buffer.readUint16();
+ Name signer(buffer);
+
+ // rdata_len must be sufficiently large to hold non empty signature data.
+ if (rdata_len <= buffer.getPosition() - pos) {
+ isc_throw(InvalidRdataLength, "RRSIG too short");
+ }
+ rdata_len -= (buffer.getPosition() - pos);
+
+ vector<uint8_t> signature(rdata_len);
+ buffer.readData(&signature[0], rdata_len);
+
+ impl_ = new RRSIGImpl(covered, algorithm, labels,
+ originalttl, timeexpire, timeinception, tag,
+ signer, signature);
+}
+
+RRSIG::RRSIG(const RRSIG& source) :
+ Rdata(), impl_(new RRSIGImpl(*source.impl_))
+{}
+
+RRSIG&
+RRSIG::operator=(const RRSIG& source) {
+ if (this == &source) {
+ return (*this);
+ }
+
+ RRSIGImpl* newimpl = new RRSIGImpl(*source.impl_);
+ delete impl_;
+ impl_ = newimpl;
+
+ return (*this);
+}
+
+RRSIG::~RRSIG() {
+ delete impl_;
+}
+
+string
+RRSIG::toText() const {
+ return (impl_->covered_.toText() +
+ " " + boost::lexical_cast<string>(static_cast<int>(impl_->algorithm_))
+ + " " + boost::lexical_cast<string>(static_cast<int>(impl_->labels_))
+ + " " + boost::lexical_cast<string>(impl_->originalttl_)
+ + " " + timeToText32(impl_->timeexpire_)
+ + " " + timeToText32(impl_->timeinception_)
+ + " " + boost::lexical_cast<string>(impl_->tag_)
+ + " " + impl_->signer_.toText()
+ + " " + encodeBase64(impl_->signature_));
+}
+
+void
+RRSIG::toWire(OutputBuffer& buffer) const {
+ impl_->covered_.toWire(buffer);
+ buffer.writeUint8(impl_->algorithm_);
+ buffer.writeUint8(impl_->labels_);
+ buffer.writeUint32(impl_->originalttl_);
+ buffer.writeUint32(impl_->timeexpire_);
+ buffer.writeUint32(impl_->timeinception_);
+ buffer.writeUint16(impl_->tag_);
+ impl_->signer_.toWire(buffer);
+ buffer.writeData(&impl_->signature_[0], impl_->signature_.size());
+}
+
+void
+RRSIG::toWire(AbstractMessageRenderer& renderer) const {
+ impl_->covered_.toWire(renderer);
+ renderer.writeUint8(impl_->algorithm_);
+ renderer.writeUint8(impl_->labels_);
+ renderer.writeUint32(impl_->originalttl_);
+ renderer.writeUint32(impl_->timeexpire_);
+ renderer.writeUint32(impl_->timeinception_);
+ renderer.writeUint16(impl_->tag_);
+ renderer.writeName(impl_->signer_, false);
+ renderer.writeData(&impl_->signature_[0], impl_->signature_.size());
+}
+
+int
+RRSIG::compare(const Rdata& other) const {
+ const RRSIG& other_rrsig = dynamic_cast<const RRSIG&>(other);
+
+ if (impl_->covered_.getCode() != other_rrsig.impl_->covered_.getCode()) {
+ return (impl_->covered_.getCode() <
+ other_rrsig.impl_->covered_.getCode() ? -1 : 1);
+ }
+ if (impl_->algorithm_ != other_rrsig.impl_->algorithm_) {
+ return (impl_->algorithm_ < other_rrsig.impl_->algorithm_ ? -1 : 1);
+ }
+ if (impl_->labels_ != other_rrsig.impl_->labels_) {
+ return (impl_->labels_ < other_rrsig.impl_->labels_ ? -1 : 1);
+ }
+ if (impl_->originalttl_ != other_rrsig.impl_->originalttl_) {
+ return (impl_->originalttl_ < other_rrsig.impl_->originalttl_ ?
+ -1 : 1);
+ }
+ if (impl_->timeexpire_ != other_rrsig.impl_->timeexpire_) {
+ return (impl_->timeexpire_ < other_rrsig.impl_->timeexpire_ ?
+ -1 : 1);
+ }
+ if (impl_->timeinception_ != other_rrsig.impl_->timeinception_) {
+ return (impl_->timeinception_ < other_rrsig.impl_->timeinception_ ?
+ -1 : 1);
+ }
+ if (impl_->tag_ != other_rrsig.impl_->tag_) {
+ return (impl_->tag_ < other_rrsig.impl_->tag_ ? -1 : 1);
+ }
+
+ int cmp = compareNames(impl_->signer_, other_rrsig.impl_->signer_);
+ if (cmp != 0) {
+ return (cmp);
+ }
+
+ size_t this_len = impl_->signature_.size();
+ size_t other_len = other_rrsig.impl_->signature_.size();
+ size_t cmplen = min(this_len, other_len);
+ cmp = memcmp(&impl_->signature_[0], &other_rrsig.impl_->signature_[0],
+ cmplen);
+ if (cmp != 0) {
+ return (cmp);
+ } else {
+ return ((this_len == other_len) ? 0 : (this_len < other_len) ? -1 : 1);
+ }
+}
+
+const RRType&
+RRSIG::typeCovered() const {
+ return (impl_->covered_);
+}
+
+// END_RDATA_NAMESPACE
+// END_ISC_NAMESPACE
diff --git a/src/lib/dns/rdata/generic/rrsig_46.h b/src/lib/dns/rdata/generic/rrsig_46.h
new file mode 100644
index 0000000..aca26ba
--- /dev/null
+++ b/src/lib/dns/rdata/generic/rrsig_46.h
@@ -0,0 +1,54 @@
+// 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/rdata.h>
+
+// BEGIN_HEADER_GUARD
+
+// BEGIN_ISC_NAMESPACE
+
+// BEGIN_COMMON_DECLARATIONS
+// END_COMMON_DECLARATIONS
+
+// BEGIN_RDATA_NAMESPACE
+
+struct RRSIGImpl;
+
+/// \brief \c rdata::RRSIG class represents the RRSIG RDATA as defined %in
+/// RFC4034.
+///
+/// This class implements the basic interfaces inherited from the abstract
+/// \c rdata::Rdata class, and provides trivial accessors specific to the
+/// RRSIG RDATA.
+class RRSIG : public Rdata {
+public:
+ // BEGIN_COMMON_MEMBERS
+ // END_COMMON_MEMBERS
+ RRSIG& operator=(const RRSIG& source);
+ ~RRSIG();
+
+ // specialized methods
+ const RRType& typeCovered() const;
+private:
+ // helper function for string and lexer constructors
+ RRSIGImpl* constructFromLexer(MasterLexer& lexer, const Name* origin);
+
+ 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
new file mode 100644
index 0000000..ee4e43d
--- /dev/null
+++ b/src/lib/dns/rdata/generic/soa_6.cc
@@ -0,0 +1,210 @@
+// 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 <dns/name.h>
+#include <dns/master_lexer.h>
+#include <dns/master_loader.h>
+#include <dns/master_loader_callbacks.h>
+#include <dns/messagerenderer.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+
+#include <dns/rdata/generic/detail/lexer_util.h>
+
+#include <boost/static_assert.hpp>
+#include <boost/lexical_cast.hpp>
+
+#include <string>
+#include <sstream>
+
+using namespace std;
+using boost::lexical_cast;
+using namespace isc::util;
+using isc::dns::rdata::generic::detail::createNameFromLexer;
+
+// BEGIN_ISC_NAMESPACE
+// BEGIN_RDATA_NAMESPACE
+
+SOA::SOA(InputBuffer& buffer, size_t) :
+ mname_(buffer), rname_(buffer)
+{
+ // we don't need rdata_len for parsing. if necessary, the caller will
+ // check consistency.
+ buffer.readData(numdata_, sizeof(numdata_));
+}
+
+namespace {
+void
+fillParameters(MasterLexer& lexer, uint8_t numdata[20]) {
+ // Copy serial, refresh, retry, expire, minimum. We accept the extended
+ // TTL-compatible style for the latter four.
+ OutputBuffer buffer(20);
+ buffer.writeUint32(lexer.getNextToken(MasterToken::NUMBER).getNumber());
+ for (int i = 0; i < 4; ++i) {
+ buffer.writeUint32(RRTTL(lexer.getNextToken(MasterToken::STRING).
+ getString()).getValue());
+ }
+ memcpy(numdata, buffer.getData(), buffer.getLength());
+}
+}
+
+/// \brief Constructor from string.
+///
+/// The given string must represent a valid SOA 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 MNAME and RNAME must be absolute since there's no parameter that
+/// specifies the origin name; if these are not absolute, \c MissingNameOrigin
+/// exception will be thrown. These 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.
+SOA::SOA(const std::string& soastr) :
+ // Fill in dummy name and replace them soon below.
+ mname_(Name::ROOT_NAME()), rname_(Name::ROOT_NAME())
+{
+ try {
+ std::istringstream ss(soastr);
+ MasterLexer lexer;
+ lexer.pushSource(ss);
+
+ mname_ = createNameFromLexer(lexer, NULL);
+ rname_ = createNameFromLexer(lexer, NULL);
+ fillParameters(lexer, numdata_);
+
+ if (lexer.getNextToken().getType() != MasterToken::END_OF_FILE) {
+ isc_throw(InvalidRdataText, "extra input text for SOA: "
+ << soastr);
+ }
+ } catch (const MasterLexer::LexerError& ex) {
+ isc_throw(InvalidRdataText, "Failed to construct SOA from '" <<
+ soastr << "': " << ex.what());
+ }
+}
+
+/// \brief Constructor with a context of MasterLexer.
+///
+/// The \c lexer should point to the beginning of valid textual representation
+/// of an SOA RDATA. The MNAME and RNAME fields can be non absolute if
+/// \c origin is non NULL, in which case \c origin is used to make them
+/// absolute. These must not be represented as a quoted string.
+///
+/// The REFRESH, RETRY, EXPIRE, and MINIMUM fields can be either a valid
+/// decimal representation of an unsigned 32-bit integer or other
+/// valid textual representation of \c RRTTL such as "1H" (which means 3600).
+///
+/// \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 MNAME and RNAME when
+/// they are non absolute.
+SOA::SOA(MasterLexer& lexer, const Name* origin,
+ MasterLoader::Options, MasterLoaderCallbacks&) :
+ mname_(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)
+{
+ OutputBuffer b(20);
+ b.writeUint32(serial);
+ b.writeUint32(refresh);
+ b.writeUint32(retry);
+ b.writeUint32(expire);
+ b.writeUint32(minimum);
+ assert(b.getLength() == sizeof(numdata_));
+ memcpy(numdata_, b.getData(), sizeof(numdata_));
+}
+
+SOA::SOA(const SOA& other) :
+ Rdata(), mname_(other.mname_), rname_(other.rname_)
+{
+ memcpy(numdata_, other.numdata_, sizeof(numdata_));
+}
+
+void
+SOA::toWire(OutputBuffer& buffer) const {
+ mname_.toWire(buffer);
+ rname_.toWire(buffer);
+ buffer.writeData(numdata_, sizeof(numdata_));
+}
+
+void
+SOA::toWire(AbstractMessageRenderer& renderer) const {
+ renderer.writeName(mname_);
+ renderer.writeName(rname_);
+ renderer.writeData(numdata_, sizeof(numdata_));
+}
+
+Serial
+SOA::getSerial() const {
+ InputBuffer b(numdata_, sizeof(numdata_));
+ return (Serial(b.readUint32()));
+}
+
+uint32_t
+SOA::getMinimum() const {
+ // Make sure the buffer access is safe.
+ BOOST_STATIC_ASSERT(sizeof(numdata_) ==
+ sizeof(uint32_t) * 4 + sizeof(uint32_t));
+
+ InputBuffer b(&numdata_[sizeof(uint32_t) * 4], sizeof(uint32_t));
+ return (b.readUint32());
+}
+
+string
+SOA::toText() const {
+ InputBuffer b(numdata_, sizeof(numdata_));
+ uint32_t serial = b.readUint32();
+ uint32_t refresh = b.readUint32();
+ uint32_t retry = b.readUint32();
+ uint32_t expire = b.readUint32();
+ uint32_t minimum = b.readUint32();
+
+ return (mname_.toText() + " " + rname_.toText() + " " +
+ lexical_cast<string>(serial) + " " +
+ lexical_cast<string>(refresh) + " " +
+ lexical_cast<string>(retry) + " " +
+ lexical_cast<string>(expire) + " " +
+ lexical_cast<string>(minimum));
+}
+
+int
+SOA::compare(const Rdata& other) const {
+ const SOA& other_soa = dynamic_cast<const SOA&>(other);
+
+ int order = compareNames(mname_, other_soa.mname_);
+ if (order != 0) {
+ return (order);
+ }
+
+ order = compareNames(rname_, other_soa.rname_);
+ if (order != 0) {
+ return (order);
+ }
+
+ return (memcmp(numdata_, other_soa.numdata_, sizeof(numdata_)));
+}
+
+// END_RDATA_NAMESPACE
+// END_ISC_NAMESPACE
diff --git a/src/lib/dns/rdata/generic/soa_6.h b/src/lib/dns/rdata/generic/soa_6.h
new file mode 100644
index 0000000..50a062e
--- /dev/null
+++ b/src/lib/dns/rdata/generic/soa_6.h
@@ -0,0 +1,51 @@
+// 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>
+#include <dns/serial.h>
+
+// BEGIN_ISC_NAMESPACE
+
+// BEGIN_COMMON_DECLARATIONS
+// END_COMMON_DECLARATIONS
+
+// BEGIN_RDATA_NAMESPACE
+
+class SOA : public Rdata {
+public:
+ // BEGIN_COMMON_MEMBERS
+ // END_COMMON_MEMBERS
+
+ SOA(const Name& mname, const Name& rname, uint32_t serial,
+ uint32_t refresh, uint32_t retry, uint32_t expire,
+ uint32_t minimum);
+
+ /// \brief Returns the serial stored in the SOA.
+ Serial getSerial() const;
+
+ /// brief Returns the minimum TTL field value of the SOA.
+ uint32_t getMinimum() const;
+private:
+ /// Note: this is a prototype version; we may reconsider
+ /// this representation later.
+ Name mname_;
+ Name rname_;
+ /// serial, refresh, retry, expire, minimum, stored in network byte order
+ uint8_t numdata_[20];
+};
+
+// 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
new file mode 100644
index 0000000..f25585a
--- /dev/null
+++ b/src/lib/dns/rdata/generic/spf_99.cc
@@ -0,0 +1,139 @@
+// 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
new file mode 100644
index 0000000..3a84d9d
--- /dev/null
+++ b/src/lib/dns/rdata/generic/spf_99.h
@@ -0,0 +1,72 @@
+// 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
new file mode 100644
index 0000000..a08a17f
--- /dev/null
+++ b/src/lib/dns/rdata/generic/sshfp_44.cc
@@ -0,0 +1,298 @@
+// Copyright (C) 2012-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 <exceptions/exceptions.h>
+
+#include <util/buffer.h>
+#include <util/encode/hex.h>
+#include <dns/name.h>
+#include <dns/messagerenderer.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+
+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
new file mode 100644
index 0000000..4eae696
--- /dev/null
+++ b/src/lib/dns/rdata/generic/sshfp_44.h
@@ -0,0 +1,56 @@
+// 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
new file mode 100644
index 0000000..435a345
--- /dev/null
+++ b/src/lib/dns/rdata/generic/tkey_249.cc
@@ -0,0 +1,613 @@
+// 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 <sstream>
+#include <vector>
+
+#include <boost/lexical_cast.hpp>
+
+#include <util/buffer.h>
+#include <util/encode/base64.h>
+#include <util/time_utilities.h>
+
+#include <dns/messagerenderer.h>
+#include <dns/name.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rcode.h>
+#include <dns/rdata/generic/detail/lexer_util.h>
+
+using namespace std;
+using boost::lexical_cast;
+using namespace isc::util;
+using namespace isc::util::encode;
+using namespace isc::dns;
+using isc::dns::rdata::generic::detail::createNameFromLexer;
+
+// BEGIN_ISC_NAMESPACE
+// BEGIN_RDATA_NAMESPACE
+
+const uint16_t TKEY::GSS_API_MODE = 3;
+
+// straightforward representation of TKEY RDATA fields
+struct TKEYImpl {
+ /// \brief Constructor from RDATA field parameters.
+ ///
+ /// \param algorithm The DNS name of the algorithm e.g. gss-tsig.
+ /// \param inception The inception time (in seconds since 1970).
+ /// \param expire The expire time (in seconds since 1970).
+ /// \param mode The mode e.g. Diffie-Hellman (2) or GSS-API (3).
+ /// \param error The error code (extended error space shared with TSIG).
+ /// \param key The key (can be empty).
+ /// \param other_data The other data (can be and usually is empty).
+ TKEYImpl(const Name& algorithm, uint32_t inception, uint32_t expire,
+ 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)
+ {}
+
+ /// \brief Constructor from RDATA field parameters.
+ ///
+ /// \param algorithm The DNS name of the algorithm e.g. gss-tsig.
+ /// \param inception The inception time (in seconds since 1970).
+ /// \param expire The expire time (in seconds since 1970).
+ /// \param mode The mode e.g. Diffie-Hellman (2) or GSS-API (3).
+ /// \param error The error code (extended error space shared with TSIG).
+ /// \param key_len The key length (0 means no key).
+ /// \param key The key (can be 0).
+ /// \param other_len The other data length (0 means no other data).
+ /// \param other_data The other data (can be and usually is 0).
+ TKEYImpl(const Name& algorithm, uint32_t inception, uint32_t expire,
+ uint16_t mode, uint16_t error, size_t key_len,
+ const void* key, size_t other_len, const void* other_data) :
+ algorithm_(algorithm), inception_(inception), expire_(expire),
+ mode_(mode), error_(error),
+ key_(key_len > 0 ?
+ vector<uint8_t>(static_cast<const uint8_t*>(key),
+ static_cast<const uint8_t*>(key) + key_len) :
+ vector<uint8_t>(key_len)),
+ other_data_(other_len > 0 ?
+ vector<uint8_t>(static_cast<const uint8_t*>(other_data),
+ static_cast<const uint8_t*>(other_data) +
+ other_len) :
+ vector<uint8_t>(other_len))
+ {}
+
+ /// \brief Common part of toWire methods.
+ /// \tparam Output \c OutputBuffer or \c AbstractMessageRenderer.
+ template <typename Output>
+ void toWireCommon(Output& output) const;
+
+ /// \brief The DNS name of the algorithm e.g. gss-tsig.
+ const Name algorithm_;
+
+ /// \brief The inception time (in seconds since 1970).
+ const uint32_t inception_;
+
+ /// \brief The expire time (in seconds since 1970).
+ const uint32_t expire_;
+
+ /// \brief The mode e.g. Diffie-Hellman (2) or GSS-API (3).
+ const uint16_t mode_;
+
+ /// \brief The error code (extended error space shared with TSIG).
+ const uint16_t error_;
+
+ /// \brief The key (can be empty).
+ const vector<uint8_t> key_;
+
+ /// \brief The other data (can be and usually is empty).
+ const vector<uint8_t> other_data_;
+};
+
+// helper function for string and lexer constructors
+TKEYImpl*
+TKEY::constructFromLexer(MasterLexer& lexer, const Name* origin) {
+ const Name& algorithm =
+ createNameFromLexer(lexer, origin ? origin : &Name::ROOT_NAME());
+
+ const uint32_t inception =
+ timeFromText32(lexer.getNextToken(MasterToken::STRING).getString());
+
+ const uint32_t expire =
+ timeFromText32(lexer.getNextToken(MasterToken::STRING).getString());
+
+ /// The mode is either a mnemonic (only one is defined: GSS-API) or
+ /// a number.
+ const string& mode_txt =
+ lexer.getNextToken(MasterToken::STRING).getString();
+ uint32_t mode = 0;
+ if (mode_txt == "GSS-API") {
+ mode = GSS_API_MODE;
+ } else {
+ /// we cast to uint32_t and range-check, because casting directly to
+ /// uint16_t will convert negative numbers to large positive numbers
+ try {
+ mode = boost::lexical_cast<uint32_t>(mode_txt);
+ } catch (const boost::bad_lexical_cast&) {
+ isc_throw(InvalidRdataText, "Invalid TKEY Mode");
+ }
+ if (mode > 0xffff) {
+ isc_throw(InvalidRdataText, "TKEY Mode out of range");
+ }
+ }
+
+ const string& error_txt =
+ lexer.getNextToken(MasterToken::STRING).getString();
+ uint32_t error = 0;
+ // XXX: In the initial implementation we hardcode the mnemonics.
+ // We'll soon generalize this.
+ if (error_txt == "NOERROR") {
+ error = Rcode::NOERROR_CODE;
+ } else if (error_txt == "BADSIG") {
+ error = TSIGError::BAD_SIG_CODE;
+ } else if (error_txt == "BADKEY") {
+ error = TSIGError::BAD_KEY_CODE;
+ } else if (error_txt == "BADTIME") {
+ error = TSIGError::BAD_TIME_CODE;
+ } else if (error_txt == "BADMODE") {
+ error = TSIGError::BAD_MODE_CODE;
+ } else if (error_txt == "BADNAME") {
+ error = TSIGError::BAD_NAME_CODE;
+ } else if (error_txt == "BADALG") {
+ error = TSIGError::BAD_ALG_CODE;
+ } else if (error_txt == "BADTRUNC") {
+ error = TSIGError::BAD_TRUNC_CODE;
+ } else {
+ /// we cast to uint32_t and range-check, because casting directly to
+ /// uint16_t will convert negative numbers to large positive numbers
+ try {
+ error = boost::lexical_cast<uint32_t>(error_txt);
+ } catch (const boost::bad_lexical_cast&) {
+ isc_throw(InvalidRdataText, "Invalid TKEY Error");
+ }
+ if (error > 0xffff) {
+ isc_throw(InvalidRdataText, "TKEY Error out of range");
+ }
+ }
+
+ const uint32_t keylen =
+ lexer.getNextToken(MasterToken::NUMBER).getNumber();
+ if (keylen > 0xffff) {
+ isc_throw(InvalidRdataText, "TKEY Key Len out of range");
+ }
+ const string keydata_txt = (keylen > 0) ?
+ lexer.getNextToken(MasterToken::STRING).getString() : "";
+ vector<uint8_t> key_data;
+ decodeBase64(keydata_txt, key_data);
+ if (key_data.size() != keylen) {
+ isc_throw(InvalidRdataText,
+ "TKEY Key Data length does not match Other Len");
+ }
+
+ const uint32_t otherlen =
+ lexer.getNextToken(MasterToken::NUMBER).getNumber();
+ if (otherlen > 0xffff) {
+ isc_throw(InvalidRdataText, "TKEY Other Len out of range");
+ }
+ const string otherdata_txt = (otherlen > 0) ?
+ lexer.getNextToken(MasterToken::STRING).getString() : "";
+ vector<uint8_t> other_data;
+ decodeBase64(otherdata_txt, other_data);
+ if (other_data.size() != otherlen) {
+ isc_throw(InvalidRdataText,
+ "TKEY Other Data length does not match Other Len");
+ }
+ // 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));
+}
+
+/// \brief Constructor from string.
+///
+/// The given string must represent a valid TKEY 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.
+///
+/// \c tkey_str must be formatted as follows:
+/// \code <Algorithm Name> <Inception> <Expire> <Mode> <Error>
+/// <Key Len> [<Key Data>] <Other Len> [<Other Data>]
+/// \endcode
+///
+/// Note that, since the Algorithm Name field is defined to be "in domain name
+/// syntax", but it is not actually a domain name, it does not have to be
+/// fully qualified.
+///
+/// The Mode field is an unsigned 16-bit decimal integer as specified
+/// in RFC2930 or a common mnemonic. Currently only "GSS-API" (case sensitive)
+/// is supported ("Diffie-Hellman" is not).
+///
+/// The Error field is an unsigned 16-bit decimal integer or a valid mnemonic
+/// as specified in RFC2845. Currently, "NOERROR", "BADSIG", "BADKEY",
+/// "BADTIME", "BADMODE", "BADNAME", and "BADALG" are supported
+/// (case sensitive). In future versions other representations that
+/// are compatible with the DNS RCODE may be supported.
+///
+/// The Key Data and Other Data fields are base-64 encoded strings that do not
+/// contain space characters.
+/// If the Key Len field is 0, the Key Data field must not appear in
+/// \c tkey_str.
+/// If the Other Len field is 0, the Other Data field must not appear in
+/// \c tkey_str.
+/// The decoded data of the Key Data field is Key Len bytes of binary stream.
+/// The decoded data of the Other Data field is Other Len bytes of binary
+/// stream.
+///
+/// An example of valid string is:
+/// \code "gss-tsig. 20210501120000 20210501130000 0 3 aabbcc 0" \endcode
+/// In this example Other Data is missing because Other Len is 0.
+///
+/// Note that RFC2930 does not define the standard presentation format
+/// of %TKEY RR, so the above syntax is implementation specific.
+/// This is, however, compatible with the format acceptable to BIND 9's
+/// RDATA parser.
+///
+/// \throw Others Exception from the Name constructors.
+/// \throw InvalidRdataText if any fields are out of their valid range,
+/// or are incorrect.
+/// \throw BadValue if Key Data or Other Data is not validly encoded
+/// in base-64.
+///
+/// \param tkey_str A string containing the RDATA to be created
+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;
+
+ try {
+ std::istringstream ss(tkey_str);
+ MasterLexer lexer;
+ lexer.pushSource(ss);
+
+ impl_ptr.reset(constructFromLexer(lexer, 0));
+
+ if (lexer.getNextToken().getType() != MasterToken::END_OF_FILE) {
+ isc_throw(InvalidRdataText,
+ "Extra input text for TKEY: " << tkey_str);
+ }
+ } catch (const MasterLexer::LexerError& ex) {
+ isc_throw(InvalidRdataText,
+ "Failed to construct TKEY from '" << tkey_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 TKEY RDATA.
+///
+/// See \c TKEY::TKEY(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
+TKEY::TKEY(MasterLexer& lexer, const Name* origin,
+ MasterLoader::Options, MasterLoaderCallbacks&) :
+ impl_(constructFromLexer(lexer, origin))
+{
+}
+
+/// \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 begin 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 RFC3597, the Algorithm field must be a non compressed form
+/// of domain name. But this implementation accepts a %TKEY RR even if that
+/// field is compressed.
+///
+/// \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.
+/// But this constructor does not use this parameter; if necessary, the caller
+/// must check consistency between the length parameter and the actual
+/// RDATA length.
+TKEY::TKEY(InputBuffer& buffer, size_t) :
+ impl_(0)
+{
+ Name algorithm(buffer);
+
+ const uint32_t inception = buffer.readUint32();
+
+ const uint32_t expire = buffer.readUint32();
+
+ const uint16_t mode = buffer.readUint16();
+
+ const uint16_t error = buffer.readUint16();
+
+ const uint16_t key_len = buffer.readUint16();
+ vector<uint8_t> key(key_len);
+ if (key_len > 0) {
+ buffer.readData(&key[0], key_len);
+ }
+
+ const uint16_t other_len = buffer.readUint16();
+ vector<uint8_t> other_data(other_len);
+ if (other_len > 0) {
+ buffer.readData(&other_data[0], other_len);
+ }
+
+ impl_ = 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)
+{
+ if ((key_len == 0 && key != 0) || (key_len > 0 && key == 0)) {
+ isc_throw(InvalidParameter, "TKEY Key length and data inconsistent");
+ }
+ if ((other_len == 0 && other_data != 0) ||
+ (other_len > 0 && other_data == 0)) {
+ 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);
+}
+
+/// \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.
+TKEY::TKEY(const TKEY& source) : Rdata(), impl_(new TKEYImpl(*source.impl_))
+{}
+
+TKEY&
+TKEY::operator=(const TKEY& source) {
+ if (this == &source) {
+ return (*this);
+ }
+
+ TKEYImpl* newimpl = new TKEYImpl(*source.impl_);
+ delete impl_;
+ impl_ = newimpl;
+
+ return (*this);
+}
+
+TKEY::~TKEY() {
+ delete impl_;
+}
+
+/// \brief Convert the \c TKEY to a string.
+///
+/// The output of this method is formatted as described in the "from string"
+/// constructor (\c TKEY(const std::string&))).
+///
+/// If internal resource allocation fails, a corresponding
+/// standard exception will be thrown.
+///
+/// \return A \c string object that represents the \c TKEY object.
+std::string
+TKEY::toText() const {
+ string result;
+
+ result += impl_->algorithm_.toText() + " " +
+ timeToText32(impl_->inception_) + " " +
+ timeToText32(impl_->expire_) + " ";
+ if (impl_->mode_ == GSS_API_MODE) {
+ result += "GSS-API ";
+ } else {
+ result += lexical_cast<string>(impl_->mode_) + " ";
+ }
+ result += TSIGError(impl_->error_).toText() + " " +
+ lexical_cast<string>(impl_->key_.size()) + " ";
+ if (!impl_->key_.empty()) {
+ result += encodeBase64(impl_->key_) + " ";
+ }
+ result += lexical_cast<string>(impl_->other_data_.size());
+ if (!impl_->other_data_.empty()) {
+ result += " " + encodeBase64(impl_->other_data_);
+ }
+
+ return (result);
+}
+
+// Common sequence of toWire() operations used for the two versions of
+// toWire().
+template <typename Output>
+void
+TKEYImpl::toWireCommon(Output& output) const {
+ output.writeUint32(inception_);
+ output.writeUint32(expire_);
+ output.writeUint16(mode_);
+ output.writeUint16(error_);
+ const uint16_t key_len = key_.size();
+ output.writeUint16(key_len);
+ if (key_len > 0) {
+ output.writeData(&key_[0], key_len);
+ }
+ const uint16_t other_len = other_data_.size();
+ output.writeUint16(other_len);
+ if (other_len > 0) {
+ output.writeData(&other_data_[0], other_len);
+ }
+}
+
+/// \brief Render the \c TKEY 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
+TKEY::toWire(OutputBuffer& buffer) const {
+ impl_->algorithm_.toWire(buffer);
+ impl_->toWireCommon<OutputBuffer>(buffer);
+}
+
+/// \brief Render the \c TKEY in the wire format with taking into account
+/// compression.
+///
+/// As specified in RFC3597, the Algorithm 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
+TKEY::toWire(AbstractMessageRenderer& renderer) const {
+ renderer.writeName(impl_->algorithm_, false);
+ impl_->toWireCommon<AbstractMessageRenderer>(renderer);
+}
+
+// A helper function commonly used for TKEY::compare().
+int
+vectorComp(const vector<uint8_t>& v1, const vector<uint8_t>& v2) {
+ const size_t this_size = v1.size();
+ const size_t other_size = v2.size();
+ if (this_size != other_size) {
+ return (this_size < other_size ? -1 : 1);
+ }
+ if (this_size > 0) {
+ return (memcmp(&v1[0], &v2[0], this_size));
+ }
+ return (0);
+}
+
+/// \brief Compare two instances of \c TKEY RDATA.
+///
+/// This method compares \c this and the \c other \c TKEY objects
+/// in terms of the DNSSEC sorting order as defined in RFC4034, and returns
+/// the result as an integer.
+///
+/// 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 TKEY object;
+/// otherwise, the standard \c bad_cast exception will be thrown.
+/// This method never throws an exception otherwise.
+///
+/// \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
+TKEY::compare(const Rdata& other) const {
+ const TKEY& other_tkey = dynamic_cast<const TKEY&>(other);
+
+ const int ncmp = compareNames(impl_->algorithm_,
+ other_tkey.impl_->algorithm_);
+ if (ncmp != 0) {
+ return (ncmp);
+ }
+
+ if (impl_->inception_ != other_tkey.impl_->inception_) {
+ return (impl_->inception_ < other_tkey.impl_->inception_ ? -1 : 1);
+ }
+ if (impl_->expire_ != other_tkey.impl_->expire_) {
+ return (impl_->expire_ < other_tkey.impl_->expire_ ? -1 : 1);
+ }
+ if (impl_->mode_ != other_tkey.impl_->mode_) {
+ return (impl_->mode_ < other_tkey.impl_->mode_ ? -1 : 1);
+ }
+ if (impl_->error_ != other_tkey.impl_->error_) {
+ return (impl_->error_ < other_tkey.impl_->error_ ? -1 : 1);
+ }
+
+ const int vcmp = vectorComp(impl_->key_, other_tkey.impl_->key_);
+ if (vcmp != 0) {
+ return (vcmp);
+ }
+ return (vectorComp(impl_->other_data_, other_tkey.impl_->other_data_));
+}
+
+const Name&
+TKEY::getAlgorithm() const {
+ return (impl_->algorithm_);
+}
+
+uint32_t
+TKEY::getInception() const {
+ return (impl_->inception_);
+}
+
+string
+TKEY::getInceptionDate() const {
+ return (timeToText32(impl_->inception_));
+}
+
+uint32_t
+TKEY::getExpire() const {
+ return (impl_->expire_);
+}
+
+string
+TKEY::getExpireDate() const {
+ return (timeToText32(impl_->expire_));
+}
+
+uint16_t
+TKEY::getMode() const {
+ return (impl_->mode_);
+}
+
+uint16_t
+TKEY::getError() const {
+ return (impl_->error_);
+}
+
+uint16_t
+TKEY::getKeyLen() const {
+ return (impl_->key_.size());
+}
+
+const void*
+TKEY::getKey() const {
+ if (!impl_->key_.empty()) {
+ return (&impl_->key_[0]);
+ } else {
+ return (0);
+ }
+}
+
+uint16_t
+TKEY::getOtherLen() const {
+ return (impl_->other_data_.size());
+}
+
+const void*
+TKEY::getOtherData() const {
+ if (!impl_->other_data_.empty()) {
+ return (&impl_->other_data_[0]);
+ } else {
+ return (0);
+ }
+}
+
+// END_RDATA_NAMESPACE
+// END_ISC_NAMESPACE
diff --git a/src/lib/dns/rdata/generic/tkey_249.h b/src/lib/dns/rdata/generic/tkey_249.h
new file mode 100644
index 0000000..d630121
--- /dev/null
+++ b/src/lib/dns/rdata/generic/tkey_249.h
@@ -0,0 +1,142 @@
+// 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/.
+
+// 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
+
+struct TKEYImpl;
+
+/// \brief \c rdata::TKEY class represents the TKEY RDATA as defined %in
+/// RFC2930.
+///
+/// This class implements the basic interfaces inherited from the abstract
+/// \c rdata::Rdata class, and provides trivial accessors specific to the
+/// TKEY RDATA.
+class TKEY : public Rdata {
+public:
+ // BEGIN_COMMON_MEMBERS
+ // END_COMMON_MEMBERS
+
+ /// \brief Constructor from RDATA field parameters.
+ ///
+ /// The parameters are a straightforward mapping of %TKEY RDATA
+ /// fields as defined %in RFC2930.
+ ///
+ /// This RR is pretty close to the TSIG RR with 32 bit timestamps,
+ /// or the RRSIG RR with a second "other" data field.
+ ///
+ /// This constructor internally involves resource allocation, and if
+ /// it fails, a corresponding standard exception will be thrown.
+ ///
+ /// \param algorithm The DNS name of the algorithm e.g. gss-tsig.
+ /// \param inception The inception time (in seconds since 1970).
+ /// \param expire The expire time (in seconds since 1970).
+ /// \param mode The mode e.g. Diffie-Hellman (2) or GSS-API (3).
+ /// \param error The error code (extended error space shared with TSIG).
+ /// \param key_len The key length (0 means no key).
+ /// \param key The key (can be 0).
+ /// \param other_len The other data length (0 means no other data).
+ /// \param other_data The other data (can be and usually is 0).
+ 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);
+
+ /// \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.
+ TKEY& operator=(const TKEY& source);
+
+ /// \brief The destructor.
+ ~TKEY();
+
+ /// \brief Return the algorithm name.
+ ///
+ /// This method never throws an exception.
+ const Name& getAlgorithm() const;
+
+ /// \brief Return the value of the Inception field as a number.
+ ///
+ /// This method never throws an exception.
+ uint32_t getInception() const;
+
+ /// \brief Return the value of the Inception field as a string.
+ std::string getInceptionDate() const;
+
+ /// \brief Return the value of the Expire field as a number.
+ ///
+ /// This method never throws an exception.
+ uint32_t getExpire() const;
+
+ /// \brief Return the value of the Expire field as a string.
+ std::string getExpireDate() const;
+
+ /// \brief Return the value of the Mode field.
+ ///
+ /// This method never throws an exception.
+ uint16_t getMode() const;
+
+ /// \brief Return the value of the Error field.
+ ///
+ /// This method never throws an exception.
+ uint16_t getError() const;
+
+ /// \brief Return the value of the Key Len field.
+ ///
+ /// This method never throws an exception.
+ uint16_t getKeyLen() const;
+
+ /// \brief Return the value of the Key field.
+ ///
+ /// This method never throws an exception.
+ const void* getKey() const;
+
+ /// \brief Return the value of the Other Len field.
+ ///
+ /// This method never throws an exception.
+ uint16_t getOtherLen() const;
+
+ /// \brief Return the value of the Other Data field.
+ ///
+ /// The same note as \c getMAC() applies.
+ ///
+ /// This method never throws an exception.
+ const void* getOtherData() const;
+
+ /// \brief The GSS_API constant for the Mode field.
+ static const uint16_t GSS_API_MODE;
+
+private:
+ TKEYImpl* constructFromLexer(MasterLexer& lexer, const Name* origin);
+
+ 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
new file mode 100644
index 0000000..330b7a2
--- /dev/null
+++ b/src/lib/dns/rdata/generic/tlsa_52.cc
@@ -0,0 +1,342 @@
+// 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 <boost/lexical_cast.hpp>
+
+#include <exceptions/exceptions.h>
+
+#include <util/buffer.h>
+#include <util/encode/hex.h>
+#include <dns/name.h>
+#include <dns/messagerenderer.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rdata_pimpl_holder.h>
+
+using namespace std;
+using boost::lexical_cast;
+using namespace isc::util;
+using namespace isc::util::encode;
+
+// BEGIN_ISC_NAMESPACE
+// BEGIN_RDATA_NAMESPACE
+
+struct TLSAImpl {
+ // straightforward representation of TLSA RDATA fields
+ TLSAImpl(uint8_t certificate_usage, uint8_t selector,
+ uint8_t matching_type, const vector<uint8_t>& data) :
+ certificate_usage_(certificate_usage),
+ selector_(selector),
+ matching_type_(matching_type),
+ data_(data)
+ {}
+
+ uint8_t certificate_usage_;
+ uint8_t selector_;
+ uint8_t matching_type_;
+ const vector<uint8_t> data_;
+};
+
+// helper function for string and lexer constructors
+TLSAImpl*
+TLSA::constructFromLexer(MasterLexer& lexer) {
+ const uint32_t certificate_usage =
+ lexer.getNextToken(MasterToken::NUMBER).getNumber();
+ if (certificate_usage > 255) {
+ isc_throw(InvalidRdataText,
+ "TLSA certificate usage field out of range");
+ }
+
+ const uint32_t selector =
+ lexer.getNextToken(MasterToken::NUMBER).getNumber();
+ if (selector > 255) {
+ isc_throw(InvalidRdataText,
+ "TLSA selector field out of range");
+ }
+
+ const uint32_t matching_type =
+ lexer.getNextToken(MasterToken::NUMBER).getNumber();
+ if (matching_type > 255) {
+ isc_throw(InvalidRdataText,
+ "TLSA matching type field out of range");
+ }
+
+ std::string certificate_assoc_data;
+ std::string data_substr;
+ while (true) {
+ const MasterToken& token =
+ lexer.getNextToken(MasterToken::STRING, true);
+ if ((token.getType() == MasterToken::END_OF_FILE) ||
+ (token.getType() == MasterToken::END_OF_LINE)) {
+ break;
+ }
+
+ token.getString(data_substr);
+ certificate_assoc_data.append(data_substr);
+ }
+ lexer.ungetToken();
+
+ if (certificate_assoc_data.empty()) {
+ isc_throw(InvalidRdataText, "Empty TLSA certificate association data");
+ }
+
+ vector<uint8_t> data;
+ try {
+ decodeHex(certificate_assoc_data, data);
+ } catch (const isc::BadValue& e) {
+ isc_throw(InvalidRdataText,
+ "Bad TLSA certificate association data: " << e.what());
+ }
+
+ return (new TLSAImpl(certificate_usage, selector, matching_type, data));
+}
+
+/// \brief Constructor from string.
+///
+/// The given string must represent a valid TLSA RDATA. There can be
+/// extra space characters at the beginning or end of the text (which
+/// are simply ignored), but other extra text, including a new line,
+/// will make the construction fail with an exception.
+///
+/// The Certificate Usage, Selector and Matching Type fields must be
+/// within their valid ranges, but are not constrained to the values
+/// defined in RFC6698.
+///
+/// The Certificate Association Data Field field may be absent, but if
+/// present it must contain a valid hex encoding of the data. Whitespace
+/// is allowed in the hex text.
+///
+/// \throw InvalidRdataText if any fields are missing, out of their
+/// valid ranges, or are incorrect, or Certificate Association Data is
+/// not a valid hex string.
+///
+/// \param tlsa_str A string containing the RDATA to be created
+TLSA::TLSA(const string& tlsa_str) :
+ impl_(NULL)
+{
+ // We use a smart pointer here because if there is an exception in
+ // this constructor, the destructor is not called and there could be
+ // a leak of the TLSAImpl that constructFromLexer() returns.
+ RdataPimplHolder<TLSAImpl> impl_ptr;
+
+ try {
+ std::istringstream ss(tlsa_str);
+ MasterLexer lexer;
+ lexer.pushSource(ss);
+
+ impl_ptr.reset(constructFromLexer(lexer));
+
+ if (lexer.getNextToken().getType() != MasterToken::END_OF_FILE) {
+ isc_throw(InvalidRdataText, "extra input text for TLSA: "
+ << tlsa_str);
+ }
+ } catch (const MasterLexer::LexerError& ex) {
+ isc_throw(InvalidRdataText, "Failed to construct TLSA from '" <<
+ tlsa_str << "': " << ex.what());
+ }
+
+ impl_ = impl_ptr.release();
+}
+
+/// \brief Constructor with a context of MasterLexer.
+///
+/// The \c lexer should point to the beginning of valid textual representation
+/// of an TLSA RDATA.
+///
+/// \throw MasterLexer::LexerError General parsing error such as missing field.
+/// \throw InvalidRdataText Fields are out of their valid range, or are
+/// incorrect, or Certificate Association Data is not a valid hex string.
+///
+/// \param lexer A \c MasterLexer object parsing a master file for the
+/// RDATA to be created
+TLSA::TLSA(MasterLexer& lexer, const Name*,
+ MasterLoader::Options, MasterLoaderCallbacks&) :
+ impl_(constructFromLexer(lexer))
+{
+}
+
+/// \brief Constructor from InputBuffer.
+///
+/// The passed buffer must contain a valid TLSA RDATA.
+///
+/// The Certificate Usage, Selector and Matching Type fields must be
+/// within their valid ranges, but are not constrained to the values
+/// defined in RFC6698. It is okay for the certificate association data
+/// to be missing (see the description of the constructor from string).
+TLSA::TLSA(InputBuffer& buffer, size_t rdata_len) {
+ if (rdata_len < 3) {
+ isc_throw(InvalidRdataLength, "TLSA record too short");
+ }
+
+ const uint8_t certificate_usage = buffer.readUint8();
+ const uint8_t selector = buffer.readUint8();
+ const uint8_t matching_type = buffer.readUint8();
+
+ vector<uint8_t> data;
+ rdata_len -= 3;
+
+ if (rdata_len == 0) {
+ isc_throw(InvalidRdataLength,
+ "Empty TLSA certificate association data");
+ }
+
+ data.resize(rdata_len);
+ buffer.readData(&data[0], rdata_len);
+
+ impl_ = new TLSAImpl(certificate_usage, selector, matching_type, data);
+}
+
+TLSA::TLSA(uint8_t certificate_usage, uint8_t selector,
+ uint8_t matching_type, const std::string& certificate_assoc_data) :
+ impl_(NULL)
+{
+ if (certificate_assoc_data.empty()) {
+ isc_throw(InvalidRdataText, "Empty TLSA certificate association data");
+ }
+
+ vector<uint8_t> data;
+ try {
+ decodeHex(certificate_assoc_data, data);
+ } catch (const isc::BadValue& e) {
+ isc_throw(InvalidRdataText,
+ "Bad TLSA certificate association data: " << e.what());
+ }
+
+ impl_ = new TLSAImpl(certificate_usage, selector, matching_type, data);
+}
+
+TLSA::TLSA(const TLSA& other) :
+ Rdata(), impl_(new TLSAImpl(*other.impl_))
+{}
+
+TLSA&
+TLSA::operator=(const TLSA& source) {
+ if (this == &source) {
+ return (*this);
+ }
+
+ TLSAImpl* newimpl = new TLSAImpl(*source.impl_);
+ delete impl_;
+ impl_ = newimpl;
+
+ return (*this);
+}
+
+TLSA::~TLSA() {
+ delete impl_;
+}
+
+void
+TLSA::toWire(OutputBuffer& buffer) const {
+ buffer.writeUint8(impl_->certificate_usage_);
+ buffer.writeUint8(impl_->selector_);
+ buffer.writeUint8(impl_->matching_type_);
+
+ // The constructors must ensure that the certificate association
+ // data field is not empty.
+ assert(!impl_->data_.empty());
+ buffer.writeData(&impl_->data_[0], impl_->data_.size());
+}
+
+void
+TLSA::toWire(AbstractMessageRenderer& renderer) const {
+ renderer.writeUint8(impl_->certificate_usage_);
+ renderer.writeUint8(impl_->selector_);
+ renderer.writeUint8(impl_->matching_type_);
+
+ // The constructors must ensure that the certificate association
+ // data field is not empty.
+ assert(!impl_->data_.empty());
+ renderer.writeData(&impl_->data_[0], impl_->data_.size());
+}
+
+string
+TLSA::toText() const {
+ // The constructors must ensure that the certificate association
+ // data field is not empty.
+ assert(!impl_->data_.empty());
+
+ return (lexical_cast<string>(static_cast<int>(impl_->certificate_usage_)) + " " +
+ lexical_cast<string>(static_cast<int>(impl_->selector_)) + " " +
+ lexical_cast<string>(static_cast<int>(impl_->matching_type_)) + " " +
+ encodeHex(impl_->data_));
+}
+
+int
+TLSA::compare(const Rdata& other) const {
+ const TLSA& other_tlsa = dynamic_cast<const TLSA&>(other);
+
+ if (impl_->certificate_usage_ < other_tlsa.impl_->certificate_usage_) {
+ return (-1);
+ } else if (impl_->certificate_usage_ >
+ other_tlsa.impl_->certificate_usage_) {
+ return (1);
+ }
+
+ if (impl_->selector_ < other_tlsa.impl_->selector_) {
+ return (-1);
+ } else if (impl_->selector_ > other_tlsa.impl_->selector_) {
+ return (1);
+ }
+
+ if (impl_->matching_type_ < other_tlsa.impl_->matching_type_) {
+ return (-1);
+ } else if (impl_->matching_type_ >
+ other_tlsa.impl_->matching_type_) {
+ return (1);
+ }
+
+ const size_t this_len = impl_->data_.size();
+ const size_t other_len = other_tlsa.impl_->data_.size();
+ const size_t cmplen = min(this_len, other_len);
+
+ if (cmplen > 0) {
+ const int cmp = memcmp(&impl_->data_[0],
+ &other_tlsa.impl_->data_[0],
+ cmplen);
+ if (cmp != 0) {
+ return (cmp);
+ }
+ }
+
+ if (this_len == other_len) {
+ return (0);
+ } else if (this_len < other_len) {
+ return (-1);
+ } else {
+ return (1);
+ }
+}
+
+uint8_t
+TLSA::getCertificateUsage() const {
+ return (impl_->certificate_usage_);
+}
+
+uint8_t
+TLSA::getSelector() const {
+ return (impl_->selector_);
+}
+
+uint8_t
+TLSA::getMatchingType() const {
+ return (impl_->matching_type_);
+}
+
+const std::vector<uint8_t>&
+TLSA::getData() const {
+ return (impl_->data_);
+}
+
+size_t
+TLSA::getDataLength() const {
+ return (impl_->data_.size());
+}
+
+// END_RDATA_NAMESPACE
+// END_ISC_NAMESPACE
diff --git a/src/lib/dns/rdata/generic/tlsa_52.h b/src/lib/dns/rdata/generic/tlsa_52.h
new file mode 100644
index 0000000..007aa43
--- /dev/null
+++ b/src/lib/dns/rdata/generic/tlsa_52.h
@@ -0,0 +1,57 @@
+// 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
new file mode 100644
index 0000000..52d6b64
--- /dev/null
+++ b/src/lib/dns/rdata/generic/txt_16.cc
@@ -0,0 +1,95 @@
+// 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
new file mode 100644
index 0000000..83979c4
--- /dev/null
+++ b/src/lib/dns/rdata/generic/txt_16.h
@@ -0,0 +1,46 @@
+// 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
new file mode 100644
index 0000000..cd4c824
--- /dev/null
+++ b/src/lib/dns/rdata/hs_4/a_1.cc
@@ -0,0 +1,64 @@
+// 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
new file mode 100644
index 0000000..6f319b9
--- /dev/null
+++ b/src/lib/dns/rdata/hs_4/a_1.h
@@ -0,0 +1,32 @@
+// 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
new file mode 100644
index 0000000..c6585b9
--- /dev/null
+++ b/src/lib/dns/rdata/in_1/a_1.cc
@@ -0,0 +1,174 @@
+// 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 <cerrno>
+#include <cstring>
+#include <string>
+
+#include <arpa/inet.h> // XXX: for inet_pton/ntop(), not exist in C++ standards
+#include <sys/socket.h> // for AF_INET/AF_INET6
+
+#include <exceptions/exceptions.h>
+
+#include <util/buffer.h>
+
+#include <dns/exceptions.h>
+#include <dns/messagerenderer.h>
+#include <dns/master_lexer.h>
+#include <dns/master_loader_callbacks.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+
+using namespace std;
+using namespace isc::util;
+
+// BEGIN_ISC_NAMESPACE
+// BEGIN_RDATA_NAMESPACE
+
+namespace {
+void
+convertToIPv4Addr(const char* src, size_t src_len, uint32_t* dst) {
+ // This check specifically rejects invalid input that begins with valid
+ // address text followed by a nul character (and possibly followed by
+ // further garbage). It cannot be detected by inet_pton().
+ //
+ // Note that this is private subroutine of the in::A constructors, which
+ // pass std::string.size() or StringRegion::len as src_len, so it should
+ // be equal to strlen() unless there's an intermediate nul character.
+ if (src_len != strlen(src)) {
+ isc_throw(InvalidRdataText,
+ "Bad IN/A RDATA text: unexpected nul in string: '"
+ << src << "'");
+ }
+ const int result = inet_pton(AF_INET, src, dst);
+ if (result == 0) {
+ isc_throw(InvalidRdataText, "Bad IN/A RDATA text: '" << src << "'");
+ } else if (result < 0) {
+ isc_throw(isc::Unexpected,
+ "Unexpected failure in parsing IN/A RDATA text: '"
+ << src << "': " << std::strerror(errno));
+ }
+}
+}
+
+/// \brief Constructor from string.
+///
+/// The given string must be a valid textual representation of an IPv4
+/// address as specified in RFC1035, that is, four decimal numbers separated
+/// by dots without any embedded spaces. Note that it excludes abbreviated
+/// forms such as "10.1" to mean "10.0.0.1".
+///
+/// Internally, this implementation uses the standard inet_pton() library
+/// function for the AF_INET family to parse and convert the textual
+/// representation. While standard compliant implementations of this function
+/// should accept exactly what this constructor expects, specific
+/// implementation may behave differently, in which case this constructor
+/// will simply accept the result of inet_pton(). In any case, the user of
+/// the class shouldn't assume such specific implementation behavior of
+/// inet_pton().
+///
+/// No extra character should be contained in \c addrstr other than the
+/// textual address. These include spaces and the nul character.
+///
+/// \throw InvalidRdata The text extracted by the lexer isn't recognized as
+/// a valid IPv4 address.
+/// \throw Unexpected Unexpected system error in conversion (this should be
+/// very rare).
+///
+/// \param addrstr Textual representation of IPv4 address to be used as the
+/// RDATA.
+A::A(const std::string& addrstr) {
+ convertToIPv4Addr(addrstr.c_str(), addrstr.size(), &addr_);
+}
+
+/// \brief Constructor with a context of MasterLexer.
+///
+/// The \c lexer should point to the beginning of valid textual representation
+/// of a class IN A RDATA.
+///
+/// The acceptable form of the textual address is generally the same as the
+/// string version of the constructor, but this version accepts beginning
+/// spaces and trailing spaces or other characters. Trailing non space
+/// characters would be considered an invalid form in an RR representation,
+/// but handling such errors is not the responsibility of this constructor.
+/// It also accepts other unusual syntax that would be considered valid
+/// in the context of DNS master file; for example, it accepts an IPv4
+/// address surrounded by parentheses, such as "(192.0.2.1)", although it's
+/// very unlikely to be used for this type of RDATA.
+///
+/// \throw MasterLexer::LexerError General parsing error such as missing field.
+/// \throw InvalidRdata The text extracted by the lexer isn't recognized as
+/// a valid IPv4 address.
+/// \throw Unexpected Unexpected system error in conversion (this should be
+/// very rare).
+///
+/// \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&)
+{
+ const MasterToken& token = lexer.getNextToken(MasterToken::STRING);
+ convertToIPv4Addr(token.getStringRegion().beg, token.getStringRegion().len,
+ &addr_);
+}
+
+A::A(InputBuffer& buffer, size_t rdata_len) {
+ if (rdata_len != sizeof(addr_)) {
+ isc_throw(DNSMessageFORMERR,
+ "IN/A RDATA construction from wire failed: Invalid length: "
+ << rdata_len);
+ }
+ if (buffer.getLength() - buffer.getPosition() < sizeof(addr_)) {
+ isc_throw(DNSMessageFORMERR,
+ "IN/A RDATA construction from wire failed: "
+ "insufficient buffer length: "
+ << buffer.getLength() - buffer.getPosition());
+ }
+ buffer.readData(&addr_, sizeof(addr_));
+}
+
+/// \brief Copy constructor.
+A::A(const A& other) : Rdata(), addr_(other.addr_)
+{}
+
+void
+A::toWire(OutputBuffer& buffer) const {
+ buffer.writeData(&addr_, sizeof(addr_));
+}
+
+void
+A::toWire(AbstractMessageRenderer& renderer) const {
+ renderer.writeData(&addr_, sizeof(addr_));
+}
+
+/// \brief Return a textual form of the underlying IPv4 address of the RDATA.
+string
+A::toText() const {
+ char addr_string[sizeof("255.255.255.255")];
+
+ if (inet_ntop(AF_INET, &addr_, addr_string, sizeof(addr_string)) == NULL) {
+ isc_throw(Unexpected,
+ "Failed to convert IN/A RDATA to textual IPv4 address");
+ }
+
+ return (addr_string);
+}
+
+/// \brief Compare two in::A RDATAs.
+///
+/// In effect, it compares the two RDATA as an unsigned 32-bit integer.
+int
+A::compare(const Rdata& other) const {
+ const A& other_a = dynamic_cast<const A&>(other);
+ return (memcmp(&addr_, &other_a.addr_, sizeof(addr_)));
+}
+// END_RDATA_NAMESPACE
+// END_ISC_NAMESPACE
diff --git a/src/lib/dns/rdata/in_1/a_1.h b/src/lib/dns/rdata/in_1/a_1.h
new file mode 100644
index 0000000..9aaeea8
--- /dev/null
+++ b/src/lib/dns/rdata/in_1/a_1.h
@@ -0,0 +1,38 @@
+// 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
+
+ //We can use the default destructor.
+ //virtual ~A() {}
+ // notyet:
+ //const struct in_addr& getAddress() const { return (addr_); }
+private:
+ uint32_t addr_; // raw IPv4 address (network byte order)
+};
+// 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
new file mode 100644
index 0000000..c967935
--- /dev/null
+++ b/src/lib/dns/rdata/in_1/aaaa_28.cc
@@ -0,0 +1,153 @@
+// 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 <dns/exceptions.h>
+#include <dns/messagerenderer.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/master_lexer.h>
+#include <dns/master_loader.h>
+
+#include <stdint.h>
+#include <string.h>
+
+#include <cerrno>
+#include <cstring>
+#include <string>
+
+#include <arpa/inet.h> // XXX: for inet_pton/ntop(), not exist in C++ standards
+#include <sys/socket.h> // for AF_INET/AF_INET6
+
+using namespace std;
+using namespace isc::util;
+
+// BEGIN_ISC_NAMESPACE
+// BEGIN_RDATA_NAMESPACE
+
+namespace {
+void
+convertToIPv6Addr(const char* src, size_t src_len, void* dst) {
+ // See a_1.cc for this check.
+ if (src_len != strlen(src)) {
+ isc_throw(InvalidRdataText,
+ "Bad IN/AAAA RDATA text: unexpected nul in string: '"
+ << src << "'");
+ }
+ const int result = inet_pton(AF_INET6, src, dst);
+ if (result == 0) {
+ isc_throw(InvalidRdataText, "Bad IN/AAAA RDATA text: '" << src << "'");
+ } else if (result < 0) {
+ isc_throw(isc::Unexpected,
+ "Unexpected failure in parsing IN/AAAA RDATA text: '"
+ << src << "': " << std::strerror(errno));
+ }
+}
+}
+
+/// \brief Constructor from string.
+///
+/// The given string must be a valid textual representation of an IPv6
+/// address as specified in RFC1886.
+///
+/// No extra character should be contained in \c addrstr other than the
+/// textual address. These include spaces and the nul character.
+///
+/// \throw InvalidRdata The text extracted by the lexer isn't recognized as
+/// a valid IPv6 address.
+/// \throw Unexpected Unexpected system error in conversion (this should be
+/// very rare).
+///
+/// \param addrstr Textual representation of IPv6 address to be used as the
+/// RDATA.
+AAAA::AAAA(const std::string& addrstr) {
+ convertToIPv6Addr(addrstr.c_str(), addrstr.size(), addr_);
+}
+
+/// \brief Constructor with a context of MasterLexer.
+///
+/// The \c lexer should point to the beginning of valid textual representation
+/// of a class IN AAAA RDATA.
+///
+/// The acceptable form of the textual address is generally the same as the
+/// string version of the constructor, but this version is slightly more
+/// flexible. See the similar constructor of \c in::A class; the same
+/// notes apply here.
+///
+/// \throw MasterLexer::LexerError General parsing error such as missing field.
+/// \throw InvalidRdata The text extracted by the lexer isn't recognized as
+/// a valid IPv6 address.
+/// \throw Unexpected Unexpected system error in conversion (this should be
+/// very rare).
+///
+/// \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&)
+{
+ const MasterToken& token = lexer.getNextToken(MasterToken::STRING);
+ convertToIPv6Addr(token.getStringRegion().beg, token.getStringRegion().len,
+ addr_);
+}
+
+/// \brief Copy constructor.
+AAAA::AAAA(InputBuffer& buffer, size_t rdata_len) {
+ if (rdata_len != sizeof(addr_)) {
+ isc_throw(DNSMessageFORMERR,
+ "IN/AAAA RDATA construction from wire failed: "
+ "Invalid length: " << rdata_len);
+ }
+ if (buffer.getLength() - buffer.getPosition() < sizeof(addr_)) {
+ isc_throw(DNSMessageFORMERR,
+ "IN/AAAA RDATA construction from wire failed: "
+ "insufficient buffer length: "
+ << buffer.getLength() - buffer.getPosition());
+ }
+ buffer.readData(&addr_, sizeof(addr_));
+}
+
+AAAA::AAAA(const AAAA& other) : Rdata() {
+ memcpy(addr_, other.addr_, sizeof(addr_));
+}
+
+/// \brief Return a textual form of the underlying IPv6 address of the RDATA.
+void
+AAAA::toWire(OutputBuffer& buffer) const {
+ buffer.writeData(&addr_, sizeof(addr_));
+}
+
+void
+AAAA::toWire(AbstractMessageRenderer& renderer) const {
+ renderer.writeData(&addr_, sizeof(addr_));
+}
+
+string
+AAAA::toText() const {
+ char addr_string[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
+
+ if (inet_ntop(AF_INET6, &addr_, addr_string, sizeof(addr_string))
+ == NULL) {
+ isc_throw(Unexpected,
+ "Failed to convert IN/AAAA RDATA to textual IPv6 address");
+ }
+
+ return (string(addr_string));
+}
+
+/// \brief Compare two in::AAAA RDATAs.
+///
+/// In effect, it compares the two RDATA as an unsigned 128-bit integer.
+int
+AAAA::compare(const Rdata& other) const {
+ const AAAA& other_a = dynamic_cast<const AAAA&>(other);
+ return (memcmp(&addr_, &other_a.addr_, sizeof(addr_)));
+}
+
+// END_RDATA_NAMESPACE
+// END_ISC_NAMESPACE
diff --git a/src/lib/dns/rdata/in_1/aaaa_28.h b/src/lib/dns/rdata/in_1/aaaa_28.h
new file mode 100644
index 0000000..a5cabf4
--- /dev/null
+++ b/src/lib/dns/rdata/in_1/aaaa_28.h
@@ -0,0 +1,38 @@
+// 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/rdata.h>
+
+// BEGIN_ISC_NAMESPACE
+
+// BEGIN_COMMON_DECLARATIONS
+// END_COMMON_DECLARATIONS
+
+// BEGIN_RDATA_NAMESPACE
+
+class AAAA : public Rdata {
+public:
+ // BEGIN_COMMON_MEMBERS
+ // END_COMMON_MEMBERS
+ // notyet:
+ //const struct in6_addr& getAddress() const { return (addr_); }
+private:
+ uint8_t addr_[16]; // raw IPv6 address (network byte order)
+};
+
+// 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
new file mode 100644
index 0000000..57c79c2
--- /dev/null
+++ b/src/lib/dns/rdata/in_1/dhcid_49.cc
@@ -0,0 +1,161 @@
+// 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 <stdint.h>
+#include <string.h>
+
+#include <exceptions/exceptions.h>
+
+#include <util/buffer.h>
+#include <util/encode/base64.h>
+#include <dns/exceptions.h>
+#include <dns/messagerenderer.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+
+using namespace std;
+using namespace isc::util;
+using namespace isc::util::encode;
+
+// BEGIN_ISC_NAMESPACE
+// BEGIN_RDATA_NAMESPACE
+
+void
+DHCID::constructFromLexer(MasterLexer& lexer) {
+ string digest_txt = lexer.getNextToken(MasterToken::STRING).getString();
+
+ // Whitespace is allowed within base64 text, so read to the end of input.
+ string digest_part;
+ 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(digest_part);
+ digest_txt.append(digest_part);
+ }
+ lexer.ungetToken();
+
+ decodeBase64(digest_txt, digest_);
+}
+
+/// \brief Constructor from string.
+///
+/// \param dhcid_str A base-64 representation of the DHCID binary data.
+///
+/// \throw InvalidRdataText if the string could not be parsed correctly.
+DHCID::DHCID(const std::string& dhcid_str) {
+ try {
+ std::istringstream iss(dhcid_str);
+ MasterLexer lexer;
+ lexer.pushSource(iss);
+
+ constructFromLexer(lexer);
+
+ if (lexer.getNextToken().getType() != MasterToken::END_OF_FILE) {
+ isc_throw(InvalidRdataText, "extra input text for DHCID: "
+ << dhcid_str);
+ }
+ } catch (const MasterLexer::LexerError& ex) {
+ isc_throw(InvalidRdataText, "Failed to construct DHCID from '" <<
+ dhcid_str << "': " << ex.what());
+ }
+}
+
+/// \brief Constructor with a context of MasterLexer.
+///
+/// The \c lexer should point to the beginning of valid textual representation
+/// of a DHCID RDATA.
+///
+/// \throw BadValue if the text is not valid base-64.
+/// \throw MasterLexer::LexerError General parsing error such as missing field.
+///
+/// \param lexer A \c MasterLexer object parsing a master file for the
+/// RDATA to be created
+DHCID::DHCID(MasterLexer& lexer, const Name*,
+ MasterLoader::Options, MasterLoaderCallbacks&) {
+ constructFromLexer(lexer);
+}
+
+/// \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
+DHCID::DHCID(InputBuffer& buffer, size_t rdata_len) {
+ if (rdata_len == 0) {
+ isc_throw(InvalidRdataLength, "Missing DHCID rdata");
+ }
+
+ digest_.resize(rdata_len);
+ buffer.readData(&digest_[0], rdata_len);
+}
+
+/// \brief The copy constructor.
+///
+/// This trivial copy constructor never throws an exception.
+DHCID::DHCID(const DHCID& other) : Rdata(), digest_(other.digest_)
+{}
+
+/// \brief Render the \c DHCID in the wire format.
+///
+/// \param buffer An output buffer to store the wire data.
+void
+DHCID::toWire(OutputBuffer& buffer) const {
+ buffer.writeData(&digest_[0], digest_.size());
+}
+
+/// \brief Render the \c DHCID in the wire format into a
+/// \c MessageRenderer object.
+///
+/// \param renderer DNS message rendering context that encapsulates the
+/// output buffer in which the \c DHCID is to be stored.
+void
+DHCID::toWire(AbstractMessageRenderer& renderer) const {
+ renderer.writeData(&digest_[0], digest_.size());
+}
+
+/// \brief Convert the \c DHCID to a string.
+///
+/// This method returns a \c std::string object representing the \c DHCID.
+///
+/// \return A string representation of \c DHCID.
+string
+DHCID::toText() const {
+ return (encodeBase64(digest_));
+}
+
+/// \brief Compare two instances of \c DHCID RDATA.
+///
+/// See documentation in \c Rdata.
+int
+DHCID::compare(const Rdata& other) const {
+ const DHCID& other_dhcid = dynamic_cast<const DHCID&>(other);
+
+ size_t this_len = digest_.size();
+ size_t other_len = other_dhcid.digest_.size();
+ size_t cmplen = min(this_len, other_len);
+ int cmp = memcmp(&digest_[0], &other_dhcid.digest_[0], cmplen);
+ if (cmp != 0) {
+ return (cmp);
+ } else {
+ return ((this_len == other_len) ? 0 : (this_len < other_len) ? -1 : 1);
+ }
+}
+
+/// \brief Accessor method to get the DHCID digest
+///
+/// \return A reference to the binary DHCID data
+const std::vector<uint8_t>&
+DHCID::getDigest() const {
+ return (digest_);
+}
+
+// END_RDATA_NAMESPACE
+// END_ISC_NAMESPACE
diff --git a/src/lib/dns/rdata/in_1/dhcid_49.h b/src/lib/dns/rdata/in_1/dhcid_49.h
new file mode 100644
index 0000000..7f79602
--- /dev/null
+++ b/src/lib/dns/rdata/in_1/dhcid_49.h
@@ -0,0 +1,53 @@
+// 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 <vector>
+
+#include <dns/rdata.h>
+
+// BEGIN_ISC_NAMESPACE
+
+// BEGIN_COMMON_DECLARATIONS
+// END_COMMON_DECLARATIONS
+
+// BEGIN_RDATA_NAMESPACE
+
+/// \brief \c rdata::DHCID class represents the DHCID RDATA as defined %in
+/// RFC4701.
+///
+/// This class implements the basic interfaces inherited from the abstract
+/// \c rdata::Rdata class, and provides trivial accessors specific to the
+/// DHCID RDATA.
+class DHCID : public Rdata {
+public:
+ // BEGIN_COMMON_MEMBERS
+ // END_COMMON_MEMBERS
+
+ /// \brief Return the digest.
+ ///
+ /// This method never throws an exception.
+ const std::vector<uint8_t>& getDigest() const;
+
+private:
+ // helper for string and lexer constructors
+ void constructFromLexer(MasterLexer& lexer);
+
+ /// \brief Private data representation
+ ///
+ /// Opaque data at least 3 octets long as per RFC4701.
+ ///
+ std::vector<uint8_t> digest_;
+};
+// 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
new file mode 100644
index 0000000..a8a050c
--- /dev/null
+++ b/src/lib/dns/rdata/in_1/srv_33.cc
@@ -0,0 +1,298 @@
+// 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
new file mode 100644
index 0000000..aca210e
--- /dev/null
+++ b/src/lib/dns/rdata/in_1/srv_33.h
@@ -0,0 +1,85 @@
+// 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
new file mode 100644
index 0000000..d205855
--- /dev/null
+++ b/src/lib/dns/rdata/template.cc
@@ -0,0 +1,67 @@
+// 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
new file mode 100644
index 0000000..d74790e
--- /dev/null
+++ b/src/lib/dns/rdata/template.h
@@ -0,0 +1,54 @@
+// 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
new file mode 100644
index 0000000..baa343a
--- /dev/null
+++ b/src/lib/dns/rdata_pimpl_holder.h
@@ -0,0 +1,52 @@
+// 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
new file mode 100644
index 0000000..dcd5e13
--- /dev/null
+++ b/src/lib/dns/rdataclass.cc
@@ -0,0 +1,7078 @@
+///////////////
+///////////////
+/////////////// THIS FILE IS AUTOMATICALLY GENERATED BY gen-rdatacode.py.
+/////////////// DO NOT EDIT!
+///////////////
+///////////////
+
+// 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 <config.h>
+
+#include <string>
+#include <sstream>
+#include <vector>
+
+#include <boost/lexical_cast.hpp>
+
+#include <util/buffer.h>
+#include <util/encode/base64.h>
+
+#include <dns/messagerenderer.h>
+#include <dns/name.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rcode.h>
+#include <dns/tsigkey.h>
+#include <dns/tsigerror.h>
+#include <dns/rdata/generic/detail/lexer_util.h>
+
+using namespace std;
+using boost::lexical_cast;
+using namespace isc::util;
+using namespace isc::util::encode;
+using namespace isc::dns;
+using isc::dns::rdata::generic::detail::createNameFromLexer;
+
+namespace isc {
+namespace dns {
+namespace rdata {
+namespace any {
+
+// straightforward representation of TSIG RDATA fields
+struct TSIGImpl {
+ TSIGImpl(const Name& algorithm, uint64_t time_signed, uint16_t fudge,
+ vector<uint8_t>& mac, uint16_t original_id, uint16_t error,
+ 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)
+ {}
+ 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) :
+ algorithm_(algorithm), time_signed_(time_signed), fudge_(fudge),
+ mac_(static_cast<const uint8_t*>(mac),
+ 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)
+ {}
+ template <typename Output>
+ void toWireCommon(Output& output) const;
+
+ const Name algorithm_;
+ const uint64_t time_signed_;
+ const uint16_t fudge_;
+ const vector<uint8_t> mac_;
+ const uint16_t original_id_;
+ const uint16_t error_;
+ const vector<uint8_t> other_data_;
+};
+
+// helper function for string and lexer constructors
+TSIGImpl*
+TSIG::constructFromLexer(MasterLexer& lexer, const Name* origin) {
+ const Name& algorithm =
+ createNameFromLexer(lexer, origin ? origin : &Name::ROOT_NAME());
+ const Name& canonical_algorithm_name =
+ (algorithm == TSIGKey::HMACMD5_SHORT_NAME()) ?
+ TSIGKey::HMACMD5_NAME() : algorithm;
+
+ const string& time_txt =
+ lexer.getNextToken(MasterToken::STRING).getString();
+ uint64_t time_signed;
+ try {
+ time_signed = boost::lexical_cast<uint64_t>(time_txt);
+ } catch (const boost::bad_lexical_cast&) {
+ isc_throw(InvalidRdataText, "Invalid TSIG Time");
+ }
+ if ((time_signed >> 48) != 0) {
+ isc_throw(InvalidRdataText, "TSIG Time out of range");
+ }
+
+ const uint32_t fudge = lexer.getNextToken(MasterToken::NUMBER).getNumber();
+ if (fudge > 0xffff) {
+ isc_throw(InvalidRdataText, "TSIG Fudge out of range");
+ }
+ const uint32_t macsize =
+ lexer.getNextToken(MasterToken::NUMBER).getNumber();
+ if (macsize > 0xffff) {
+ isc_throw(InvalidRdataText, "TSIG MAC Size out of range");
+ }
+
+ const string& mac_txt = (macsize > 0) ?
+ lexer.getNextToken(MasterToken::STRING).getString() : "";
+ vector<uint8_t> mac;
+ decodeBase64(mac_txt, mac);
+ if (mac.size() != macsize) {
+ isc_throw(InvalidRdataText, "TSIG MAC Size and data are inconsistent");
+ }
+
+ const uint32_t orig_id =
+ lexer.getNextToken(MasterToken::NUMBER).getNumber();
+ if (orig_id > 0xffff) {
+ isc_throw(InvalidRdataText, "TSIG Original ID out of range");
+ }
+
+ const string& error_txt =
+ lexer.getNextToken(MasterToken::STRING).getString();
+ uint32_t error = 0;
+ // XXX: In the initial implementation we hardcode the mnemonics.
+ // We'll soon generalize this.
+ if (error_txt == "NOERROR") {
+ error = Rcode::NOERROR_CODE;
+ } else if (error_txt == "BADSIG") {
+ error = TSIGError::BAD_SIG_CODE;
+ } else if (error_txt == "BADKEY") {
+ error = TSIGError::BAD_KEY_CODE;
+ } else if (error_txt == "BADTIME") {
+ error = TSIGError::BAD_TIME_CODE;
+ } else if (error_txt == "BADMODE") {
+ error = TSIGError::BAD_MODE_CODE;
+ } else if (error_txt == "BADNAME") {
+ error = TSIGError::BAD_NAME_CODE;
+ } else if (error_txt == "BADALG") {
+ error = TSIGError::BAD_ALG_CODE;
+ } else if (error_txt == "BADTRUNC") {
+ error = TSIGError::BAD_TRUNC_CODE;
+ } else {
+ /// we cast to uint32_t and range-check, because casting directly to
+ /// uint16_t will convert negative numbers to large positive numbers
+ try {
+ error = boost::lexical_cast<uint32_t>(error_txt);
+ } catch (const boost::bad_lexical_cast&) {
+ isc_throw(InvalidRdataText, "Invalid TSIG Error");
+ }
+ if (error > 0xffff) {
+ isc_throw(InvalidRdataText, "TSIG Error out of range");
+ }
+ }
+
+ const uint32_t otherlen =
+ lexer.getNextToken(MasterToken::NUMBER).getNumber();
+ if (otherlen > 0xffff) {
+ isc_throw(InvalidRdataText, "TSIG Other Len out of range");
+ }
+ const string otherdata_txt = (otherlen > 0) ?
+ lexer.getNextToken(MasterToken::STRING).getString() : "";
+ vector<uint8_t> other_data;
+ decodeBase64(otherdata_txt, other_data);
+ if (other_data.size() != otherlen) {
+ isc_throw(InvalidRdataText,
+ "TSIG Other Data length does not match Other Len");
+ }
+ // 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));
+}
+
+/// \brief Constructor from string.
+///
+/// The given string must represent a valid TSIG 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.
+///
+/// \c tsig_str must be formatted as follows:
+/// \code <Algorithm Name> <Time Signed> <Fudge> <MAC Size> [<MAC>]
+/// <Original ID> <Error> <Other Len> [<Other Data>]
+/// \endcode
+///
+/// Note that, since the Algorithm Name field is defined to be "in domain name
+/// syntax", but it is not actually a domain name, it does not have to be
+/// fully qualified.
+///
+/// The Error field is an unsigned 16-bit decimal integer or a valid mnemonic
+/// as specified in RFC2845. Currently, "NOERROR", "BADSIG", "BADKEY", and
+/// "BADTIME" are supported (case sensitive). In future versions other
+/// representations that are compatible with the DNS RCODE may be supported.
+///
+/// The MAC and Other Data fields are base-64 encoded strings that do not
+/// contain space characters.
+/// If the MAC Size field is 0, the MAC field must not appear in \c tsig_str.
+/// If the Other Len field is 0, the Other Data field must not appear in
+/// \c tsig_str.
+/// The decoded data of the MAC field is MAC Size bytes of binary stream.
+/// The decoded data of the Other Data field is Other Len bytes of binary
+/// stream.
+///
+/// An example of valid string is:
+/// \code "hmac-sha256. 853804800 300 3 AAAA 2845 0 0" \endcode
+/// In this example Other Data is missing because Other Len is 0.
+///
+/// Note that RFC2845 does not define the standard presentation format
+/// of %TSIG RR, so the above syntax is implementation specific.
+/// This is, however, compatible with the format acceptable to BIND 9's
+/// RDATA parser.
+///
+/// \throw Others Exception from the Name constructors.
+/// \throw InvalidRdataText if any fields are out of their valid range,
+/// or are incorrect.
+/// \throw BadValue if MAC or Other Data is not validly encoded in base-64.
+///
+/// \param tsig_str A string containing the RDATA to be created
+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;
+
+ try {
+ std::istringstream ss(tsig_str);
+ MasterLexer lexer;
+ lexer.pushSource(ss);
+
+ impl_ptr.reset(constructFromLexer(lexer, NULL));
+
+ if (lexer.getNextToken().getType() != MasterToken::END_OF_FILE) {
+ isc_throw(InvalidRdataText,
+ "Extra input text for TSIG: " << tsig_str);
+ }
+ } catch (const MasterLexer::LexerError& ex) {
+ isc_throw(InvalidRdataText,
+ "Failed to construct TSIG from '" << tsig_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 TSIG RDATA.
+///
+/// See \c TSIG::TSIG(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
+TSIG::TSIG(MasterLexer& lexer, const Name* origin,
+ MasterLoader::Options, MasterLoaderCallbacks&) :
+ impl_(constructFromLexer(lexer, origin))
+{
+}
+
+/// \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 begin 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 RFC3597, the Algorithm field must be a non compressed form
+/// of domain name. But this implementation accepts a %TSIG RR even if that
+/// field is compressed.
+///
+/// \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.
+/// But this constructor does not use this parameter; if necessary, the caller
+/// must check consistency between the length parameter and the actual
+/// RDATA length.
+TSIG::TSIG(InputBuffer& buffer, size_t) :
+ impl_(NULL)
+{
+ Name algorithm(buffer);
+
+ uint8_t time_signed_buf[6];
+ buffer.readData(time_signed_buf, sizeof(time_signed_buf));
+ const uint64_t time_signed =
+ (static_cast<uint64_t>(time_signed_buf[0]) << 40 |
+ static_cast<uint64_t>(time_signed_buf[1]) << 32 |
+ static_cast<uint64_t>(time_signed_buf[2]) << 24 |
+ static_cast<uint64_t>(time_signed_buf[3]) << 16 |
+ static_cast<uint64_t>(time_signed_buf[4]) << 8 |
+ static_cast<uint64_t>(time_signed_buf[5]));
+
+ const uint16_t fudge = buffer.readUint16();
+
+ const uint16_t mac_size = buffer.readUint16();
+ vector<uint8_t> mac(mac_size);
+ if (mac_size > 0) {
+ buffer.readData(&mac[0], mac_size);
+ }
+
+ const uint16_t original_id = buffer.readUint16();
+ const uint16_t error = buffer.readUint16();
+
+ const uint16_t other_len = buffer.readUint16();
+ vector<uint8_t> other_data(other_len);
+ if (other_len > 0) {
+ buffer.readData(&other_data[0], other_len);
+ }
+
+ 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);
+}
+
+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)
+{
+ // Time Signed is a 48-bit value.
+ if ((time_signed >> 48) != 0) {
+ isc_throw(OutOfRange, "TSIG Time Signed is too large: " <<
+ time_signed);
+ }
+ if ((mac_size == 0 && mac != NULL) || (mac_size > 0 && mac == NULL)) {
+ isc_throw(InvalidParameter, "TSIG MAC size and data inconsistent");
+ }
+ if ((other_len == 0 && other_data != NULL) ||
+ (other_len > 0 && other_data == NULL)) {
+ isc_throw(InvalidParameter,
+ "TSIG Other data length and data inconsistent");
+ }
+ 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);
+}
+
+/// \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.
+TSIG::TSIG(const TSIG& source) : Rdata(), impl_(new TSIGImpl(*source.impl_))
+{}
+
+TSIG&
+TSIG::operator=(const TSIG& source) {
+ if (this == &source) {
+ return (*this);
+ }
+
+ TSIGImpl* newimpl = new TSIGImpl(*source.impl_);
+ delete impl_;
+ impl_ = newimpl;
+
+ return (*this);
+}
+
+TSIG::~TSIG() {
+ delete impl_;
+}
+
+/// \brief Convert the \c TSIG to a string.
+///
+/// The output of this method is formatted as described in the "from string"
+/// constructor (\c TSIG(const std::string&))).
+///
+/// If internal resource allocation fails, a corresponding
+/// standard exception will be thrown.
+///
+/// \return A \c string object that represents the \c TSIG object.
+std::string
+TSIG::toText() const {
+ string result;
+
+ result += impl_->algorithm_.toText() + " " +
+ lexical_cast<string>(impl_->time_signed_) + " " +
+ lexical_cast<string>(impl_->fudge_) + " " +
+ lexical_cast<string>(impl_->mac_.size()) + " ";
+ if (!impl_->mac_.empty()) {
+ result += encodeBase64(impl_->mac_) + " ";
+ }
+ result += lexical_cast<string>(impl_->original_id_) + " ";
+ result += TSIGError(impl_->error_).toText() + " ";
+ result += lexical_cast<string>(impl_->other_data_.size());
+ if (!impl_->other_data_.empty()) {
+ result += " " + encodeBase64(impl_->other_data_);
+ }
+
+ return (result);
+}
+
+// Common sequence of toWire() operations used for the two versions of
+// toWire().
+template <typename Output>
+void
+TSIGImpl::toWireCommon(Output& output) const {
+ output.writeUint16(time_signed_ >> 32);
+ output.writeUint32(time_signed_ & 0xffffffff);
+ output.writeUint16(fudge_);
+ const uint16_t mac_size = mac_.size();
+ output.writeUint16(mac_size);
+ if (mac_size > 0) {
+ output.writeData(&mac_[0], mac_size);
+ }
+ output.writeUint16(original_id_);
+ output.writeUint16(error_);
+ const uint16_t other_len = other_data_.size();
+ output.writeUint16(other_len);
+ if (other_len > 0) {
+ output.writeData(&other_data_[0], other_len);
+ }
+}
+
+/// \brief Render the \c TSIG 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
+TSIG::toWire(OutputBuffer& buffer) const {
+ impl_->algorithm_.toWire(buffer);
+ impl_->toWireCommon<OutputBuffer>(buffer);
+}
+
+/// \brief Render the \c TSIG in the wire format with taking into account
+/// compression.
+///
+/// As specified in RFC3597, the Algorithm 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
+TSIG::toWire(AbstractMessageRenderer& renderer) const {
+ renderer.writeName(impl_->algorithm_, false);
+ impl_->toWireCommon<AbstractMessageRenderer>(renderer);
+}
+
+// A helper function commonly used for TSIG::compare().
+int
+vectorComp(const vector<uint8_t>& v1, const vector<uint8_t>& v2) {
+ const size_t this_size = v1.size();
+ const size_t other_size = v2.size();
+ if (this_size != other_size) {
+ return (this_size < other_size ? -1 : 1);
+ }
+ if (this_size > 0) {
+ return (memcmp(&v1[0], &v2[0], this_size));
+ }
+ return (0);
+}
+
+/// \brief Compare two instances of \c TSIG RDATA.
+///
+/// This method compares \c this and the \c other \c TSIG objects
+/// in terms of the DNSSEC sorting order as defined in RFC4034, and returns
+/// the result as an integer.
+///
+/// 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 TSIG object;
+/// otherwise, the standard \c bad_cast exception will be thrown.
+/// This method never throws an exception otherwise.
+///
+/// \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
+TSIG::compare(const Rdata& other) const {
+ const TSIG& other_tsig = dynamic_cast<const TSIG&>(other);
+
+ const int ncmp = compareNames(impl_->algorithm_,
+ other_tsig.impl_->algorithm_);
+ if (ncmp != 0) {
+ return (ncmp);
+ }
+
+ if (impl_->time_signed_ != other_tsig.impl_->time_signed_) {
+ return (impl_->time_signed_ < other_tsig.impl_->time_signed_ ? -1 : 1);
+ }
+ if (impl_->fudge_ != other_tsig.impl_->fudge_) {
+ return (impl_->fudge_ < other_tsig.impl_->fudge_ ? -1 : 1);
+ }
+ const int vcmp = vectorComp(impl_->mac_, other_tsig.impl_->mac_);
+ if (vcmp != 0) {
+ return (vcmp);
+ }
+ if (impl_->original_id_ != other_tsig.impl_->original_id_) {
+ return (impl_->original_id_ < other_tsig.impl_->original_id_ ? -1 : 1);
+ }
+ if (impl_->error_ != other_tsig.impl_->error_) {
+ return (impl_->error_ < other_tsig.impl_->error_ ? -1 : 1);
+ }
+ return (vectorComp(impl_->other_data_, other_tsig.impl_->other_data_));
+}
+
+const Name&
+TSIG::getAlgorithm() const {
+ return (impl_->algorithm_);
+}
+
+uint64_t
+TSIG::getTimeSigned() const {
+ return (impl_->time_signed_);
+}
+
+uint16_t
+TSIG::getFudge() const {
+ return (impl_->fudge_);
+}
+
+uint16_t
+TSIG::getMACSize() const {
+ return (impl_->mac_.size());
+}
+
+const void*
+TSIG::getMAC() const {
+ if (!impl_->mac_.empty()) {
+ return (&impl_->mac_[0]);
+ } else {
+ return (NULL);
+ }
+}
+
+uint16_t
+TSIG::getOriginalID() const {
+ return (impl_->original_id_);
+}
+
+uint16_t
+TSIG::getError() const {
+ return (impl_->error_);
+}
+
+uint16_t
+TSIG::getOtherLen() const {
+ return (impl_->other_data_.size());
+}
+
+const void*
+TSIG::getOtherData() const {
+ if (!impl_->other_data_.empty()) {
+ return (&impl_->other_data_[0]);
+ } else {
+ return (NULL);
+ }
+}
+
+} // end of namespace "any"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
+// 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 <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-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 <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-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 <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-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 <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-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 <util/buffer.h>
+#include <util/encode/hex.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-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 <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-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 <iostream>
+#include <string>
+#include <sstream>
+#include <vector>
+
+#include <boost/lexical_cast.hpp>
+#include <boost/foreach.hpp>
+
+#include <util/encode/base64.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-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 <util/buffer.h>
+#include <util/encode/hex.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-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 <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-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 <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-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 <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-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/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-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 <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-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 <iostream>
+#include <iomanip>
+#include <string>
+#include <sstream>
+#include <vector>
+#include <cassert>
+
+#include <boost/lexical_cast.hpp>
+
+#include <util/encode/base32hex.h>
+#include <util/encode/hex.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-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 <util/encode/hex.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-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 <iostream>
+#include <string>
+#include <sstream>
+#include <vector>
+
+#include <util/encode/base64.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-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/messagerenderer.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+
+#include <boost/foreach.hpp>
+
+#include <string>
+#include <string.h>
+
+using namespace std;
+using namespace isc::util;
+
+namespace isc {
+namespace dns {
+namespace rdata {
+namespace generic {
+
+/// \brief Constructor.
+OPT::PseudoRR::PseudoRR(uint16_t code,
+ boost::shared_ptr<std::vector<uint8_t> >& data) :
+ code_(code),
+ data_(data)
+{
+}
+
+uint16_t
+OPT::PseudoRR::getCode() const {
+ return (code_);
+}
+
+const uint8_t*
+OPT::PseudoRR::getData() const {
+ return (&(*data_)[0]);
+}
+
+uint16_t
+OPT::PseudoRR::getLength() const {
+ return (data_->size());
+}
+
+struct OPTImpl {
+ OPTImpl() :
+ rdlength_(0)
+ {}
+
+ uint16_t rdlength_;
+ std::vector<OPT::PseudoRR> pseudo_rrs_;
+};
+
+/// \brief Default constructor.
+OPT::OPT() :
+ impl_(new OPTImpl)
+{
+}
+
+/// \brief Constructor from string.
+///
+/// This constructor cannot be used, and always throws an exception.
+///
+/// \throw InvalidRdataText OPT RR cannot be constructed from text.
+OPT::OPT(const std::string&) :
+ impl_(NULL)
+{
+ isc_throw(InvalidRdataText, "OPT RR cannot be constructed from text");
+}
+
+/// \brief Constructor with a context of MasterLexer.
+///
+/// This constructor cannot be used, and always throws an exception.
+///
+/// \throw InvalidRdataText OPT RR cannot be constructed from text.
+OPT::OPT(MasterLexer&, const Name*,
+ MasterLoader::Options, MasterLoaderCallbacks&) :
+ 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);
+
+ while (true) {
+ if (rdata_len == 0) {
+ break;
+ }
+
+ if (rdata_len < 4) {
+ isc_throw(InvalidRdataLength,
+ "Pseudo OPT RR record too short: "
+ << rdata_len << " bytes");
+ }
+
+ const uint16_t option_code = buffer.readUint16();
+ const uint16_t option_length = buffer.readUint16();
+ rdata_len -= 4;
+
+ if (static_cast<uint16_t>(impl_ptr->rdlength_ + option_length) <
+ impl_ptr->rdlength_)
+ {
+ isc_throw(InvalidRdataText,
+ "Option length " << option_length
+ << " would overflow OPT RR RDLEN (currently "
+ << impl_ptr->rdlength_ << ").");
+ }
+
+ if (rdata_len < option_length) {
+ isc_throw(InvalidRdataLength, "Corrupt pseudo OPT RR record");
+ }
+
+ boost::shared_ptr<std::vector<uint8_t> >
+ option_data(new std::vector<uint8_t>(option_length));
+ buffer.readData(&(*option_data)[0], option_length);
+ impl_ptr->pseudo_rrs_.push_back(PseudoRR(option_code, option_data));
+ impl_ptr->rdlength_ += option_length;
+ rdata_len -= option_length;
+ }
+
+ impl_ = impl_ptr.release();
+}
+
+OPT::OPT(const OPT& other) :
+ Rdata(), impl_(new OPTImpl(*other.impl_))
+{
+}
+
+OPT&
+OPT::operator=(const OPT& source) {
+ if (this == &source) {
+ return (*this);
+ }
+
+ OPTImpl* newimpl = new OPTImpl(*source.impl_);
+ delete impl_;
+ impl_ = newimpl;
+
+ return (*this);
+}
+
+OPT::~OPT() {
+ delete impl_;
+}
+
+std::string
+OPT::toText() const {
+ isc_throw(isc::InvalidOperation,
+ "OPT RRs do not have a presentation format");
+}
+
+void
+OPT::toWire(OutputBuffer& buffer) const {
+ BOOST_FOREACH(const PseudoRR& pseudo_rr, impl_->pseudo_rrs_) {
+ buffer.writeUint16(pseudo_rr.getCode());
+ const uint16_t length = pseudo_rr.getLength();
+ buffer.writeUint16(length);
+ if (length > 0) {
+ buffer.writeData(pseudo_rr.getData(), length);
+ }
+ }
+}
+
+void
+OPT::toWire(AbstractMessageRenderer& renderer) const {
+ BOOST_FOREACH(const PseudoRR& pseudo_rr, impl_->pseudo_rrs_) {
+ renderer.writeUint16(pseudo_rr.getCode());
+ const uint16_t length = pseudo_rr.getLength();
+ renderer.writeUint16(length);
+ if (length > 0) {
+ renderer.writeData(pseudo_rr.getData(), length);
+ }
+ }
+}
+
+int
+OPT::compare(const Rdata&) const {
+ isc_throw(isc::InvalidOperation,
+ "It is meaningless to compare a set of OPT pseudo RRs; "
+ "they have unspecified order");
+ return (0);
+}
+
+void
+OPT::appendPseudoRR(uint16_t code, const uint8_t* data, uint16_t length) {
+ // See if it overflows 16-bit length field. We only worry about the
+ // pseudo-RR length here, not the whole message length (which should
+ // be checked and enforced elsewhere).
+ if (static_cast<uint16_t>(impl_->rdlength_ + length) <
+ impl_->rdlength_)
+ {
+ isc_throw(isc::InvalidParameter,
+ "Option length " << length
+ << " would overflow OPT RR RDLEN (currently "
+ << impl_->rdlength_ << ").");
+ }
+
+ boost::shared_ptr<std::vector<uint8_t> >
+ option_data(new std::vector<uint8_t>(length));
+ if (length != 0) {
+ std::memcpy(&(*option_data)[0], data, length);
+ }
+ impl_->pseudo_rrs_.push_back(PseudoRR(code, option_data));
+ impl_->rdlength_ += length;
+}
+
+const std::vector<OPT::PseudoRR>&
+OPT::getPseudoRRs() const {
+ return (impl_->pseudo_rrs_);
+}
+
+} // end of namespace "generic"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
+// 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 <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 PTR 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 PTRDNAME 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.
+PTR::PTR(const std::string& type_str) :
+ // Fill in dummy name and replace them soon below.
+ ptr_name_(Name::ROOT_NAME())
+{
+ try {
+ std::istringstream ss(type_str);
+ MasterLexer lexer;
+ lexer.pushSource(ss);
+
+ ptr_name_ = createNameFromLexer(lexer, NULL);
+
+ if (lexer.getNextToken().getType() != MasterToken::END_OF_FILE) {
+ isc_throw(InvalidRdataText, "extra input text for PTR: "
+ << type_str);
+ }
+ } catch (const MasterLexer::LexerError& ex) {
+ isc_throw(InvalidRdataText, "Failed to construct PTR from '" <<
+ type_str << "': " << ex.what());
+ }
+}
+
+PTR::PTR(InputBuffer& buffer, size_t) :
+ ptr_name_(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 PTR RDATA. The PTRDNAME 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 PTRDNAME when it
+/// is non-absolute.
+PTR::PTR(MasterLexer& lexer, const Name* origin,
+ MasterLoader::Options, MasterLoaderCallbacks&) :
+ ptr_name_(createNameFromLexer(lexer, origin))
+{}
+
+PTR::PTR(const PTR& source) :
+ Rdata(), ptr_name_(source.ptr_name_)
+{}
+
+std::string
+PTR::toText() const {
+ return (ptr_name_.toText());
+}
+
+void
+PTR::toWire(OutputBuffer& buffer) const {
+ ptr_name_.toWire(buffer);
+}
+
+void
+PTR::toWire(AbstractMessageRenderer& renderer) const {
+ renderer.writeName(ptr_name_);
+}
+
+int
+PTR::compare(const Rdata& other) const {
+ // The compare method normally begins with this dynamic cast.
+ const PTR& other_ptr = dynamic_cast<const PTR&>(other);
+
+ return (compareNames(ptr_name_, other_ptr.ptr_name_));
+
+}
+
+const Name&
+PTR::getPTRName() const {
+ return (ptr_name_);
+}
+
+} // end of namespace "generic"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
+// 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/.
+
+#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-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 <iomanip>
+#include <iostream>
+#include <sstream>
+#include <vector>
+
+#include <boost/lexical_cast.hpp>
+
+#include <util/encode/base64.h>
+#include <util/buffer.h>
+#include <util/time_utilities.h>
+#include <dns/messagerenderer.h>
+#include <dns/name.h>
+#include <dns/rrtype.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.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 isc::dns::rdata::generic::detail::createNameFromLexer;
+
+namespace isc {
+namespace dns {
+namespace rdata {
+namespace generic {
+
+namespace {
+// This is the minimum necessary length of all wire-format RRSIG RDATA:
+// - two 8-bit fields (algorithm and labels)
+// - two 16-bit fields (covered and tag)
+// - three 32-bit fields (original TTL, expire and inception)
+const size_t RRSIG_MINIMUM_LEN = 2 * sizeof(uint8_t) + 2 * sizeof(uint16_t) +
+ 3 * sizeof(uint32_t);
+}
+
+struct RRSIGImpl {
+ // straightforward representation of RRSIG RDATA fields
+ RRSIGImpl(const RRType& covered, uint8_t algorithm, uint8_t labels,
+ uint32_t originalttl, uint32_t timeexpire,
+ uint32_t timeinception, uint16_t tag, const Name& signer,
+ const vector<uint8_t>& signature) :
+ covered_(covered), algorithm_(algorithm), labels_(labels),
+ originalttl_(originalttl), timeexpire_(timeexpire),
+ timeinception_(timeinception), tag_(tag), signer_(signer),
+ signature_(signature)
+ {}
+
+ const RRType covered_;
+ uint8_t algorithm_;
+ uint8_t labels_;
+ uint32_t originalttl_;
+ uint32_t timeexpire_;
+ uint32_t timeinception_;
+ uint16_t tag_;
+ const Name signer_;
+ const vector<uint8_t> signature_;
+};
+
+// helper function for string and lexer constructors
+RRSIGImpl*
+RRSIG::constructFromLexer(MasterLexer& lexer, const Name* origin) {
+ const RRType covered(lexer.getNextToken(MasterToken::STRING).getString());
+ const uint32_t algorithm =
+ lexer.getNextToken(MasterToken::NUMBER).getNumber();
+ if (algorithm > 0xff) {
+ isc_throw(InvalidRdataText, "RRSIG algorithm out of range");
+ }
+ const uint32_t labels =
+ lexer.getNextToken(MasterToken::NUMBER).getNumber();
+ if (labels > 0xff) {
+ isc_throw(InvalidRdataText, "RRSIG labels out of range");
+ }
+ const uint32_t originalttl =
+ lexer.getNextToken(MasterToken::NUMBER).getNumber();
+ const uint32_t timeexpire =
+ timeFromText32(lexer.getNextToken(MasterToken::STRING).getString());
+ const uint32_t timeinception =
+ timeFromText32(lexer.getNextToken(MasterToken::STRING).getString());
+ const uint32_t tag =
+ lexer.getNextToken(MasterToken::NUMBER).getNumber();
+ if (tag > 0xffff) {
+ isc_throw(InvalidRdataText, "RRSIG key tag out of range");
+ }
+ const Name& signer = createNameFromLexer(lexer, origin);
+
+ string signature_txt;
+ string signature_part;
+ // Whitespace is allowed within base64 text, so read to the end of input.
+ while (true) {
+ const MasterToken& token =
+ lexer.getNextToken(MasterToken::STRING, true);
+ if ((token.getType() == MasterToken::END_OF_FILE) ||
+ (token.getType() == MasterToken::END_OF_LINE)) {
+ break;
+ }
+ token.getString(signature_part);
+ signature_txt.append(signature_part);
+ }
+ lexer.ungetToken();
+
+ vector<uint8_t> signature;
+ // missing signature is okay
+ if (signature_txt.size() > 0) {
+ decodeBase64(signature_txt, signature);
+ }
+
+ return (new RRSIGImpl(covered, algorithm, labels,
+ originalttl, timeexpire, timeinception,
+ static_cast<uint16_t>(tag), signer, signature));
+}
+
+/// \brief Constructor from string.
+///
+/// The given string must represent a valid RRSIG 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 Signer's Name must be absolute since there's no parameter that
+/// specifies the origin name; if this is not absolute, \c MissingNameOrigin
+/// exception will be thrown. This must not be represented as a quoted
+/// string.
+///
+/// See the construction that takes \c MasterLexer for other fields.
+///
+/// \throw Others Exception from the Name constructor.
+/// \throw InvalidRdataText Other general syntax errors.
+RRSIG::RRSIG(const std::string& rrsig_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 RRSIGImpl that constructFromLexer() returns.
+ std::unique_ptr<RRSIGImpl> impl_ptr;
+
+ try {
+ std::istringstream iss(rrsig_str);
+ MasterLexer lexer;
+ lexer.pushSource(iss);
+
+ impl_ptr.reset(constructFromLexer(lexer, NULL));
+
+ if (lexer.getNextToken().getType() != MasterToken::END_OF_FILE) {
+ isc_throw(InvalidRdataText, "extra input text for RRSIG: "
+ << rrsig_str);
+ }
+ } catch (const MasterLexer::LexerError& ex) {
+ isc_throw(InvalidRdataText, "Failed to construct RRSIG from '" <<
+ rrsig_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 RRSIG RDATA. The Signer's Name fields can be non absolute if \c
+/// origin is non NULL, in which case \c origin is used to make it absolute.
+/// This must not be represented as a quoted string.
+///
+/// The Original TTL field is a valid decimal representation of an unsigned
+/// 32-bit integer. Note that alternate textual representations of \c RRTTL,
+/// such as "1H" for 3600 seconds, are not allowed here.
+///
+/// \throw MasterLexer::LexerError General parsing error such as missing field.
+/// \throw Other Exceptions from the Name constructor 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 Signer's Name when
+/// it is non absolute.
+RRSIG::RRSIG(MasterLexer& lexer, const Name* origin,
+ MasterLoader::Options, MasterLoaderCallbacks&) :
+ impl_(constructFromLexer(lexer, origin))
+{
+}
+
+RRSIG::RRSIG(InputBuffer& buffer, size_t rdata_len) {
+ size_t pos = buffer.getPosition();
+
+ if (rdata_len < RRSIG_MINIMUM_LEN) {
+ isc_throw(InvalidRdataLength, "RRSIG too short");
+ }
+
+ RRType covered(buffer);
+ uint8_t algorithm = buffer.readUint8();
+ uint8_t labels = buffer.readUint8();
+ uint32_t originalttl = buffer.readUint32();
+ uint32_t timeexpire = buffer.readUint32();
+ uint32_t timeinception = buffer.readUint32();
+ uint16_t tag = buffer.readUint16();
+ Name signer(buffer);
+
+ // rdata_len must be sufficiently large to hold non empty signature data.
+ if (rdata_len <= buffer.getPosition() - pos) {
+ isc_throw(InvalidRdataLength, "RRSIG too short");
+ }
+ rdata_len -= (buffer.getPosition() - pos);
+
+ vector<uint8_t> signature(rdata_len);
+ buffer.readData(&signature[0], rdata_len);
+
+ impl_ = new RRSIGImpl(covered, algorithm, labels,
+ originalttl, timeexpire, timeinception, tag,
+ signer, signature);
+}
+
+RRSIG::RRSIG(const RRSIG& source) :
+ Rdata(), impl_(new RRSIGImpl(*source.impl_))
+{}
+
+RRSIG&
+RRSIG::operator=(const RRSIG& source) {
+ if (this == &source) {
+ return (*this);
+ }
+
+ RRSIGImpl* newimpl = new RRSIGImpl(*source.impl_);
+ delete impl_;
+ impl_ = newimpl;
+
+ return (*this);
+}
+
+RRSIG::~RRSIG() {
+ delete impl_;
+}
+
+string
+RRSIG::toText() const {
+ return (impl_->covered_.toText() +
+ " " + boost::lexical_cast<string>(static_cast<int>(impl_->algorithm_))
+ + " " + boost::lexical_cast<string>(static_cast<int>(impl_->labels_))
+ + " " + boost::lexical_cast<string>(impl_->originalttl_)
+ + " " + timeToText32(impl_->timeexpire_)
+ + " " + timeToText32(impl_->timeinception_)
+ + " " + boost::lexical_cast<string>(impl_->tag_)
+ + " " + impl_->signer_.toText()
+ + " " + encodeBase64(impl_->signature_));
+}
+
+void
+RRSIG::toWire(OutputBuffer& buffer) const {
+ impl_->covered_.toWire(buffer);
+ buffer.writeUint8(impl_->algorithm_);
+ buffer.writeUint8(impl_->labels_);
+ buffer.writeUint32(impl_->originalttl_);
+ buffer.writeUint32(impl_->timeexpire_);
+ buffer.writeUint32(impl_->timeinception_);
+ buffer.writeUint16(impl_->tag_);
+ impl_->signer_.toWire(buffer);
+ buffer.writeData(&impl_->signature_[0], impl_->signature_.size());
+}
+
+void
+RRSIG::toWire(AbstractMessageRenderer& renderer) const {
+ impl_->covered_.toWire(renderer);
+ renderer.writeUint8(impl_->algorithm_);
+ renderer.writeUint8(impl_->labels_);
+ renderer.writeUint32(impl_->originalttl_);
+ renderer.writeUint32(impl_->timeexpire_);
+ renderer.writeUint32(impl_->timeinception_);
+ renderer.writeUint16(impl_->tag_);
+ renderer.writeName(impl_->signer_, false);
+ renderer.writeData(&impl_->signature_[0], impl_->signature_.size());
+}
+
+int
+RRSIG::compare(const Rdata& other) const {
+ const RRSIG& other_rrsig = dynamic_cast<const RRSIG&>(other);
+
+ if (impl_->covered_.getCode() != other_rrsig.impl_->covered_.getCode()) {
+ return (impl_->covered_.getCode() <
+ other_rrsig.impl_->covered_.getCode() ? -1 : 1);
+ }
+ if (impl_->algorithm_ != other_rrsig.impl_->algorithm_) {
+ return (impl_->algorithm_ < other_rrsig.impl_->algorithm_ ? -1 : 1);
+ }
+ if (impl_->labels_ != other_rrsig.impl_->labels_) {
+ return (impl_->labels_ < other_rrsig.impl_->labels_ ? -1 : 1);
+ }
+ if (impl_->originalttl_ != other_rrsig.impl_->originalttl_) {
+ return (impl_->originalttl_ < other_rrsig.impl_->originalttl_ ?
+ -1 : 1);
+ }
+ if (impl_->timeexpire_ != other_rrsig.impl_->timeexpire_) {
+ return (impl_->timeexpire_ < other_rrsig.impl_->timeexpire_ ?
+ -1 : 1);
+ }
+ if (impl_->timeinception_ != other_rrsig.impl_->timeinception_) {
+ return (impl_->timeinception_ < other_rrsig.impl_->timeinception_ ?
+ -1 : 1);
+ }
+ if (impl_->tag_ != other_rrsig.impl_->tag_) {
+ return (impl_->tag_ < other_rrsig.impl_->tag_ ? -1 : 1);
+ }
+
+ int cmp = compareNames(impl_->signer_, other_rrsig.impl_->signer_);
+ if (cmp != 0) {
+ return (cmp);
+ }
+
+ size_t this_len = impl_->signature_.size();
+ size_t other_len = other_rrsig.impl_->signature_.size();
+ size_t cmplen = min(this_len, other_len);
+ cmp = memcmp(&impl_->signature_[0], &other_rrsig.impl_->signature_[0],
+ cmplen);
+ if (cmp != 0) {
+ return (cmp);
+ } else {
+ return ((this_len == other_len) ? 0 : (this_len < other_len) ? -1 : 1);
+ }
+}
+
+const RRType&
+RRSIG::typeCovered() const {
+ return (impl_->covered_);
+}
+
+} // end of namespace "generic"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
+// 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 <config.h>
+
+#include <exceptions/exceptions.h>
+
+#include <util/buffer.h>
+#include <dns/name.h>
+#include <dns/master_lexer.h>
+#include <dns/master_loader.h>
+#include <dns/master_loader_callbacks.h>
+#include <dns/messagerenderer.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+
+#include <dns/rdata/generic/detail/lexer_util.h>
+
+#include <boost/static_assert.hpp>
+#include <boost/lexical_cast.hpp>
+
+#include <string>
+#include <sstream>
+
+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 {
+
+SOA::SOA(InputBuffer& buffer, size_t) :
+ mname_(buffer), rname_(buffer)
+{
+ // we don't need rdata_len for parsing. if necessary, the caller will
+ // check consistency.
+ buffer.readData(numdata_, sizeof(numdata_));
+}
+
+namespace {
+void
+fillParameters(MasterLexer& lexer, uint8_t numdata[20]) {
+ // Copy serial, refresh, retry, expire, minimum. We accept the extended
+ // TTL-compatible style for the latter four.
+ OutputBuffer buffer(20);
+ buffer.writeUint32(lexer.getNextToken(MasterToken::NUMBER).getNumber());
+ for (int i = 0; i < 4; ++i) {
+ buffer.writeUint32(RRTTL(lexer.getNextToken(MasterToken::STRING).
+ getString()).getValue());
+ }
+ memcpy(numdata, buffer.getData(), buffer.getLength());
+}
+}
+
+/// \brief Constructor from string.
+///
+/// The given string must represent a valid SOA 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 MNAME and RNAME must be absolute since there's no parameter that
+/// specifies the origin name; if these are not absolute, \c MissingNameOrigin
+/// exception will be thrown. These 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.
+SOA::SOA(const std::string& soastr) :
+ // Fill in dummy name and replace them soon below.
+ mname_(Name::ROOT_NAME()), rname_(Name::ROOT_NAME())
+{
+ try {
+ std::istringstream ss(soastr);
+ MasterLexer lexer;
+ lexer.pushSource(ss);
+
+ mname_ = createNameFromLexer(lexer, NULL);
+ rname_ = createNameFromLexer(lexer, NULL);
+ fillParameters(lexer, numdata_);
+
+ if (lexer.getNextToken().getType() != MasterToken::END_OF_FILE) {
+ isc_throw(InvalidRdataText, "extra input text for SOA: "
+ << soastr);
+ }
+ } catch (const MasterLexer::LexerError& ex) {
+ isc_throw(InvalidRdataText, "Failed to construct SOA from '" <<
+ soastr << "': " << ex.what());
+ }
+}
+
+/// \brief Constructor with a context of MasterLexer.
+///
+/// The \c lexer should point to the beginning of valid textual representation
+/// of an SOA RDATA. The MNAME and RNAME fields can be non absolute if
+/// \c origin is non NULL, in which case \c origin is used to make them
+/// absolute. These must not be represented as a quoted string.
+///
+/// The REFRESH, RETRY, EXPIRE, and MINIMUM fields can be either a valid
+/// decimal representation of an unsigned 32-bit integer or other
+/// valid textual representation of \c RRTTL such as "1H" (which means 3600).
+///
+/// \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 MNAME and RNAME when
+/// they are non absolute.
+SOA::SOA(MasterLexer& lexer, const Name* origin,
+ MasterLoader::Options, MasterLoaderCallbacks&) :
+ mname_(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)
+{
+ OutputBuffer b(20);
+ b.writeUint32(serial);
+ b.writeUint32(refresh);
+ b.writeUint32(retry);
+ b.writeUint32(expire);
+ b.writeUint32(minimum);
+ assert(b.getLength() == sizeof(numdata_));
+ memcpy(numdata_, b.getData(), sizeof(numdata_));
+}
+
+SOA::SOA(const SOA& other) :
+ Rdata(), mname_(other.mname_), rname_(other.rname_)
+{
+ memcpy(numdata_, other.numdata_, sizeof(numdata_));
+}
+
+void
+SOA::toWire(OutputBuffer& buffer) const {
+ mname_.toWire(buffer);
+ rname_.toWire(buffer);
+ buffer.writeData(numdata_, sizeof(numdata_));
+}
+
+void
+SOA::toWire(AbstractMessageRenderer& renderer) const {
+ renderer.writeName(mname_);
+ renderer.writeName(rname_);
+ renderer.writeData(numdata_, sizeof(numdata_));
+}
+
+Serial
+SOA::getSerial() const {
+ InputBuffer b(numdata_, sizeof(numdata_));
+ return (Serial(b.readUint32()));
+}
+
+uint32_t
+SOA::getMinimum() const {
+ // Make sure the buffer access is safe.
+ BOOST_STATIC_ASSERT(sizeof(numdata_) ==
+ sizeof(uint32_t) * 4 + sizeof(uint32_t));
+
+ InputBuffer b(&numdata_[sizeof(uint32_t) * 4], sizeof(uint32_t));
+ return (b.readUint32());
+}
+
+string
+SOA::toText() const {
+ InputBuffer b(numdata_, sizeof(numdata_));
+ uint32_t serial = b.readUint32();
+ uint32_t refresh = b.readUint32();
+ uint32_t retry = b.readUint32();
+ uint32_t expire = b.readUint32();
+ uint32_t minimum = b.readUint32();
+
+ return (mname_.toText() + " " + rname_.toText() + " " +
+ lexical_cast<string>(serial) + " " +
+ lexical_cast<string>(refresh) + " " +
+ lexical_cast<string>(retry) + " " +
+ lexical_cast<string>(expire) + " " +
+ lexical_cast<string>(minimum));
+}
+
+int
+SOA::compare(const Rdata& other) const {
+ const SOA& other_soa = dynamic_cast<const SOA&>(other);
+
+ int order = compareNames(mname_, other_soa.mname_);
+ if (order != 0) {
+ return (order);
+ }
+
+ order = compareNames(rname_, other_soa.rname_);
+ if (order != 0) {
+ return (order);
+ }
+
+ return (memcmp(numdata_, other_soa.numdata_, sizeof(numdata_)));
+}
+
+} // end of namespace "generic"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
+// 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 <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-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 <boost/lexical_cast.hpp>
+
+#include <exceptions/exceptions.h>
+
+#include <util/buffer.h>
+#include <util/encode/hex.h>
+#include <dns/name.h>
+#include <dns/messagerenderer.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+
+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 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 <vector>
+
+#include <boost/lexical_cast.hpp>
+
+#include <util/buffer.h>
+#include <util/encode/base64.h>
+#include <util/time_utilities.h>
+
+#include <dns/messagerenderer.h>
+#include <dns/name.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rcode.h>
+#include <dns/rdata/generic/detail/lexer_util.h>
+
+using namespace std;
+using boost::lexical_cast;
+using namespace isc::util;
+using namespace isc::util::encode;
+using namespace isc::dns;
+using isc::dns::rdata::generic::detail::createNameFromLexer;
+
+namespace isc {
+namespace dns {
+namespace rdata {
+namespace generic {
+
+const uint16_t TKEY::GSS_API_MODE = 3;
+
+// straightforward representation of TKEY RDATA fields
+struct TKEYImpl {
+ /// \brief Constructor from RDATA field parameters.
+ ///
+ /// \param algorithm The DNS name of the algorithm e.g. gss-tsig.
+ /// \param inception The inception time (in seconds since 1970).
+ /// \param expire The expire time (in seconds since 1970).
+ /// \param mode The mode e.g. Diffie-Hellman (2) or GSS-API (3).
+ /// \param error The error code (extended error space shared with TSIG).
+ /// \param key The key (can be empty).
+ /// \param other_data The other data (can be and usually is empty).
+ TKEYImpl(const Name& algorithm, uint32_t inception, uint32_t expire,
+ 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)
+ {}
+
+ /// \brief Constructor from RDATA field parameters.
+ ///
+ /// \param algorithm The DNS name of the algorithm e.g. gss-tsig.
+ /// \param inception The inception time (in seconds since 1970).
+ /// \param expire The expire time (in seconds since 1970).
+ /// \param mode The mode e.g. Diffie-Hellman (2) or GSS-API (3).
+ /// \param error The error code (extended error space shared with TSIG).
+ /// \param key_len The key length (0 means no key).
+ /// \param key The key (can be 0).
+ /// \param other_len The other data length (0 means no other data).
+ /// \param other_data The other data (can be and usually is 0).
+ TKEYImpl(const Name& algorithm, uint32_t inception, uint32_t expire,
+ uint16_t mode, uint16_t error, size_t key_len,
+ const void* key, size_t other_len, const void* other_data) :
+ algorithm_(algorithm), inception_(inception), expire_(expire),
+ mode_(mode), error_(error),
+ key_(key_len > 0 ?
+ vector<uint8_t>(static_cast<const uint8_t*>(key),
+ static_cast<const uint8_t*>(key) + key_len) :
+ vector<uint8_t>(key_len)),
+ other_data_(other_len > 0 ?
+ vector<uint8_t>(static_cast<const uint8_t*>(other_data),
+ static_cast<const uint8_t*>(other_data) +
+ other_len) :
+ vector<uint8_t>(other_len))
+ {}
+
+ /// \brief Common part of toWire methods.
+ /// \tparam Output \c OutputBuffer or \c AbstractMessageRenderer.
+ template <typename Output>
+ void toWireCommon(Output& output) const;
+
+ /// \brief The DNS name of the algorithm e.g. gss-tsig.
+ const Name algorithm_;
+
+ /// \brief The inception time (in seconds since 1970).
+ const uint32_t inception_;
+
+ /// \brief The expire time (in seconds since 1970).
+ const uint32_t expire_;
+
+ /// \brief The mode e.g. Diffie-Hellman (2) or GSS-API (3).
+ const uint16_t mode_;
+
+ /// \brief The error code (extended error space shared with TSIG).
+ const uint16_t error_;
+
+ /// \brief The key (can be empty).
+ const vector<uint8_t> key_;
+
+ /// \brief The other data (can be and usually is empty).
+ const vector<uint8_t> other_data_;
+};
+
+// helper function for string and lexer constructors
+TKEYImpl*
+TKEY::constructFromLexer(MasterLexer& lexer, const Name* origin) {
+ const Name& algorithm =
+ createNameFromLexer(lexer, origin ? origin : &Name::ROOT_NAME());
+
+ const uint32_t inception =
+ timeFromText32(lexer.getNextToken(MasterToken::STRING).getString());
+
+ const uint32_t expire =
+ timeFromText32(lexer.getNextToken(MasterToken::STRING).getString());
+
+ /// The mode is either a mnemonic (only one is defined: GSS-API) or
+ /// a number.
+ const string& mode_txt =
+ lexer.getNextToken(MasterToken::STRING).getString();
+ uint32_t mode = 0;
+ if (mode_txt == "GSS-API") {
+ mode = GSS_API_MODE;
+ } else {
+ /// we cast to uint32_t and range-check, because casting directly to
+ /// uint16_t will convert negative numbers to large positive numbers
+ try {
+ mode = boost::lexical_cast<uint32_t>(mode_txt);
+ } catch (const boost::bad_lexical_cast&) {
+ isc_throw(InvalidRdataText, "Invalid TKEY Mode");
+ }
+ if (mode > 0xffff) {
+ isc_throw(InvalidRdataText, "TKEY Mode out of range");
+ }
+ }
+
+ const string& error_txt =
+ lexer.getNextToken(MasterToken::STRING).getString();
+ uint32_t error = 0;
+ // XXX: In the initial implementation we hardcode the mnemonics.
+ // We'll soon generalize this.
+ if (error_txt == "NOERROR") {
+ error = Rcode::NOERROR_CODE;
+ } else if (error_txt == "BADSIG") {
+ error = TSIGError::BAD_SIG_CODE;
+ } else if (error_txt == "BADKEY") {
+ error = TSIGError::BAD_KEY_CODE;
+ } else if (error_txt == "BADTIME") {
+ error = TSIGError::BAD_TIME_CODE;
+ } else if (error_txt == "BADMODE") {
+ error = TSIGError::BAD_MODE_CODE;
+ } else if (error_txt == "BADNAME") {
+ error = TSIGError::BAD_NAME_CODE;
+ } else if (error_txt == "BADALG") {
+ error = TSIGError::BAD_ALG_CODE;
+ } else if (error_txt == "BADTRUNC") {
+ error = TSIGError::BAD_TRUNC_CODE;
+ } else {
+ /// we cast to uint32_t and range-check, because casting directly to
+ /// uint16_t will convert negative numbers to large positive numbers
+ try {
+ error = boost::lexical_cast<uint32_t>(error_txt);
+ } catch (const boost::bad_lexical_cast&) {
+ isc_throw(InvalidRdataText, "Invalid TKEY Error");
+ }
+ if (error > 0xffff) {
+ isc_throw(InvalidRdataText, "TKEY Error out of range");
+ }
+ }
+
+ const uint32_t keylen =
+ lexer.getNextToken(MasterToken::NUMBER).getNumber();
+ if (keylen > 0xffff) {
+ isc_throw(InvalidRdataText, "TKEY Key Len out of range");
+ }
+ const string keydata_txt = (keylen > 0) ?
+ lexer.getNextToken(MasterToken::STRING).getString() : "";
+ vector<uint8_t> key_data;
+ decodeBase64(keydata_txt, key_data);
+ if (key_data.size() != keylen) {
+ isc_throw(InvalidRdataText,
+ "TKEY Key Data length does not match Other Len");
+ }
+
+ const uint32_t otherlen =
+ lexer.getNextToken(MasterToken::NUMBER).getNumber();
+ if (otherlen > 0xffff) {
+ isc_throw(InvalidRdataText, "TKEY Other Len out of range");
+ }
+ const string otherdata_txt = (otherlen > 0) ?
+ lexer.getNextToken(MasterToken::STRING).getString() : "";
+ vector<uint8_t> other_data;
+ decodeBase64(otherdata_txt, other_data);
+ if (other_data.size() != otherlen) {
+ isc_throw(InvalidRdataText,
+ "TKEY Other Data length does not match Other Len");
+ }
+ // 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));
+}
+
+/// \brief Constructor from string.
+///
+/// The given string must represent a valid TKEY 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.
+///
+/// \c tkey_str must be formatted as follows:
+/// \code <Algorithm Name> <Inception> <Expire> <Mode> <Error>
+/// <Key Len> [<Key Data>] <Other Len> [<Other Data>]
+/// \endcode
+///
+/// Note that, since the Algorithm Name field is defined to be "in domain name
+/// syntax", but it is not actually a domain name, it does not have to be
+/// fully qualified.
+///
+/// The Mode field is an unsigned 16-bit decimal integer as specified
+/// in RFC2930 or a common mnemonic. Currently only "GSS-API" (case sensitive)
+/// is supported ("Diffie-Hellman" is not).
+///
+/// The Error field is an unsigned 16-bit decimal integer or a valid mnemonic
+/// as specified in RFC2845. Currently, "NOERROR", "BADSIG", "BADKEY",
+/// "BADTIME", "BADMODE", "BADNAME", and "BADALG" are supported
+/// (case sensitive). In future versions other representations that
+/// are compatible with the DNS RCODE may be supported.
+///
+/// The Key Data and Other Data fields are base-64 encoded strings that do not
+/// contain space characters.
+/// If the Key Len field is 0, the Key Data field must not appear in
+/// \c tkey_str.
+/// If the Other Len field is 0, the Other Data field must not appear in
+/// \c tkey_str.
+/// The decoded data of the Key Data field is Key Len bytes of binary stream.
+/// The decoded data of the Other Data field is Other Len bytes of binary
+/// stream.
+///
+/// An example of valid string is:
+/// \code "gss-tsig. 20210501120000 20210501130000 0 3 aabbcc 0" \endcode
+/// In this example Other Data is missing because Other Len is 0.
+///
+/// Note that RFC2930 does not define the standard presentation format
+/// of %TKEY RR, so the above syntax is implementation specific.
+/// This is, however, compatible with the format acceptable to BIND 9's
+/// RDATA parser.
+///
+/// \throw Others Exception from the Name constructors.
+/// \throw InvalidRdataText if any fields are out of their valid range,
+/// or are incorrect.
+/// \throw BadValue if Key Data or Other Data is not validly encoded
+/// in base-64.
+///
+/// \param tkey_str A string containing the RDATA to be created
+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;
+
+ try {
+ std::istringstream ss(tkey_str);
+ MasterLexer lexer;
+ lexer.pushSource(ss);
+
+ impl_ptr.reset(constructFromLexer(lexer, 0));
+
+ if (lexer.getNextToken().getType() != MasterToken::END_OF_FILE) {
+ isc_throw(InvalidRdataText,
+ "Extra input text for TKEY: " << tkey_str);
+ }
+ } catch (const MasterLexer::LexerError& ex) {
+ isc_throw(InvalidRdataText,
+ "Failed to construct TKEY from '" << tkey_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 TKEY RDATA.
+///
+/// See \c TKEY::TKEY(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
+TKEY::TKEY(MasterLexer& lexer, const Name* origin,
+ MasterLoader::Options, MasterLoaderCallbacks&) :
+ impl_(constructFromLexer(lexer, origin))
+{
+}
+
+/// \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 begin 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 RFC3597, the Algorithm field must be a non compressed form
+/// of domain name. But this implementation accepts a %TKEY RR even if that
+/// field is compressed.
+///
+/// \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.
+/// But this constructor does not use this parameter; if necessary, the caller
+/// must check consistency between the length parameter and the actual
+/// RDATA length.
+TKEY::TKEY(InputBuffer& buffer, size_t) :
+ impl_(0)
+{
+ Name algorithm(buffer);
+
+ const uint32_t inception = buffer.readUint32();
+
+ const uint32_t expire = buffer.readUint32();
+
+ const uint16_t mode = buffer.readUint16();
+
+ const uint16_t error = buffer.readUint16();
+
+ const uint16_t key_len = buffer.readUint16();
+ vector<uint8_t> key(key_len);
+ if (key_len > 0) {
+ buffer.readData(&key[0], key_len);
+ }
+
+ const uint16_t other_len = buffer.readUint16();
+ vector<uint8_t> other_data(other_len);
+ if (other_len > 0) {
+ buffer.readData(&other_data[0], other_len);
+ }
+
+ impl_ = 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)
+{
+ if ((key_len == 0 && key != 0) || (key_len > 0 && key == 0)) {
+ isc_throw(InvalidParameter, "TKEY Key length and data inconsistent");
+ }
+ if ((other_len == 0 && other_data != 0) ||
+ (other_len > 0 && other_data == 0)) {
+ 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);
+}
+
+/// \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.
+TKEY::TKEY(const TKEY& source) : Rdata(), impl_(new TKEYImpl(*source.impl_))
+{}
+
+TKEY&
+TKEY::operator=(const TKEY& source) {
+ if (this == &source) {
+ return (*this);
+ }
+
+ TKEYImpl* newimpl = new TKEYImpl(*source.impl_);
+ delete impl_;
+ impl_ = newimpl;
+
+ return (*this);
+}
+
+TKEY::~TKEY() {
+ delete impl_;
+}
+
+/// \brief Convert the \c TKEY to a string.
+///
+/// The output of this method is formatted as described in the "from string"
+/// constructor (\c TKEY(const std::string&))).
+///
+/// If internal resource allocation fails, a corresponding
+/// standard exception will be thrown.
+///
+/// \return A \c string object that represents the \c TKEY object.
+std::string
+TKEY::toText() const {
+ string result;
+
+ result += impl_->algorithm_.toText() + " " +
+ timeToText32(impl_->inception_) + " " +
+ timeToText32(impl_->expire_) + " ";
+ if (impl_->mode_ == GSS_API_MODE) {
+ result += "GSS-API ";
+ } else {
+ result += lexical_cast<string>(impl_->mode_) + " ";
+ }
+ result += TSIGError(impl_->error_).toText() + " " +
+ lexical_cast<string>(impl_->key_.size()) + " ";
+ if (!impl_->key_.empty()) {
+ result += encodeBase64(impl_->key_) + " ";
+ }
+ result += lexical_cast<string>(impl_->other_data_.size());
+ if (!impl_->other_data_.empty()) {
+ result += " " + encodeBase64(impl_->other_data_);
+ }
+
+ return (result);
+}
+
+// Common sequence of toWire() operations used for the two versions of
+// toWire().
+template <typename Output>
+void
+TKEYImpl::toWireCommon(Output& output) const {
+ output.writeUint32(inception_);
+ output.writeUint32(expire_);
+ output.writeUint16(mode_);
+ output.writeUint16(error_);
+ const uint16_t key_len = key_.size();
+ output.writeUint16(key_len);
+ if (key_len > 0) {
+ output.writeData(&key_[0], key_len);
+ }
+ const uint16_t other_len = other_data_.size();
+ output.writeUint16(other_len);
+ if (other_len > 0) {
+ output.writeData(&other_data_[0], other_len);
+ }
+}
+
+/// \brief Render the \c TKEY 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
+TKEY::toWire(OutputBuffer& buffer) const {
+ impl_->algorithm_.toWire(buffer);
+ impl_->toWireCommon<OutputBuffer>(buffer);
+}
+
+/// \brief Render the \c TKEY in the wire format with taking into account
+/// compression.
+///
+/// As specified in RFC3597, the Algorithm 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
+TKEY::toWire(AbstractMessageRenderer& renderer) const {
+ renderer.writeName(impl_->algorithm_, false);
+ impl_->toWireCommon<AbstractMessageRenderer>(renderer);
+}
+
+// A helper function commonly used for TKEY::compare().
+int
+vectorComp(const vector<uint8_t>& v1, const vector<uint8_t>& v2) {
+ const size_t this_size = v1.size();
+ const size_t other_size = v2.size();
+ if (this_size != other_size) {
+ return (this_size < other_size ? -1 : 1);
+ }
+ if (this_size > 0) {
+ return (memcmp(&v1[0], &v2[0], this_size));
+ }
+ return (0);
+}
+
+/// \brief Compare two instances of \c TKEY RDATA.
+///
+/// This method compares \c this and the \c other \c TKEY objects
+/// in terms of the DNSSEC sorting order as defined in RFC4034, and returns
+/// the result as an integer.
+///
+/// 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 TKEY object;
+/// otherwise, the standard \c bad_cast exception will be thrown.
+/// This method never throws an exception otherwise.
+///
+/// \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
+TKEY::compare(const Rdata& other) const {
+ const TKEY& other_tkey = dynamic_cast<const TKEY&>(other);
+
+ const int ncmp = compareNames(impl_->algorithm_,
+ other_tkey.impl_->algorithm_);
+ if (ncmp != 0) {
+ return (ncmp);
+ }
+
+ if (impl_->inception_ != other_tkey.impl_->inception_) {
+ return (impl_->inception_ < other_tkey.impl_->inception_ ? -1 : 1);
+ }
+ if (impl_->expire_ != other_tkey.impl_->expire_) {
+ return (impl_->expire_ < other_tkey.impl_->expire_ ? -1 : 1);
+ }
+ if (impl_->mode_ != other_tkey.impl_->mode_) {
+ return (impl_->mode_ < other_tkey.impl_->mode_ ? -1 : 1);
+ }
+ if (impl_->error_ != other_tkey.impl_->error_) {
+ return (impl_->error_ < other_tkey.impl_->error_ ? -1 : 1);
+ }
+
+ const int vcmp = vectorComp(impl_->key_, other_tkey.impl_->key_);
+ if (vcmp != 0) {
+ return (vcmp);
+ }
+ return (vectorComp(impl_->other_data_, other_tkey.impl_->other_data_));
+}
+
+const Name&
+TKEY::getAlgorithm() const {
+ return (impl_->algorithm_);
+}
+
+uint32_t
+TKEY::getInception() const {
+ return (impl_->inception_);
+}
+
+string
+TKEY::getInceptionDate() const {
+ return (timeToText32(impl_->inception_));
+}
+
+uint32_t
+TKEY::getExpire() const {
+ return (impl_->expire_);
+}
+
+string
+TKEY::getExpireDate() const {
+ return (timeToText32(impl_->expire_));
+}
+
+uint16_t
+TKEY::getMode() const {
+ return (impl_->mode_);
+}
+
+uint16_t
+TKEY::getError() const {
+ return (impl_->error_);
+}
+
+uint16_t
+TKEY::getKeyLen() const {
+ return (impl_->key_.size());
+}
+
+const void*
+TKEY::getKey() const {
+ if (!impl_->key_.empty()) {
+ return (&impl_->key_[0]);
+ } else {
+ return (0);
+ }
+}
+
+uint16_t
+TKEY::getOtherLen() const {
+ return (impl_->other_data_.size());
+}
+
+const void*
+TKEY::getOtherData() const {
+ if (!impl_->other_data_.empty()) {
+ return (&impl_->other_data_[0]);
+ } else {
+ return (0);
+ }
+}
+
+} // end of namespace "generic"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
+// 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/.
+
+#include <config.h>
+
+#include <boost/lexical_cast.hpp>
+
+#include <exceptions/exceptions.h>
+
+#include <util/buffer.h>
+#include <util/encode/hex.h>
+#include <dns/name.h>
+#include <dns/messagerenderer.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rdata_pimpl_holder.h>
+
+using namespace std;
+using boost::lexical_cast;
+using namespace isc::util;
+using namespace isc::util::encode;
+
+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-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 <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-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 <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-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 <stdint.h>
+#include <string.h>
+
+#include <cerrno>
+#include <cstring>
+#include <string>
+
+#include <arpa/inet.h> // XXX: for inet_pton/ntop(), not exist in C++ standards
+#include <sys/socket.h> // for AF_INET/AF_INET6
+
+#include <exceptions/exceptions.h>
+
+#include <util/buffer.h>
+
+#include <dns/exceptions.h>
+#include <dns/messagerenderer.h>
+#include <dns/master_lexer.h>
+#include <dns/master_loader_callbacks.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+
+using namespace std;
+using namespace isc::util;
+
+namespace isc {
+namespace dns {
+namespace rdata {
+namespace in {
+
+namespace {
+void
+convertToIPv4Addr(const char* src, size_t src_len, uint32_t* dst) {
+ // This check specifically rejects invalid input that begins with valid
+ // address text followed by a nul character (and possibly followed by
+ // further garbage). It cannot be detected by inet_pton().
+ //
+ // Note that this is private subroutine of the in::A constructors, which
+ // pass std::string.size() or StringRegion::len as src_len, so it should
+ // be equal to strlen() unless there's an intermediate nul character.
+ if (src_len != strlen(src)) {
+ isc_throw(InvalidRdataText,
+ "Bad IN/A RDATA text: unexpected nul in string: '"
+ << src << "'");
+ }
+ const int result = inet_pton(AF_INET, src, dst);
+ if (result == 0) {
+ isc_throw(InvalidRdataText, "Bad IN/A RDATA text: '" << src << "'");
+ } else if (result < 0) {
+ isc_throw(isc::Unexpected,
+ "Unexpected failure in parsing IN/A RDATA text: '"
+ << src << "': " << std::strerror(errno));
+ }
+}
+}
+
+/// \brief Constructor from string.
+///
+/// The given string must be a valid textual representation of an IPv4
+/// address as specified in RFC1035, that is, four decimal numbers separated
+/// by dots without any embedded spaces. Note that it excludes abbreviated
+/// forms such as "10.1" to mean "10.0.0.1".
+///
+/// Internally, this implementation uses the standard inet_pton() library
+/// function for the AF_INET family to parse and convert the textual
+/// representation. While standard compliant implementations of this function
+/// should accept exactly what this constructor expects, specific
+/// implementation may behave differently, in which case this constructor
+/// will simply accept the result of inet_pton(). In any case, the user of
+/// the class shouldn't assume such specific implementation behavior of
+/// inet_pton().
+///
+/// No extra character should be contained in \c addrstr other than the
+/// textual address. These include spaces and the nul character.
+///
+/// \throw InvalidRdata The text extracted by the lexer isn't recognized as
+/// a valid IPv4 address.
+/// \throw Unexpected Unexpected system error in conversion (this should be
+/// very rare).
+///
+/// \param addrstr Textual representation of IPv4 address to be used as the
+/// RDATA.
+A::A(const std::string& addrstr) {
+ convertToIPv4Addr(addrstr.c_str(), addrstr.size(), &addr_);
+}
+
+/// \brief Constructor with a context of MasterLexer.
+///
+/// The \c lexer should point to the beginning of valid textual representation
+/// of a class IN A RDATA.
+///
+/// The acceptable form of the textual address is generally the same as the
+/// string version of the constructor, but this version accepts beginning
+/// spaces and trailing spaces or other characters. Trailing non space
+/// characters would be considered an invalid form in an RR representation,
+/// but handling such errors is not the responsibility of this constructor.
+/// It also accepts other unusual syntax that would be considered valid
+/// in the context of DNS master file; for example, it accepts an IPv4
+/// address surrounded by parentheses, such as "(192.0.2.1)", although it's
+/// very unlikely to be used for this type of RDATA.
+///
+/// \throw MasterLexer::LexerError General parsing error such as missing field.
+/// \throw InvalidRdata The text extracted by the lexer isn't recognized as
+/// a valid IPv4 address.
+/// \throw Unexpected Unexpected system error in conversion (this should be
+/// very rare).
+///
+/// \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&)
+{
+ const MasterToken& token = lexer.getNextToken(MasterToken::STRING);
+ convertToIPv4Addr(token.getStringRegion().beg, token.getStringRegion().len,
+ &addr_);
+}
+
+A::A(InputBuffer& buffer, size_t rdata_len) {
+ if (rdata_len != sizeof(addr_)) {
+ isc_throw(DNSMessageFORMERR,
+ "IN/A RDATA construction from wire failed: Invalid length: "
+ << rdata_len);
+ }
+ if (buffer.getLength() - buffer.getPosition() < sizeof(addr_)) {
+ isc_throw(DNSMessageFORMERR,
+ "IN/A RDATA construction from wire failed: "
+ "insufficient buffer length: "
+ << buffer.getLength() - buffer.getPosition());
+ }
+ buffer.readData(&addr_, sizeof(addr_));
+}
+
+/// \brief Copy constructor.
+A::A(const A& other) : Rdata(), addr_(other.addr_)
+{}
+
+void
+A::toWire(OutputBuffer& buffer) const {
+ buffer.writeData(&addr_, sizeof(addr_));
+}
+
+void
+A::toWire(AbstractMessageRenderer& renderer) const {
+ renderer.writeData(&addr_, sizeof(addr_));
+}
+
+/// \brief Return a textual form of the underlying IPv4 address of the RDATA.
+string
+A::toText() const {
+ char addr_string[sizeof("255.255.255.255")];
+
+ if (inet_ntop(AF_INET, &addr_, addr_string, sizeof(addr_string)) == NULL) {
+ isc_throw(Unexpected,
+ "Failed to convert IN/A RDATA to textual IPv4 address");
+ }
+
+ return (addr_string);
+}
+
+/// \brief Compare two in::A RDATAs.
+///
+/// In effect, it compares the two RDATA as an unsigned 32-bit integer.
+int
+A::compare(const Rdata& other) const {
+ const A& other_a = dynamic_cast<const A&>(other);
+ return (memcmp(&addr_, &other_a.addr_, sizeof(addr_)));
+}
+} // end of namespace "in"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
+// 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 <config.h>
+
+#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/master_lexer.h>
+#include <dns/master_loader.h>
+
+#include <stdint.h>
+#include <string.h>
+
+#include <cerrno>
+#include <cstring>
+#include <string>
+
+#include <arpa/inet.h> // XXX: for inet_pton/ntop(), not exist in C++ standards
+#include <sys/socket.h> // for AF_INET/AF_INET6
+
+using namespace std;
+using namespace isc::util;
+
+namespace isc {
+namespace dns {
+namespace rdata {
+namespace in {
+
+namespace {
+void
+convertToIPv6Addr(const char* src, size_t src_len, void* dst) {
+ // See a_1.cc for this check.
+ if (src_len != strlen(src)) {
+ isc_throw(InvalidRdataText,
+ "Bad IN/AAAA RDATA text: unexpected nul in string: '"
+ << src << "'");
+ }
+ const int result = inet_pton(AF_INET6, src, dst);
+ if (result == 0) {
+ isc_throw(InvalidRdataText, "Bad IN/AAAA RDATA text: '" << src << "'");
+ } else if (result < 0) {
+ isc_throw(isc::Unexpected,
+ "Unexpected failure in parsing IN/AAAA RDATA text: '"
+ << src << "': " << std::strerror(errno));
+ }
+}
+}
+
+/// \brief Constructor from string.
+///
+/// The given string must be a valid textual representation of an IPv6
+/// address as specified in RFC1886.
+///
+/// No extra character should be contained in \c addrstr other than the
+/// textual address. These include spaces and the nul character.
+///
+/// \throw InvalidRdata The text extracted by the lexer isn't recognized as
+/// a valid IPv6 address.
+/// \throw Unexpected Unexpected system error in conversion (this should be
+/// very rare).
+///
+/// \param addrstr Textual representation of IPv6 address to be used as the
+/// RDATA.
+AAAA::AAAA(const std::string& addrstr) {
+ convertToIPv6Addr(addrstr.c_str(), addrstr.size(), addr_);
+}
+
+/// \brief Constructor with a context of MasterLexer.
+///
+/// The \c lexer should point to the beginning of valid textual representation
+/// of a class IN AAAA RDATA.
+///
+/// The acceptable form of the textual address is generally the same as the
+/// string version of the constructor, but this version is slightly more
+/// flexible. See the similar constructor of \c in::A class; the same
+/// notes apply here.
+///
+/// \throw MasterLexer::LexerError General parsing error such as missing field.
+/// \throw InvalidRdata The text extracted by the lexer isn't recognized as
+/// a valid IPv6 address.
+/// \throw Unexpected Unexpected system error in conversion (this should be
+/// very rare).
+///
+/// \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&)
+{
+ const MasterToken& token = lexer.getNextToken(MasterToken::STRING);
+ convertToIPv6Addr(token.getStringRegion().beg, token.getStringRegion().len,
+ addr_);
+}
+
+/// \brief Copy constructor.
+AAAA::AAAA(InputBuffer& buffer, size_t rdata_len) {
+ if (rdata_len != sizeof(addr_)) {
+ isc_throw(DNSMessageFORMERR,
+ "IN/AAAA RDATA construction from wire failed: "
+ "Invalid length: " << rdata_len);
+ }
+ if (buffer.getLength() - buffer.getPosition() < sizeof(addr_)) {
+ isc_throw(DNSMessageFORMERR,
+ "IN/AAAA RDATA construction from wire failed: "
+ "insufficient buffer length: "
+ << buffer.getLength() - buffer.getPosition());
+ }
+ buffer.readData(&addr_, sizeof(addr_));
+}
+
+AAAA::AAAA(const AAAA& other) : Rdata() {
+ memcpy(addr_, other.addr_, sizeof(addr_));
+}
+
+/// \brief Return a textual form of the underlying IPv6 address of the RDATA.
+void
+AAAA::toWire(OutputBuffer& buffer) const {
+ buffer.writeData(&addr_, sizeof(addr_));
+}
+
+void
+AAAA::toWire(AbstractMessageRenderer& renderer) const {
+ renderer.writeData(&addr_, sizeof(addr_));
+}
+
+string
+AAAA::toText() const {
+ char addr_string[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
+
+ if (inet_ntop(AF_INET6, &addr_, addr_string, sizeof(addr_string))
+ == NULL) {
+ isc_throw(Unexpected,
+ "Failed to convert IN/AAAA RDATA to textual IPv6 address");
+ }
+
+ return (string(addr_string));
+}
+
+/// \brief Compare two in::AAAA RDATAs.
+///
+/// In effect, it compares the two RDATA as an unsigned 128-bit integer.
+int
+AAAA::compare(const Rdata& other) const {
+ const AAAA& other_a = dynamic_cast<const AAAA&>(other);
+ return (memcmp(&addr_, &other_a.addr_, sizeof(addr_)));
+}
+
+} // end of namespace "in"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
+// 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/.
+
+#include <config.h>
+
+#include <stdint.h>
+#include <string.h>
+
+#include <exceptions/exceptions.h>
+
+#include <util/buffer.h>
+#include <util/encode/base64.h>
+#include <dns/exceptions.h>
+#include <dns/messagerenderer.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+
+using namespace std;
+using namespace isc::util;
+using namespace isc::util::encode;
+
+namespace isc {
+namespace dns {
+namespace rdata {
+namespace in {
+
+void
+DHCID::constructFromLexer(MasterLexer& lexer) {
+ string digest_txt = lexer.getNextToken(MasterToken::STRING).getString();
+
+ // Whitespace is allowed within base64 text, so read to the end of input.
+ string digest_part;
+ 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(digest_part);
+ digest_txt.append(digest_part);
+ }
+ lexer.ungetToken();
+
+ decodeBase64(digest_txt, digest_);
+}
+
+/// \brief Constructor from string.
+///
+/// \param dhcid_str A base-64 representation of the DHCID binary data.
+///
+/// \throw InvalidRdataText if the string could not be parsed correctly.
+DHCID::DHCID(const std::string& dhcid_str) {
+ try {
+ std::istringstream iss(dhcid_str);
+ MasterLexer lexer;
+ lexer.pushSource(iss);
+
+ constructFromLexer(lexer);
+
+ if (lexer.getNextToken().getType() != MasterToken::END_OF_FILE) {
+ isc_throw(InvalidRdataText, "extra input text for DHCID: "
+ << dhcid_str);
+ }
+ } catch (const MasterLexer::LexerError& ex) {
+ isc_throw(InvalidRdataText, "Failed to construct DHCID from '" <<
+ dhcid_str << "': " << ex.what());
+ }
+}
+
+/// \brief Constructor with a context of MasterLexer.
+///
+/// The \c lexer should point to the beginning of valid textual representation
+/// of a DHCID RDATA.
+///
+/// \throw BadValue if the text is not valid base-64.
+/// \throw MasterLexer::LexerError General parsing error such as missing field.
+///
+/// \param lexer A \c MasterLexer object parsing a master file for the
+/// RDATA to be created
+DHCID::DHCID(MasterLexer& lexer, const Name*,
+ MasterLoader::Options, MasterLoaderCallbacks&) {
+ constructFromLexer(lexer);
+}
+
+/// \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
+DHCID::DHCID(InputBuffer& buffer, size_t rdata_len) {
+ if (rdata_len == 0) {
+ isc_throw(InvalidRdataLength, "Missing DHCID rdata");
+ }
+
+ digest_.resize(rdata_len);
+ buffer.readData(&digest_[0], rdata_len);
+}
+
+/// \brief The copy constructor.
+///
+/// This trivial copy constructor never throws an exception.
+DHCID::DHCID(const DHCID& other) : Rdata(), digest_(other.digest_)
+{}
+
+/// \brief Render the \c DHCID in the wire format.
+///
+/// \param buffer An output buffer to store the wire data.
+void
+DHCID::toWire(OutputBuffer& buffer) const {
+ buffer.writeData(&digest_[0], digest_.size());
+}
+
+/// \brief Render the \c DHCID in the wire format into a
+/// \c MessageRenderer object.
+///
+/// \param renderer DNS message rendering context that encapsulates the
+/// output buffer in which the \c DHCID is to be stored.
+void
+DHCID::toWire(AbstractMessageRenderer& renderer) const {
+ renderer.writeData(&digest_[0], digest_.size());
+}
+
+/// \brief Convert the \c DHCID to a string.
+///
+/// This method returns a \c std::string object representing the \c DHCID.
+///
+/// \return A string representation of \c DHCID.
+string
+DHCID::toText() const {
+ return (encodeBase64(digest_));
+}
+
+/// \brief Compare two instances of \c DHCID RDATA.
+///
+/// See documentation in \c Rdata.
+int
+DHCID::compare(const Rdata& other) const {
+ const DHCID& other_dhcid = dynamic_cast<const DHCID&>(other);
+
+ size_t this_len = digest_.size();
+ size_t other_len = other_dhcid.digest_.size();
+ size_t cmplen = min(this_len, other_len);
+ int cmp = memcmp(&digest_[0], &other_dhcid.digest_[0], cmplen);
+ if (cmp != 0) {
+ return (cmp);
+ } else {
+ return ((this_len == other_len) ? 0 : (this_len < other_len) ? -1 : 1);
+ }
+}
+
+/// \brief Accessor method to get the DHCID digest
+///
+/// \return A reference to the binary DHCID data
+const std::vector<uint8_t>&
+DHCID::getDigest() const {
+ return (digest_);
+}
+
+} // end of namespace "in"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
+// 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/.
+
+#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
new file mode 100644
index 0000000..85e6551
--- /dev/null
+++ b/src/lib/dns/rdataclass.h
@@ -0,0 +1,2746 @@
+///////////////
+///////////////
+/////////////// THIS FILE IS AUTOMATICALLY GENERATED BY gen-rdatacode.py.
+/////////////// DO NOT EDIT!
+///////////////
+///////////////
+
+
+#ifndef DNS_RDATACLASS_H
+#define DNS_RDATACLASS_H 1
+
+#include <dns/master_loader.h>
+
+namespace isc {
+namespace dns {
+class Name;
+class MasterLexer;
+class MasterLoaderCallbacks;
+}
+}
+// 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 ANY_TSIG_250_H
+#define ANY_TSIG_250_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 any {
+
+struct TSIGImpl;
+
+/// \brief \c rdata::TSIG class represents the TSIG RDATA as defined %in
+/// RFC2845.
+///
+/// This class implements the basic interfaces inherited from the abstract
+/// \c rdata::Rdata class, and provides trivial accessors specific to the
+/// TSIG RDATA.
+class TSIG : public Rdata {
+public:
+ // BEGIN_COMMON_MEMBERS
+
+ explicit TSIG(const std::string& type_str);
+ TSIG(isc::util::InputBuffer& buffer, size_t rdata_len);
+ TSIG(const TSIG& other);
+ TSIG(
+ 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 Constructor from RDATA field parameters.
+ ///
+ /// The parameters are a straightforward mapping of %TSIG RDATA
+ /// fields as defined %in RFC2845, but there are some implementation
+ /// specific notes as follows.
+ ///
+ /// \c algorithm is a \c Name object that specifies the algorithm.
+ /// For example, if the algorithm is HMAC-SHA256, \c algorithm would be
+ /// \c Name("hmac-sha256").
+ ///
+ /// \c time_signed corresponds to the Time Signed field, which is of
+ /// 48-bit unsigned integer type, and therefore cannot exceed 2^48-1;
+ /// otherwise, an exception of type \c OutOfRange will be thrown.
+ ///
+ /// \c mac_size and \c mac correspond to the MAC Size and MAC fields,
+ /// respectively. When the MAC field is empty, \c mac must be NULL.
+ /// \c mac_size and \c mac must be consistent %in that \c mac_size is 0 if
+ /// and only if \c mac is NULL; otherwise an exception of type
+ /// InvalidParameter will be thrown.
+ ///
+ /// The same restriction applies to \c other_len and \c other_data,
+ /// which correspond to the Other Len and Other Data fields, respectively.
+ ///
+ /// This constructor internally involves resource allocation, and if
+ /// it fails, a corresponding standard exception will be thrown.
+ 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);
+
+ /// \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.
+ TSIG& operator=(const TSIG& source);
+
+ /// \brief The destructor.
+ ~TSIG();
+
+ /// \brief Return the algorithm name.
+ ///
+ /// This method never throws an exception.
+ const Name& getAlgorithm() const;
+
+ /// \brief Return the value of the Time Signed field.
+ ///
+ /// The returned value does not exceed 2^48-1.
+ ///
+ /// This method never throws an exception.
+ uint64_t getTimeSigned() const;
+
+ /// \brief Return the value of the Fudge field.
+ ///
+ /// This method never throws an exception.
+ uint16_t getFudge() const;
+
+ /// \brief Return the value of the MAC Size field.
+ ///
+ /// This method never throws an exception.
+ uint16_t getMACSize() const;
+
+ /// \brief Return the value of the MAC field.
+ ///
+ /// If the MAC field is empty, it returns NULL.
+ /// Otherwise, the memory region beginning at the address returned by
+ /// this method is valid up to the bytes specified by the return value
+ /// of \c getMACSize().
+ /// The memory region is only valid while the corresponding \c TSIG
+ /// object is valid. The caller must hold the \c TSIG object while
+ /// it needs to refer to the region or it must make a local copy of the
+ /// region.
+ ///
+ /// This method never throws an exception.
+ const void* getMAC() const;
+
+ /// \brief Return the value of the Original ID field.
+ ///
+ /// This method never throws an exception.
+ uint16_t getOriginalID() const;
+
+ /// \brief Return the value of the Error field.
+ ///
+ /// This method never throws an exception.
+ uint16_t getError() const;
+
+ /// \brief Return the value of the Other Len field.
+ ///
+ /// This method never throws an exception.
+ uint16_t getOtherLen() const;
+
+ /// \brief Return the value of the Other Data field.
+ ///
+ /// The same note as \c getMAC() applies.
+ ///
+ /// This method never throws an exception.
+ const void* getOtherData() const;
+private:
+ TSIGImpl* constructFromLexer(MasterLexer& lexer, const Name* origin);
+
+ TSIGImpl* impl_;
+};
+
+} // end of namespace "any"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
+#endif // ANY_TSIG_250_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 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
+
+#include <string>
+
+#include <dns/rdata.h>
+
+#include <boost/shared_ptr.hpp>
+
+#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 OPTImpl;
+
+class OPT : public Rdata {
+public:
+ // BEGIN_COMMON_MEMBERS
+
+ explicit OPT(const std::string& type_str);
+ OPT(isc::util::InputBuffer& buffer, size_t rdata_len);
+ OPT(const OPT& other);
+ OPT(
+ 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
+
+ // The default constructor makes sense for OPT as it can be empty.
+ OPT();
+ OPT& operator=(const OPT& source);
+ ~OPT();
+
+ /// \brief A class representing a pseudo RR (or option) within an
+ /// OPT RR (see RFC 6891).
+ class PseudoRR {
+ public:
+ /// \brief Constructor.
+ /// \param code The OPTION-CODE field of the pseudo RR.
+ /// \param data The OPTION-DATA field of the pseudo
+ /// RR. OPTION-LENGTH is set to the length of this vector.
+ PseudoRR(uint16_t code,
+ boost::shared_ptr<std::vector<uint8_t> >& data);
+
+ /// \brief Return the option code of this pseudo RR.
+ uint16_t getCode() const;
+
+ /// \brief Return the option data of this pseudo RR.
+ const uint8_t* getData() const;
+
+ /// \brief Return the length of the option data of this
+ /// pseudo RR.
+ uint16_t getLength() const;
+
+ private:
+ uint16_t code_;
+ boost::shared_ptr<std::vector<uint8_t> > data_;
+ };
+
+ /// \brief Append a pseudo RR (option) in this OPT RR.
+ ///
+ /// \param code The OPTION-CODE field of the pseudo RR.
+ /// \param data The OPTION-DATA field of the pseudo RR.
+ /// \param length The size of the \c data argument. OPTION-LENGTH is
+ /// set to this size.
+ /// \throw isc::InvalidParameter if this pseudo RR would cause
+ /// the OPT RDATA to overflow its RDLENGTH.
+ void appendPseudoRR(uint16_t code, const uint8_t* data, uint16_t length);
+
+ /// \brief Return a vector of the pseudo RRs (options) in this
+ /// OPT RR.
+ ///
+ /// Note: The returned reference is only valid during the lifetime
+ /// of this \c generic::OPT object. It should not be used
+ /// afterwards.
+ const std::vector<PseudoRR>& getPseudoRRs() const;
+
+private:
+ OPTImpl* impl_;
+};
+
+} // end of namespace "generic"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
+#endif // GENERIC_OPT_41_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_PTR_12_H
+#define GENERIC_PTR_12_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 PTR : public Rdata {
+public:
+ // BEGIN_COMMON_MEMBERS
+
+ explicit PTR(const std::string& type_str);
+ PTR(isc::util::InputBuffer& buffer, size_t rdata_len);
+ PTR(const PTR& other);
+ PTR(
+ 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 PTR(const Name& ptr_name) : ptr_name_(ptr_name) {}
+ ///
+ /// Specialized methods
+ ///
+ const Name& getPTRName() const;
+private:
+ Name ptr_name_;
+};
+
+} // end of namespace "generic"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // 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
+// 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/rdata.h>
+
+#ifndef GENERIC_RRSIG_46_H
+#define GENERIC_RRSIG_46_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 RRSIGImpl;
+
+/// \brief \c rdata::RRSIG class represents the RRSIG RDATA as defined %in
+/// RFC4034.
+///
+/// This class implements the basic interfaces inherited from the abstract
+/// \c rdata::Rdata class, and provides trivial accessors specific to the
+/// RRSIG RDATA.
+class RRSIG : public Rdata {
+public:
+ // BEGIN_COMMON_MEMBERS
+
+ explicit RRSIG(const std::string& type_str);
+ RRSIG(isc::util::InputBuffer& buffer, size_t rdata_len);
+ RRSIG(const RRSIG& other);
+ RRSIG(
+ 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
+ RRSIG& operator=(const RRSIG& source);
+ ~RRSIG();
+
+ // specialized methods
+ const RRType& typeCovered() const;
+private:
+ // helper function for string and lexer constructors
+ RRSIGImpl* constructFromLexer(MasterLexer& lexer, const Name* origin);
+
+ RRSIGImpl* impl_;
+};
+
+} // end of namespace "generic"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
+#endif // GENERIC_RRSIG_46_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_SOA_6_H
+#define GENERIC_SOA_6_H 1
+
+#include <string>
+
+#include <dns/name.h>
+#include <dns/rdata.h>
+#include <dns/serial.h>
+
+namespace isc {
+namespace util {
+
+class InputBuffer;
+class OutputBuffer;
+}
+
+namespace dns {
+
+// BEGIN_COMMON_DECLARATIONS
+
+class AbstractMessageRenderer;
+
+// END_COMMON_DECLARATIONS
+
+namespace rdata {
+namespace generic {
+
+class SOA : public Rdata {
+public:
+ // BEGIN_COMMON_MEMBERS
+
+ explicit SOA(const std::string& type_str);
+ SOA(isc::util::InputBuffer& buffer, size_t rdata_len);
+ SOA(const SOA& other);
+ SOA(
+ 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
+
+ SOA(const Name& mname, const Name& rname, uint32_t serial,
+ uint32_t refresh, uint32_t retry, uint32_t expire,
+ uint32_t minimum);
+
+ /// \brief Returns the serial stored in the SOA.
+ Serial getSerial() const;
+
+ /// brief Returns the minimum TTL field value of the SOA.
+ uint32_t getMinimum() const;
+private:
+ /// Note: this is a prototype version; we may reconsider
+ /// this representation later.
+ Name mname_;
+ Name rname_;
+ /// serial, refresh, retry, expire, minimum, stored in network byte order
+ uint8_t numdata_[20];
+};
+
+} // end of namespace "generic"
+} // end of namespace "rdata"
+} // 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
+
+// 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/.
+
+#ifndef GENERIC_TKEY_249_H
+#define GENERIC_TKEY_249_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 {
+
+struct TKEYImpl;
+
+/// \brief \c rdata::TKEY class represents the TKEY RDATA as defined %in
+/// RFC2930.
+///
+/// This class implements the basic interfaces inherited from the abstract
+/// \c rdata::Rdata class, and provides trivial accessors specific to the
+/// TKEY RDATA.
+class TKEY : public Rdata {
+public:
+ // BEGIN_COMMON_MEMBERS
+
+ explicit TKEY(const std::string& type_str);
+ TKEY(isc::util::InputBuffer& buffer, size_t rdata_len);
+ TKEY(const TKEY& other);
+ TKEY(
+ 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 Constructor from RDATA field parameters.
+ ///
+ /// The parameters are a straightforward mapping of %TKEY RDATA
+ /// fields as defined %in RFC2930.
+ ///
+ /// This RR is pretty close to the TSIG RR with 32 bit timestamps,
+ /// or the RRSIG RR with a second "other" data field.
+ ///
+ /// This constructor internally involves resource allocation, and if
+ /// it fails, a corresponding standard exception will be thrown.
+ ///
+ /// \param algorithm The DNS name of the algorithm e.g. gss-tsig.
+ /// \param inception The inception time (in seconds since 1970).
+ /// \param expire The expire time (in seconds since 1970).
+ /// \param mode The mode e.g. Diffie-Hellman (2) or GSS-API (3).
+ /// \param error The error code (extended error space shared with TSIG).
+ /// \param key_len The key length (0 means no key).
+ /// \param key The key (can be 0).
+ /// \param other_len The other data length (0 means no other data).
+ /// \param other_data The other data (can be and usually is 0).
+ 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);
+
+ /// \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.
+ TKEY& operator=(const TKEY& source);
+
+ /// \brief The destructor.
+ ~TKEY();
+
+ /// \brief Return the algorithm name.
+ ///
+ /// This method never throws an exception.
+ const Name& getAlgorithm() const;
+
+ /// \brief Return the value of the Inception field as a number.
+ ///
+ /// This method never throws an exception.
+ uint32_t getInception() const;
+
+ /// \brief Return the value of the Inception field as a string.
+ std::string getInceptionDate() const;
+
+ /// \brief Return the value of the Expire field as a number.
+ ///
+ /// This method never throws an exception.
+ uint32_t getExpire() const;
+
+ /// \brief Return the value of the Expire field as a string.
+ std::string getExpireDate() const;
+
+ /// \brief Return the value of the Mode field.
+ ///
+ /// This method never throws an exception.
+ uint16_t getMode() const;
+
+ /// \brief Return the value of the Error field.
+ ///
+ /// This method never throws an exception.
+ uint16_t getError() const;
+
+ /// \brief Return the value of the Key Len field.
+ ///
+ /// This method never throws an exception.
+ uint16_t getKeyLen() const;
+
+ /// \brief Return the value of the Key field.
+ ///
+ /// This method never throws an exception.
+ const void* getKey() const;
+
+ /// \brief Return the value of the Other Len field.
+ ///
+ /// This method never throws an exception.
+ uint16_t getOtherLen() const;
+
+ /// \brief Return the value of the Other Data field.
+ ///
+ /// The same note as \c getMAC() applies.
+ ///
+ /// This method never throws an exception.
+ const void* getOtherData() const;
+
+ /// \brief The GSS_API constant for the Mode field.
+ static const uint16_t GSS_API_MODE;
+
+private:
+ TKEYImpl* constructFromLexer(MasterLexer& lexer, const Name* origin);
+
+ TKEYImpl* impl_;
+};
+
+} // end of namespace "generic"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // 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
+// 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_A_1_H
+#define IN_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 in {
+
+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
+
+ //We can use the default destructor.
+ //virtual ~A() {}
+ // notyet:
+ //const struct in_addr& getAddress() const { return (addr_); }
+private:
+ uint32_t addr_; // raw IPv4 address (network byte order)
+};
+} // end of namespace "in"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
+#endif // IN_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
+// 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_AAAA_28_H
+#define IN_AAAA_28_H 1
+
+#include <stdint.h>
+
+#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 in {
+
+class AAAA : public Rdata {
+public:
+ // BEGIN_COMMON_MEMBERS
+
+ explicit AAAA(const std::string& type_str);
+ AAAA(isc::util::InputBuffer& buffer, size_t rdata_len);
+ AAAA(const AAAA& other);
+ AAAA(
+ 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
+ // notyet:
+ //const struct in6_addr& getAddress() const { return (addr_); }
+private:
+ uint8_t addr_[16]; // raw IPv6 address (network byte order)
+};
+
+} // end of namespace "in"
+} // end of namespace "rdata"
+} // end of namespace "dns"
+} // end of namespace "isc"
+#endif // IN_AAAA_28_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_DHCID_49_H
+#define IN_DHCID_49_H 1
+
+#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 in {
+
+/// \brief \c rdata::DHCID class represents the DHCID RDATA as defined %in
+/// RFC4701.
+///
+/// This class implements the basic interfaces inherited from the abstract
+/// \c rdata::Rdata class, and provides trivial accessors specific to the
+/// DHCID RDATA.
+class DHCID : public Rdata {
+public:
+ // BEGIN_COMMON_MEMBERS
+
+ explicit DHCID(const std::string& type_str);
+ DHCID(isc::util::InputBuffer& buffer, size_t rdata_len);
+ DHCID(const DHCID& other);
+ DHCID(
+ 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 Return the digest.
+ ///
+ /// This method never throws an exception.
+ const std::vector<uint8_t>& getDigest() const;
+
+private:
+ // helper for string and lexer constructors
+ void constructFromLexer(MasterLexer& lexer);
+
+ /// \brief Private data representation
+ ///
+ /// Opaque data at least 3 octets long as per RFC4701.
+ ///
+ std::vector<uint8_t> digest_;
+};
+} // end of namespace "in"
+} // end of namespace "rdata"
+} // 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
new file mode 100644
index 0000000..e02ec8f
--- /dev/null
+++ b/src/lib/dns/rdatafields.cc
@@ -0,0 +1,216 @@
+// 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
new file mode 100644
index 0000000..c4a64ad
--- /dev/null
+++ b/src/lib/dns/rdatafields.h
@@ -0,0 +1,419 @@
+// 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: