]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[(no branch, rebasing 1880-implement-the-tkey-rr)] [(no branch, rebasing 1880-impleme...
authorFrancis Dupont <fdupont@isc.org>
Fri, 21 May 2021 08:09:44 +0000 (10:09 +0200)
committerFrancis Dupont <fdupont@isc.org>
Thu, 3 Jun 2021 09:42:14 +0000 (11:42 +0200)
src/lib/dns/Makefile.am
src/lib/dns/gen-rdatacode.py.in
src/lib/dns/rdata/generic/tkey_249.cc [new file with mode: 0644]
src/lib/dns/rdata/generic/tkey_249.h [new file with mode: 0644]

index c97eba5563c9a90ec0b475858a4ee8959bed62a7..da72e76f78e81c24efdd541f693e2df11c04e559 100644 (file)
@@ -74,6 +74,8 @@ EXTRA_DIST += rdata/generic/sshfp_44.cc
 EXTRA_DIST += rdata/generic/sshfp_44.h
 EXTRA_DIST += rdata/generic/tlsa_52.cc
 EXTRA_DIST += rdata/generic/tlsa_52.h
+EXTRA_DIST += rdata/generic/tkey_249.cc
+EXTRA_DIST += rdata/generic/tkey_249.h
 EXTRA_DIST += rdata/generic/txt_16.cc
 EXTRA_DIST += rdata/generic/txt_16.h
 EXTRA_DIST += rdata/generic/minfo_14.cc
index 362f5e077e6df45f0d87a3f165e7c55af9dff852..f39fc095cf05aad593c1b4e823135748132f9907 100644 (file)
@@ -1,6 +1,6 @@
 #!@PYTHON@
 
-# Copyright (C) 2010-2016,2021 Internet Systems Consortium, Inc. ("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
@@ -39,7 +39,7 @@ meta_types = {
     '23': 'nsap-ptr', '24': 'sig', '20': 'isdn', '25': 'key', '26': 'px',
     '27': 'gpos', '29': 'loc', '36': 'kx', '37': 'cert', '42': 'apl',
     '45': 'ipseckey', '55': 'hip', '103': 'unspec',
-    '104': 'nid', '105': 'l32', '106': 'l64', '107': 'lp', '249':  'tkey',
+    '104': 'nid', '105': 'l32', '106': 'l64', '107': 'lp',
     '253': 'mailb', '256': 'uri'
     }
 # Classes that don't have any known types.  This is a dict from type code
diff --git a/src/lib/dns/rdata/generic/tkey_249.cc b/src/lib/dns/rdata/generic/tkey_249.cc
new file mode 100644 (file)
index 0000000..562ba10
--- /dev/null
@@ -0,0 +1,556 @@
+// 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 <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
+
+// straightforward representation of TKEY RDATA fields
+struct TKEYImpl {
+    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)
+    {}
+    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_(static_cast<const uint8_t*>(key),
+             static_cast<const uint8_t*>(key) + key_len),
+        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 uint32_t inception_;
+    const uint32_t expire_;
+    const uint16_t mode_;
+    const uint16_t error_;
+    const vector<uint8_t> key_;
+    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 =
+       lexer.getNextToken(MasterToken::NUMBER).getNumber();
+    
+    const uint32_t expire =
+       lexer.getNextToken(MasterToken::NUMBER).getNumber();
+
+    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 = TKEYError::BAD_SIG_CODE;
+    } else if (error_txt == "BADKEY") {
+        error = TKEYError::BAD_KEY_CODE;
+    } else if (error_txt == "BADTIME") {
+        error = TKEYError::BAD_TIME_CODE;
+    } else if (error_txt == "BADMODE") {
+        error = TKEYError::BAD_MODE_CODE;
+    } else if (error_txt == "BADNAME") {
+        error = TKEYError::BAD_NAME_CODE;
+    } else if (error_txt == "BADALG") {
+        error = TKEYError::BAD_ALG_CODE;
+    } else if (error_txt == "BADTRUNC") {
+        error = TKEYError::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 or a valid mnemonic
+/// as specified in RFC2920. 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. 928321914 928321915 123 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, NULL));
+
+        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_(NULL)
+{
+    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, erro,
+                        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() + " " +
+       lexical_cast<string>(impl_->inception_) + " " +
+       lexical_cast<string>(impl_->expire_) + " ";
+    if (impl_->mode_ == GSS_API_MODE) {
+       result += "GSS-API ";
+    } else {
+       result += lexical_cast<string>(impl_->mode_) + " ";
+    }
+    result += TKEYError(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_);
+}
+
+uint32_t
+TKEY::getExpire() const {
+    return (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 (NULL);
+    }
+}
+
+// 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 (file)
index 0000000..692b69d
--- /dev/null
@@ -0,0 +1,125 @@
+// 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 one with 32 bit timestamps.
+    ///
+    /// This constructor internally involves resource allocation, and if
+    /// it fails, a corresponding standard exception will be thrown.
+    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.
+    ///
+    /// This method never throws an exception.
+    uint32_t getInception() const;
+
+    /// \brief Return the value of the Expire field.
+    ///
+    /// This method never throws an exception.
+    uint32_t getExpire() 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 = 3;
+
+private:
+    TKEYImpl* constructFromLexer(MasterLexer& lexer, const Name* origin);
+
+    TKEYImpl* impl_;
+};
+
+// END_RDATA_NAMESPACE
+// END_ISC_NAMESPACE
+// END_HEADER_GUARD
+
+// Local Variables:
+// mode: c++
+// End: