BIND 10 trac1555, updated. 0a5d26dfc2ee6a4a84d596cbcb39e894e7432f3c [1555] Reopen active sockets when configuration changes.

BIND 10 source code commits bind10-changes at lists.isc.org
Thu Jul 11 11:31:19 UTC 2013


The branch, trac1555 has been updated
       via  0a5d26dfc2ee6a4a84d596cbcb39e894e7432f3c (commit)
      from  9517e24b3bc274e4a8f080cb15358db8017c3f44 (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 0a5d26dfc2ee6a4a84d596cbcb39e894e7432f3c
Author: Marcin Siodelski <marcin at isc.org>
Date:   Thu Jul 11 13:31:01 2013 +0200

    [1555] Reopen active sockets when configuration changes.

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

Summary of changes:
 src/bin/dhcp4/ctrl_dhcp4_srv.cc |   46 ++++++++++++++++++++++++++++++++++++---
 src/bin/dhcp4/ctrl_dhcp4_srv.h  |   11 ++++++++++
 src/bin/dhcp4/dhcp4_srv.cc      |    5 +++--
 src/bin/dhcp4/dhcp4_srv.h       |   29 ++++++++++++++++++++++++
 src/lib/dhcp/iface_mgr.cc       |    9 +++++---
 src/lib/dhcp/iface_mgr.h        |    4 ++++
 6 files changed, 96 insertions(+), 8 deletions(-)

-----------------------------------------------------------------------
diff --git a/src/bin/dhcp4/ctrl_dhcp4_srv.cc b/src/bin/dhcp4/ctrl_dhcp4_srv.cc
index eb7d559..9050a16 100644
--- a/src/bin/dhcp4/ctrl_dhcp4_srv.cc
+++ b/src/bin/dhcp4/ctrl_dhcp4_srv.cc
@@ -20,17 +20,18 @@
 #include <config/ccsession.h>
 #include <dhcp/iface_mgr.h>
 #include <dhcpsrv/dhcp_config_parser.h>
+#include <dhcpsrv/cfgmgr.h>
 #include <dhcp4/ctrl_dhcp4_srv.h>
 #include <dhcp4/dhcp4_log.h>
 #include <dhcp4/spec_config.h>
 #include <dhcp4/config_parser.h>
 #include <exceptions/exceptions.h>
+#include <boost/bind.hpp>
 #include <util/buffer.h>
-#include <cassert>
-#include <iostream>
 
 #include <cassert>
 #include <iostream>
+#include <sstream>
 
 using namespace isc::asiolink;
 using namespace isc::cc;
@@ -101,7 +102,27 @@ ControlledDhcpv4Srv::dhcp4ConfigHandler(ConstElementPtr new_config) {
     }
 
     // Configure the server.
-    return (configureDhcp4Server(*server_, merged_config));
+    ConstElementPtr answer = configureDhcp4Server(*server_, merged_config);
+
+    // Check that configuration was successful. If not, do not reopen sockets.
+    int rcode = 0;
+    parseAnswer(rcode, answer);
+    if (rcode != 0) {
+        return (answer);
+    }
+
+    // Configuration may change active interfaces. Therefore, we have to reopen
+    // sockets according to new configuration. This operation is not exception
+    // safe and we really don't want to emit exceptions to the callback caller.
+    // Instead, catch an exception and create appropriate answer.
+    try {
+        server_->openActiveSockets(server_->getPort(), server_->useBroadcast());
+    } catch (std::exception& ex) {
+        std::ostringstream err;
+        err << "failed to open sockets after server reconfiguration: " << ex.what();
+        answer = isc::config::createAnswer(1, err.str());
+    }
+    return (answer);
 }
 
 ConstElementPtr
@@ -228,6 +249,25 @@ ControlledDhcpv4Srv::execDhcpv4ServerCommand(const std::string& command_id,
     }
 }
 
+void
+ControlledDhcpv4Srv::openActiveSockets(const uint16_t port, const bool use_bcast) {
+    IfaceMgr::instance().closeSockets();
+
+    // Get the reference to the collection of interfaces. This reference should be
+    // valid as long as the program is run because IfaceMgr is a singleton.
+    // Therefore we can safely iterate over instances of all interfaces and modify
+    // their flags. Here we modify flags which indicate wheter socket should be
+    // open for a particular interface or not.
+    IfaceMgr::IfaceCollection ifaces = IfaceMgr::instance().getIfaces();
+    for (IfaceMgr::IfaceCollection::iterator iface = ifaces.begin();
+         iface != ifaces.end(); ++iface) {
+        iface->inactive_ = !CfgMgr::instance().isActiveIface(iface->getName());
+    }
+    // Let's reopen active sockets. openSockets4 will check internally whether
+    // sockets are marked active or inactive.
+    IfaceMgr::instance().openSockets4(port, use_bcast);
+}
+
 
 };
 };
diff --git a/src/bin/dhcp4/ctrl_dhcp4_srv.h b/src/bin/dhcp4/ctrl_dhcp4_srv.h
index 8f14f4b..e5104b5 100644
--- a/src/bin/dhcp4/ctrl_dhcp4_srv.h
+++ b/src/bin/dhcp4/ctrl_dhcp4_srv.h
@@ -130,6 +130,17 @@ protected:
     /// when there is a new command or configuration sent over msgq.
     static void sessionReader(void);
 
+    /// @brief Open sockets which are marked as active in @c CfgMgr.
+    ///
+    /// This function reopens sockets according to the current settings in the
+    /// Configuration Manager. It holds the list of the interfaces which server
+    /// should listen on. This function will open sockets on these interfaces
+    /// only. This function is not exception safe.
+    ///
+    /// @param port UDP port on which server should listen.
+    /// @param use_bcast should broadcast flags be set on the sockets.
+    static void openActiveSockets(const uint16_t port, const bool use_bcast);
+
     /// @brief IOService object, used for all ASIO operations.
     isc::asiolink::IOService io_service_;
 
