summaryrefslogtreecommitdiffstats
path: root/src/lib/dns/rdata/generic/detail/ds_like.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/dns/rdata/generic/detail/ds_like.h')
-rw-r--r--src/lib/dns/rdata/generic/detail/ds_like.h277
1 files changed, 277 insertions, 0 deletions
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: