]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#3094] Finished tests and doc
authorFrancis Dupont <fdupont@isc.org>
Sun, 30 Jun 2024 13:31:39 +0000 (15:31 +0200)
committerFrancis Dupont <fdupont@isc.org>
Thu, 18 Jul 2024 12:45:25 +0000 (14:45 +0200)
ChangeLog
doc/sphinx/arm/dhcp4-srv.rst
src/bin/dhcp4/dhcp4_srv.cc
src/bin/dhcp4/tests/dhcp4_srv_unittest.cc

index 6f57e2836d7b1897a831fc442d698011f56377d1..62ea1d562fd65db89747993d5091ce7c4a8456ba 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2263.  [func]          fdupont
+       RFC 8925 "IPv6-Only Preferred Option for DHCPv4" is now
+       fully implemented: 0.0.0.0 address can be offerred.
+       (Gitlab #3094)
+
 2262.  [bug]           marcin
        Corrected a bug in storing and fetching the encapsulated DHCP
        options from the configuration backend. These options were
index d47f55c866643dbfbcaa8ce0bab63ec18a7dbd36..3ceed35c020a32f5670c39cdd90515ae7aa0103e 100644 (file)
@@ -3038,6 +3038,19 @@ the same option code) and to fuse the data chunks into one option. This is
 also supported for sub-options if each sub-option data chunk also contains the
 sub-option code and sub-option length.
 
+.. _dhcp4-support-for-v6-only-preferred-option:
+
+Support for IPv6-Only Preferred Option
+--------------------------------------
+
+The ``v6-only-preferred`` (code 108) option is handled in a specific
+way described in `RFC 8925 <https://tools.ietf.org/html/rfc8925>`_
+by :iscman:`kea-dhcp4` when it is configured in a subnet or a
+shared network: when the client requests the option (i.e. puts
+the 108 code in the DHCP parameter request list option) and
+the subnet or shared network is selected the 0.0.0.0 address
+is offered and the option returned in the response.
+
 .. _dhcp4-stateless-configuration:
 
 Stateless Configuration of DHCPv4 Clients
