From: Tomek Mrugalski Date: Wed, 21 May 2014 14:16:41 +0000 (+0200) Subject: [3399] Missign ctrl_dhcp4_srv.cc added. X-Git-Tag: trac3434_base~15^2~12 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=ab261756804b4f358bdee6fcae13f7d4d9347dda;p=thirdparty%2Fkea.git [3399] Missign ctrl_dhcp4_srv.cc added. --- diff --git a/src/bin/dhcp4/ctrl_dhcp4_srv.cc b/src/bin/dhcp4/ctrl_dhcp4_srv.cc new file mode 100644 index 0000000000..083f7c25c7 --- /dev/null +++ b/src/bin/dhcp4/ctrl_dhcp4_srv.cc @@ -0,0 +1,183 @@ +// Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC") +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +// PERFORMANCE OF THIS SOFTWARE. + +#include +#include +#include +#include +#include +#include + +using namespace isc::data; +using namespace isc::hooks; +using namespace std; + +namespace isc { +namespace dhcp { + +ControlledDhcpv4Srv* ControlledDhcpv4Srv::server_ = NULL; + +ConstElementPtr +ControlledDhcpv4Srv::commandShutdownHandler(const string&, ConstElementPtr) { + if (ControlledDhcpv4Srv::server_) { + ControlledDhcpv4Srv::server_->shutdown(); + } else { + LOG_WARN(dhcp4_logger, DHCP4_NOT_RUNNING); + ConstElementPtr answer = isc::config::createAnswer(1, + "Shutdown failure."); + return (answer); + } + ConstElementPtr answer = isc::config::createAnswer(0, "Shutting down."); + return (answer); +} + +ConstElementPtr +ControlledDhcpv4Srv::commandLibReloadHandler(const string&, ConstElementPtr) { + + /// @todo delete any stored CalloutHandles referring to the old libraries + /// Get list of currently loaded libraries and reload them. + vector loaded = HooksManager::getLibraryNames(); + bool status = HooksManager::loadLibraries(loaded); + if (!status) { + LOG_ERROR(dhcp4_logger, DHCP4_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 +ControlledDhcpv4Srv::commandConfigReloadHandler(const string&, + ConstElementPtr args) { + return (processConfig(args)); +} + +ConstElementPtr +ControlledDhcpv4Srv::processCommand(const string& command, + ConstElementPtr args) { + LOG_DEBUG(dhcp4_logger, DBG_DHCP4_COMMAND, DHCP4_COMMAND_RECEIVED) + .arg(command).arg(args->str()); + + ControlledDhcpv4Srv* srv = ControlledDhcpv4Srv::getInstance(); + + if (!srv) { + ConstElementPtr no_srv = isc::config::createAnswer(1, + "Server object not initialized, can't process command '" + + command + "'."); + return (no_srv); + } + + try { + if (command == "shutdown") { + return (srv->commandShutdownHandler(command, args)); + + } else if (command == "libreload") { + return (srv->commandLibReloadHandler(command, args)); + + } else if (command == "config-reload") { + return (srv->commandConfigReloadHandler(command, args)); + + } + ConstElementPtr answer = isc::config::createAnswer(1, + "Unrecognized command:" + command); + return (answer); + } catch (const Exception& ex) { + return (isc::config::createAnswer(1, "Error while processing command '" + + command + "':" + ex.what())); + } +} + +isc::data::ConstElementPtr +ControlledDhcpv4Srv::processConfig(isc::data::ConstElementPtr config) { + ControlledDhcpv4Srv* srv = ControlledDhcpv4Srv::getInstance(); + + if (!srv) { + ConstElementPtr no_srv = isc::config::createAnswer(1, + "Server object not initialized, can't process config."); + return (no_srv); + } + + ConstElementPtr answer = configureDhcp4Server(*srv, config); + + // Check that configuration was successful. If not, do not reopen sockets + // and don't bother with DDNS stuff. + try { + int rcode = 0; + isc::config::parseAnswer(rcode, answer); + if (rcode != 0) { + return (answer); + } + } catch (const std::exception& ex) { + return (isc::config::createAnswer(1, "Failed to process configuration:" + + string(ex.what()))); + } + + // Server will start DDNS communications if its enabled. + try { + srv->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 { + srv->openActiveSockets(srv->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); +} + +ControlledDhcpv4Srv::ControlledDhcpv4Srv(uint16_t port /*= DHCP4_SERVER_PORT*/) + :Dhcpv4Srv(port) { + if (server_) { + isc_throw(InvalidOperation, + "There is another Dhcpv4Srv instance already."); + } + server_ = this; // remember this instance for use in callback +} + +void ControlledDhcpv4Srv::shutdown() { + io_service_.stop(); // Stop ASIO transmissions + Dhcpv4Srv::shutdown(); // Initiate DHCPv4 shutdown procedure. +} + +ControlledDhcpv4Srv::~ControlledDhcpv4Srv() { + cleanup(); + + server_ = NULL; // forget this instance. There should be no callback anymore + // at this stage anyway. +} + +void ControlledDhcpv4Srv::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(); + } +} + +}; // end of isc::dhcp namespace +}; // end of isc namespace