]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#3141] DNRv6 UTs edited
authorPiotrek Zadroga <piotrek@isc.org>
Fri, 16 Feb 2024 19:39:14 +0000 (20:39 +0100)
committerPiotrek Zadroga <piotrek@isc.org>
Fri, 23 Feb 2024 16:14:05 +0000 (17:14 +0100)
src/lib/dhcp/option6_dnr.h
src/lib/dhcp/tests/option6_dnr_unittest.cc

index f7fbeaa4d45c96b78011be92645589e55b06339d..e1cbcf743ec0afbf0c48253898bc7698807dc087 100644 (file)
@@ -45,41 +45,6 @@ public:
                OptionBufferConstIter end,
                bool convenient_notation = false);
 
-    /// @brief Constructor of the %Option with all fields from params.
-    ///
-    /// Constructor of the %Option where all fields
-    /// i.e. Service priority, ADN, IP address(es) and Service params
-    /// are provided as ctor parameters.
-    ///
-    /// @param service_priority Service priority
-    /// @param adn ADN FQDN
-    /// @param ip_addresses Container of IP addresses
-    /// @param svc_params Service Parameters
-    ///
-    /// @throw InvalidOptionDnrDomainName Thrown in case of any issue with parsing ADN
-    /// @throw InvalidOptionDnrSvcParams Thrown when @c checkSvcParams(from_wire_data) throws
-    /// @throw OutOfRange Thrown in case of no IP addresses found or when IP addresses length
-    /// is too big
-    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) {
-    }
-
-    /// @brief Constructor of the %Option in ADN only mode.
-    ///
-    /// Constructor of the %Option in ADN only mode
-    /// i.e. only Service priority and ADN FQDN
-    /// are provided as ctor parameters.
-    ///
-    /// @param service_priority Service priority
-    /// @param adn ADN FQDN
-    ///
-    /// @throw InvalidOptionDnrDomainName Thrown in case of any issue with parsing ADN
-    Option6Dnr(const uint16_t service_priority, const std::string& adn)
-        : Option(V6, D6O_V6_DNR), DnrInstance(V6, service_priority, adn) {}
-
     /// @brief Copies this option and returns a pointer to the copy.
     ///
     /// @return Pointer to the copy of the option.
index 29c082da68445b2f8a55291ff40fee046f1b91ee..bf00fbeaa3636f98347b2cacc9d026ab8cf5382e 100644 (file)
@@ -283,8 +283,11 @@ TEST(Option6DnrTest, onWireCtorSvcParamsIncluded) {
         0x03, 0x43, 0x6F, 0x6D, 0x00,                    // Com.
         0x00, 0x10,                                      // Addr Len field value = 16 dec
         0x20, 0x01, 0x0d, 0xb8, 0x00, 0x01, 0x00, 0x00,  // 2001:db8:1::dead:beef
-        0x00, 0x00, 0x00, 0x00, 0xde, 0xad, 0xbe, 0xef,
-        'a', 'b', 'c'                                    // example SvcParams data
+        0x00, 0x00, 0x00, 0x00, 0xde, 0xad, 0xbe, 0xef,  //
+        0,    1,                                         // SvcParamKey alpn
+        0,    8,                                         // SvcParamVal Len
+        3,    'd',  'o',  't',                           // 3 octets long alpn-id dot
+        3,    'd',  'o',  'q'                            // 3 octets long alpn-id doq
     };
 
     OptionBuffer buf(buf_data, buf_data + sizeof(buf_data));
