BIND 10 trac2902, updated. 85d28a85b04c5c6a6905c6e018dc9a899afc4494 [2902] Do not allow to set new packet filter when there are sockets open.

BIND 10 source code commits bind10-changes at lists.isc.org
Fri Apr 26 14:49:17 UTC 2013


The branch, trac2902 has been updated
       via  85d28a85b04c5c6a6905c6e018dc9a899afc4494 (commit)
      from  80f01bc608cbd779c76a6e5d5ca8dade8b37dbdd (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 85d28a85b04c5c6a6905c6e018dc9a899afc4494
Author: Marcin Siodelski <marcin at isc.org>
Date:   Fri Apr 26 16:48:59 2013 +0200

    [2902] Do not allow to set new packet filter when there are sockets open.

-----------------------------------------------------------------------

Summary of changes:
 src/lib/dhcp/iface_mgr.cc                |   30 ++++++++++++++++++++++++++++++
 src/lib/dhcp/iface_mgr.h                 |   19 ++++++++++++-------
 src/lib/dhcp/tests/iface_mgr_unittest.cc |   29 +++++++++++++++++++++--------
 3 files changed, 63 insertions(+), 15 deletions(-)

-----------------------------------------------------------------------
diff --git a/src/lib/dhcp/iface_mgr.cc b/src/lib/dhcp/iface_mgr.cc
index b5c155b..93e6205 100644
--- a/src/lib/dhcp/iface_mgr.cc
+++ b/src/lib/dhcp/iface_mgr.cc
@@ -203,6 +203,36 @@ IfaceMgr::isDirectResponseSupported() const {
     return (packet_filter_->isDirectResponseSupported());
 }
 
+void
+IfaceMgr::setPacketFilter(const boost::shared_ptr<PktFilter>& packet_filter) {
+    // Do not allow NULL pointer.
+    if (!packet_filter) {
+        isc_throw(InvalidPacketFilter, "NULL packet filter object specified");
+    }
+    // Different packet filters use different socket types. It does not make
+    // sense to allow the change of packet filter when there are IPv4 sockets
+    // open because they can't be used by the receive/send functions of the
+    // new packet filter. Below, we check that there are no open IPv4 sockets.
+    // If we find at least one, we have to fail. However, caller still has a
+    // chance to replace the packet filter if he closes sockets explicitly.
+    for (IfaceCollection::const_iterator iface = ifaces_.begin();
+         iface != ifaces_.end(); ++iface) {
+        const Iface::SocketCollection& sockets = iface->getSockets();
+        for (Iface::SocketCollection::const_iterator sock = sockets.begin();
+             sock != sockets.end(); ++sock) {
+            // There is at least one socket open, so we have to fail.
+            if (sock->family_ == AF_INET) {
+                isc_throw(PacketFilterChangeDenied, "it is not allowed to set new packet"
+                          << " filter when there are open IPv4 sockets - need"
+                          << " to close them first");
+            }
+        }
+    }
+    // Everything is fine, so replace packet filter.
+    packet_filter_ = packet_filter;
+}
+
+
 void IfaceMgr::stubDetectIfaces() {
     string ifaceName;
     const string v4addr("127.0.0.1"), v6addr("::1");
diff --git a/src/lib/dhcp/iface_mgr.h b/src/lib/dhcp/iface_mgr.h
index 7dd8bac..6eb9740 100644
--- a/src/lib/dhcp/iface_mgr.h
+++ b/src/lib/dhcp/iface_mgr.h
@@ -39,6 +39,13 @@ public:
         isc::Exception(file, line, what) { };
 };
 
+/// @brief Exception thrown when it is not allowed to set new Packet Filter.
+class PacketFilterChangeDenied : public Exception {
+public:
+    PacketFilterChangeDenied(const char* file, size_t line, const char* what) :
+        isc::Exception(file, line, what) { };
+};
+
 /// @brief IfaceMgr exception thrown thrown when socket opening
 /// or configuration failed.
 class SocketConfigError : public Exception {
@@ -602,18 +609,16 @@ public:
     /// Packet Filters expose low-level functions handling sockets opening
     /// and sending/receiving packets through those sockets. This function
     /// sets custom Packet Filter (represented by a class derived from PktFilter)
-    /// to be used by IfaceMgr.
+    /// to be used by IfaceMgr. Note that, there must be no IPv4 sockets
+    /// when this function is called. Call closeSockets(AF_INET) to close
+    /// all hanging IPv4 sockets opened by the current packet filter object.
     ///
     /// @param packet_filter new packet filter to be used by IfaceMgr to send/receive
     /// packets and open sockets.
     ///
     /// @throw InvalidPacketFilter if provided packet filter object is NULL.
-    void setPacketFilter(const boost::shared_ptr<PktFilter>& packet_filter) {
-        if (!packet_filter) {
-            isc_throw(InvalidPacketFilter, "NULL packet filter object specified");
-        }
-        packet_filter_ = packet_filter;
-    }
+    /// @throw PacketFilterChangeDenied if there are open IPv4 sockets
+    void setPacketFilter(const boost::shared_ptr<PktFilter>& packet_filter);
 
     /// @brief Set Packet Filter object to handle send/receive packets.
     ///
diff --git a/src/lib/dhcp/tests/iface_mgr_unittest.cc b/src/lib/dhcp/tests/iface_mgr_unittest.cc
index e2e5191..89a2110 100644
--- a/src/lib/dhcp/tests/iface_mgr_unittest.cc
+++ b/src/lib/dhcp/tests/iface_mgr_unittest.cc
@@ -689,19 +689,23 @@ TEST_F(IfaceMgrTest, socketsFromRemoteAddress) {
     // open sockets on the same ports.
     ifacemgr->closeSockets();
 
-    // The following test is currently disabled for OSes other than
-    // Linux because interface detection is not implemented on them.
-    // @todo enable this test for all OSes once interface detection
-    // is implemented.
-#if defined(OS_LINUX)
+    // The check below has been commented out. It verified the ability
+    // to open suitable socket for sending broadcast request. However,
+    // there is no guarantee for such test to work on all systems
+    // because some systems may have no broadcast capable interfaces at all.
+
+/* #if defined(OS_LINUX)
     // Open v4 socket to connect to broadcast address.
     int socket3  = 0;
     IOAddress bcastAddr("255.255.255.255");
-    EXPECT_NO_THROW(
+    try {
         socket3 = ifacemgr->openSocketFromRemoteAddress(bcastAddr, PORT2);
-    );
+    } catch (const Exception& ex) {
+        std::cout << ex.what() << std::endl;
+        FAIL();
+    }
     EXPECT_GT(socket3, 0);
-#endif
+#endif */
 
     // Do not call closeSockets() because it is called by IfaceMgr's
     // virtual destructor.
@@ -919,6 +923,15 @@ TEST_F(IfaceMgrTest, setPacketFilter) {
     EXPECT_TRUE(custom_packet_filter->open_socket_called_);
     // This function always returns fake socket descriptor equal to 1024.
     EXPECT_EQ(1024, socket1);
+
+    // Replacing current packet filter object while there are IPv4
+    // sockets open is not allowed!
+    EXPECT_THROW(iface_mgr->setPacketFilter(custom_packet_filter),
+                 PacketFilterChangeDenied);
+
+    // So, let's close the open IPv4 sockets and retry. Now it should succeed.
+    iface_mgr->closeSockets(AF_INET);
+    EXPECT_NO_THROW(iface_mgr->setPacketFilter(custom_packet_filter));
 }
 
 #if defined OS_LINUX



More information about the bind10-changes mailing list