index b47cc74c01867d3cf0ce6d985e6a74db413ba0fc..88a928d1eb857cacf0543eaa87967416048cd649 100644 (file)
@@ -3873,7 +3873,7 @@ Dhcpv4Srv::processRequest(Pkt4Ptr& request, AllocEngine::ClientContext4Ptr& cont
         if (ex.getIPv6OnlyPreferred()) {
             if (!response->getOption(DHO_V6_ONLY_PREFERRED)) {
                 // Better to drop the packet than to send an insane response.
-                LOG_ERROR(packet4_logger, DHCP4_V6_ONLY_PREFERRED_MISSING_IN_OFFER)
+                LOG_ERROR(packet4_logger, DHCP4_V6_ONLY_PREFERRED_MISSING_IN_ACK)
                     .arg(request->getLabel());
                 return (Pkt4Ptr());
             }
index 02c8e9d51feba813df8e71c22edbca4e00d9aa69..f9a193aa05e5f3aa7618eb76a0f7d56f55f258b3 100644 (file)
@@ -6249,6 +6249,100 @@ TEST_F(Dhcpv4SrvTest, noV6OnlyPreferredRequestGlobal) {
     EXPECT_EQ(v6only_wait, got_v6op_opt->getValue());
 }
 
+// Verify that when discover requesting v6-only-preferred 0.0.0.0 is offered
+// but the option is not added to the response is an error case.
+TEST_F(Dhcpv4SrvTest, v6OnlyPreferredDiscoverError) {
+    IfaceMgrTestConfig test_config(true);
+    IfaceMgr::instance().openSockets4();
+
+    NakedDhcpv4Srv srv(0);
+
+    // Recreate subnet.
+    Triplet<uint32_t> unspecified;
+    Triplet<uint32_t> valid_lft(500, 1000, 1500);
+    subnet_ = Subnet4::create(IOAddress("192.0.2.0"), 24,
+                              unspecified,
+                              unspecified,
+                              valid_lft,
+                              subnet_->getID());
+    // Add the v6-only-preferred option data.
+    const uint32_t v6only_wait(3600);
+    OptionUint32Ptr v6op_opt(new OptionUint32(Option::V4,
+                                              DHO_V6_ONLY_PREFERRED,
+                                              v6only_wait));
+    subnet_->getCfgOption()->add(v6op_opt, false, false, DHCP4_OPTION_SPACE);
+    CfgMgr::instance().clear();
+    CfgMgr::instance().getStagingCfg()->getCfgSubnets4()->add(subnet_);
+    // Cancel the v6-only-preferred option at the global level.
+    CfgMgr::instance().getStagingCfg()->getCfgOption()->
+        add(v6op_opt, false, true, DHCP4_OPTION_SPACE);
+    CfgMgr::instance().commit();
+
+    Pkt4Ptr dis = Pkt4Ptr(new Pkt4(DHCPDISCOVER, 1234));
+    dis->setRemoteAddr(IOAddress("192.0.2.1"));
+    OptionPtr clientid = generateClientId();
+    dis->addOption(clientid);
+    dis->setIface("eth1");
+    dis->setIndex(ETH1_INDEX);
+
+    // Add a PRL with v6-only-preferred.
+    OptionUint8ArrayPtr prl(new OptionUint8Array(Option::V4,
+                                                 DHO_DHCP_PARAMETER_REQUEST_LIST));
+    ASSERT_TRUE(prl);
+    prl->addValue(DHO_V6_ONLY_PREFERRED);
+    dis->addOption(prl);
+
+    // No DHCPOFFER is returned.
+    EXPECT_FALSE(srv.processDiscover(dis));
+}
+
+// Verify that when request requesting v6-only-preferred 0.0.0.0 is offered
+// but the option is not added to the response is an error case.
+TEST_F(Dhcpv4SrvTest, v6OnlyPreferredRequestError) {
+    IfaceMgrTestConfig test_config(true);
+    IfaceMgr::instance().openSockets4();
+
+    NakedDhcpv4Srv srv(0);
+
+    // Recreate subnet.
+    Triplet<uint32_t> unspecified;
+    Triplet<uint32_t> valid_lft(500, 1000, 1500);
+    subnet_ = Subnet4::create(IOAddress("192.0.2.0"), 24,
+                              unspecified,
+                              unspecified,
+                              valid_lft,
+                              subnet_->getID());
+    // Add the v6-only-preferred option data.
+    const uint32_t v6only_wait(3600);
+    OptionUint32Ptr v6op_opt(new OptionUint32(Option::V4,
+                                              DHO_V6_ONLY_PREFERRED,
+                                              v6only_wait));
+    subnet_->getCfgOption()->add(v6op_opt, false, false, DHCP4_OPTION_SPACE);
+    CfgMgr::instance().clear();
+    CfgMgr::instance().getStagingCfg()->getCfgSubnets4()->add(subnet_);
+    // Cancel the v6-only-preferred option at the global level.
+    CfgMgr::instance().getStagingCfg()->getCfgOption()->
+        add(v6op_opt, false, true, DHCP4_OPTION_SPACE);
+    CfgMgr::instance().commit();
+
+    Pkt4Ptr req = Pkt4Ptr(new Pkt4(DHCPREQUEST, 1234));
+    req->setRemoteAddr(IOAddress("192.0.2.1"));
+    OptionPtr clientid = generateClientId();
+    req->addOption(clientid);
+    req->setIface("eth1");
+    req->setIndex(ETH1_INDEX);
+
+    // Add a PRL with v6-only-preferred.
+    OptionUint8ArrayPtr prl(new OptionUint8Array(Option::V4,
+                                                 DHO_DHCP_PARAMETER_REQUEST_LIST));
+    ASSERT_TRUE(prl);
+    prl->addValue(DHO_V6_ONLY_PREFERRED);
+    req->addOption(prl);
+
+    // No DHCPACK is returned.
+    EXPECT_FALSE(srv.processRequest(req));
+}
+
 /// @brief Test fixture for recoverStashedAgentOption.
 class StashAgentOptionTest : public Dhcpv4SrvTest {
 public: