main.cc 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. // Copyright (C) 2011-2012, 2014-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 <dhcp4/ctrl_dhcp4_srv.h>
  16. #include <dhcp4/dhcp4_log.h>
  17. #include <dhcpsrv/cfgmgr.h>
  18. #include <log/logger_support.h>
  19. #include <log/logger_manager.h>
  20. #include <cfgrpt/config_report.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 DHCPv4 server
  26. /// component of Kea software suite. It parses command-line arguments and
  27. /// instantiates ControlledDhcpv4Srv class that is responsible for establishing
  28. /// connection with msgq (receiving commands and configuration) and also
  29. /// creating Dhcpv4 server object as well.
  30. namespace {
  31. const char* const DHCP4_NAME = "kea-dhcp4";
  32. /// @brief Prints Kea Usage and exits
  33. ///
  34. /// Note: This function never returns. It terminates the process.
  35. void
  36. usage() {
  37. cerr << "Kea DHCPv4 server, version " << VERSION << endl;
  38. cerr << endl;
  39. cerr << "Usage: " << DHCP4_NAME
  40. << " -[v|V|W] [-d] [-c cfgfile] [-p number]" << endl;
  41. cerr << " -v: print version number and exit" << endl;
  42. cerr << " -V: print extended version and exit" << endl;
  43. cerr << " -W: display the configuration report and exit" << endl;
  44. cerr << " -d: debug mode with extra verbosity (former -v)" << endl;
  45. cerr << " -c file: specify configuration file" << endl;
  46. cerr << " -p number: specify non-standard port number 1-65535 "
  47. << "(useful for testing only)" << endl;
  48. exit(EXIT_FAILURE);
  49. }
  50. } // end of anonymous namespace
  51. int
  52. main(int argc, char* argv[]) {
  53. int ch;
  54. int port_number = DHCP4_SERVER_PORT; // The default. any other values are
  55. // useful for testing only.
  56. bool verbose_mode = false; // Should server be verbose?
  57. // The standard config file
  58. std::string config_file("");
  59. while ((ch = getopt(argc, argv, "dvVWc:p:")) != -1) {
  60. switch (ch) {
  61. case 'd':
  62. verbose_mode = true;
  63. break;
  64. case 'v':
  65. cout << Dhcpv4Srv::getVersion(false) << endl;
  66. return (EXIT_SUCCESS);
  67. case 'V':
  68. cout << Dhcpv4Srv::getVersion(true) << endl;
  69. return (EXIT_SUCCESS);
  70. case 'W':
  71. cout << isc::detail::getConfigReport() << endl;
  72. return (EXIT_SUCCESS);
  73. case 'c': // config file
  74. config_file = optarg;
  75. break;
  76. case 'p':
  77. try {
  78. port_number = boost::lexical_cast<int>(optarg);
  79. } catch (const boost::bad_lexical_cast &) {
  80. cerr << "Failed to parse port number: [" << optarg
  81. << "], 1-65535 allowed." << endl;
  82. usage();
  83. }
  84. if (port_number <= 0 || port_number > 65535) {
  85. cerr << "Failed to parse port number: [" << optarg
  86. << "], 1-65535 allowed." << endl;
  87. usage();
  88. }
  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(DHCP4_ROOT_LOGGER_NAME);
  109. // Initialize logging. If verbose, we'll use maximum verbosity.
  110. Daemon::loggerInit(DHCP4_ROOT_LOGGER_NAME, verbose_mode);
  111. LOG_DEBUG(dhcp4_logger, DBG_DHCP4_START, DHCP4_START_INFO)
  112. .arg(getpid()).arg(port_number).arg(verbose_mode ? "yes" : "no");
  113. LOG_INFO(dhcp4_logger, DHCP4_STARTING).arg(VERSION);
  114. // Create the server instance.
  115. ControlledDhcpv4Srv server(port_number);
  116. // Remember verbose-mode
  117. server.setVerbose(verbose_mode);
  118. // Create our PID file.
  119. server.setProcName(DHCP4_NAME);
  120. server.setConfigFile(config_file);
  121. server.createPIDFile();
  122. try {
  123. // Initialize the server.
  124. server.init(config_file);
  125. } catch (const std::exception& ex) {
  126. try {
  127. // Let's log out what went wrong.
  128. isc::log::LoggerManager log_manager;
  129. log_manager.process();
  130. LOG_ERROR(dhcp4_logger, DHCP4_INIT_FAIL).arg(ex.what());
  131. } catch (...) {
  132. // The exception thrown during the initialization could
  133. // originate from logger subsystem. Therefore LOG_ERROR()
  134. // may fail as well.
  135. cerr << "Failed to initialize server: " << ex.what() << endl;
  136. }
  137. return (EXIT_FAILURE);
  138. }
  139. // Tell the admin we are ready to process packets
  140. LOG_INFO(dhcp4_logger, DHCP4_STARTED).arg(VERSION);
  141. // And run the main loop of the server.
  142. server.run();
  143. LOG_INFO(dhcp4_logger, DHCP4_SHUTDOWN);
  144. } catch (const isc::dhcp::DaemonPIDExists& ex) {
  145. // First, we print the error on stderr (that should always work)
  146. cerr << DHCP4_NAME << " already running? " << ex.what()
  147. << endl;
  148. // Let's also try to log it using logging system, but we're not
  149. // sure if it's usable (the exception may have been thrown from
  150. // the logger subsystem)
  151. LOG_FATAL(dhcp4_logger, DHCP4_ALREADY_RUNNING)
  152. .arg(DHCP4_NAME).arg(ex.what());
  153. ret = EXIT_FAILURE;
  154. } catch (const std::exception& ex) {
  155. // First, we print the error on stderr (that should always work)
  156. cerr << DHCP4_NAME << ": Fatal error during start up: " << ex.what()
  157. << endl;
  158. // Let's also try to log it using logging system, but we're not
  159. // sure if it's usable (the exception may have been thrown from
  160. // the logger subsystem)
  161. LOG_FATAL(dhcp4_logger, DHCP4_SERVER_FAILED).arg(ex.what());
  162. ret = EXIT_FAILURE;
  163. }
  164. return (ret);
  165. }