From: Francis Dupont Date: Mon, 6 Jul 2026 08:14:20 +0000 (+0200) Subject: [#4424] Fixed the compliance bug X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e4da878e47d6b08b2d328d9c3803a8faf6975ee7;p=thirdparty%2Fkea.git [#4424] Fixed the compliance bug --- diff --git a/changelog_unreleased/4424-dhcpnak-broadcast-bit-relayed-dhcprequest b/changelog_unreleased/4424-dhcpnak-broadcast-bit-relayed-dhcprequest new file mode 100644 index 0000000000..87c476272b --- /dev/null +++ b/changelog_unreleased/4424-dhcpnak-broadcast-bit-relayed-dhcprequest @@ -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) diff --git a/src/bin/dhcp4/dhcp4_srv.cc b/src/bin/dhcp4/dhcp4_srv.cc index e2de71c907..36ba1c346f 100644 --- a/src/bin/dhcp4/dhcp4_srv.cc +++ b/src/bin/dhcp4/dhcp4_srv.cc @@ -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 diff --git a/src/bin/dhcp4/tests/dora_unittest.cc b/src/bin/dhcp4/tests/dora_unittest.cc index 7cd739cf2b..fc8c1ef1ef 100644 --- a/src/bin/dhcp4/tests/dora_unittest.cc +++ b/src/bin/dhcp4/tests/dora_unittest.cc @@ -1536,6 +1536,9 @@ DORATest::authoritativeSubnetSelectionFail() { auto resp = client.getContext().response_; ASSERT_TRUE(resp); EXPECT_EQ(DHCPNAK, static_cast(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) {