|
@@ -47,10 +47,33 @@ using namespace std;
|
|
|
namespace isc {
|
|
|
namespace dhcp {
|
|
|
|
|
|
-ControlledDhcpv6Srv* ControlledDhcpv6Srv::server_ = NULL;
|
|
|
-
|
|
|
+/// @brief Helper session object that represents raw connection to msgq.
|
|
|
+isc::cc::Session* cc_session_ = NULL;
|
|
|
+
|
|
|
+/// @brief Session that receives configuration and commands
|
|
|
+isc::config::ModuleCCSession* config_session_ = NULL;
|
|
|
+
|
|
|
+/// @brief A dummy configuration handler that always returns success.
|
|
|
+///
|
|
|
+/// This configuration handler does not perform configuration
|
|
|
+/// parsing and always returns success. A dummy handler should
|
|
|
+/// be installed using \ref isc::config::ModuleCCSession ctor
|
|
|
+/// to get the initial configuration. This initial configuration
|
|
|
+/// comprises values for only those elements that were modified
|
|
|
+/// the previous session. The \ref dhcp6ConfigHandler can't be
|
|
|
+/// used to parse the initial configuration because it needs the
|
|
|
+/// full configuration to satisfy dependencies between the
|
|
|
+/// various configuration values. Installing the dummy handler
|
|
|
+/// that guarantees to return success causes initial configuration
|
|
|
+/// to be stored for the session being created and that it can
|
|
|
+/// be later accessed with
|
|
|
+/// \ref isc::config::ConfigData::getFullConfig().
|
|
|
+///
|
|
|
+/// @param new_config new configuration.
|
|
|
+///
|
|
|
+/// @return success configuration status.
|
|
|
ConstElementPtr
|
|
|
-ControlledDhcpv6Srv::dhcp6StubConfigHandler(ConstElementPtr) {
|
|
|
+dhcp6StubConfigHandler(ConstElementPtr) {
|
|
|
// This configuration handler is intended to be used only
|
|
|
// when the initial configuration comes in. To receive this
|
|
|
// configuration a pointer to this handler must be passed
|
|
@@ -65,9 +88,9 @@ ControlledDhcpv6Srv::dhcp6StubConfigHandler(ConstElementPtr) {
|
|
|
}
|
|
|
|
|
|
ConstElementPtr
|
|
|
-ControlledDhcpv6Srv::dhcp6ConfigHandler(ConstElementPtr new_config) {
|
|
|
+bundyConfigHandler(ConstElementPtr new_config) {
|
|
|
|
|
|
- if (!server_ || !server_->config_session_) {
|
|
|
+ if (!ControlledDhcpv6Srv::getInstance() || !config_session_) {
|
|
|
// That should never happen as we install config_handler
|
|
|
// after we instantiate the server.
|
|
|
ConstElementPtr answer =
|
|
@@ -91,7 +114,7 @@ ControlledDhcpv6Srv::dhcp6ConfigHandler(ConstElementPtr new_config) {
|
|
|
// Let's create a new object that will hold the merged configuration.
|
|
|
boost::shared_ptr<MapElement> merged_config(new MapElement());
|
|
|
// Let's get the existing configuration.
|
|
|
- ConstElementPtr full_config = server_->config_session_->getFullConfig();
|
|
|
+ ConstElementPtr full_config = config_session_->getFullConfig();
|
|
|
// The full_config and merged_config should be always non-NULL
|
|
|
// but to provide some level of exception safety we check that they
|
|
|
// really are (in case we go out of memory).
|
|
@@ -105,92 +128,14 @@ ControlledDhcpv6Srv::dhcp6ConfigHandler(ConstElementPtr new_config) {
|
|
|
}
|
|
|
|
|
|
// Configure the server.
|
|
|
- ConstElementPtr answer = configureDhcp6Server(*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);
|
|
|
- }
|
|
|
-
|
|
|
- // Server will start DDNS communications if its enabled.
|
|
|
- try {
|
|
|
- server_->startD2();
|
|
|
- } catch (const std::exception& ex) {
|
|
|
- std::ostringstream err;
|
|
|
- err << "error starting DHCP_DDNS client "
|
|
|
- " after server reconfiguration: " << ex.what();
|
|
|
- return (isc::config::createAnswer(1, err.str()));
|
|
|
- }
|
|
|
|
|
|
- // 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());
|
|
|
- } catch (const 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);
|
|
|
+ return (ControlledDhcpv6Srv::processConfig(merged_config));
|
|
|
}
|
|
|
|
|
|
-ConstElementPtr
|
|
|
-ControlledDhcpv6Srv::dhcp6CommandHandler(const string& command, ConstElementPtr args) {
|
|
|
- LOG_DEBUG(dhcp6_logger, DBG_DHCP6_COMMAND, DHCP6_COMMAND_RECEIVED)
|
|
|
- .arg(command).arg(args->str());
|
|
|
-
|
|
|
- if (command == "shutdown") {
|
|
|
- if (ControlledDhcpv6Srv::server_) {
|
|
|
- ControlledDhcpv6Srv::server_->shutdown();
|
|
|
- } else {
|
|
|
- LOG_WARN(dhcp6_logger, DHCP6_NOT_RUNNING);
|
|
|
- ConstElementPtr answer = isc::config::createAnswer(1,
|
|
|
- "Shutdown failure.");
|
|
|
- return (answer);
|
|
|
- }
|
|
|
- ConstElementPtr answer = isc::config::createAnswer(0,
|
|
|
- "Shutting down.");
|
|
|
- return (answer);
|
|
|
-
|
|
|
- } else if (command == "libreload") {
|
|
|
- // TODO delete any stored CalloutHandles referring to the old libraries
|
|
|
- // Get list of currently loaded libraries and reload them.
|
|
|
- vector<string> loaded = HooksManager::getLibraryNames();
|
|
|
- bool status = HooksManager::loadLibraries(loaded);
|
|
|
- if (!status) {
|
|
|
- LOG_ERROR(dhcp6_logger, DHCP6_HOOKS_LIBS_RELOAD_FAIL);
|
|
|
- ConstElementPtr answer = isc::config::createAnswer(1,
|
|
|
- "Failed to reload hooks libraries.");
|
|
|
- return (answer);
|
|
|
- }
|
|
|
- ConstElementPtr answer = isc::config::createAnswer(0,
|
|
|
- "Hooks libraries successfully reloaded.");
|
|
|
- return (answer);
|
|
|
- }
|
|
|
-
|
|
|
- ConstElementPtr answer = isc::config::createAnswer(1,
|
|
|
- "Unrecognized command.");
|
|
|
-
|
|
|
- return (answer);
|
|
|
-}
|
|
|
-
|
|
|
-void ControlledDhcpv6Srv::sessionReader(void) {
|
|
|
- // Process one asio event. If there are more events, iface_mgr will call
|
|
|
- // this callback more than once.
|
|
|
- if (server_) {
|
|
|
- server_->io_service_.run_one();
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
bool
|
|
|
ControlledDhcpv6Srv::init(const std::string& /* config_file*/) {
|
|
|
- // This is BIND10 configuration backed. It established control session
|
|
|
- // that is used to connect to BIND10 framework.
|
|
|
+ // This is Bundy configuration backed. It established control session
|
|
|
+ // that is used to connect to Bundy framework.
|
|
|
//
|
|
|
// Creates session that will be used to receive commands and updated
|
|
|
// configuration from cfgmgr (or indirectly from user via bindctl).
|
|
@@ -217,18 +162,18 @@ ControlledDhcpv6Srv::init(const std::string& /* config_file*/) {
|
|
|
// been lost.
|
|
|
config_session_ = new ModuleCCSession(specfile, *cc_session_,
|
|
|
dhcp6StubConfigHandler,
|
|
|
- dhcp6CommandHandler, false);
|
|
|
+ processCommand, false);
|
|
|
config_session_->start();
|
|
|
|
|
|
// The constructor already pulled the configuration that had
|
|
|
// been created in the previous session thanks to the dummy
|
|
|
// handler. We can switch to the handler that will be
|
|
|
// parsing future changes to the configuration.
|
|
|
- config_session_->setConfigHandler(dhcp6ConfigHandler);
|
|
|
+ config_session_->setConfigHandler(bundyConfigHandler);
|
|
|
|
|
|
try {
|
|
|
// Pull the full configuration out from the session.
|
|
|
- configureDhcp6Server(*this, config_session_->getFullConfig());
|
|
|
+ processConfig(config_session_->getFullConfig());
|
|
|
|
|
|
// Server will start DDNS communications if its enabled.
|
|
|
server_->startD2();
|
|
@@ -242,7 +187,7 @@ ControlledDhcpv6Srv::init(const std::string& /* config_file*/) {
|
|
|
|
|
|
}
|
|
|
|
|
|
- /// Integrate the asynchronous I/O model of BIND 10 configuration
|
|
|
+ /// Integrate the asynchronous I/O model of Bundy configuration
|
|
|
/// control with the "select" model of the DHCP server. This is
|
|
|
/// fully explained in \ref dhcpv6Session.
|
|
|
int ctrl_socket = cc_session_->getSocketDesc();
|
|
@@ -271,34 +216,6 @@ void ControlledDhcpv6Srv::cleanup() {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-ControlledDhcpv6Srv::ControlledDhcpv6Srv(uint16_t port)
|
|
|
- : Dhcpv6Srv(port), cc_session_(NULL), config_session_(NULL) {
|
|
|
- server_ = this; // remember this instance for use in callback
|
|
|
-}
|
|
|
-
|
|
|
-void ControlledDhcpv6Srv::shutdown() {
|
|
|
- io_service_.stop(); // Stop ASIO transmissions
|
|
|
- Dhcpv6Srv::shutdown(); // Initiate DHCPv6 shutdown procedure.
|
|
|
-}
|
|
|
-
|
|
|
-ControlledDhcpv6Srv::~ControlledDhcpv6Srv() {
|
|
|
- cleanup();
|
|
|
-
|
|
|
- server_ = NULL; // forget this instance. There should be no callback anymore
|
|
|
- // at this stage anyway.
|
|
|
-}
|
|
|
-
|
|
|
-isc::data::ConstElementPtr
|
|
|
-ControlledDhcpv6Srv::execDhcpv6ServerCommand(const std::string& command_id,
|
|
|
- isc::data::ConstElementPtr args) {
|
|
|
- try {
|
|
|
- return (dhcp6CommandHandler(command_id, args));
|
|
|
- } catch (const Exception& ex) {
|
|
|
- ConstElementPtr answer = isc::config::createAnswer(1, ex.what());
|
|
|
- return (answer);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
void
|
|
|
Daemon::loggerInit(const char* log_name, bool verbose, bool stand_alone) {
|
|
|
isc::log::initLogger(log_name,
|
|
@@ -306,5 +223,5 @@ Daemon::loggerInit(const char* log_name, bool verbose, bool stand_alone) {
|
|
|
isc::log::MAX_DEBUG_LEVEL, NULL, !stand_alone);
|
|
|
}
|
|
|
|
|
|
-};
|
|
|
-};
|
|
|
+}; // end of isc::dhcp namespace
|
|
|
+}; // end of isc namespace
|