diff options
Diffstat (limited to 'src/lib/dns/rdata/generic/nsec_47.cc')
-rw-r--r-- | src/lib/dns/rdata/generic/nsec_47.cc | 216 |
1 files changed, 216 insertions, 0 deletions
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 |