]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#3390] Checkpoint: code done
authorFrancis Dupont <fdupont@isc.org>
Thu, 29 Aug 2024 10:26:44 +0000 (12:26 +0200)
committerFrancis Dupont <fdupont@isc.org>
Thu, 26 Sep 2024 09:41:33 +0000 (11:41 +0200)
src/lib/dhcp/dhcp6.h
src/lib/dhcp/libdhcp++.cc
src/lib/dhcp/std_option_defs.h
src/lib/dhcp/tests/libdhcp++_unittest.cc

index ef9162bea4267b56b8ee4118f952b997b0c296cf..cc7574a40f152772df9a83f28d216b239d30808f 100644 (file)
@@ -73,7 +73,7 @@ enum DHCPv6OptionType {
    D6O_RELAY_ID                            = 53, /* RFC5460 */
 // D6O_IPV6_ADDRESS_MOS                    = 54, /* RFC5678 */
 // D6O_IPV6_FQDN_MOS                       = 55, /* RFC5678 */
-// D6O_NTP_SERVER                          = 56, /* RFC5908 */
+   D6O_NTP_SERVER                          = 56, /* RFC5908 */
    D6O_V6_ACCESS_DOMAIN                    = 57, /* RFC5986 */
    D6O_SIP_UA_CS_LIST                      = 58, /* RFC6011 */
    D6O_BOOTFILE_URL                        = 59, /* RFC5970 */
@@ -153,7 +153,7 @@ enum DHCPv6OptionType {
 // D6O_F_START_TIME_OF_STATE              = 133, /* RFC8156 */
 // D6O_F_STATE_EXPIRATION_TIME            = 134, /* RFC8156 */
    D6O_RELAY_SOURCE_PORT                  = 135, /* RFC8357 */
-   D60_V6_SZTP_REDIRECT                   = 136, /* RFC8572 */
+   D6O_V6_SZTP_REDIRECT                   = 136, /* RFC8572 */
    // Option codes 137-142 are unassigned.
    D6O_IPV6_ADDRESS_ANDSF                 = 143, /* RFC6153 */
    D6O_V6_DNR                             = 144 /* RFC9463 */
@@ -259,6 +259,11 @@ static const uint16_t ISC_V6_4O6_INTERFACE = 60000;
 static const uint16_t ISC_V6_4O6_SRC_ADDRESS = 60001;
 static const uint16_t ISC_V6_4O6_SRC_PORT = 60002;
 
+/* NTP server (RFC 5908) suboptions. */
+static const uint16_t NTP_SUBOPTION_SRV_ADDR = 1;
+static const uint16_t NTP_SUBOPTION_MC_ADDR = 2;
+static const uint16_t NTP_SUBOPTION_SRV_FQDN = 3;
+
 /* Offsets into IA_*'s where Option spaces commence.  */
 static const uint16_t IA_NA_OFFSET = 12; /* IAID, T1, T2, all 4 octets each */
 static const uint16_t IA_TA_OFFSET = 4; /* IAID only, 4 octets */
index 3f74a156f4c38ef769b84df40f787c0b359fc32f..0e0dd448c85c605d7a9084759885384a6bdb0f3e 100644 (file)
@@ -56,8 +56,9 @@ const OptionDefParamsEncapsulation OPTION_DEF_PARAMS[] = {
     { LW_V6_OPTION_DEFINITIONS,             LW_V6_OPTION_DEFINITIONS_SIZE,           LW_V6_OPTION_SPACE          },
     { V4V6_RULE_OPTION_DEFINITIONS,         V4V6_RULE_OPTION_DEFINITIONS_SIZE,       V4V6_RULE_OPTION_SPACE      },
     { V4V6_BIND_OPTION_DEFINITIONS,         V4V6_BIND_OPTION_DEFINITIONS_SIZE,       V4V6_BIND_OPTION_SPACE      },
-    { DHCP_AGENT_OPTION_DEFINITIONS,        DHCP_AGENT_OPTION_DEFINITIONS_SIZE,      DHCP_AGENT_OPTION_SPACE     },
+    { V6_NTP_SERVER_DEFINITIONS,            V6_NTP_SERVER_DEFINITIONS_SIZE,          V6_NTP_SERVER_SPACE         },
     { LAST_RESORT_V4_OPTION_DEFINITIONS,    LAST_RESORT_V4_OPTION_DEFINITIONS_SIZE,  LAST_RESORT_V4_OPTION_SPACE },
+    { DHCP_AGENT_OPTION_DEFINITIONS,        DHCP_AGENT_OPTION_DEFINITIONS_SIZE,      DHCP_AGENT_OPTION_SPACE     },
     { NULL,                                 0,                                       ""                          }
 };
 
index 145784549911a3478a80a7bc35405be73b472867..6ead5f6fe4278df45e68c88a27ee392d8b2e74f1 100644 (file)
@@ -21,6 +21,7 @@
 #define LW_V6_OPTION_SPACE               "s46-cont-lw-options"
 #define V4V6_RULE_OPTION_SPACE           "s46-rule-options"
 #define V4V6_BIND_OPTION_SPACE           "s46-v4v6bind-options"
+#define V6_NTP_SERVER_SPACE              "v6-ntp-server-suboptions"
 #define LAST_RESORT_V4_OPTION_SPACE      "last-resort-v4"
 
 /// @brief encapsulated option spaces
@@ -606,6 +607,8 @@ const OptionDefParams STANDARD_V6_OPTION_DEFINITIONS[] = {
       OPT_IPV6_ADDRESS_TYPE, true, NO_RECORD_DEF, "" },
     { "relay-id", D6O_RELAY_ID, DHCP6_OPTION_SPACE, OPT_BINARY_TYPE, false,
       NO_RECORD_DEF, "" },
+    { "ntp-server", D6O_NTP_SERVER, DHCP6_OPTION_SPACE, OPT_EMPTY_TYPE,
+      false, NO_RECORD_DEF, V6_NTP_SERVER_SPACE },
     { "v6-access-domain", D6O_V6_ACCESS_DOMAIN, DHCP6_OPTION_SPACE,
       OPT_FQDN_TYPE, false, NO_RECORD_DEF, "" },
     { "sip-ua-cs-list", D6O_SIP_UA_CS_LIST, DHCP6_OPTION_SPACE,
@@ -644,7 +647,7 @@ const OptionDefParams STANDARD_V6_OPTION_DEFINITIONS[] = {
       OPT_STRING_TYPE, false, NO_RECORD_DEF, "" },
     { "relay-source-port", D6O_RELAY_SOURCE_PORT, DHCP6_OPTION_SPACE,
       OPT_UINT16_TYPE, false, NO_RECORD_DEF, "" },
-    { "v6-sztp-redirect", D60_V6_SZTP_REDIRECT, DHCP6_OPTION_SPACE,
+    { "v6-sztp-redirect", D6O_V6_SZTP_REDIRECT, DHCP6_OPTION_SPACE,
       OPT_TUPLE_TYPE, true, NO_RECORD_DEF, "" },
     { "ipv6-address-andsf", D6O_IPV6_ADDRESS_ANDSF, DHCP6_OPTION_SPACE,
       OPT_IPV6_ADDRESS_TYPE, true, NO_RECORD_DEF, "" },
@@ -742,6 +745,20 @@ const int V4V6_BIND_OPTION_DEFINITIONS_SIZE =
     sizeof(V4V6_BIND_OPTION_DEFINITIONS) /
     sizeof(V4V6_BIND_OPTION_DEFINITIONS[0]);
 
+/// @brief NTP server suboption definitions
+const OptionDefParams V6_NTP_SERVER_DEFINITIONS[] = {
+    { "ntp-server-address", NTP_SUBOPTION_SRV_ADDR, V6_NTP_SERVER_SPACE,
+      OPT_IPV6_ADDRESS_TYPE, false, NO_RECORD_DEF, "" },
+    { "ntp-server-multicast", NTP_SUBOPTION_MC_ADDR, V6_NTP_SERVER_SPACE,
+      OPT_IPV6_ADDRESS_TYPE, false, NO_RECORD_DEF, "" },
+    { "ntp-server-fqdn", NTP_SUBOPTION_SRV_FQDN, V6_NTP_SERVER_SPACE,
+      OPT_FQDN_TYPE, false, NO_RECORD_DEF, "" }
+};
+
+const int V6_NTP_SERVER_DEFINITIONS_SIZE =
+    sizeof(V6_NTP_SERVER_DEFINITIONS) /
+    sizeof(V6_NTP_SERVER_DEFINITIONS[0]);
+
 }  // namespace
 
 }  // namespace dhcp
index 2b51a119b04ca18b088ea9f0b61c846dcb9f6512..3d4ee37fe19120305155346e3f379efab114a035 100644 (file)
@@ -3261,7 +3261,7 @@ TEST_F(LibDhcpTest, stdOptionDefs6) {
     std::vector<uint8_t> opaque_tuple_buf(opaque_tuple_data,
                                           opaque_tuple_data + sizeof(opaque_tuple_data));
 
-    LibDhcpTest::testStdOptionDefs6(D60_V6_SZTP_REDIRECT,
+    LibDhcpTest::testStdOptionDefs6(D6O_V6_SZTP_REDIRECT,
                                     opaque_tuple_buf.begin(),
                                     opaque_tuple_buf.end(),
                                     typeid(OptionOpaqueDataTuples));
@@ -3732,4 +3732,121 @@ TEST_F(LibDhcpTest, unpackOptions6LenientFqdn) {
     EXPECT_EQ(77, elapsed->getValue());
 }
 
+// RFC 5908 v6 NTP server option and suboptions.
+TEST_F(LibDhcpTest, v6NtpServer) {
+    // A NTP server option with the 3 suboptions.
+    std::vector<uint8_t> bin {
+        0, 56, 0, 53,    // ntp-server
+        0, 1, 0, 16,    // ntp-server-address
+        0x20, 0x01, 0xd, 0xb8, 0, 0, 0, 0, // 2001:db8::abcd
+        0, 0, 0, 0, 0, 0, 0xab, 0xcd,
+        0, 2, 0, 16,    // ntp-server-multicast
+        0xff, 0x02, 0, 0, 0, 0, 0, 0, // ff02::101
+        0, 0, 0, 0, 0, 0, 0x01, 0x01,
+        0, 3, 0, 9,     // ntp-server-fqdn
+        3, 0x66, 0x6f, 0x6f, // foo.bar.
+        3, 0x62, 0x61, 0x72, 0
+    };
+
+    // List of parsed options will be stored here.
+    isc::dhcp::OptionCollection options;
+
+    OptionBuffer buf(bin);
+
+    size_t parsed = 0;
+
+    EXPECT_NO_THROW(parsed = LibDHCP::unpackOptions6(buf, DHCP6_OPTION_SPACE,
+                                                     options));
+    EXPECT_EQ(bin.size(), parsed);
+
+    // We expect to have exactly one option with 3 suboptions.
+    EXPECT_EQ(1, options.size());
+    auto opt = options.find(D6O_NTP_SERVER);
+    ASSERT_FALSE(opt == options.end());
+
+    // Get the option.
+    OptionCustomPtr option =
+        boost::dynamic_pointer_cast<OptionCustom>(opt->second);
+    ASSERT_TRUE(option);
+    EXPECT_EQ(D6O_NTP_SERVER, option->getType());
+    EXPECT_EQ(57, option->len());
+    EXPECT_EQ(53, option->getData().size());
+
+    // Check the address suboption.
+    ASSERT_TRUE(option->getOption(NTP_SUBOPTION_SRV_ADDR));
+    OptionCustomPtr addr =
+        boost::dynamic_pointer_cast<OptionCustom>(option->getOption(NTP_SUBOPTION_SRV_ADDR));
+    ASSERT_TRUE(addr);
+    EXPECT_EQ("type=00001, len=00016: 2001:db8::abcd (ipv6-address)",
+              addr->toText());
+
+    // Check the multicast suboption.
+    ASSERT_TRUE(option->getOption(NTP_SUBOPTION_MC_ADDR));
+    OptionCustomPtr multicast =
+        boost::dynamic_pointer_cast<OptionCustom>(option->getOption(NTP_SUBOPTION_MC_ADDR));
+    ASSERT_TRUE(multicast);
+    EXPECT_EQ("type=00002, len=00016: ff02::101 (ipv6-address)",
+              multicast->toText());
+
+    // Check the fqdn suboption.
+    ASSERT_TRUE(option->getOption(NTP_SUBOPTION_SRV_FQDN));
+    OptionCustomPtr fqdn =
+        boost::dynamic_pointer_cast<OptionCustom>(option->getOption(NTP_SUBOPTION_SRV_FQDN));
+    ASSERT_TRUE(fqdn);
+    EXPECT_EQ("type=00003, len=00009: \"foo.bar.\" (fqdn)",
+              fqdn->toText());
+
+    // Build back the NTP server option.
+    OptionDefinitionPtr opt_def =
+        LibDHCP::getOptionDef(DHCP6_OPTION_SPACE, D6O_NTP_SERVER);
+    ASSERT_TRUE(opt_def);
+    ASSERT_NO_THROW(option.reset(new OptionCustom(*opt_def, Option::V6)));
+    ASSERT_TRUE(option);
+
+    // Add address.
+    OptionDefinitionPtr addr_def =
+        LibDHCP::getOptionDef(V6_NTP_SERVER_SPACE, NTP_SUBOPTION_SRV_ADDR);
+    ASSERT_TRUE(addr_def);
+    OptionBuffer addr_buf = {
+        0x20, 0x01, 0xd, 0xb8, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0xab, 0xcd
+    };
+    ASSERT_NO_THROW(addr.reset(new OptionCustom(*addr_def, Option::V6,
+                                                addr_buf)));
+    ASSERT_TRUE(addr);
+    option->addOption(addr);
+
+    // Add multicast.
+    OptionDefinitionPtr multicast_def =
+        LibDHCP::getOptionDef(V6_NTP_SERVER_SPACE, NTP_SUBOPTION_MC_ADDR);
+    ASSERT_TRUE(multicast_def);
+    OptionBuffer multicast_buf = {
+        0xff, 0x02, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0x01, 0x01
+    };
+    ASSERT_NO_THROW(multicast.reset(new OptionCustom(*multicast_def,
+                                                     Option::V6,
+                                                     multicast_buf)));
+    ASSERT_TRUE(multicast);
+    option->addOption(multicast);
+
+    // Add fqdn.
+    OptionDefinitionPtr fqdn_def =
+        LibDHCP::getOptionDef(V6_NTP_SERVER_SPACE, NTP_SUBOPTION_SRV_FQDN);
+    ASSERT_TRUE(fqdn_def);
+    OptionBuffer fqdn_buf = {
+        3, 0x66, 0x6f, 0x6f, 3, 0x62, 0x61, 0x72, 0
+    };
+    ASSERT_NO_THROW(fqdn.reset(new OptionCustom(*fqdn_def, Option::V6,
+                                                fqdn_buf)));
+    ASSERT_TRUE(fqdn);
+    option->addOption(fqdn);
+
+    // Pack output.
+    isc::util::OutputBuffer outbuf(0);
+    ASSERT_NO_THROW(option->pack(outbuf, true));
+    ASSERT_EQ(bin.size(), outbuf.getLength());
+    EXPECT_TRUE(memcmp(&bin[0], outbuf.getData(), bin.size()) == 0);
+}
+
 }  // namespace