@@ -305,28 +308,34 @@ TEST(Option6DnrTest, onWireCtorSvcParamsIncluded) {
     const Option6Dnr::AddressContainer& addresses = option->getAddresses();
     EXPECT_EQ(1, addresses.size());
     EXPECT_EQ("2001:db8:1::dead:beef", addresses[0].toText());
-    EXPECT_EQ(3, option->getSvcParamsLength());
-    EXPECT_EQ("abc", option->getSvcParams());
+    EXPECT_EQ(12, option->getSvcParamsLength());
+    const OptionBuffer svc_params = {
+        0, 1,              // SvcParamKey alpn
+        0, 8,              // SvcParamVal Len
+        3, 'd', 'o', 't',  // 3 octets long alpn-id dot
+        3, 'd', 'o', 'q'   // 3 octets long alpn-id doq
+    };
+    EXPECT_EQ(svc_params, option->getSvcParams());
 
     // BTW let's check if len() works ok.
     // expected len: 20 (FQDN) + 2 (ADN Len) + 2 (Service priority) + 4 (headers) = 28
-    //             + 16 (IP address) + 2 (Addr Len) + 3 (SvcParams) = 49.
-    EXPECT_EQ(49, option->len());
+    //             + 16 (IP address) + 2 (Addr Len) + 12 (SvcParams) = 58.
+    EXPECT_EQ(58, option->len());
 
     // BTW let's check if toText() works ok.
     // toText() len does not count in headers len.
-    EXPECT_EQ("type=144(V6_DNR), len=45, "
+    EXPECT_EQ("type=144(V6_DNR), len=54, "
               "service_priority=32769, adn_length=20, "
               "adn='myhost.example.com.', "
               "addr_length=16, "
               "address(es): 2001:db8:1::dead:beef, "
-              "svc_params='abc'",
+              "svc_params='alpn=dot,doq'",
               option->toText());
 }
 
 // Test checks that exception is thrown when trying to unpack malformed wire data
-// - SvcParams Key contains char that is not allowed.
-TEST(Option6DnrTest, onWireCtorSvcParamsInvalidCharKey) {
+// - SvcParams Key contains truncated SvcParamVal Len data.
+TEST(Option6DnrTest, onWireCtorSvcParamsTruncatedParamLen) {
     // Prepare data to decode with invalid SvcParams.
     const uint8_t buf_data[] = {
         0x80, 0x01,                                      // Service priority is 32769 dec
@@ -334,213 +343,247 @@ TEST(Option6DnrTest, onWireCtorSvcParamsInvalidCharKey) {
         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
+        0x00, 0x10,                                      // Addr Len field value
         0x20, 0x01, 0x0d, 0xb8, 0x00, 0x01, 0x00, 0x00,  // 2001:db8:1::dead:beef
-        0x00, 0x00, 0x00, 0x00, 0xde, 0xad, 0xbe, 0xef,
-        'a', '+', 'c'                                    // Allowed "a"-"z", "0"-"9", and "-"
+        0x00, 0x00, 0x00, 0x00, 0xde, 0xad, 0xbe, 0xef,  //
+        0,    1,                                         // SvcParamKey alpn
+        0,    8,                                         // SvcParamVal Len
+        3,    'd',  'o',  't',                           // 3 octets long alpn-id dot
+        3,    'd',  'o',  'q',                           // 3 octets long alpn-id doq
+        0,    3,                                         // SvcParamKey port
+        0                                                // truncated SvcParamVal Len
     };
 
     OptionBuffer buf(buf_data, buf_data + sizeof(buf_data));
-    // Create option instance. Check that constructor throws InvalidOptionDnrSvcParams exception.
+    // Create option instance. Check that constructor throws exception.
     Option6DnrPtr option;
-    EXPECT_THROW(option.reset(new Option6Dnr(buf.begin(), buf.end())), InvalidOptionDnrSvcParams);
+    EXPECT_THROW(option.reset(new Option6Dnr(buf.begin(), buf.end())), OutOfRange);
     ASSERT_FALSE(option);
 }
 
-// This test verifies option constructor in ADN only mode.
-// Service priority and ADN are provided via ctor.
-TEST(Option6DnrTest, adnOnlyModeCtor) {
-    // Prepare example parameters.
-    const uint16_t service_priority = 9;
-    const std::string adn = "myhost.example.com.";
+// Test checks that exception is thrown when trying to unpack malformed wire data
+// - SvcParams Key contains truncated data.
+TEST(Option6DnrTest, onWireCtorSvcParamsTruncatedParamData) {
+    // Prepare data to decode with invalid SvcParams.
+    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
+        0x20, 0x01, 0x0d, 0xb8, 0x00, 0x01, 0x00, 0x00,  // 2001:db8:1::dead:beef
+        0x00, 0x00, 0x00, 0x00, 0xde, 0xad, 0xbe, 0xef,  //
+        0,    1,                                         // SvcParamKey alpn
+        0,    8,                                         // SvcParamVal Len
+        3,    'd',  'o',  't',                           // 3 octets long alpn-id dot
+        3,    'd',  'o',  'q',                           // 3 octets long alpn-id doq
+        0,    3,                                         // SvcParamKey port
+        0,    2,                                         // SvcParamVal Len
+        1                                                // truncated data
+    };
 
-    // Create option instance. Check that constructor doesn't throw.
+    OptionBuffer buf(buf_data, buf_data + sizeof(buf_data));
+    // Create option instance. Check that constructor throws exception.
     Option6DnrPtr option;
-    EXPECT_NO_THROW(option.reset(new Option6Dnr(service_priority, adn)));
-    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());
-    EXPECT_EQ(service_priority, option->getServicePriority());
-    EXPECT_EQ(20, option->getAdnLength());
-    EXPECT_EQ(adn, option->getAdnAsText());
-
-    // This is ADN only mode, so Addr Length and SvcParams Length
-    // are both expected to be zero.
-    EXPECT_EQ(0, option->getAddrLength());
-    EXPECT_EQ(0, option->getSvcParamsLength());
-
-    // BTW let's check if len() works ok.
-    // expected len: 20 (FQDN) + 2 (ADN Len) + 2 (Service priority) + 4 (headers) = 28.
-    EXPECT_EQ(28, option->len());
-
-    // BTW let's check if toText() works ok.
-    // 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());
+    EXPECT_THROW(option.reset(new Option6Dnr(buf.begin(), buf.end())), InvalidOptionDnrSvcParams);
+    ASSERT_FALSE(option);
 }
 
-// This test verifies that option constructor in ADN only mode throws
-// an exception when mandatory ADN is empty.
-TEST(Option6DnrTest, adnOnlyModeCtorNoFqdn) {
-    // Prepare example parameters.
-    const uint16_t service_priority = 9;
-    const std::string adn;  // invalid empty ADN
+// Test checks that exception is thrown when trying to unpack malformed wire data
+// - SvcParams Key contains unknown key.
+TEST(Option6DnrTest, onWireCtorSvcParamsUnknownKey) {
+    // Prepare data to decode with invalid SvcParams.
+    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
+        0x20, 0x01, 0x0d, 0xb8, 0x00, 0x01, 0x00, 0x00,  // 2001:db8:1::dead:beef
+        0x00, 0x00, 0x00, 0x00, 0xde, 0xad, 0xbe, 0xef,  //
+        0,    1,                                         // SvcParamKey alpn
+        0,    8,                                         // SvcParamVal Len
+        3,    'd',  'o',  't',                           // 3 octets long alpn-id dot
+        3,    'd',  'o',  'q',                           // 3 octets long alpn-id doq
+        0,    99,                                        // unknown SvcParamKey
+        0,    2,                                         // SvcParamVal Len
+        1,    2                                          // random data
+    };
 
-    // Create option instance. Check that constructor throws.
+    OptionBuffer buf(buf_data, buf_data + sizeof(buf_data));
+    // Create option instance. Check that constructor throws exception.
     Option6DnrPtr option;
-    EXPECT_THROW(option.reset(new Option6Dnr(service_priority, adn)), InvalidOptionDnrDomainName);
+    EXPECT_THROW(option.reset(new Option6Dnr(buf.begin(), buf.end())), InvalidOptionDnrSvcParams);
     ASSERT_FALSE(option);
 }
 
-// This test verifies option constructor where all fields
-// i.e. Service priority, ADN, IP address(es) and Service params
-// are provided as ctor parameters.
-TEST(Option6DnrTest, allFieldsCtor) {
-    // Prepare example parameters
-    const uint16_t service_priority = 9;
-    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 = "alpn";
+// Test checks that exception is thrown when trying to unpack malformed wire data
+// - SvcParams Key contains forbidden key.
+TEST(Option6DnrTest, onWireCtorSvcParamsForbiddenKey) {
+    // Prepare data to decode with invalid SvcParams.
+    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
+        0x20, 0x01, 0x0d, 0xb8, 0x00, 0x01, 0x00, 0x00,  // 2001:db8:1::dead:beef
+        0x00, 0x00, 0x00, 0x00, 0xde, 0xad, 0xbe, 0xef,  //
+        0,    1,                                         // SvcParamKey alpn
+        0,    8,                                         // SvcParamVal Len
+        3,    'd',  'o',  't',                           // 3 octets long alpn-id dot
+        3,    'd',  'o',  'q',                           // 3 octets long alpn-id doq
+        0,    4,                                         // SvcParamKey ipv4hint is forbidden
+        0,    2,                                         // SvcParamVal Len
+        1,    2                                          // random data
+    };
 
-    // Create option instance. Check that constructor doesn't throw.
+    OptionBuffer buf(buf_data, buf_data + sizeof(buf_data));
+    // Create option instance. Check that constructor throws exception.
     Option6DnrPtr option;
-    EXPECT_NO_THROW(option.reset(new Option6Dnr(service_priority, adn, addresses, svc_params)));
-    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());
-    EXPECT_EQ(service_priority, option->getServicePriority());
-    EXPECT_EQ(20, option->getAdnLength());
-    EXPECT_EQ(adn, option->getAdnAsText());
-    EXPECT_EQ(16, option->getAddrLength());
-    EXPECT_EQ(4, option->getSvcParamsLength());
-    EXPECT_EQ(svc_params, option->getSvcParams());
-
-    // BTW let's check if len() works ok.
-    // expected len: 20 (FQDN) + 2 (ADN Len) + 2 (Service priority) + 4 (headers) = 28
-    //             + 16 (IPv6) + 2 (Addr Len) + 4 (Svc Params) = 50.
-    EXPECT_EQ(50, option->len());
-
-    // BTW let's check if toText() works ok.
-    // toText() len does not count in headers len.
-    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());
+    EXPECT_THROW(option.reset(new Option6Dnr(buf.begin(), buf.end())), InvalidOptionDnrSvcParams);
+    ASSERT_FALSE(option);
 }
 
