ctrl_dhcp6_srv.cc 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. // Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // Permission to use, copy, modify, and/or distribute this software for any
  4. // purpose with or without fee is hereby granted, provided that the above
  5. // copyright notice and this permission notice appear in all copies.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  8. // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  9. // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  10. // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  11. // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  12. // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  13. // PERFORMANCE OF THIS SOFTWARE.
  14. #include <config.h>
  15. #include <asiolink/asiolink.h>
  16. #include <cc/data.h>
  17. #include <cc/session.h>
  18. #include <config/ccsession.h>
  19. #include <dhcp/iface_mgr.h>
  20. #include <dhcpsrv/dhcp_config_parser.h>
  21. #include <dhcp6/config_parser.h>
  22. #include <dhcp6/ctrl_dhcp6_srv.h>
  23. #include <dhcp6/dhcp6_log.h>
  24. #include <dhcp6/spec_config.h>
  25. #include <exceptions/exceptions.h>
  26. #include <util/buffer.h>
  27. #include <cassert>
  28. #include <iostream>
  29. using namespace isc::asiolink;
  30. using namespace isc::cc;
  31. using namespace isc::config;
  32. using namespace isc::data;
  33. using namespace isc::dhcp;
  34. using namespace isc::log;
  35. using namespace isc::util;
  36. using namespace std;
  37. namespace isc {
  38. namespace dhcp {
  39. ControlledDhcpv6Srv* ControlledDhcpv6Srv::server_ = NULL;
  40. ConstElementPtr
  41. ControlledDhcpv6Srv::dhcp6ConfigHandler(ConstElementPtr new_config) {
  42. LOG_DEBUG(dhcp6_logger, DBG_DHCP6_COMMAND, DHCP6_CONFIG_UPDATE)
  43. .arg(new_config->str());
  44. if (server_) {
  45. return (configureDhcp6Server(*server_, new_config));
  46. }
  47. // That should never happen as we install config_handler after we instantiate
  48. // the server.
  49. ConstElementPtr answer = isc::config::createAnswer(1,
  50. "Configuration rejected, server is during startup/shutdown phase.");
  51. return (answer);
  52. }
  53. ConstElementPtr
  54. ControlledDhcpv6Srv::dhcp6CommandHandler(const string& command, ConstElementPtr args) {
  55. LOG_DEBUG(dhcp6_logger, DBG_DHCP6_COMMAND, DHCP6_COMMAND_RECEIVED)
  56. .arg(command).arg(args->str());
  57. if (command == "shutdown") {
  58. if (ControlledDhcpv6Srv::server_) {
  59. ControlledDhcpv6Srv::server_->shutdown();
  60. } else {
  61. LOG_WARN(dhcp6_logger, DHCP6_NOT_RUNNING);
  62. ConstElementPtr answer = isc::config::createAnswer(1,
  63. "Shutdown failure.");
  64. return (answer);
  65. }
  66. ConstElementPtr answer = isc::config::createAnswer(0,
  67. "Shutting down.");
  68. return (answer);
  69. }
  70. ConstElementPtr answer = isc::config::createAnswer(1,
  71. "Unrecognized command.");
  72. return (answer);
  73. }
  74. void ControlledDhcpv6Srv::sessionReader(void) {
  75. // Process one asio event. If there are more events, iface_mgr will call
  76. // this callback more than once.
  77. if (server_) {
  78. server_->io_service_.run_one();
  79. }
  80. }
  81. void ControlledDhcpv6Srv::establishSession() {
  82. string specfile;
  83. if (getenv("B10_FROM_BUILD")) {
  84. specfile = string(getenv("B10_FROM_BUILD")) +
  85. "/src/bin/dhcp6/dhcp6.spec";
  86. } else {
  87. specfile = string(DHCP6_SPECFILE_LOCATION);
  88. }
  89. /// @todo: Check if session is not established already. Throw, if it is.
  90. LOG_DEBUG(dhcp6_logger, DBG_DHCP6_START, DHCP6_CCSESSION_STARTING)
  91. .arg(specfile);
  92. cc_session_ = new Session(io_service_.get_io_service());
  93. config_session_ = new ModuleCCSession(specfile, *cc_session_,
  94. NULL,
  95. dhcp6CommandHandler, false);
  96. config_session_->start();
  97. // We initially create ModuleCCSession() without configHandler, as
  98. // the session module is too eager to send partial configuration.
  99. // We want to get the full configuration, so we explicitly call
  100. // getFullConfig() and then pass it to our configHandler.
  101. config_session_->setConfigHandler(dhcp6ConfigHandler);
  102. try {
  103. configureDhcp6Server(*this, config_session_->getFullConfig());
  104. } catch (const DhcpConfigError& ex) {
  105. LOG_ERROR(dhcp6_logger, DHCP6_CONFIG_LOAD_FAIL).arg(ex.what());
  106. }
  107. /// Integrate the asynchronous I/O model of BIND 10 configuration
  108. /// control with the "select" model of the DHCP server. This is
  109. /// fully explained in \ref dhcpv6Session.
  110. int ctrl_socket = cc_session_->getSocketDesc();
  111. LOG_DEBUG(dhcp6_logger, DBG_DHCP6_START, DHCP6_CCSESSION_STARTED)
  112. .arg(ctrl_socket);
  113. IfaceMgr::instance().set_session_socket(ctrl_socket, sessionReader);
  114. }
  115. void ControlledDhcpv6Srv::disconnectSession() {
  116. if (config_session_) {
  117. delete config_session_;
  118. config_session_ = NULL;
  119. }
  120. if (cc_session_) {
  121. cc_session_->disconnect();
  122. delete cc_session_;
  123. cc_session_ = NULL;
  124. }
  125. // deregister session socket
  126. IfaceMgr::instance().set_session_socket(IfaceMgr::INVALID_SOCKET, NULL);
  127. }
  128. ControlledDhcpv6Srv::ControlledDhcpv6Srv(uint16_t port, const char* dbconfig)
  129. : Dhcpv6Srv(port, dbconfig), cc_session_(NULL), config_session_(NULL) {
  130. server_ = this; // remember this instance for use in callback
  131. }
  132. void ControlledDhcpv6Srv::shutdown() {
  133. io_service_.stop(); // Stop ASIO transmissions
  134. Dhcpv6Srv::shutdown(); // Initiate DHCPv6 shutdown procedure.
  135. }
  136. ControlledDhcpv6Srv::~ControlledDhcpv6Srv() {
  137. disconnectSession();
  138. server_ = NULL; // forget this instance. There should be no callback anymore
  139. // at this stage anyway.
  140. }
  141. isc::data::ConstElementPtr
  142. ControlledDhcpv6Srv::execDhcpv6ServerCommand(const std::string& command_id,
  143. isc::data::ConstElementPtr args) {
  144. try {
  145. return (dhcp6CommandHandler(command_id, args));
  146. } catch (const Exception& ex) {
  147. ConstElementPtr answer = isc::config::createAnswer(1, ex.what());
  148. return (answer);
  149. }
  150. }
  151. };
  152. };