portconfig.cc 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. // Copyright (C) 2011 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 <server_common/portconfig.h>
  15. #include <server_common/logger.h>
  16. #include <server_common/socket_request.h>
  17. #include <asiolink/io_address.h>
  18. #include <asiodns/dns_service.h>
  19. #include <boost/foreach.hpp>
  20. #include <boost/lexical_cast.hpp>
  21. using namespace std;
  22. using namespace isc::data;
  23. using namespace isc::asiolink;
  24. using namespace isc::asiodns;
  25. namespace isc {
  26. namespace server_common {
  27. namespace portconfig {
  28. AddressList
  29. parseAddresses(isc::data::ConstElementPtr addresses,
  30. const std::string& elemName)
  31. {
  32. AddressList result;
  33. if (addresses) {
  34. if (addresses->getType() == Element::list) {
  35. for (size_t i(0); i < addresses->size(); ++ i) {
  36. ConstElementPtr addrPair(addresses->get(i));
  37. ConstElementPtr addr(addrPair->get("address"));
  38. ConstElementPtr port(addrPair->get("port"));
  39. if (!addr || ! port) {
  40. LOG_ERROR(logger, SRVCOMM_ADDRESS_MISSING).
  41. arg(addrPair->str());
  42. isc_throw(BadValue, "Address must contain both the IP"
  43. "address and port");
  44. }
  45. try {
  46. // We create an IOAddress object to just check that
  47. // construction passes. It is immediately destroyed.
  48. // cppcheck-suppress unusedScopedObject
  49. IOAddress(addr->stringValue());
  50. if (port->intValue() < 0 ||
  51. port->intValue() > 0xffff) {
  52. LOG_ERROR(logger, SRVCOMM_PORT_RANGE).
  53. arg(port->intValue()).arg(addrPair->str());
  54. isc_throw(BadValue, "Bad port value (" <<
  55. port->intValue() << ")");
  56. }
  57. result.push_back(AddressPair(addr->stringValue(),
  58. port->intValue()));
  59. } catch (const TypeError&) { // Better error message
  60. LOG_ERROR(logger, SRVCOMM_ADDRESS_TYPE).
  61. arg(addrPair->str());
  62. isc_throw(TypeError,
  63. "Address must be a string and port an integer");
  64. }
  65. }
  66. } else if (addresses->getType() != Element::null) {
  67. LOG_ERROR(logger, SRVCOMM_ADDRESSES_NOT_LIST).arg(elemName);
  68. isc_throw(TypeError, elemName + " config element must be a list");
  69. }
  70. }
  71. return (result);
  72. }
  73. namespace {
  74. vector<string> current_sockets;
  75. void
  76. setAddresses(DNSServiceBase& service, const AddressList& addresses,
  77. DNSService::ServerFlag server_options)
  78. {
  79. service.clearServers();
  80. BOOST_FOREACH(const string& token, current_sockets) {
  81. socketRequestor().releaseSocket(token);
  82. }
  83. current_sockets.clear();
  84. BOOST_FOREACH(const AddressPair &address, addresses) {
  85. const int af(IOAddress(address.first).getFamily());
  86. // We use the application name supplied to the socket requestor on
  87. // creation. So we can freely use the SHARE_SAME
  88. const SocketRequestor::SocketID
  89. tcp(socketRequestor().requestSocket(SocketRequestor::TCP,
  90. address.first, address.second,
  91. SocketRequestor::SHARE_SAME));
  92. current_sockets.push_back(tcp.second);
  93. service.addServerTCPFromFD(tcp.first, af);
  94. const SocketRequestor::SocketID
  95. udp(socketRequestor().requestSocket(SocketRequestor::UDP,
  96. address.first, address.second,
  97. SocketRequestor::SHARE_SAME));
  98. current_sockets.push_back(udp.second);
  99. service.addServerUDPFromFD(udp.first, af, server_options);
  100. }
  101. }
  102. }
  103. void
  104. installListenAddresses(const AddressList& new_addresses,
  105. AddressList& address_store,
  106. DNSServiceBase& service,
  107. DNSService::ServerFlag server_options)
  108. {
  109. try {
  110. LOG_DEBUG(logger, DBG_TRACE_BASIC, SRVCOMM_SET_LISTEN);
  111. BOOST_FOREACH(const AddressPair& addr, new_addresses) {
  112. string addr_str;
  113. if (addr.first.find(':') != string::npos) {
  114. addr_str = "[" + addr.first + "]";
  115. } else {
  116. addr_str = addr.first;
  117. }
  118. LOG_DEBUG(logger, DBG_TRACE_VALUES, SRVCOMM_ADDRESS_VALUE).
  119. arg(addr_str).arg(addr.second);
  120. }
  121. setAddresses(service, new_addresses, server_options);
  122. address_store = new_addresses;
  123. } catch (const SocketRequestor::NonFatalSocketError& e) {
  124. /*
  125. * If one of the addresses isn't set successfully, we will restore
  126. * the old addresses, the behavior is that either all address are
  127. * set successuflly or none of them will be used. whether this
  128. * behavior is user desired, maybe we need revisited it later. And
  129. * if address setting is more smarter, it should check whether some
  130. * part of the new address already in used to avoid interrupting the
  131. * service.
  132. *
  133. * If the address setting still failed, we can live with it, since
  134. * user will get error info, command control can be used to set new
  135. * address. So we just catch the exception without propagating outside
  136. */
  137. LOG_ERROR(logger, SRVCOMM_ADDRESS_FAIL).arg(e.what());
  138. try {
  139. setAddresses(service, address_store, server_options);
  140. } catch (const SocketRequestor::NonFatalSocketError& e2) {
  141. LOG_FATAL(logger, SRVCOMM_ADDRESS_UNRECOVERABLE).arg(e2.what());
  142. // If we can't set the new ones, nor the old ones, at least
  143. // releasing everything should work. If it doesn't, there isn't
  144. // anything else we could do.
  145. setAddresses(service, AddressList(), server_options);
  146. address_store.clear();
  147. }
  148. //Anyway the new configure has problem, we need to notify configure
  149. //manager the new configure doesn't work
  150. throw;
  151. } catch (const exception& e) {
  152. // Any other kind of exception is fatal. It might mean we are in
  153. // inconsistent state with the b10-init/socket creator, so we abort
  154. // to make sure it doesn't last.
  155. LOG_FATAL(logger, SRVCOMM_EXCEPTION_ALLOC).arg(e.what());
  156. abort();
  157. } catch (...) {
  158. // As the previous one, but we know even less info
  159. LOG_FATAL(logger, SRVCOMM_UNKNOWN_EXCEPTION_ALLOC);
  160. abort();
  161. }
  162. }
  163. }
  164. }
  165. }