From: Piotrek Zadroga Date: Fri, 7 Apr 2023 15:38:25 +0000 (+0200) Subject: [#2536] Implementing DNRv6 Option with TDD X-Git-Tag: Kea-2.3.8~183 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a4ec9f28bee6e28f04723310090258666235eb81;p=thirdparty%2Fkea.git [#2536] Implementing DNRv6 Option with TDD --- diff --git a/src/lib/dhcp/option_dnr.cc b/src/lib/dhcp/option_dnr.cc index 83fe76fef1..ef6d762e4f 100644 --- a/src/lib/dhcp/option_dnr.cc +++ b/src/lib/dhcp/option_dnr.cc @@ -75,6 +75,7 @@ OptionDnr6::unpack(OptionBufferConstIter begin, OptionBufferConstIter end) { // ADN only mode, other fields are not included. return; } + adn_only_mode_ = false; if (std::distance(begin, end) < ADDR_LENGTH_SIZE) { isc_throw(OutOfRange, "DHCPv6 Encrypted DNS Option (" << type_ << ") malformed: after" " ADN field, there should be at least " @@ -99,6 +100,7 @@ OptionDnr6::unpack(OptionBufferConstIter begin, OptionBufferConstIter end) { // SvcParams (variable length) field is last svc_params_length_ = std::distance(begin, end); + // TBD svcParams unpack } std::string @@ -108,15 +110,18 @@ OptionDnr6::toText(int indent) const { uint16_t OptionDnr6::len() const { - return Option::len(); + return adn_only_mode_ ? + (OPTION6_HDR_LEN + SERVICE_PRIORITY_SIZE + adn_length_ + ADN_LENGTH_SIZE) : + (OPTION6_HDR_LEN + SERVICE_PRIORITY_SIZE + adn_length_ + ADN_LENGTH_SIZE + + addr_length_ + ADDR_LENGTH_SIZE + svc_params_length_); } std::string OptionDnr6::getAdn() const { if (adn_) { - return adn_->toText(); + return (adn_->toText()); } - return ""; + return (""); } OptionDnr4::OptionDnr4() : Option(V4, DHO_V4_DNR) { diff --git a/src/lib/dhcp/option_dnr.h b/src/lib/dhcp/option_dnr.h index a1b3e2896b..d95fa4a10c 100644 --- a/src/lib/dhcp/option_dnr.h +++ b/src/lib/dhcp/option_dnr.h @@ -47,14 +47,14 @@ public: /// /// @return The priority of this OPTION_V6_DNR instance compared to other instances. uint16_t getServicePriority() const { - return service_priority_; + 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_; + return (adn_length_); } /// @brief Returns the Authentication domain name in the text format. @@ -68,14 +68,14 @@ public: /// /// @return Length of enclosed IPv6 addresses in octets. uint16_t getAddrLength() const { - return addr_length_; + return (addr_length_); } /// @brief Getter of the @c svc_params_length_ /// /// @return Length of Service Parameters field in octets. uint16_t getSvcParamsLength() const { - return svc_params_length_; + return (svc_params_length_); } /// @brief Returns vector with addresses. @@ -87,7 +87,7 @@ public: /// /// @return address container with addresses AddressContainer getAddresses() const { - return ipv6_addresses_; + return (ipv6_addresses_); } private: @@ -116,6 +116,8 @@ private: /// @brief Length of Service Parameters field in octets. uint16_t svc_params_length_ = 0; + bool adn_only_mode_ = true; + /// @brief Returns minimal length of the option data (without headers) in octets. /// /// If the ADN-only mode is used, then "Addr Length", "ipv6-address(es)", diff --git a/src/lib/dhcp/tests/option_dnr_unittest.cc b/src/lib/dhcp/tests/option_dnr_unittest.cc index e8d69cd1c5..d7d2a8603b 100644 --- a/src/lib/dhcp/tests/option_dnr_unittest.cc +++ b/src/lib/dhcp/tests/option_dnr_unittest.cc @@ -49,6 +49,7 @@ TEST(OptionDnr6Test, constructorAdnOnlyMode) { EXPECT_EQ("myhost.example.com.", option->getAdn()); EXPECT_EQ(0, option->getAddrLength()); EXPECT_EQ(0, option->getSvcParamsLength()); + EXPECT_EQ(28, option->len()); } TEST(OptionDnr6Test, constructorDataTruncated) { @@ -155,6 +156,7 @@ TEST(OptionDnr6Test, addrLenZero) { EXPECT_EQ("myhost.example.com.", option->getAdn()); EXPECT_EQ(0, option->getAddrLength()); EXPECT_EQ(0, option->getSvcParamsLength()); + EXPECT_EQ(30, option->len()); } TEST(OptionDnr6Test, addrLenNot16Modulo) { @@ -214,6 +216,43 @@ TEST(OptionDnr6Test, validIpV6Addresses) { EXPECT_EQ("ff02::face:b00c", addresses[1].toText()); EXPECT_EQ("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", addresses[2].toText()); EXPECT_EQ(0, option->getSvcParamsLength()); + EXPECT_EQ(78, option->len()); +} + +TEST(OptionDnr6Test, svcParamsIncluded) { + // Prepare data to decode + 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. + 0x00, 0x10, // Addr Len field value = 48 dec + 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x01, 0x00, 0x00, // 2001:db8:1::dead:beef + 0x00, 0x00, 0x00, 0x00, 0xde, 0xad, 0xbe, 0xef, + 0xff, 0xff // example SvcParams data + }; + + OptionBuffer buf(buf_data, buf_data + sizeof(buf_data)); + // Create option instance. Check that constructor doesn't throw. + scoped_ptr 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(16, option->getAddrLength()); + const OptionDnr6::AddressContainer& addresses = option->getAddresses(); + EXPECT_EQ(1, addresses.size()); + EXPECT_EQ("2001:db8:1::dead:beef", addresses[0].toText()); + EXPECT_EQ(2, option->getSvcParamsLength()); + EXPECT_EQ(48, option->len()); } } // namespace \ No newline at end of file