summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrancis Dupont <fdupont@isc.org>2024-06-30 15:31:39 +0200
committerFrancis Dupont <fdupont@isc.org>2024-07-18 14:45:25 +0200
commit0975949b9cf133dadd2cff9e5539c973df8bb962 (patch)
tree9c5eab5fe68e1489c3a466a179973f36534890ed
parent[#3094] Checkpoint: added UTs, doc to do (diff)
downloadkea-0975949b9cf133dadd2cff9e5539c973df8bb962.tar.xz
kea-0975949b9cf133dadd2cff9e5539c973df8bb962.zip
[#3094] Finished tests and doc
-rw-r--r--ChangeLog5
-rw-r--r--doc/sphinx/arm/dhcp4-srv.rst13
-rw-r--r--src/bin/dhcp4/dhcp4_srv.cc2
-rw-r--r--src/bin/dhcp4/tests/dhcp4_srv_unittest.cc94
4 files changed, 113 insertions, 1 deletions
diff --git a/ChangeLog b/ChangeLog
index 6f57e2836d..62ea1d562f 100644
--- 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
diff --git a/doc/sphinx/arm/dhcp4-srv.rst b/doc/sphinx/arm/dhcp4-srv.rst
index d47f55c866..3ceed35c02 100644
--- a/doc/sphinx/arm/dhcp4-srv.rst
+++ b/doc/sphinx/arm/dhcp4-srv.rst
@@ -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
diff --git a/src/bin/dhcp4/dhcp4_srv.cc b/src/bin/dhcp4/dhcp4_srv.cc
index b47cc74c01..88a928d1eb 100644
--- a/src/bin/dhcp4/dhcp4_srv.cc
+++ b/src/bin/dhcp4/dhcp4_srv.cc
@@ -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());
}
diff --git a/src/bin/dhcp4/tests/dhcp4_srv_unittest.cc b/src/bin/dhcp4/tests/dhcp4_srv_unittest.cc
index 02c8e9d51f..f9a193aa05 100644
--- a/src/bin/dhcp4/tests/dhcp4_srv_unittest.cc
+++ b/src/bin/dhcp4/tests/dhcp4_srv_unittest.cc
@@ -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: