]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#4424] Fixed the compliance bug
authorFrancis Dupont <fdupont@isc.org>
Mon, 6 Jul 2026 08:14:20 +0000 (10:14 +0200)
committerFrancis Dupont <fdupont@isc.org>
Wed, 15 Jul 2026 13:47:27 +0000 (15:47 +0200)
changelog_unreleased/4424-dhcpnak-broadcast-bit-relayed-dhcprequest [new file with mode: 0644]
src/bin/dhcp4/dhcp4_srv.cc
src/bin/dhcp4/tests/dora_unittest.cc

diff --git a/changelog_unreleased/4424-dhcpnak-broadcast-bit-relayed-dhcprequest b/changelog_unreleased/4424-dhcpnak-broadcast-bit-relayed-dhcprequest
new file mode 100644 (file)
index 0000000..87c4762
--- /dev/null
@@ -0,0 +1,4 @@
+[bug]          fdupont
+       Set the broadcast flag in DHCPNAK responses to relayed
+       DHCPREQUEST queries as required by RFC 2131 4.3.2.
+       (Gitlab #4424)
index e2de71c907e187b6bc23e8ac9cca9c17cfebb43d..36ba1c346f3e1bed62278bab94815b4ca81c4704 100644 (file)
@@ -3787,6 +3787,14 @@ Dhcpv4Srv::adjustRemoteAddr(Dhcpv4Exchange& ex) {
             query->getCiaddr().isV4Zero()) {
             response->setFlags(BOOTP_BROADCAST);
         }
+        // DHCPNAK to a client on a different subnet: the client may not
+        // have a correct network address or subnet mask, and may not be
+        // answering ARP requests, so set the broadcast bit to amke the
+        // relay to broadcast the DHCPNAK to the client.
+        if ((query->getType() == DHCPREQUEST) &&
+            (response->getType() == DHCPNAK)) {
+            response->setFlags(BOOTP_BROADCAST);
+        }
         response->setRemoteAddr(query->getGiaddr());
 
     // If giaddr is 0 but client set ciaddr, server should unicast the
index 7cd739cf2b799bfaa6b1f9588d0fee1b54b13e0c..fc8c1ef1efa374792b64f8b3131fa64ee700ab14 100644 (file)
@@ -1536,6 +1536,9 @@ DORATest::authoritativeSubnetSelectionFail() {
     auto resp = client.getContext().response_;
     ASSERT_TRUE(resp);
     EXPECT_EQ(DHCPNAK, static_cast<int>(resp->getType()));
+    // The DHCPNAK is relayed and its broadcast flag is set.
+    EXPECT_TRUE(resp->isRelayed());
+    EXPECT_EQ(BOOTP_BROADCAST, resp->getFlags());
 }
 
 TEST_F(DORATest, authoritativeSubnetSelectionFail) {