-// This test verifies that option constructor throws
-// an exception when option fields provided via ctor are malformed
-// - no IPv6 address provided.
-TEST(Option6DnrTest, allFieldsCtorNoIpAddress) {
-    // 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 std::string svc_params = "alpn";
+// Test checks that exception is thrown when trying to unpack malformed wire data
+// - SvcParams Key contains unsupported key.
+TEST(Option6DnrTest, onWireCtorSvcParamsUnsupportedKey) {
+    // Prepare data to decode with invalid SvcParams.
+    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
+        0x20, 0x01, 0x0d, 0xb8, 0x00, 0x01, 0x00, 0x00,  // 2001:db8:1::dead:beef
+        0x00, 0x00, 0x00, 0x00, 0xde, 0xad, 0xbe, 0xef,  //
+        0,    1,                                         // SvcParamKey alpn
+        0,    8,                                         // SvcParamVal Len
+        3,    'd',  'o',  't',                           // 3 octets long alpn-id dot
+        3,    'd',  'o',  'q',                           // 3 octets long alpn-id doq
+        0,    5,  // SvcParamKey ech is unsupported in DHCP DNR option
+        0,    2,  // SvcParamVal Len
+        1,    2   // random data
+    };
 
-    // Create option instance. Check that constructor throws.
+    OptionBuffer buf(buf_data, buf_data + sizeof(buf_data));
+    // Create option instance. Check that constructor throws exception.
     Option6DnrPtr option;
-    EXPECT_THROW(option.reset(new Option6Dnr(service_priority, adn, addresses, svc_params)),
-                 OutOfRange);
+    EXPECT_THROW(option.reset(new Option6Dnr(buf.begin(), buf.end())), InvalidOptionDnrSvcParams);
     ASSERT_FALSE(option);
 }
 
