main.cc 7.2 KB

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