]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#4349] check for unicast in hasOpenSocket
authorRazvan Becheriu <razvan@isc.org>
Wed, 18 Feb 2026 15:12:23 +0000 (17:12 +0200)
committerRazvan Becheriu <razvan@isc.org>
Thu, 19 Feb 2026 18:34:51 +0000 (18:34 +0000)
src/lib/dhcp/iface_mgr.cc
src/lib/dhcp/iface_mgr.h
src/lib/dhcp/tests/iface_mgr_unittest.cc
src/lib/dhcpsrv/tests/cfg_iface_unittest.cc

index d2e0c02b492a2c96f5505fc5d4d295a790b07750..205217898bee23a129d3cedd5a8c2f02914cf5f9 100644 (file)
@@ -473,7 +473,7 @@ IfaceMgr::hasOpenSocket(const uint16_t family) const {
 }
 
 bool
-IfaceMgr::hasOpenSocket(const IOAddress& addr) const {
+IfaceMgr::hasOpenSocket(const IOAddress& addr, bool unicast) const {
     // Fast track for IPv4 using bound addresses.
     if (addr.isV4() && !bound_address_.empty()) {
         return (bound_address_.count(addr.toUint32()) != 0);
@@ -485,7 +485,7 @@ IfaceMgr::hasOpenSocket(const IOAddress& addr) const {
             // if address is unspecified (in6addr_any).
             if (sock.addr_ == addr) {
                 return (true);
-            } else if (sock.addr_.isV6Zero()) {
+            } else if (sock.addr_.isV6Zero() && !unicast) {
                 // Handle the case that the address is unspecified (any).
                 // This happens only with IPv6 so we do not check IPv4.
                 // In this case, we should check if the specified address
@@ -684,7 +684,7 @@ IfaceMgr::openSockets6(const uint16_t port,
             // address on BSD and Solaris on any interface, so we make sure that
             // that interface actually has opened sockets by checking the number
             // of sockets to be non zero.
-            if (!skip_opened || !IfaceMgr::hasOpenSocket(addr) ||
+            if (!skip_opened || !IfaceMgr::hasOpenSocket(addr, true) ||
                 !iface->getSockets().size()) {
                 try {
                     IfaceMgr::openSocket(iface->getName(), addr, port, false, false);
index c3fa432907871544ceb2b1d78345ab052c0b8d1b..71ac410c44516f77aeaa49b090ede92f9f0ea668 100644 (file)
@@ -1362,9 +1362,10 @@ public:
     /// specified link-local address and returns true.
     ///
     /// @param addr Address of the socket being searched.
+    /// @param unicast Flag which indicates if the address is unicast.
     ///
     /// @return true if there is a socket bound to the specified address.
-    bool hasOpenSocket(const isc::asiolink::IOAddress& addr) const;
+    bool hasOpenSocket(const isc::asiolink::IOAddress& addr, bool unicast = false) const;
 
     /// @brief Fetches the DHCPv4 packet queue manager
     ///
index 3e1a6c7ca3b4ee6923655647f58b7a8cc91a4f54..008f5434c6380e4392971f1990ab220ebe203c6a 100644 (file)
@@ -2653,6 +2653,9 @@ TEST_F(IfaceMgrTest, hasOpenSocketForAddress6) {
     ASSERT_TRUE(filter);
     ASSERT_NO_THROW(ifacemgr.setPacketFilter(filter));
 
+    ifacemgr.getIface("eth0")->addUnicast(IOAddress("2001:db8:1::1"));
+    ifacemgr.getIface("eth1")->addAddress(IOAddress("3001:db8:1::1"));
+
     // Simulate opening sockets using the dummy packet filter.
     bool success = false;
     ASSERT_NO_THROW(success = ifacemgr.openSockets6(DHCP6_SERVER_PORT));
@@ -2670,6 +2673,18 @@ TEST_F(IfaceMgrTest, hasOpenSocketForAddress6) {
     // for interfaces.
     EXPECT_TRUE(ifacemgr.hasOpenSocket(IOAddress("fe80::3a60:77ff:fed5:cdef")));
     EXPECT_TRUE(ifacemgr.hasOpenSocket(IOAddress("fe80::3a60:77ff:fed5:abcd")));
+    EXPECT_TRUE(ifacemgr.hasOpenSocket(IOAddress("2001:db8:1::1")));
+    EXPECT_TRUE(ifacemgr.hasOpenSocket(IOAddress("2001:db8:1::1"), true));
+    if (ifacemgr.hasOpenSocket(IOAddress("::"))) {
+        // On BSD binding is done using "::" when address is multicast which
+        // makes the address match interface address.
+        EXPECT_TRUE(ifacemgr.hasOpenSocket(IOAddress("3001:db8:1::1")));
+    } else {
+        // On Linux binding is done using link-local and all-servers address
+        // when address is multicast.
+        EXPECT_FALSE(ifacemgr.hasOpenSocket(IOAddress("3001:db8:1::1")));
+    }
+    EXPECT_FALSE(ifacemgr.hasOpenSocket(IOAddress("3001:db8:1::1"), true));
     // Check that there is no socket bound to the address which hasn't been
     // configured on any interface.
     EXPECT_FALSE(ifacemgr.hasOpenSocket(IOAddress("fe80::3a60:77ff:feed:1")));
index f0e1d0f158231d7dba9cc6de05308122c6154076..b133b005190f32f363b4738d855e38031fd0b2cd 100644 (file)
@@ -1180,7 +1180,7 @@ TEST_F(CfgIfaceTest, retryOpenServiceSockets6OmitNewInterfaces) {
 #if defined OS_LINUX
     const uint32_t opened_by_eth0 = 3;
 #else
-    const uint32_t opened_by_eth0 = 1;
+    const uint32_t opened_by_eth0 = 2;
 #endif
 
 #if defined OS_LINUX