-// This test verifies that option constructor throws
-// an exception when option fields provided via ctor are malformed
-// - Svc Params key=val pair has 2 equal signs.
-TEST(Option6DnrTest, svcParamsTwoEqualSignsPerParam) {
-    // Prepare example parameters.
-    const uint16_t service_priority = 9;
-    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
+// Test checks that exception is thrown when trying to unpack malformed wire data
+// - SvcParams Key contains duplicated key.
+TEST(Option6DnrTest, onWireCtorSvcParamsDuplicatedKey) {
+    // Prepare data to decode with invalid SvcParams.
+    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
+        0x20, 0x01, 0x0d, 0xb8, 0x00, 0x01, 0x00, 0x00,  // 2001:db8:1::dead:beef
+        0x00, 0x00, 0x00, 0x00, 0xde, 0xad, 0xbe, 0xef,  //
+        0,    1,                                         // SvcParamKey alpn
+        0,    8,                                         // SvcParamVal Len
+        3,    'd',  'o',  't',                           // 3 octets long alpn-id dot
+        3,    'd',  'o',  'q',                           // 3 octets long alpn-id doq
+        0,    1,                                         // SvcParamKey alpn is duplicated
+        0,    4,                                         // SvcParamVal Len
+        3,    'd',  'o',  't'                            // 3 octets long alpn-id dot
+    };
 
-    // Create option instance. Check that constructor throws.
+    OptionBuffer buf(buf_data, buf_data + sizeof(buf_data));
+    // Create option instance. Check that constructor throws exception.
     Option6DnrPtr option;
-    EXPECT_THROW(option.reset(new Option6Dnr(service_priority, adn, addresses, svc_params)),
-                 InvalidOptionDnrSvcParams);
+    EXPECT_THROW(option.reset(new Option6Dnr(buf.begin(), buf.end())), InvalidOptionDnrSvcParams);
     ASSERT_FALSE(option);
 }
 
