portconfig.cc 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  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 <asiolink/io_address.h>
  17. #include <asiodns/dns_service.h>
  18. #include <boost/foreach.hpp>
  19. #include <boost/lexical_cast.hpp>
  20. using namespace std;
  21. using namespace isc::data;
  22. using namespace isc::asiolink;
  23. using namespace isc::asiodns;
  24. namespace isc {
  25. namespace server_common {
  26. namespace portconfig {
  27. AddressList
  28. parseAddresses(isc::data::ConstElementPtr addresses,
  29. const std::string& elemName)
  30. {
  31. AddressList result;
  32. if (addresses) {
  33. if (addresses->getType() == Element::list) {
  34. for (size_t i(0); i < addresses->size(); ++ i) {
  35. ConstElementPtr addrPair(addresses->get(i));
  36. ConstElementPtr addr(addrPair->get("address"));
  37. ConstElementPtr port(addrPair->get("port"));
  38. if (!addr || ! port) {
  39. LOG_ERROR(logger, SRVCOMM_ADDRESS_MISSING).
  40. arg(addrPair->str());
  41. isc_throw(BadValue, "Address must contain both the IP"
  42. "address and port");
  43. }
  44. try {
  45. IOAddress(addr->stringValue());
  46. if (port->intValue() < 0 ||
  47. port->intValue() > 0xffff) {
  48. LOG_ERROR(logger, SRVCOMM_PORT_RANGE).
  49. arg(port->intValue()).arg(addrPair->str());
  50. isc_throw(BadValue, "Bad port value (" <<
  51. port->intValue() << ")");
  52. }
  53. result.push_back(AddressPair(addr->stringValue(),
  54. port->intValue()));
  55. }
  56. catch (const TypeError &e) { // Better error message
  57. LOG_ERROR(logger, SRVCOMM_ADDRESS_TYPE).
  58. arg(addrPair->str());
  59. isc_throw(TypeError,
  60. "Address must be a string and port an integer");
  61. }
  62. }
  63. } else if (addresses->getType() != Element::null) {
  64. LOG_ERROR(logger, SRVCOMM_ADDRESSES_NOT_LIST).arg(elemName);
  65. isc_throw(TypeError, elemName + " config element must be a list");
  66. }
  67. }
  68. return (result);
  69. }
  70. namespace {
  71. void
  72. setAddresses(DNSService& service, const AddressList& addresses) {
  73. service.clearServers();
  74. BOOST_FOREACH(const AddressPair &address, addresses) {
  75. service.addServer(address.second, address.first);
  76. }
  77. }
  78. }
  79. void
  80. installListenAddresses(const AddressList& newAddresses,
  81. AddressList& addressStore,
  82. isc::asiodns::DNSService& service)
  83. {
  84. try {
  85. LOG_DEBUG(logger, DBG_TRACE_BASIC, SRVCOMM_SET_LISTEN);
  86. BOOST_FOREACH(const AddressPair& addr, newAddresses) {
  87. LOG_DEBUG(logger, DBG_TRACE_VALUES, SRVCOMM_ADDRESS_VALUE).
  88. arg(addr.first).arg(addr.second);
  89. }
  90. setAddresses(service, newAddresses);
  91. addressStore = newAddresses;
  92. }
  93. catch (const exception& e) {
  94. /*
  95. * If one of the addresses isn't set successfully, we will restore
  96. * the old addresses, the behavior is that either all address are
  97. * set successuflly or none of them will be used. whether this
  98. * behavior is user desired, maybe we need revisited it later. And
  99. * if address setting is more smarter, it should check whether some
  100. * part of the new address already in used to avoid interuption the
  101. * service.
  102. *
  103. * If the address setting still failed, we can live with it, since
  104. * user will get error info, command control can be used to set new
  105. * address. So we just catch the exception without propagating outside
  106. */
  107. LOG_ERROR(logger, SRVCOMM_ADDRESS_FAIL).arg(e);
  108. try {
  109. setAddresses(service, addressStore);
  110. }
  111. catch (const exception& e2) {
  112. LOG_FATAL(logger, SRVCOMM_ADDRESS_UNRECOVERABLE).arg(e2);
  113. }
  114. //Anyway the new configure has problem, we need to notify configure
  115. //manager the new configure doesn't work
  116. throw;
  117. }
  118. }
  119. }
  120. }
  121. }