main.cc 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  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 <boost/lexical_cast.hpp>
  22. #include <iostream>
  23. using namespace isc::dhcp;
  24. using namespace std;
  25. /// This file contains entry point (main() function) for standard DHCPv6 server
  26. /// component of Kea software suite. It parses command-line arguments and
  27. /// instantiates ControlledDhcpv6Srv class that is responsible for establishing
  28. /// connection with msgq (receiving commands and configuration) and also
  29. /// creating Dhcpv6 server object as well.
  30. ///
  31. /// For detailed explanation or relations between main(), ControlledDhcpv6Srv,
  32. /// Dhcpv6Srv and other classes, see \ref dhcpv6Session.
  33. namespace {
  34. const char* const DHCP6_NAME = "kea-dhcp6";
  35. const char* const DHCP6_LOGGER_NAME = "kea-dhcp6";
  36. /// @brief Prints Kea Usage and exits
  37. ///
  38. /// Note: This function never returns. It terminates the process.
  39. void
  40. usage() {
  41. cerr << "Kea DHCPv6 server, version " << VERSION << endl;
  42. cerr << endl;
  43. cerr << "Usage: " << DHCP6_NAME
  44. << " [-c cfgfile] [-v] [-V] [-d] [-p port_number]" << endl;
  45. cerr << " -c file: specify configuration file" << endl;
  46. cerr << " -v: print version number and exit." << endl;
  47. cerr << " -V: print extended version and exit" << endl;
  48. cerr << " -d: debug mode with extra verbosity (former -v)" << endl;
  49. cerr << " -p number: specify non-standard port number 1-65535 "
  50. << "(useful for testing only)" << endl;
  51. exit(EXIT_FAILURE);
  52. }
  53. } // end of anonymous namespace
  54. int
  55. main(int argc, char* argv[]) {
  56. int ch;
  57. int port_number = DHCP6_SERVER_PORT; // The default. Any other values are
  58. // useful for testing only.
  59. bool verbose_mode = false; // Should server be verbose?
  60. // The standard config file
  61. std::string config_file("");
  62. while ((ch = getopt(argc, argv, "dvVp:c:")) != -1) {
  63. switch (ch) {
  64. case 'd':
  65. verbose_mode = true;
  66. break;
  67. case 'v':
  68. cout << Daemon::getVersion(false) << endl;
  69. return (EXIT_SUCCESS);
  70. case 'V':
  71. cout << Daemon::getVersion(true) << endl;
  72. return (EXIT_SUCCESS);
  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. case 'c': // config file
  88. config_file = optarg;
  89. break;
  90. default:
  91. usage();
  92. }
  93. }
  94. // Check for extraneous parameters.
  95. if (argc > optind) {
  96. usage();
  97. }
  98. // Configuration file is required.
  99. if (config_file.empty()) {
  100. cerr << "Configuration file not specified." << endl;
  101. usage();
  102. }
  103. int ret = EXIT_SUCCESS;
  104. try {
  105. // It is important that we set a default logger name because this name
  106. // will be used when the user doesn't provide the logging configuration
  107. // in the Kea configuration file.
  108. CfgMgr::instance().setDefaultLoggerName(DHCP6_LOGGER_NAME);
  109. // Initialize logging. If verbose, we'll use maximum verbosity.
  110. Daemon::loggerInit(DHCP6_LOGGER_NAME, verbose_mode);
  111. LOG_DEBUG(dhcp6_logger, DBG_DHCP6_START, DHCP6_START_INFO)
  112. .arg(getpid()).arg(port_number).arg(verbose_mode ? "yes" : "no");
  113. LOG_INFO(dhcp6_logger, DHCP6_STARTING).arg(VERSION);
  114. // Create the server instance.
  115. ControlledDhcpv6Srv server(port_number);
  116. // Remember verbose-mode
  117. server.setVerbose(verbose_mode);
  118. try {
  119. // Initialize the server, e.g. establish control session
  120. // if Bundy backend is used or read a configuration file
  121. // if Kea backend is used.
  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 std::exception& ex) {
  142. // First, we print the error on stderr (that should always work)
  143. cerr << DHCP6_NAME << "Fatal error during start up: " << 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. LOG_FATAL(dhcp6_logger, DHCP6_SERVER_FAILED).arg(ex.what());
  149. ret = EXIT_FAILURE;
  150. }
  151. return (ret);
  152. }