-// This test verifies that option constructor throws
-// an exception when option fields provided via ctor are malformed
-// - Svc Params forbidden key provided.
-TEST(Option6DnrTest, svcParamsForbiddenKey) {
-    // Prepare example parameters.
-    const uint16_t service_priority = 9;
-    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
+// Test checks that exception is thrown when trying to unpack malformed wire data
+// - SvcParams Keys are in wrong order.
+TEST(Option6DnrTest, onWireCtorSvcParamsWrongKeyOrder) {
+    // Prepare data to decode with invalid SvcParams.
+    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
+        0x20, 0x01, 0x0d, 0xb8, 0x00, 0x01, 0x00, 0x00,  // 2001:db8:1::dead:beef
+        0x00, 0x00, 0x00, 0x00, 0xde, 0xad, 0xbe, 0xef,  //
+        0,    3,                                         // SvcParamKey port
+        0,    2,                                         // SvcParamVal Len
+        23,   23,                                        // 2 octets long port number
+        0,    1,                                         // SvcParamKey alpn is duplicated
+        0,    4,                                         // SvcParamVal Len
+        3,    'd',  'o',  't'                            // 3 octets long alpn-id dot
+    };
 
-    // Create option instance. Check that constructor throws.
+    OptionBuffer buf(buf_data, buf_data + sizeof(buf_data));
+    // Create option instance. Check that constructor throws exception.
     Option6DnrPtr option;
-    EXPECT_THROW(option.reset(new Option6Dnr(service_priority, adn, addresses, svc_params)),
-                 InvalidOptionDnrSvcParams);
+    EXPECT_THROW(option.reset(new Option6Dnr(buf.begin(), buf.end())), InvalidOptionDnrSvcParams);
     ASSERT_FALSE(option);
 }
 
 // This test verifies that option constructor throws
