main.cc 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. // Copyright (C) 2011-2016 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // This Source Code Form is subject to the terms of the Mozilla Public
  4. // License, v. 2.0. If a copy of the MPL was not distributed with this
  5. // file, You can obtain one at http://mozilla.org/MPL/2.0/.
  6. #include <config.h>
  7. #include <dhcp6/ctrl_dhcp6_srv.h>
  8. #include <dhcp6/dhcp6_log.h>
  9. #include <dhcpsrv/cfgmgr.h>
  10. #include <log/logger_support.h>
  11. #include <log/logger_manager.h>
  12. #include <exceptions/exceptions.h>
  13. #include <cfgrpt/config_report.h>
  14. #include <boost/lexical_cast.hpp>
  15. #include <iostream>
  16. using namespace isc::dhcp;
  17. using namespace std;
  18. /// This file contains entry point (main() function) for standard DHCPv6 server
  19. /// component of Kea software suite. It parses command-line arguments and
  20. /// instantiates ControlledDhcpv6Srv class that is responsible for establishing
  21. /// connection with msgq (receiving commands and configuration) and also
  22. /// creating Dhcpv6 server object as well.
  23. ///
  24. /// For detailed explanation or relations between main(), ControlledDhcpv6Srv,
  25. /// Dhcpv6Srv and other classes, see \ref dhcpv6Session.
  26. namespace {
  27. const char* const DHCP6_NAME = "kea-dhcp6";
  28. const char* const DHCP6_LOGGER_NAME = "kea-dhcp6";
  29. /// @brief Prints Kea Usage and exits
  30. ///
  31. /// Note: This function never returns. It terminates the process.
  32. void
  33. usage() {
  34. cerr << "Kea DHCPv6 server, version " << VERSION << endl;
  35. cerr << endl;
  36. cerr << "Usage: " << DHCP6_NAME
  37. << " -[v|V|W] [-d] [-c cfgfile] [-p port_number]" << endl;
  38. cerr << " -v: print version number and exit." << endl;
  39. cerr << " -V: print extended version and exit" << endl;
  40. cerr << " -W: display the configuration report and exit" << endl;
  41. cerr << " -d: debug mode with extra verbosity (former -v)" << endl;
  42. cerr << " -c file: specify configuration file" << endl;
  43. cerr << " -p number: specify non-standard port number 1-65535 "
  44. << "(useful for testing only)" << endl;
  45. exit(EXIT_FAILURE);
  46. }
  47. } // end of anonymous namespace
  48. int
  49. main(int argc, char* argv[]) {
  50. int ch;
  51. int port_number = DHCP6_SERVER_PORT; // The default. Any other values are
  52. // useful for testing only.
  53. bool verbose_mode = false; // Should server be verbose?
  54. // The standard config file
  55. std::string config_file("");
  56. while ((ch = getopt(argc, argv, "dvVWc:p:")) != -1) {
  57. switch (ch) {
  58. case 'd':
  59. verbose_mode = true;
  60. break;
  61. case 'v':
  62. cout << Dhcpv6Srv::getVersion(false) << endl;
  63. return (EXIT_SUCCESS);
  64. case 'V':
  65. cout << Dhcpv6Srv::getVersion(true) << endl;
  66. return (EXIT_SUCCESS);
  67. case 'W':
  68. cout << isc::detail::getConfigReport() << endl;
  69. return (EXIT_SUCCESS);
  70. case 'c': // config file
  71. config_file = optarg;
  72. break;
  73. case 'p': // port number
  74. try {
  75. port_number = boost::lexical_cast<int>(optarg);
  76. } catch (const boost::bad_lexical_cast &) {
  77. cerr << "Failed to parse port number: [" << optarg
  78. << "], 1-65535 allowed." << endl;
  79. usage();
  80. }
  81. if (port_number <= 0 || port_number > 65535) {
  82. cerr << "Failed to parse port number: [" << optarg
  83. << "], 1-65535 allowed." << endl;
  84. usage();
  85. }
  86. break;
  87. default:
  88. usage();
  89. }
  90. }
  91. // Check for extraneous parameters.
  92. if (argc > optind) {
  93. usage();
  94. }
  95. // Configuration file is required.
  96. if (config_file.empty()) {
  97. cerr << "Configuration file not specified." << endl;
  98. usage();
  99. }
  100. int ret = EXIT_SUCCESS;
  101. try {
  102. // It is important that we set a default logger name because this name
  103. // will be used when the user doesn't provide the logging configuration
  104. // in the Kea configuration file.
  105. CfgMgr::instance().setDefaultLoggerName(DHCP6_LOGGER_NAME);
  106. // Initialize logging. If verbose, we'll use maximum verbosity.
  107. Daemon::loggerInit(DHCP6_LOGGER_NAME, verbose_mode);
  108. LOG_DEBUG(dhcp6_logger, DBG_DHCP6_START, DHCP6_START_INFO)
  109. .arg(getpid()).arg(port_number).arg(verbose_mode ? "yes" : "no");
  110. LOG_INFO(dhcp6_logger, DHCP6_STARTING).arg(VERSION);
  111. // Create the server instance.
  112. ControlledDhcpv6Srv server(port_number);
  113. // Remember verbose-mode
  114. server.setVerbose(verbose_mode);
  115. // Create our PID file
  116. server.setProcName(DHCP6_NAME);
  117. server.setConfigFile(config_file);
  118. server.createPIDFile();
  119. try {
  120. // Initialize the server, e.g. establish control session
  121. // Read a configuration file
  122. server.init(config_file);
  123. } catch (const std::exception& ex) {
  124. try {
  125. // Let's log out what went wrong.
  126. isc::log::LoggerManager log_manager;
  127. log_manager.process();
  128. LOG_ERROR(dhcp6_logger, DHCP6_INIT_FAIL).arg(ex.what());
  129. } catch (...) {
  130. // The exeption thrown during the initialization could originate
  131. // from logger subsystem. Therefore LOG_ERROR() may fail as well.
  132. cerr << "Failed to initialize server: " << ex.what() << endl;
  133. }
  134. return (EXIT_FAILURE);
  135. }
  136. // Tell the admin we are ready to process packets
  137. LOG_INFO(dhcp6_logger, DHCP6_STARTED).arg(VERSION);
  138. // And run the main loop of the server.
  139. server.run();
  140. LOG_INFO(dhcp6_logger, DHCP6_SHUTDOWN);
  141. } catch (const isc::dhcp::DaemonPIDExists& ex) {
  142. // First, we print the error on stderr (that should always work)
  143. cerr << DHCP6_NAME << " already running? " << ex.what()
  144. << endl;
  145. // Let's also try to log it using logging system, but we're not
  146. // sure if it's usable (the exception may have been thrown from
  147. // the logger subsystem)
  148. try {
  149. LOG_FATAL(dhcp6_logger, DHCP6_ALREADY_RUNNING)
  150. .arg(DHCP6_NAME).arg(ex.what());
  151. } catch (...) {
  152. // Already logged so ignore
  153. }
  154. ret = EXIT_FAILURE;
  155. } catch (const std::exception& ex) {
  156. // First, we print the error on stderr (that should always work)
  157. cerr << DHCP6_NAME << "Fatal error during start up: " << ex.what()
  158. << endl;
  159. // Let's also try to log it using logging system, but we're not
  160. // sure if it's usable (the exception may have been thrown from
  161. // the logger subsystem)
  162. try {
  163. LOG_FATAL(dhcp6_logger, DHCP6_SERVER_FAILED).arg(ex.what());
  164. } catch (...) {
  165. // Already logged so ignore
  166. }
  167. ret = EXIT_FAILURE;
  168. }
  169. return (ret);
  170. }