iface_cfg.cc 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. // Copyright (C) 2014 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 <dhcp/iface_mgr.h>
  15. #include <dhcpsrv/dhcpsrv_log.h>
  16. #include <dhcpsrv/iface_cfg.h>
  17. #include <util/strutil.h>
  18. #include <boost/bind.hpp>
  19. namespace isc {
  20. namespace dhcp {
  21. const char* IfaceCfg::ALL_IFACES_KEYWORD = "*";
  22. IfaceCfg::IfaceCfg(Family family)
  23. : family_(family),
  24. wildcard_used_(false) {
  25. }
  26. void
  27. IfaceCfg::closeSockets() {
  28. IfaceMgr::instance().closeSockets();
  29. }
  30. void
  31. IfaceCfg::openSockets(const uint16_t port, const bool use_bcast) {
  32. // If wildcard interface '*' was not specified, set all interfaces to
  33. // inactive state. We will later enable them selectively using the
  34. // interface names specified by the user. If wildcard interface was
  35. // specified, mark all interfaces active.
  36. setState(!wildcard_used_);
  37. // If there is no wildcard interface specified, we will have to iterate
  38. // over the names specified by the caller and enable them.
  39. if (!wildcard_used_) {
  40. for (IfaceSet::const_iterator iface_name = iface_set_.begin();
  41. iface_name != iface_set_.end(); ++iface_name) {
  42. Iface* iface = IfaceMgr::instance().getIface(*iface_name);
  43. // This shouldn't really happen because we are checking the
  44. // names of interfaces when they are being added (use()
  45. // function). But, if someone has triggered detection of
  46. // interfaces since then, some interfaces may have disappeared.
  47. if (iface == NULL) {
  48. isc_throw(Unexpected,
  49. "fail to open socket on interface '"
  50. << *iface_name << "' as this interface doesn't"
  51. " exist");
  52. } else if (getFamily() == V4) {
  53. iface->inactive4_ = false;
  54. } else {
  55. iface->inactive6_ = false;
  56. }
  57. }
  58. }
  59. // Set the callback which is called when the socket fails to open
  60. // for some specific interface. This callback will simply log a
  61. // warning message.
  62. IfaceMgrErrorMsgCallback error_callback =
  63. boost::bind(&IfaceCfg::socketOpenErrorHandler, this, _1);
  64. bool sopen;
  65. if (getFamily() == V4) {
  66. sopen = IfaceMgr::instance().openSockets4(port, use_bcast,
  67. error_callback);
  68. } else {
  69. // use_bcast is ignored for V6.
  70. sopen = IfaceMgr::instance().openSockets6(port, error_callback);
  71. }
  72. // If no socket were opened, log a warning because the server will
  73. // not respond to any queries.
  74. if (!sopen) {
  75. LOG_WARN(dhcpsrv_logger, DHCPSRV_NO_SOCKETS_OPEN);
  76. }
  77. }
  78. void
  79. IfaceCfg::reset() {
  80. wildcard_used_ = false;
  81. iface_set_.clear();
  82. }
  83. void
  84. IfaceCfg::setState(const bool inactive) {
  85. IfaceMgr::IfaceCollection ifaces = IfaceMgr::instance().getIfaces();
  86. for (IfaceMgr::IfaceCollection::iterator iface = ifaces.begin();
  87. iface != ifaces.end(); ++iface) {
  88. Iface* iface_ptr = IfaceMgr::instance().getIface(iface->getName());
  89. if (getFamily() == V4) {
  90. iface_ptr->inactive4_ = inactive;
  91. } else {
  92. iface_ptr->inactive6_ = inactive;
  93. }
  94. }
  95. }
  96. void
  97. IfaceCfg::socketOpenErrorHandler(const std::string& errmsg) {
  98. LOG_WARN(dhcpsrv_logger, DHCPSRV_OPEN_SOCKET_FAIL).arg(errmsg);
  99. }
  100. void
  101. IfaceCfg::use(const std::string& iface_name) {
  102. // In theory the configuration parser should strip extraneous spaces but
  103. // since this is a common library it may be better to make sure that it
  104. // is really the case.
  105. std::string name = util::str::trim(iface_name);
  106. if (name.empty()) {
  107. isc_throw(InvalidIfaceName,
  108. "empty interface name used in configuration");
  109. } else if (name != ALL_IFACES_KEYWORD) {
  110. if (IfaceMgr::instance().getIface(name) == NULL) {
  111. isc_throw(NoSuchIface, "interface '" << name
  112. << "' doesn't exist in the system");
  113. }
  114. std::pair<IfaceSet::iterator, bool> res = iface_set_.insert(name);
  115. if (!res.second) {
  116. isc_throw(DuplicateIfaceName, "interface '" << name
  117. << "' has already been specified");
  118. }
  119. } else if (wildcard_used_) {
  120. isc_throw(DuplicateIfaceName, "the wildcard interface '"
  121. << ALL_IFACES_KEYWORD << "' can only be specified once");
  122. } else {
  123. wildcard_used_ = true;
  124. }
  125. }
  126. } // end of isc::dhcp namespace
  127. } // end of isc namespace