nameserver_entry.cc 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. // Copyright (C) 2010 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. // $Id$
  15. #include <algorithm>
  16. #include <functional>
  17. #include <cassert>
  18. #include <iostream>
  19. #include <ctype.h>
  20. #include <strings.h>
  21. #include "config.h"
  22. #include "exceptions/exceptions.h"
  23. #include "name.h"
  24. #include "rrclass.h"
  25. #include "rrttl.h"
  26. #include "address_entry.h"
  27. #include "nameserver_entry.h"
  28. using namespace asiolink;
  29. using namespace isc::nsas;
  30. using namespace isc::dns;
  31. using namespace std;
  32. namespace isc {
  33. namespace nsas {
  34. // Constructor, initialized with the list of addresses associated with this
  35. // nameserver.
  36. NameserverEntry::NameserverEntry(const AbstractRRset* v4Set,
  37. const AbstractRRset* v6Set, time_t curtime) : expiration_(0)
  38. {
  39. // TODO: Use pseudo-random RTT
  40. uint32_t rtt = 0; // Round-trip time for an address
  41. string v4name = ""; // Name from the V4 RRset
  42. string v6name = ""; // Name from the v6 RRset
  43. uint16_t v4class = 0; // Class of V4 RRset
  44. uint16_t v6class = 0; // Class for V6 RRset
  45. // Get the time for setting the expiration time.
  46. if (curtime == 0) {
  47. curtime = time(NULL);
  48. }
  49. // Add the v4 addresses to the list of addresses. Each address is assigned
  50. // a small RTT that ensures that each server is used at least once (in a
  51. // random order).
  52. // Do the V4 addresses first
  53. // XXX: Do we need to check that these are V4 addresses?
  54. if (v4Set) {
  55. RdataIteratorPtr i = v4Set->getRdataIterator();
  56. i->first();
  57. while (! i->isLast()) {
  58. address_.push_back(AddressEntry(IOAddress(i->getCurrent().toText()),
  59. ++rtt));
  60. i->next();
  61. }
  62. // Set the expiration time and extract the owner name and class
  63. expiration_ = curtime + v4Set->getTTL().getValue();
  64. v4name = v4Set->getName().toText(false); // Ensure trailing dot
  65. v4class = v4Set->getClass().getCode();
  66. }
  67. // Now the v6 addresses
  68. // XXX: Do we need to check that these are V6 addresses?
  69. if (v6Set) {
  70. RdataIteratorPtr i = v6Set->getRdataIterator();
  71. i->first();
  72. while (! i->isLast()) {
  73. address_.push_back(AddressEntry(IOAddress(i->getCurrent().toText()),
  74. ++rtt));
  75. i->next();
  76. }
  77. // Update the expiration time of the data
  78. time_t v6expiration = curtime + v6Set->getTTL().getValue();
  79. if (expiration_ == 0) {
  80. expiration_ = v6expiration;
  81. }
  82. else {
  83. expiration_ = min(expiration_, v6expiration);
  84. }
  85. // Extract the name of the v6 set and its class
  86. v6name = v6Set->getName().toText(false); // Ensure trailing dot
  87. v6class = v6Set->getClass().getCode();
  88. }
  89. // TODO: Log a problem if both V4 and V6 address were null.
  90. if (v4Set && v6Set) {
  91. // If two owner names were specified and they were different, something
  92. // has gone wrong with the logic that created this object.
  93. if (strcasecmp(v4name.c_str(), v6name.c_str()) != 0) {
  94. isc_throw(InconsistentOwnerNames,
  95. "Owner names for NameserverEntry RRsets are different");
  96. }
  97. // Likewise with the class
  98. if (v4class != v6class) {
  99. isc_throw(InconsistentClass,
  100. "Class codes for NameserverEntry RRsets are different");
  101. }
  102. }
  103. // Otherwise set the owner name
  104. name_ = v4Set ? v4name : v6name;
  105. classCode_ = v4Set ? v4class : v6class;
  106. }
  107. // Returns the list of addresses matching the given family
  108. void NameserverEntry::getAddresses(AddressVector& addresses, short family) const {
  109. // Quick check that allows validation of the assumption in the header file
  110. // that a family value of 0 will select all address families.
  111. assert(AF_INET != 0);
  112. assert(AF_INET6 != 0);
  113. // Now copy all entries that meet the criteria. Since remove_copy_if
  114. // does the inverse (copies all entries that do not meet the criteria),
  115. // the predicate for address selection is negated.
  116. remove_copy_if(address_.begin(), address_.end(), back_inserter(addresses),
  117. bind1st(AddressSelection(), family));
  118. }
  119. asiolink::IOAddress NameserverEntry::getAddressAtIndex(uint32_t index) const
  120. {
  121. assert(index < address_.size());
  122. return address_[index].getAddress();
  123. }
  124. // Set the address RTT to a specific value
  125. void NameserverEntry::setAddressRTT(const IOAddress& address, uint32_t rtt) {
  126. // Search through the list of addresses for a match
  127. for (AddressVectorIterator i = address_.begin(); i != address_.end(); ++i) {
  128. if (i->getAddress().equal(address)) {
  129. i->setRTT(rtt);
  130. }
  131. }
  132. }
  133. // Update the address's rtt
  134. void NameserverEntry::updateAddressRTTAtIndex(uint32_t rtt, uint32_t index) {
  135. //make sure it is a valid index
  136. if(index >= address_.size()) return;
  137. //update the rtt
  138. address_[index].setRTT(rtt);
  139. }
  140. // Sets the address to be unreachable
  141. void NameserverEntry::setAddressUnreachable(const IOAddress& address) {
  142. setAddressRTT(address, AddressEntry::UNREACHABLE);
  143. }
  144. } // namespace dns
  145. } // namespace isc