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