return (OptionPtr(new Option6PDExclude(begin, end)));
case D6O_V6_DNR:
- return (OptionPtr(new OptionDNR6(begin, end)));
+ return (OptionPtr(new OptionDnr6(begin, end)));
default:
break;
return (factoryOpaqueDataTuples(Option::V4, getCode(), begin, end, OpaqueDataTuple::LENGTH_2_BYTES));
case DHO_V4_DNR:
- return (OptionPtr(new OptionDNR4(begin, end)));
+ return (OptionPtr(new OptionDnr4(begin, end)));
default:
break;
namespace isc {
namespace dhcp {
-OptionDNR6::OptionDNR6(OptionBufferConstIter begin, OptionBufferConstIter end)
- : Option(V6, D6O_V6_DNR) {
+OptionDnr6::OptionDnr6(OptionBufferConstIter begin, OptionBufferConstIter end)
+ : Option(V6, D6O_V6_DNR), addr_length_(0) {
unpack(begin, end);
}
OptionPtr
-OptionDNR6::clone() const {
+OptionDnr6::clone() const {
return Option::clone();
}
void
-OptionDNR6::pack(util::OutputBuffer& buf, bool check) const {
+OptionDnr6::pack(util::OutputBuffer& buf, bool check) const {
packHeader(buf, check);
buf.writeUint16(service_priority_);
}
void
-OptionDNR6::unpack(OptionBufferConstIter begin, OptionBufferConstIter end) {
+OptionDnr6::unpack(OptionBufferConstIter begin, OptionBufferConstIter end) {
if (std::distance(begin, end) < getMinimalLength()) {
isc_throw(OutOfRange, "parsed DHCPv6 Encrypted DNS Option ("
<< D6O_V6_DNR << ") data truncated to"
adn_length_ = adn_tuple.getLength();
if (adn_length_ > 0) {
// Let's try to extract ADN FQDN data
- isc::util::InputBuffer name_buf(&adn_tuple.getData(),
- adn_length_);
+ isc::util::InputBuffer name_buf(&adn_tuple.getData()[0], adn_length_);
try {
adn_.reset(new isc::dns::Name(name_buf, true));
- } catch (const Exception&) {
- isc_throw(InvalidOptionDNR6DomainName, "failed to parse "
- "fully qualified domain-name from wire format");
+ } catch (const Exception& ex) {
+ isc_throw(InvalidOptionDnr6DomainName, "failed to parse "
+ "fully qualified domain-name from wire format "
+ "- " << ex.what());
}
}
begin += adn_tuple.getTotalLength();
}
std::string
-OptionDNR6::toText(int indent) const {
+OptionDnr6::toText(int indent) const {
return Option::toText(indent);
}
uint16_t
-OptionDNR6::len() const {
+OptionDnr6::len() const {
return Option::len();
}
-OptionDNR4::OptionDNR4() : Option(V4, DHO_V4_DNR) {
+std::string
+OptionDnr6::getAdn() const {
+ if (adn_) {
+ return adn_->toText();
+ }
+ return "";
+}
+
+OptionDnr4::OptionDnr4() : Option(V4, DHO_V4_DNR) {
}
-OptionDNR4::OptionDNR4(OptionBufferConstIter begin, OptionBufferConstIter end)
+OptionDnr4::OptionDnr4(OptionBufferConstIter begin, OptionBufferConstIter end)
: Option(V4, DHO_V4_DNR) {
unpack(begin, end);
}
OptionPtr
-OptionDNR4::clone() const {
+OptionDnr4::clone() const {
return Option::clone();
}
void
-OptionDNR4::pack(util::OutputBuffer& buf, bool check) const {
+OptionDnr4::pack(util::OutputBuffer& buf, bool check) const {
Option::pack(buf, check);
}
void
-OptionDNR4::unpack(OptionBufferConstIter begin, OptionBufferConstIter end) {
+OptionDnr4::unpack(OptionBufferConstIter begin, OptionBufferConstIter end) {
Option::unpack(begin, end);
}
std::string
-OptionDNR4::toText(int indent) const {
+OptionDnr4::toText(int indent) const {
return Option::toText(indent);
}
uint16_t
-OptionDNR4::len() const {
+OptionDnr4::len() const {
return Option::len();
}
namespace dhcp {
/// @brief Exception thrown when invalid domain name is specified.
-class InvalidOptionDNR6DomainName : public Exception {
+class InvalidOptionDnr6DomainName : public Exception {
public:
- InvalidOptionDNR6DomainName(const char* file, size_t line,
- const char* what) :
- isc::Exception(file, line, what) {}
+ InvalidOptionDnr6DomainName(const char* file, size_t line, const char* what)
+ : isc::Exception(file, line, what) {
+ }
};
-class OptionDNR6 : public Option {
+class OptionDnr6 : public Option {
public:
-
/// @brief Size in octets of Service Priority field
static const uint8_t SERVICE_PRIORITY_SIZE = 2;
/// @brief Size in octets of Addr Length field
static const uint8_t ADDR_LENGTH_SIZE = 2;
- OptionDNR6() : Option(V6, D6O_V6_DNR) {
- };
- OptionDNR6(OptionBufferConstIter begin, OptionBufferConstIter end);
+ OptionDnr6(OptionBufferConstIter begin, OptionBufferConstIter end);
virtual OptionPtr clone() const;
virtual void pack(util::OutputBuffer& buf, bool check) const;
virtual void unpack(OptionBufferConstIter begin, OptionBufferConstIter end);
virtual std::string toText(int indent) const;
virtual uint16_t len() const;
+ /// @brief Getter of the @c service_priority_
+ ///
+ /// @return The priority of this OPTION_V6_DNR instance compared to other instances.
+ uint16_t getServicePriority() const {
+ return service_priority_;
+ }
+
+ /// @brief Getter of the @c adn_length_
+ ///
+ /// @return Length of the authentication-domain-name data in octets.
+ uint16_t getAdnLength() const {
+ return adn_length_;
+ }
+
+ /// @brief Returns the Authentication domain name in the text format.
+ ///
+ /// FQDN data stored in @c adn_ is converted into text format and returned.
+ ///
+ /// @return Authentication domain name in the text format.
+ std::string getAdn() const;
+
+ /// @brief Getter of the @c addr_length_
+ ///
+ /// @return Length of enclosed IPv6 addresses in octets.
+ uint16_t getAddrLength() const {
+ return addr_length_;
+ }
+
private:
/// @brief The priority of this OPTION_V6_DNR instance compared to other instances.
uint16_t service_priority_;
- /// @brief Length of the authentication-domain-name field in octets.
+ /// @brief Length of the authentication-domain-name data in octets.
uint16_t adn_length_;
- /// @brief Authentication domain name field of variable length
+ /// @brief Authentication domain name field of variable length.
///
/// Authentication domain name field of variable length holding
/// a fully qualified domain name of the encrypted DNS resolver.
};
};
-class OptionDNR4 : public Option {
+class OptionDnr4 : public Option {
public:
- OptionDNR4();
- OptionDNR4(OptionBufferConstIter begin, OptionBufferConstIter end);
+ OptionDnr4();
+ OptionDnr4(OptionBufferConstIter begin, OptionBufferConstIter end);
virtual OptionPtr clone() const;
virtual void pack(util::OutputBuffer& buf, bool check) const;
virtual void unpack(OptionBufferConstIter begin, OptionBufferConstIter end);
virtual uint16_t len() const;
};
+/// A pointer to the @c OptionDnr6 object.
+typedef boost::shared_ptr<OptionDnr6> OptionDnr6Ptr;
+
+/// A pointer to the @c OptionDnr4 object.
+typedef boost::shared_ptr<OptionDnr4> OptionDnr4Ptr;
+
} // namespace dhcp
} // namespace isc
{ "v4-portparams", DHO_V4_PORTPARAMS, DHCP4_OPTION_SPACE, OPT_RECORD_TYPE,
false, RECORD_DEF(V4_PORTPARAMS_RECORDS), "" },
{ "v4-dnr", DHO_V4_DNR, DHCP4_OPTION_SPACE, OPT_BINARY_TYPE,
- true, NO_RECORD_DEF, "" },
+ false, NO_RECORD_DEF, "" },
{ "option-6rd", DHO_6RD, DHCP4_OPTION_SPACE, OPT_RECORD_TYPE, true,
RECORD_DEF(OPT_6RD_RECORDS), "" },
{ "v4-access-domain", DHO_V4_ACCESS_DOMAIN, DHCP4_OPTION_SPACE,
libdhcp___unittests_SOURCES += option_definition_unittest.cc
libdhcp___unittests_SOURCES += option_copy_unittest.cc
libdhcp___unittests_SOURCES += option_custom_unittest.cc
+libdhcp___unittests_SOURCES += option_dnr_unittest.cc
libdhcp___unittests_SOURCES += option_opaque_data_tuples_unittest.cc
libdhcp___unittests_SOURCES += option_unittest.cc
libdhcp___unittests_SOURCES += option_space_unittest.cc
--- /dev/null
+// Copyright (C) 2015-2023 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 <dhcp/dhcp6.h>
+#include <dhcp/option_dnr.h>
+
+#include <boost/scoped_ptr.hpp>
+#include <gtest/gtest.h>
+
+using namespace isc;
+using namespace isc::dhcp;
+using boost::scoped_ptr;
+
+namespace {
+
+// This test verifies option constructor from wire data.
+// Provided wire data is in the ADN only mode i.e. only
+// Service priority and Authentication domain name FQDN
+// fields are present.
+TEST(OptionDnr6Test, constructorAdnOnlyMode) {
+ // Prepare data to decode - ADN only mode.
+ const uint8_t buf_data[] = {
+ 0x80, 0x01, // Service priority is 32769 dec
+ 0x00, 0x14, // ADN Length is 20 dec
+ 0x06, 0x4D, 0x79, 0x68, 0x6F, 0x73, 0x74, // FQDN: Myhost.
+ 0x07, 0x45, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, // Example.
+ 0x03, 0x43, 0x6F, 0x6D, 0x00 // Com.
+ };
+
+ OptionBuffer buf(buf_data, buf_data + sizeof(buf_data));
+ // Create option instance. Check that constructor doesn't throw.
+ scoped_ptr<OptionDnr6> option;
+ EXPECT_NO_THROW(option.reset(new OptionDnr6(buf.begin(), buf.end())));
+ ASSERT_TRUE(option);
+
+ // Check if member variables were correctly set by ctor.
+ EXPECT_EQ(Option::V6, option->getUniverse());
+ EXPECT_EQ(D6O_V6_DNR, option->getType());
+
+ // Check if data was unpacked correctly from wire data.
+ EXPECT_EQ(0x8001, option->getServicePriority());
+ EXPECT_EQ(20, option->getAdnLength());
+ EXPECT_EQ("myhost.example.com.", option->getAdn());
+ EXPECT_EQ(0, option->getAddrLength());
+}
+
+TEST(OptionDnr6Test, constructorDataTruncated) {
+ // Prepare data to decode - data too short.
+ const uint8_t buf_data[] = {
+ 0x80, 0x01 // Service priority is 32769 dec, other data is missing
+ };
+
+ OptionBuffer buf(buf_data, buf_data + sizeof(buf_data));
+ // Create option instance. Check that constructor throws OutOfRange exception.
+ scoped_ptr<OptionDnr6> option;
+ EXPECT_THROW(option.reset(new OptionDnr6(buf.begin(), buf.end())), OutOfRange);
+ ASSERT_FALSE(option);
+}
+
+TEST(OptionDnr6Test, onlyWhitespaceFqdn) {
+ // Prepare data to decode - ADN only mode.
+ const uint8_t buf_data[] = {
+ 0x80, 0x01, // Service priority is 32769 dec
+ 0x00, 0x02, // ADN Length is 2 dec
+ 0x01, 0x20 // FQDN consists only of whitespace
+ };
+
+ OptionBuffer buf(buf_data, buf_data + sizeof(buf_data));
+ // Create option instance. Check that constructor throws InvalidOptionDnr6DomainName exception.
+ scoped_ptr<OptionDnr6> option;
+ EXPECT_THROW(option.reset(new OptionDnr6(buf.begin(), buf.end())), InvalidOptionDnr6DomainName);
+ ASSERT_FALSE(option);
+}
+
+} // namespace
\ No newline at end of file