#include <dhcp/opaque_data_tuple.h>
#include <dhcp/option4_dnr.h>
#include <dhcp/option6_dnr.h>
+#include <dhcp/option_data_types.h>
#include <dns/labelsequence.h>
#include <util/strutil.h>
#include <set>
void
Option4Dnr::unpack(OptionBufferConstIter begin, OptionBufferConstIter end) {
setData(begin, end);
- size_t offset = 0;
- while (offset < std::distance(begin, end)) {
+ while (begin != end) {
DnrInstance dnr_instance(V4);
- if (std::distance(begin + offset, end) < dnr_instance.getMinimalLength()) {
- isc_throw(OutOfRange, "DHCPv4 Encrypted DNS Option (" << type_ << ") malformed: "
- "DNR instance data truncated to size "
- << std::distance(begin + offset, end));
- }
- dnr_instance.setDnrInstanceDataLength(
- readUint16(&(*(begin + offset)), dnr_instance.getDnrInstanceDataLengthSize()));
- offset += dnr_instance.getDnrInstanceDataLengthSize();
- OptionBufferConstIter dnr_instance_end = begin + offset +
- dnr_instance.getDnrInstanceDataLength();
-
- dnr_instance.setServicePriority(
- readUint16(&(*(begin + offset)), dnr_instance.SERVICE_PRIORITY_SIZE));
- offset += dnr_instance.SERVICE_PRIORITY_SIZE;
-
- OpaqueDataTuple adn_tuple(OpaqueDataTuple::LENGTH_1_BYTE, begin + offset, dnr_instance_end);
- auto adn_length = adn_tuple.getLength();
- dnr_instance.setAdnLength(adn_length);
-
- // Encrypted DNS options are designed to always include an authentication domain name,
- // so when there is no FQDN included, we shall throw an exception.
- if (adn_length == 0) {
- isc_throw(InvalidOptionDnrDomainName, "Mandatory Authentication Domain Name fully "
- "qualified domain-name is missing");
+ if (std::distance(begin, end) < dnr_instance.getMinimalLength()) {
+ isc_throw(OutOfRange, dnr_instance.getLogPrefix()
+ << " malformed: DNR instance data truncated to size "
+ << std::distance(begin, end));
}
- // Let's try to extract ADN FQDN data.
- dnr_instance.unpackAdn(adn_tuple.getData().begin(), adn_length);
+ // Unpack DnrInstanceDataLength.
+ dnr_instance.unpackDnrInstanceDataLength(begin);
+
+ const OptionBufferConstIter dnr_instance_end = begin +
+ dnr_instance.getDnrInstanceDataLength();
+
+ // Unpack Service priority.
+ dnr_instance.unpackServicePriority(begin);
- offset += adn_tuple.getTotalLength();
+ // Unpack ADN len + ADN.
+ dnr_instance.unpackAdn(begin, dnr_instance_end);
- if (begin + offset == dnr_instance_end) {
+ if (begin == dnr_instance_end) {
// ADN only mode, other fields are not included.
addDnrInstance(dnr_instance);
continue;
}
dnr_instance.setAdnOnlyMode(false);
- OpaqueDataTuple addr_tuple(OpaqueDataTuple::LENGTH_1_BYTE, begin + offset,
- dnr_instance_end);
- auto addr_length = addr_tuple.getLength();
- dnr_instance.setAddrLength(addr_length);
- // It MUST be a multiple of 4.
- if ((addr_length % V4ADDRESS_LEN) != 0) {
- isc_throw(OutOfRange, "DHCPv4 Encrypted DNS Option ("
- << type_ << ")"
- << " malformed: Addr Len=" << addr_length
- << " is not divisible by 4");
- }
-
- // As per draft-ietf-add-dnr 3.1.8:
- // If additional data is supplied (i.e. not ADN only mode),
- // the option includes at least one valid IP address.
- if (addr_length == 0) {
- isc_throw(OutOfRange, "DHCPv4 Encrypted DNS Option ("
- << type_ << ")"
- << " malformed: Addr Len=" << addr_length
- << " is not greater than 0");
- }
-
- offset += dnr_instance.getAddrLengthSize();
- OptionBufferConstIter addr_begin = begin + offset;
- OptionBufferConstIter addr_end = addr_begin + addr_length;
-
- while (addr_begin != addr_end) {
- const uint8_t* ptr = &(*addr_begin);
- dnr_instance.addIpAddress(IOAddress(readUint32(ptr, std::distance(addr_begin, addr_end))));
- addr_begin += V4ADDRESS_LEN;
- offset += V4ADDRESS_LEN;
- }
+ // Unpack Addr Len + IPv4 Address(es).
+ dnr_instance.unpackAddresses(begin, dnr_instance_end);
// SvcParams (variable length) field is last.
- auto svc_params_length = std::distance(begin + offset, dnr_instance_end);
- dnr_instance.setSvcParamsLength(svc_params_length);
- if (svc_params_length > 0) {
- std::string svc_params;
- svc_params.assign(begin + offset, dnr_instance_end);
- dnr_instance.setSvcParams(svc_params);
- dnr_instance.checkSvcParams();
- offset += svc_params_length;
- }
+ dnr_instance.unpackSvcParams(begin, end);
addDnrInstance(dnr_instance);
}
adn_length_ = adn_len;
if (universe_ == Option::V4) {
- setDnrInstanceDataLength(dnrInstanceLen());
+ dnr_instance_data_length_ = dnrInstanceLen();
}
}
void
-DnrInstance::unpackAdn(OptionBufferConstIter begin, uint16_t adn_len) {
- InputBuffer name_buf(&*begin, adn_len);
+DnrInstance::unpackAdn(OptionBufferConstIter& begin, OptionBufferConstIter end) {
+ OpaqueDataTuple::LengthFieldType lft = OptionDataTypeUtil::getTupleLenFieldType(universe_);
+ OpaqueDataTuple adn_tuple(lft, begin, end);
+ adn_length_ = adn_tuple.getLength();
+
+ // Encrypted DNS options are designed to always include an authentication domain name,
+ // so when there is no FQDN included, we shall throw an exception.
+ if (adn_length_ == 0) {
+ isc_throw(InvalidOptionDnrDomainName, "Mandatory Authentication Domain Name fully "
+ "qualified domain-name is missing");
+ }
+ InputBuffer name_buf(&*adn_tuple.getData().begin(), adn_length_);
try {
adn_.reset(new isc::dns::Name(name_buf, true));
} catch (const Exception& ex) {
"fully qualified domain-name from wire format "
"- " << ex.what());
}
+ begin += adn_length_ + getAdnLengthSize();
}
void
auto addr_len = ip_addresses_.size() * addr_field_len;
if (addr_len > max_addr_len) {
isc_throw(OutOfRange, "Given IP addresses length " << addr_len << " is bigger than MAX "
- << max_addr_len);
+ << max_addr_len);
}
addr_length_ = addr_len;
if (universe_ == Option::V4) {
- setDnrInstanceDataLength(dnrInstanceLen());
+ dnr_instance_data_length_ = dnrInstanceLen();
}
}
text += ", svc_params='" + svc_params_ + "'";
}
}
- return text;
+ return (text);
}
uint16_t
ip_addresses_.push_back(ip_address);
}
+void
+DnrInstance::unpackDnrInstanceDataLength(OptionBufferConstIter& begin) {
+ dnr_instance_data_length_ = readUint16(&*begin, getDnrInstanceDataLengthSize());
+ begin += getDnrInstanceDataLengthSize();
+}
+
+void
+DnrInstance::unpackServicePriority(OptionBufferConstIter& begin) {
+ service_priority_ = readUint16(&*begin, SERVICE_PRIORITY_SIZE);
+ begin += SERVICE_PRIORITY_SIZE;
+}
+
+void
+DnrInstance::unpackAddresses(OptionBufferConstIter& begin, const OptionBufferConstIter end) {
+ OpaqueDataTuple addr_tuple(OpaqueDataTuple::LENGTH_1_BYTE, begin, end);
+ addr_length_ = addr_tuple.getLength();
+ // It MUST be a multiple of 4.
+ if ((addr_length_ % V4ADDRESS_LEN) != 0) {
+ isc_throw(OutOfRange, getLogPrefix() << " malformed: Addr Len=" << addr_length_
+ << " is not divisible by 4");
+ }
+
+ // As per draft-ietf-add-dnr 3.1.8:
+ // If additional data is supplied (i.e. not ADN only mode),
+ // the option includes at least one valid IP address.
+ if (addr_length_ == 0) {
+ isc_throw(OutOfRange, getLogPrefix() << " malformed: Addr Len=" << addr_length_
+ << " is not greater than 0");
+ }
+
+ begin += getAddrLengthSize();
+ OptionBufferConstIter addr_begin = begin;
+ OptionBufferConstIter addr_end = addr_begin + addr_length_;
+
+ while (addr_begin != addr_end) {
+ const uint8_t* ptr = &(*addr_begin);
+ addIpAddress(IOAddress(readUint32(ptr, std::distance(addr_begin, addr_end))));
+ addr_begin += V4ADDRESS_LEN;
+ begin += V4ADDRESS_LEN;
+ }
+}
+
+void
+DnrInstance::unpackSvcParams(OptionBufferConstIter& begin, OptionBufferConstIter end) {
+ svc_params_length_ = std::distance(begin, end);
+ if (svc_params_length_ > 0) {
+ svc_params_.assign(begin, end);
+ checkSvcParams();
+ begin += svc_params_length_;
+ }
+}
+
} // namespace dhcp
} // namespace isc
///
/// DNR Instance includes the configuration data of an encrypted DNS resolver.
/// It is used to build OPTION_V4_DNR (code 162). There may be multiple DNR Instances
-/// in one OPTION_V4_DNR %Option. It can be also used to build OPTION_V6_DNR (code 144).
-/// There must be only one DNR Instance in one OPTION_V6_DNR %Option.
+/// in one OPTION_V4_DNR %Option. OPTION_V6_DNR (code 144) is using very similar structure,
+/// only that there must be only one DNR Instance per one OPTION_V6_DNR %Option. That's why
+/// @c Option6Dnr class can derive from this @c DnrInstance class, whereas @c Option4Dnr class
+/// should have a container of @c DnrInstance's.
///
-/// DNR Instance Data Format has been defined in the draft-ietf-add-dnr-15 (to be replaced
+/// DNR Instance Data Format has been defined in the @c draft-ietf-add-dnr (to be replaced
/// with published RFC).
class DnrInstance {
public:
/// @param adn ADN FQDN
/// @param ip_addresses Container of IP addresses
/// @param svc_params Service Parameters
- DnrInstance(Option::Universe universe, const uint16_t service_priority,
+ DnrInstance(Option::Universe universe,
+ uint16_t service_priority,
const std::string& adn,
const AddressContainer& ip_addresses,
const std::string& svc_params);
/// @param universe either V4 or V6 Option universe
/// @param service_priority Service priority
/// @param adn ADN FQDN
- DnrInstance(Option::Universe universe, const uint16_t service_priority,
- const std::string& adn);
+ DnrInstance(Option::Universe universe, uint16_t service_priority, const std::string& adn);
/// @brief Default destructor.
virtual ~DnrInstance() = default;
///
/// @return Returns Service Parameters as a string.
const std::string& getSvcParams() const {
- return svc_params_;
+ return (svc_params_);
}
/// @brief Returns minimal length of the DNR instance data (without headers) in octets.
/// @brief Returns size in octets of DNR Instance Data Length field.
uint8_t getDnrInstanceDataLengthSize() const;
+ /// @brief Returns size in octets of ADN Length field.
+ uint8_t getAdnLengthSize() const;
+
+ /// @brief Constructs Log prefix depending on V4/V6 Option universe.
+ /// @return Log prefix as a string which can be used for prints when throwing an exception.
+ std::string getLogPrefix() const;
+
/// @brief Returns whether ADN only mode is enabled or disabled.
bool isAdnOnlyMode() const {
- return adn_only_mode_;
+ return (adn_only_mode_);
}
/// @brief Sets Authentication domain name from given string.
/// @param adn string representation of ADN FQDN
void setAdn(const std::string& adn);
- /// @brief Setter of the @c dnr_instance_data_length_ field.
- ///
- /// @param dnr_instance_data_length length to be set
- void setDnrInstanceDataLength(uint16_t dnr_instance_data_length) {
- dnr_instance_data_length_ = dnr_instance_data_length;
- }
-
- /// @brief Setter of the @c service_priority_ field.
- /// @param service_priority priority to be set
- void setServicePriority(uint16_t service_priority) {
- service_priority_ = service_priority;
- }
-
- /// @brief Setter of the @c adn_length_ field.
- /// @param adn_length length to be set
- void setAdnLength(uint16_t adn_length) {
- adn_length_ = adn_length;
- }
-
- /// @brief Setter of the @c addr_length_ field.
- /// @param addr_length length to be set
- void setAddrLength(uint16_t addr_length) {
- addr_length_ = addr_length;
- }
-
/// @brief Setter of the @c adn_only_mode_ field.
/// @param adn_only_mode enabled/disabled setting
void setAdnOnlyMode(bool adn_only_mode) {
adn_only_mode_ = adn_only_mode;
}
- /// @brief Setter of the @c svc_params_ field.
- /// @param svc_params Svc Params to be set
- void setSvcParams(const std::string& svc_params) {
- svc_params_ = svc_params;
- }
-
- /// @brief Setter of the @c svc_params_length_ field.
- /// @param svc_params_length len to be set
- void setSvcParamsLength(uint16_t svc_params_length) {
- svc_params_length_ = svc_params_length;
- }
-
/// @brief Writes the ADN FQDN in the wire format into a buffer.
///
/// The Authentication Domain Name - fully qualified domain name of the encrypted
/// @param [out] buf buffer where SvcParams will be written.
void packSvcParams(isc::util::OutputBuffer& buf) const;
+ /// @brief Unpacks DNR Instance Data Length from wire data buffer and stores
+ /// it in @c dnr_instance_data_length_.
+ /// @param begin beginning of the buffer from which the field will be read
+ void unpackDnrInstanceDataLength(OptionBufferConstIter& begin);
+
+ /// @brief Unpacks Service Priority from wire data buffer and stores it in @c service_priority_.
+ /// @param begin beginning of the buffer from which the field will be read
+ void unpackServicePriority(OptionBufferConstIter& begin);
+
/// @brief Unpacks the ADN from given wire data buffer and stores it in @c adn_ field.
/// @param begin beginning of the buffer from which the ADN will be read
- /// @param adn_len length of the ADN to be read
- void unpackAdn(OptionBufferConstIter begin, uint16_t adn_len);
+ /// @param end end of the buffer from which the ADN will be read
+ void unpackAdn(OptionBufferConstIter& begin, OptionBufferConstIter end);
+
+ /// @brief Unpacks IP address(es) from wire data and stores it/them in @c ip_addresses_.
+ /// @param begin beginning of the buffer from which the field will be read
+ /// @param end end of the buffer from which the field will be read
+ virtual void unpackAddresses(OptionBufferConstIter& begin, OptionBufferConstIter end);
+
+ /// @brief Unpacks Service Parameters from wire data buffer and stores it in @c svc_params_.
+ /// @param begin beginning of the buffer from which the field will be read
+ /// @param end end of the buffer from which the field will be read
+ void unpackSvcParams(OptionBufferConstIter& begin, OptionBufferConstIter end);
/// @brief Checks SvcParams field if encoded correctly and throws in case of issue found.
///
/// @brief Calculates and returns length of DNR Instance data in octets.
/// @return length of DNR Instance data in octets.
uint16_t dnrInstanceLen() const;
-
-private:
- /// @brief Constructs Log prefix depending on V4/V6 Option universe.
- /// @return Log prefix as a string which can be used for prints when throwing an exception.
- std::string getLogPrefix() const;
-
- /// @brief Returns size in octets of ADN Length field.
- uint8_t getAdnLengthSize() const;
};
/// @brief Represents DHCPv4 Encrypted DNS %Option (code 162).
///
-/// This option has been defined in the draft-ietf-add-dnr-15 (to be replaced
+/// This option has been defined in the @c draft-ietf-add-dnr (to be replaced
/// with published RFC) and it has a following structure:
/// - option-code = 162 (1 octet)
/// - option-len (1 octet)
/// @brief Getter of the @c dnr_instances_ field.
/// @return Reference to Option's DNR Instance container
const DnrInstanceContainer& getDnrInstances() const {
- return dnr_instances_;
+ return (dnr_instances_);
}
- virtual OptionPtr clone() const;
- virtual void pack(util::OutputBuffer& buf, bool check = true) const;
- virtual void unpack(OptionBufferConstIter begin, OptionBufferConstIter end);
- virtual std::string toText(int indent = 0) const;
- virtual uint16_t len() const;
+ OptionPtr clone() const override;
+ void pack(util::OutputBuffer& buf, bool check = true) const override;
+ void unpack(OptionBufferConstIter begin, OptionBufferConstIter end) override;
+ std::string toText(int indent = 0) const override;
+ uint16_t len() const override;
protected:
/// @brief Container holding DNR Instances.
void
Option6Dnr::unpack(OptionBufferConstIter begin, OptionBufferConstIter end) {
if (std::distance(begin, end) < getMinimalLength()) {
- isc_throw(OutOfRange, "DHCPv6 Encrypted DNS Option (" << type_ << ") malformed: "
- "data truncated to"
- " size " << std::distance(begin, end));
+ isc_throw(OutOfRange, getLogPrefix() << " malformed: data truncated to size "
+ << std::distance(begin, end));
}
setData(begin, end);
+
// First two octets of Option data is Service Priority - this is mandatory field.
- service_priority_ = isc::util::readUint16(&(*begin), SERVICE_PRIORITY_SIZE);
- begin += SERVICE_PRIORITY_SIZE;
+ unpackServicePriority(begin);
// Next come two octets of ADN Length plus the ADN data itself (variable length).
// This is Opaque Data Tuple so let's use this class to retrieve the ADN data.
- OpaqueDataTuple adn_tuple(OpaqueDataTuple::LENGTH_2_BYTES, begin, end);
- adn_length_ = adn_tuple.getLength();
-
- // Encrypted DNS options are designed to always include an authentication domain name,
- // so when there is no FQDN included, we shall throw an exception.
- if (adn_length_ == 0) {
- isc_throw(InvalidOptionDnrDomainName, "Mandatory Authentication Domain Name fully "
- "qualified domain-name is missing");
- }
-
- // Let's try to extract ADN FQDN data.
- unpackAdn(adn_tuple.getData().begin(), adn_length_);
-
- begin += adn_tuple.getTotalLength();
+ unpackAdn(begin, end);
if (begin == end) {
// ADN only mode, other fields are not included.
return;
}
adn_only_mode_ = false;
+
+ unpackAddresses(begin, end);
+
+ // SvcParams (variable length) field is last.
+ unpackSvcParams(begin, end);
+}
+
+std::string
+Option6Dnr::toText(int indent) const {
+ std::ostringstream stream;
+ std::string in(indent, ' '); // base indentation
+ stream << in << "type=" << type_ << "(V6_DNR), "
+ << "len=" << (len() - getHeaderLen()) << ", " << getDnrInstanceAsText();
+ return (stream.str());
+}
+
+uint16_t
+Option6Dnr::len() const {
+ return (OPTION6_HDR_LEN + dnrInstanceLen());
+}
+
+void
+Option6Dnr::unpackAddresses(OptionBufferConstIter& begin, OptionBufferConstIter end) {
if (std::distance(begin, end) < getAddrLengthSize()) {
- isc_throw(OutOfRange, "DHCPv6 Encrypted DNS Option (" << type_ << ") malformed: after"
- " ADN field, there should be at least "
- "2 bytes long Addr Length field");
+ isc_throw(OutOfRange, getLogPrefix() << " malformed: after"
+ " ADN field, there should be at least "
+ "2 bytes long Addr Length field");
}
// Next come two octets of Addr Length.
addr_length_ = isc::util::readUint16(&(*begin), getAddrLengthSize());
begin += getAddrLengthSize();
// It MUST be a multiple of 16.
if ((addr_length_ % V6ADDRESS_LEN) != 0) {
- isc_throw(OutOfRange, "DHCPv6 Encrypted DNS Option (" << type_ << ")"
- << " malformed: Addr Len=" << addr_length_
- << " is not divisible by 16");
+ isc_throw(OutOfRange, getLogPrefix() << " malformed: Addr Len=" << addr_length_
+ << " is not divisible by 16");
}
// As per draft-ietf-add-dnr 3.1.8:
// If additional data is supplied (i.e. not ADN only mode),
// the option includes at least one valid IP address.
if (addr_length_ == 0) {
- isc_throw(OutOfRange, "DHCPv6 Encrypted DNS Option (" << type_ << ")"
- << " malformed: Addr Len=" << addr_length_
- << " is not greater than 0");
+ isc_throw(OutOfRange, getLogPrefix() << " malformed: Addr Len=" << addr_length_
+ << " is not greater than 0");
}
// Check if IPv6 Address(es) field is not truncated.
if (std::distance(begin, end) < addr_length_) {
- isc_throw(OutOfRange, "DHCPv6 Encrypted DNS Option (" << type_ << ")"
- << " malformed: Addr Len=" << addr_length_
- << " but IPv6 address(es) are truncated to len="
- << std::distance(begin, end));
+ isc_throw(OutOfRange, getLogPrefix() << " malformed: Addr Len=" << addr_length_
+ << " but IPv6 address(es) are truncated to len="
+ << std::distance(begin, end));
}
// Let's unpack the ipv6-address(es).
ip_addresses_.push_back(IOAddress::fromBytes(AF_INET6, &(*begin)));
begin += V6ADDRESS_LEN;
}
-
- // SvcParams (variable length) field is last.
- svc_params_length_ = std::distance(begin, end);
- if (svc_params_length_ > 0) {
- svc_params_.assign(begin, end);
- checkSvcParams();
- }
-}
-
-std::string
-Option6Dnr::toText(int indent) const {
- std::ostringstream stream;
- std::string in(indent, ' '); // base indentation
- stream << in << "type=" << type_ << "(V6_DNR), "
- << "len=" << (len() - getHeaderLen()) << ", " << getDnrInstanceAsText();
- return (stream.str());
-}
-
-uint16_t
-Option6Dnr::len() const {
- return (OPTION6_HDR_LEN + dnrInstanceLen());
}
} // namespace dhcp
/// @brief Represents DHCPv6 Encrypted DNS %Option (code 144).
///
-/// This option has been defined in the draft-ietf-add-dnr-15 (to be replaced
+/// This option has been defined in the @c draft-ietf-add-dnr (to be replaced
/// with published RFC) and it has a following structure:
/// - option-code = 144 (2 octets)
/// - option-len (2 octets)
/// - Service Parameters (variable length).
class Option6Dnr : public Option, public DnrInstance {
public:
-
/// @brief Constructor of the %Option from on-wire data.
///
/// This constructor creates an instance of the option using a buffer with
/// @param ip_addresses Container of IP addresses
/// @param svc_params Service Parameters
Option6Dnr(const uint16_t service_priority,
- const std::string& adn,
- const Option6Dnr::AddressContainer& ip_addresses,
- const std::string& svc_params)
- : Option(V6, D6O_V6_DNR),
- DnrInstance(V6, service_priority, adn, ip_addresses, svc_params) {}
+ const std::string& adn,
+ const Option6Dnr::AddressContainer& ip_addresses,
+ const std::string& svc_params)
+ : Option(V6, D6O_V6_DNR), DnrInstance(V6, service_priority, adn, ip_addresses, svc_params) {
+ }
/// @brief Constructor of the %Option in ADN only mode.
///
Option6Dnr(const uint16_t service_priority, const std::string& adn)
: Option(V6, D6O_V6_DNR), DnrInstance(V6, service_priority, adn) {}
- virtual OptionPtr clone() const;
- virtual void pack(util::OutputBuffer& buf, bool check = false) const;
- virtual void unpack(OptionBufferConstIter begin, OptionBufferConstIter end);
- virtual std::string toText(int indent = 0) const;
- virtual uint16_t len() const;
+ OptionPtr clone() const override;
+ void pack(util::OutputBuffer& buf, bool check = false) const override;
+ void unpack(OptionBufferConstIter begin, OptionBufferConstIter end) override;
+ std::string toText(int indent = 0) const override;
+ uint16_t len() const override;
- virtual void packAddresses(isc::util::OutputBuffer& buf) const;
+ void packAddresses(isc::util::OutputBuffer& buf) const override;
+ void unpackAddresses(OptionBufferConstIter& begin, OptionBufferConstIter end) override;
};
/// A pointer to the @c Option6Dnr object.
EXPECT_EQ(66, option->len());
}
+TEST(Option4DnrTest, unpackMixedDnrInstances) {
+ // Prepare data to decode - 2 DNR instances.
+ const uint8_t buf_data[] = {
+ 0x00, 24, // DNR Instance Data Len
+ 0x00, 0x01, // Service priority is 1 dec
+ 21, // ADN Length is 21 dec
+ 0x07, 0x6D, 0x79, 0x68, 0x6F, 0x73, 0x74, '1', // FQDN: myhost1.
+ 0x07, 0x65, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, // example.
+ 0x03, 0x63, 0x6F, 0x6D, 0x00, // com.
+ 0x00, 62, // DNR Instance Data Len
+ 0x00, 0x02, // Service priority is 2 dec
+ 21, // ADN Length is 21 dec
+ 0x07, 0x6D, 0x79, 0x68, 0x6F, 0x73, 0x74, '2', // FQDN: myhost2.
+ 0x07, 0x65, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, // example.
+ 0x03, 0x63, 0x6F, 0x6D, 0x00, // com.
+ 8, // Addr Len
+ 192, 168, 0, 1, // IP address 1
+ 192, 168, 0, 2, // IP address 2
+ 'k', 'e', 'y', '1', '2', '3', '=', 'v', // Svc Params
+ 'a', 'l', ' ', 'k', 'e', 'y', '2', '3', // Svc Params
+ '4', '=', 'v', 'a', 'l', '2', ' ', 'k', // Svc Params
+ 'e', 'y', '3', '4', '5' // Svc Params
+ };
+ OptionBuffer buf(buf_data, buf_data + sizeof(buf_data));
+ // Create option instance. Check that constructor doesn't throw.
+ scoped_ptr<Option4Dnr> option;
+ EXPECT_NO_THROW(option.reset(new Option4Dnr(buf.begin(), buf.end())));
+ ASSERT_TRUE(option);
+
+ // Check if member variables were correctly set by ctor.
+ EXPECT_EQ(Option::V4, option->getUniverse());
+ EXPECT_EQ(DHO_V4_DNR, option->getType());
+
+ // Check if data was unpacked correctly from wire data.
+ const DnrInstance& dnr_1 = option->getDnrInstances()[0];
+ EXPECT_EQ(24, dnr_1.getDnrInstanceDataLength());
+ EXPECT_EQ(1, dnr_1.getServicePriority());
+ EXPECT_EQ(21, dnr_1.getAdnLength());
+ EXPECT_EQ("myhost1.example.com.", dnr_1.getAdnAsText());
+ EXPECT_EQ(0, dnr_1.getAddrLength());
+ EXPECT_EQ(0, dnr_1.getSvcParamsLength());
+
+ const DnrInstance& dnr_2 = option->getDnrInstances()[1];
+ EXPECT_EQ(62, dnr_2.getDnrInstanceDataLength());
+ EXPECT_EQ(2, dnr_2.getServicePriority());
+ EXPECT_EQ(21, dnr_2.getAdnLength());
+ EXPECT_EQ("myhost2.example.com.", dnr_2.getAdnAsText());
+ EXPECT_EQ(8, dnr_2.getAddrLength());
+ EXPECT_EQ(29, dnr_2.getSvcParamsLength());
+ EXPECT_EQ(2, dnr_2.getAddresses().size());
+ EXPECT_EQ("192.168.0.1", dnr_2.getAddresses()[0].toText());
+ EXPECT_EQ("192.168.0.2", dnr_2.getAddresses()[1].toText());
+ EXPECT_EQ("key123=val key234=val2 key345", dnr_2.getSvcParams());
+
+ EXPECT_EQ(92, option->len());
+}
+
} // namespace
\ No newline at end of file
// toText() len does not count in headers len.
EXPECT_EQ("type=144(V6_DNR), len=24, "
"service_priority=32769, adn_length=20, "
- "adn='myhost.example.com.'", option->toText());
+ "adn='myhost.example.com.'",
+ option->toText());
}
// Test checks that exception is thrown when trying to unpack malformed wire data
"addr_length=48, "
"address(es): 2001:db8:1::dead:beef "
"ff02::face:b00c "
- "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", option->toText());
+ "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff",
+ option->toText());
}
// Test checks that exception is thrown when trying to unpack malformed wire data
"adn='myhost.example.com.', "
"addr_length=16, "
"address(es): 2001:db8:1::dead:beef, "
- "svc_params='abc'", option->toText());
+ "svc_params='abc'",
+ option->toText());
}
// Test checks that exception is thrown when trying to unpack malformed wire data
// toText() len does not count in headers len.
EXPECT_EQ("type=144(V6_DNR), len=24, "
"service_priority=9, adn_length=20, "
- "adn='myhost.example.com.'", option->toText());
+ "adn='myhost.example.com.'",
+ option->toText());
}
// This test verifies that option constructor in ADN only mode throws
TEST(Option6DnrTest, adnOnlyModeCtorNoFqdn) {
// Prepare example parameters.
const uint16_t service_priority = 9;
- const std::string adn; // invalid empty ADN
+ const std::string adn; // invalid empty ADN
// Create option instance. Check that constructor throws.
scoped_ptr<Option6Dnr> option;
EXPECT_EQ("type=144(V6_DNR), len=46, "
"service_priority=9, adn_length=20, "
"adn='myhost.example.com.', addr_length=16, "
- "address(es): 2001:db8:1::baca, svc_params='alpn'", option->toText());
+ "address(es): 2001:db8:1::baca, svc_params='alpn'",
+ option->toText());
}
// This test verifies that option constructor throws
// Prepare example parameters
const uint16_t service_priority = 9;
const std::string adn = "myhost.example.com.";
- const Option6Dnr::AddressContainer addresses; // no IPv6 address in here
+ const Option6Dnr::AddressContainer addresses; // no IPv6 address in here
const std::string svc_params = "alpn";
// Create option instance. Check that constructor throws.
scoped_ptr<Option6Dnr> option;
- EXPECT_THROW(option.reset(new Option6Dnr(service_priority, adn, addresses, svc_params)), OutOfRange);
+ EXPECT_THROW(option.reset(new Option6Dnr(service_priority, adn, addresses, svc_params)),
+ OutOfRange);
ASSERT_FALSE(option);
}
const std::string adn = "myhost.example.com.";
Option6Dnr::AddressContainer addresses;
addresses.push_back(isc::asiolink::IOAddress("2001:db8:1::baca"));
- const std::string svc_params = "key123=val1=val2 key234"; // invalid svc param - 2 equal signs
+ const std::string svc_params = "key123=val1=val2 key234"; // invalid svc param - 2 equal signs
// Create option instance. Check that constructor throws.
scoped_ptr<Option6Dnr> option;
- EXPECT_THROW(option.reset(new Option6Dnr(service_priority, adn, addresses, svc_params)), InvalidOptionDnrSvcParams);
+ EXPECT_THROW(option.reset(new Option6Dnr(service_priority, adn, addresses, svc_params)),
+ InvalidOptionDnrSvcParams);
ASSERT_FALSE(option);
}
const std::string adn = "myhost.example.com.";
Option6Dnr::AddressContainer addresses;
addresses.push_back(isc::asiolink::IOAddress("2001:db8:1::baca"));
- const std::string svc_params = "key123=val1 ipv6hint"; // forbidden svc param key - ipv6hint
+ const std::string svc_params = "key123=val1 ipv6hint"; // forbidden svc param key - ipv6hint
// Create option instance. Check that constructor throws.
scoped_ptr<Option6Dnr> option;
- EXPECT_THROW(option.reset(new Option6Dnr(service_priority, adn, addresses, svc_params)), InvalidOptionDnrSvcParams);
+ EXPECT_THROW(option.reset(new Option6Dnr(service_priority, adn, addresses, svc_params)),
+ InvalidOptionDnrSvcParams);
ASSERT_FALSE(option);
}
const std::string adn = "myhost.example.com.";
Option6Dnr::AddressContainer addresses;
addresses.push_back(isc::asiolink::IOAddress("2001:db8:1::baca"));
- const std::string svc_params = "key123=val1 key234 key123"; // svc param key key123 repeated
+ const std::string svc_params = "key123=val1 key234 key123"; // svc param key key123 repeated
// Create option instance. Check that constructor throws.
scoped_ptr<Option6Dnr> option;
- EXPECT_THROW(option.reset(new Option6Dnr(service_priority, adn, addresses, svc_params)), InvalidOptionDnrSvcParams);
+ EXPECT_THROW(option.reset(new Option6Dnr(service_priority, adn, addresses, svc_params)),
+ InvalidOptionDnrSvcParams);
ASSERT_FALSE(option);
}
addresses.push_back(isc::asiolink::IOAddress("2001:db8:1::baca"));
const std::string svc_params = "thisisveryveryveryvery"
"veryveryveryveryveryvery"
- "veryveryveryveryvlongkey"; // svc param key longer than 63
+ "veryveryveryveryvlongkey"; // svc param key longer than 63
// Create option instance. Check that constructor throws.
scoped_ptr<Option6Dnr> option;
- EXPECT_THROW(option.reset(new Option6Dnr(service_priority, adn, addresses, svc_params)), InvalidOptionDnrSvcParams);
+ EXPECT_THROW(option.reset(new Option6Dnr(service_priority, adn, addresses, svc_params)),
+ InvalidOptionDnrSvcParams);
ASSERT_FALSE(option);
}
// Create option instance. Check that constructor throws.
scoped_ptr<Option6Dnr> option;
- EXPECT_THROW(option.reset(new Option6Dnr(service_priority, adn, addresses, svc_params)), InvalidOptionDnrSvcParams);
+ EXPECT_THROW(option.reset(new Option6Dnr(service_priority, adn, addresses, svc_params)),
+ InvalidOptionDnrSvcParams);
ASSERT_FALSE(option);
}
ASSERT_TRUE(option);
const int indent = 4;
- std::string expected = " type=144(V6_DNR), len=46, " // the indentation of 4 spaces
+ std::string expected = " type=144(V6_DNR), len=46, " // the indentation of 4 spaces
"service_priority=9, adn_length=20, "
"adn='myhost.example.com.', addr_length=16, "
"address(es): 2001:db8:1::baca, svc_params='alpn'";