diff --git a/src/bin/dhcp4/dhcp4_srv.cc b/src/bin/dhcp4/dhcp4_srv.cc
index 8aa913c..f414e5a 100644
--- a/src/bin/dhcp4/dhcp4_srv.cc
+++ b/src/bin/dhcp4/dhcp4_srv.cc
@@ -58,7 +58,8 @@ static const char* SERVER_ID_FILE = "b10-dhcp4-serverid";
 // grants those options and a single, fixed, hardcoded lease.
 
 Dhcpv4Srv::Dhcpv4Srv(uint16_t port, const char* dbconfig, const bool use_bcast,
-                     const bool direct_response_desired) {
+                     const bool direct_response_desired)
+    : port_(port), use_bcast_(use_bcast) {
     LOG_DEBUG(dhcp4_logger, DBG_DHCP4_START, DHCP4_OPEN_SOCKET).arg(port);
     try {
         // First call to instance() will create IfaceMgr (it's a singleton)
@@ -73,7 +74,7 @@ Dhcpv4Srv::Dhcpv4Srv(uint16_t port, const char* dbconfig, const bool use_bcast,
         if (port) {
             // open sockets only if port is non-zero. Port 0 is used
             // for non-socket related testing.
-            IfaceMgr::instance().openSockets4(port, use_bcast);
+            IfaceMgr::instance().openSockets4(port_, use_bcast_);
         }
 
         string srvid_file = CfgMgr::instance().getDataDir() + "/" + string(SERVER_ID_FILE);
diff --git a/src/bin/dhcp4/dhcp4_srv.h b/src/bin/dhcp4/dhcp4_srv.h
index f98233c..59bb95c 100644
--- a/src/bin/dhcp4/dhcp4_srv.h
+++ b/src/bin/dhcp4/dhcp4_srv.h
@@ -113,6 +113,32 @@ public:
     ///         be freed by the caller.
     static const char* serverReceivedPacketName(uint8_t type);
 
+    ///
+    /// @name Public accessors returning values required to (re)open sockets.
+    ///
+    /// These accessors must be public because sockets are reopened from the
+    /// static configuration callback handler. This callback handler invokes
+    /// @c ControlledDhcpv4Srv::openActiveSockets which requires parameters
+    /// which has to be retrieved from the @c ControlledDhcpv4Srv object.
+    /// They are retrieved using these public functions
+    //@{
+    ///
+    /// @brief Get UDP port on which server should listen.
+    ///
+    /// @return UDP port on which server should listen.
+    uint16_t getPort() const {
+        return (port_);
+    }
+
+    /// @brief Return bool value indicating that broadcast flags should be set
+    /// on sockets.
+    ///
+    /// @return A bool value indicating that broadcast should be used (if true).
+    bool useBroadcast() const {
+        return (use_bcast_);
+    }
+    //@}
+
 protected:
 
     /// @brief verifies if specified packet meets RFC requirements
@@ -310,6 +336,9 @@ private:
     /// during normal operation (e.g. to use different allocators)
     boost::shared_ptr<AllocEngine> alloc_engine_;
 
+    uint16_t port_;  ///< UDP port number on which server listens.
+    bool use_bcast_; ///< Should broadcast be enabled on sockets (if true).
+
 };
 
 }; // namespace isc::dhcp
diff --git a/src/lib/dhcp/iface_mgr.cc b/src/lib/dhcp/iface_mgr.cc
index 1e97205..dfe0f36 100644
--- a/src/lib/dhcp/iface_mgr.cc
+++ b/src/lib/dhcp/iface_mgr.cc
@@ -51,7 +51,8 @@ IfaceMgr::instance() {
 Iface::Iface(const std::string& name, int ifindex)
     :name_(name), ifindex_(ifindex), mac_len_(0), hardware_type_(0),
      flag_loopback_(false), flag_up_(false), flag_running_(false),
-     flag_multicast_(false), flag_broadcast_(false), flags_(0)
+     flag_multicast_(false), flag_broadcast_(false), flags_(0),
+     inactive_(false)
 {
     memset(mac_, 0, sizeof(mac_));
 }
@@ -295,7 +296,8 @@ bool IfaceMgr::openSockets4(const uint16_t port, const bool use_bcast) {
 
         if (iface->flag_loopback_ ||
             !iface->flag_up_ ||
-            !iface->flag_running_) {
+            !iface->flag_running_,
+            iface->inactive_) {
             continue;
         }
 
@@ -361,7 +363,8 @@ bool IfaceMgr::openSockets6(const uint16_t port) {
 
         if (iface->flag_loopback_ ||
             !iface->flag_up_ ||
-            !iface->flag_running_) {
+            !iface->flag_running_,
+            !iface->inactive_) {
             continue;
         }
 
diff --git a/src/lib/dhcp/iface_mgr.h b/src/lib/dhcp/iface_mgr.h
index 35b4dc0..442107d 100644
--- a/src/lib/dhcp/iface_mgr.h
+++ b/src/lib/dhcp/iface_mgr.h
@@ -309,6 +309,10 @@ public:
     /// Interface flags (this value is as is returned by OS,
     /// it may mean different things on different OSes).
     uint32_t flags_;
+
+    /// Interface is inactive. This can be explicitly set to prevent Interface
+    /// Manager from opening the socket on this interface.
+    bool inactive_;
 };
 
 /// @brief Handles network interfaces, transmission and reception.



More information about the bind10-changes mailing list