-// an exception when option fields provided via ctor are malformed
-// - Svc Params key was repeated.
-TEST(Option6DnrTest, svcParamsKeyRepeated) {
-    // Prepare example parameters.
-    const uint16_t service_priority = 9;
-    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
+// an exception when config provided via ctor is malformed
+// - SvcParam key=val pair has 2 equal signs.
+TEST(Option6DnrTest, fromConfigCtorSvcParamsTwoEqualSignsPerParam) {
+    // Prepare example config.
+    const std::string config = "100, dot1.example.org., 2001:db8::1 2001:db8::2, "
+                               "alpn=dot=doq port=8530 dohpath=/q{?dns}";
+
+    OptionBuffer buf;
+    buf.assign(config.begin(), config.end());
 
     // Create option instance. Check that constructor throws.
     Option6DnrPtr option;
-    EXPECT_THROW(option.reset(new Option6Dnr(service_priority, adn, addresses, svc_params)),
+    EXPECT_THROW(option.reset(new Option6Dnr(buf.begin(), buf.end(), true)),
                  InvalidOptionDnrSvcParams);
     ASSERT_FALSE(option);
 }
 
 // This test verifies that option constructor throws
-// an exception when option fields provided via ctor are malformed
-// - Svc Params key is too long.
-TEST(Option6DnrTest, svcParamsKeyTooLong) {
-    // Prepare example parameters.
-    const uint16_t service_priority = 9;
-    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 = "thisisveryveryveryvery"
-                                   "veryveryveryveryveryvery"
-                                   "veryveryveryveryvlongkey";  // svc param key longer than 63
+// an exception when config provided via ctor is malformed
+// - SvcParam has forbidden key.
+TEST(Option6DnrTest, fromConfigCtorSvcParamsForbiddenKey) {
+    // Prepare example config.
+    const std::string config = "100, dot1.example.org., 2001:db8::1 2001:db8::2, "
+                               "ipv6hint=something port=8530 dohpath=/q{?dns}";
+
+    OptionBuffer buf;
+    buf.assign(config.begin(), config.end());
 
     // Create option instance. Check that constructor throws.
     Option6DnrPtr option;
-    EXPECT_THROW(option.reset(new Option6Dnr(service_priority, adn, addresses, svc_params)),
+    EXPECT_THROW(option.reset(new Option6Dnr(buf.begin(), buf.end(), true)),
                  InvalidOptionDnrSvcParams);
     ASSERT_FALSE(option);
 }
 
 // This test verifies that option constructor throws
-// an exception when option fields provided via ctor are malformed
-// - Svc Params key has chars that are not allowed.
-TEST(Option6DnrTest, svcParamsKeyHasInvalidChar) {
-    // Prepare example parameters.
-    const uint16_t service_priority = 9;
-    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 = "alpn=h2 NOT_ALLOWED_CHARS_KEY=123"; // svc param key has forbidden chars
+// an exception when config provided via ctor is malformed
+// - Svc Params key was repeated.
+TEST(Option6DnrTest, fromConfigCtorSvcParamsKeyRepeated) {
+    // Prepare example config.
+    const std::string config = "100, dot1.example.org., 2001:db8::1 2001:db8::2, "
+                               "port=8530 port=1234 dohpath=/q{?dns}";
+
+    OptionBuffer buf;
+    buf.assign(config.begin(), config.end());
 
     // Create option instance. Check that constructor throws.
     Option6DnrPtr option;
-    EXPECT_THROW(option.reset(new Option6Dnr(service_priority, adn, addresses, svc_params)),
+    EXPECT_THROW(option.reset(new Option6Dnr(buf.begin(), buf.end(), true)),
                  InvalidOptionDnrSvcParams);
     ASSERT_FALSE(option);
 }
@@ -548,35 +591,38 @@ TEST(Option6DnrTest, svcParamsKeyHasInvalidChar) {
 // This test verifies that string representation of the option returned by
 // toText method is correctly formatted.
 TEST(Option6DnrTest, toText) {
-    // Prepare example parameters.
-    const uint16_t service_priority = 9;
-    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 = "alpn";
+    // Prepare example config.
+    const std::string config = "9, myhost.example.com., 2001:db8:1::baca, "
+                               "alpn=h3 port=1234 dohpath=/q{?dns}";
+
+    OptionBuffer buf;
+    buf.assign(config.begin(), config.end());
 
     // Create option instance. Check that constructor doesn't throw.
     Option6DnrPtr option;
-    EXPECT_NO_THROW(option.reset(new Option6Dnr(service_priority, adn, addresses, svc_params)));
+    EXPECT_NO_THROW(option.reset(new Option6Dnr(buf.begin(), buf.end(), true)));
     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=67, "  // 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'";
+                           "address(es): 2001:db8:1::baca, svc_params='alpn=h3 port=1234 "
+                           "dohpath=/q{?dns}'";
     EXPECT_EQ(expected, option->toText(indent));
 }
 
 // This test verifies on-wire format of the option is correctly created in ADN only mode.
-TEST(Option6DnrTest, packAdnOnlyMode) {
-    // Prepare example parameters.
-    const uint16_t service_priority = 9;
-    const std::string adn = "myhost.example.com.";
+TEST(Option6DnrTest, fromConfigCtorPackAdnOnlyMode) {
+    // Prepare example config.
+    const std::string config = "9, myhost.example.com.";
+
+    OptionBuffer in_buf;
+    in_buf.assign(config.begin(), config.end());
 
     // Create option instance. Check that constructor doesn't throw.
     Option6DnrPtr option;
-    EXPECT_NO_THROW(option.reset(new Option6Dnr(service_priority, adn)));
+    EXPECT_NO_THROW(option.reset(new Option6Dnr(in_buf.begin(), in_buf.end(), true)));
     ASSERT_TRUE(option);
 
     // Prepare on-wire format of the option.
@@ -588,7 +634,7 @@ TEST(Option6DnrTest, packAdnOnlyMode) {
         0x00, D6O_V6_DNR,                                // Option code
         0x00, 24,                                        // Option len=24 dec
         0x00, 0x09,                                      // Service priority is 9 dec
-        0x00, 0x14,                                      // ADN Length is 20 dec
+        0x00, 20,                                        // ADN Length is 20 dec
         0x06, 0x6D, 0x79, 0x68, 0x6F, 0x73, 0x74,        // FQDN: myhost.
         0x07, 0x65, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65,  // example.
         0x03, 0x63, 0x6F, 0x6D, 0x00                     // com.
@@ -605,17 +651,16 @@ TEST(Option6DnrTest, packAdnOnlyMode) {
 // This test verifies on-wire format of the option is correctly created when
 // IP addresses and Svc Params are also included.
 TEST(Option6DnrTest, pack) {
-    // Prepare example parameters.
-    const uint16_t service_priority = 9;
-    const std::string adn = "myhost.example.com.";
-    Option6Dnr::AddressContainer addresses;
-    addresses.push_back(isc::asiolink::IOAddress("2001:db8:1::dead:beef"));
-    addresses.push_back(isc::asiolink::IOAddress("ff02::face:b00c"));
-    const std::string svc_params = "alpn";
+    // Prepare example config.
+    const std::string config = "9, myhost.example.com., 2001:db8:1::dead:beef ff02::face:b00c,"
+                               " alpn=imap";
+
+    OptionBuffer in_buf;
+    in_buf.assign(config.begin(), config.end());
 
     // Create option instance. Check that constructor doesn't throw.
     Option6DnrPtr option;
-    EXPECT_NO_THROW(option.reset(new Option6Dnr(service_priority, adn, addresses, svc_params)));
+    EXPECT_NO_THROW(option.reset(new Option6Dnr(in_buf.begin(), in_buf.end(), true)));
     ASSERT_TRUE(option);
 
     // Prepare on-wire format of the option.
@@ -624,19 +669,21 @@ TEST(Option6DnrTest, pack) {
 
     // Prepare reference data.
     const uint8_t ref_data[] = {
-        0x00, D6O_V6_DNR,                                // Option code
-        0x00, 62,                                        // Option len=62 dec
-        0x00, 0x09,                                      // Service priority is 9 dec
-        0x00, 0x14,                                      // ADN Length is 20 dec
-        0x06, 0x6D, 0x79, 0x68, 0x6F, 0x73, 0x74,        // FQDN: myhost.
-        0x07, 0x65, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65,  // example.
-        0x03, 0x63, 0x6F, 0x6D, 0x00,                    // com.
-        0x00, 0x20,                                      // Addr Len field value = 32 dec
-        0x20, 0x01, 0x0d, 0xb8, 0x00, 0x01, 0x00, 0x00,  // 2001:db8:1::dead:beef
-        0x00, 0x00, 0x00, 0x00, 0xde, 0xad, 0xbe, 0xef,
-        0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // ff02::face:b00c
-        0x00, 0x00, 0x00, 0x00, 0xfa, 0xce, 0xb0, 0x0c,
-         'a',  'l',  'p',  'n'                           // Svc Params
+        0x00, D6O_V6_DNR,                                           // Option code
+        0x00, 67,                                                   // Option len=67 dec
+        0x00, 0x09,                                                 // Service priority is 9 dec
+        0x00, 0x14,                                                 // ADN Length is 20 dec
+        0x06, 0x6D, 0x79, 0x68, 0x6F, 0x73, 0x74,                   // FQDN: myhost.
+        0x07, 0x65, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65,             // example.
+        0x03, 0x63, 0x6F, 0x6D, 0x00,                               // com.
+        0x00, 0x20,                                                 // Addr Len field value = 32 dec
+        0x20, 0x01, 0x0d, 0xb8, 0x00, 0x01, 0x00, 0x00,             // 2001:db8:1::dead:beef
+        0x00, 0x00, 0x00, 0x00, 0xde, 0xad, 0xbe, 0xef, 0xff, 0x02, //
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,                         // ff02::face:b00c
+        0x00, 0x00, 0x00, 0x00, 0xfa, 0xce, 0xb0, 0x0c,             //
+        0,    1,                                                    // SvcParamKey alpn
+        0,    5,                                                    // SvcParamVal len
+        4,    'i',  'm',  'a',  'p'                                 // alpn-id
     };
 
     size_t ref_data_size = sizeof(ref_data) / sizeof(ref_data[0]);