nameserver_entry.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  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. #ifndef NAMESERVER_ENTRY_H
  15. #define NAMESERVER_ENTRY_H
  16. #include <string>
  17. #include <vector>
  18. #include <boost/enable_shared_from_this.hpp>
  19. #include <exceptions/exceptions.h>
  20. #include <dns/rrset.h>
  21. #include <dns/rrtype.h>
  22. #include <resolve/resolver_interface.h>
  23. #include <util/lru_list.h>
  24. #include "address_entry.h"
  25. #include "asiolink.h"
  26. #include "nsas_types.h"
  27. #include "hash_key.h"
  28. #include "fetchable.h"
  29. #include "nsas_entry.h"
  30. #include "nameserver_address.h"
  31. namespace isc {
  32. namespace nsas {
  33. class NameserverAddress;
  34. /// \brief Inconsistent Owner Names
  35. ///
  36. /// Thrown if a NameserverEntry is constructed from both an A and AAAA RRset
  37. /// where the owner names do not match.
  38. class InconsistentOwnerNames : public Exception {
  39. public:
  40. InconsistentOwnerNames(const char* file, size_t line, const char* what) :
  41. isc::Exception(file, line, what)
  42. {}
  43. };
  44. /// \brief RTT is zero
  45. ///
  46. /// Thrown if a RTT related with an address is 0.
  47. class RTTIsZero : public Exception {
  48. public:
  49. RTTIsZero(const char* file, size_t line, const char* what) :
  50. isc::Exception(file, line, what)
  51. {}
  52. };
  53. /// \brief Inconsistent Class
  54. ///
  55. /// Thrown if a NameserverEntry is constructed from both an A and AAAA RRset
  56. /// where the classes do not match.
  57. class InconsistentClass : public Exception {
  58. public:
  59. InconsistentClass(const char* file, size_t line, const char* what) :
  60. isc::Exception(file, line, what)
  61. {}
  62. };
  63. class ZoneEntry;
  64. /// \brief Nameserver Entry
  65. ///
  66. /// Describes a nameserver and its addresses. A nameserver be authoritative
  67. /// for several zones (hence is pointed to by more than one zone entry), and
  68. /// may have several addresses associated with it.
  69. ///
  70. /// The addresses expire after their TTL has been reached. For simplicity,
  71. /// (and because it is unlikely that A and AAAA records from the same zone have
  72. /// different TTLs) there is one expiration time for all address records.
  73. /// When that is reached, all records are declared expired and new fetches
  74. /// started for the information.
  75. ///
  76. /// As this object will be stored in the nameserver address store LRU list,
  77. /// it is derived from the LRU list entry class.
  78. ///
  79. /// It uses shared_from_this in its methods. It must live inside a shared_ptr.
  80. class NameserverEntry : public NsasEntry<NameserverEntry>, public Fetchable {
  81. public:
  82. /// List of addresses associated with this nameserver
  83. typedef std::vector<NameserverAddress> AddressVector;
  84. typedef AddressVector::iterator AddressVectorIterator;
  85. /// \brief Constructor where no A records are supplied.
  86. ///
  87. /// \param name Name of the nameserver,
  88. /// \param class_code class of the nameserver
  89. NameserverEntry(const std::string& name,
  90. const isc::dns::RRClass& class_code) :
  91. name_(name),
  92. classCode_(class_code),
  93. expiration_(0)
  94. {
  95. has_address_[V4_ONLY] = false;
  96. has_address_[V6_ONLY] = false;
  97. has_address_[ANY_OK] = false;
  98. expect_address_[V4_ONLY] = false;
  99. expect_address_[V6_ONLY] = false;
  100. expect_address_[ANY_OK] = false;
  101. }
  102. /*
  103. * \brief Return Address
  104. *
  105. * Returns a vector of addresses corresponding to this nameserver.
  106. *
  107. * \param addresses Vector of address entries into which will be appended
  108. * addresses that match the specified criteria. (The reason for
  109. * choosing this signature is that addresses from more than one
  110. * nameserver may be retrieved, in which case appending to an existing
  111. * list of addresses is convenient.)
  112. * \param family The family of address that is requested.
  113. * \param expired_ok Return addresses even when expired. This is here
  114. * because an address with TTL 0 is expired at the exact time it
  115. * arrives. But when we call the callback, the owner of callback
  116. * is allowed to use them anyway so it should set expired_ok
  117. * to true.
  118. * \return The state this is currently in. If the TTL expires, it enters
  119. * the EXPIRED state by itself and passes no addresses. It may be
  120. * IN_PROGRESS and still return some addresses (when one address family
  121. * arrived and is is returned, but the other is still on the way).
  122. * \todo Should we sort out unreachable addresses as well?
  123. */
  124. Fetchable::State getAddresses(AddressVector& addresses,
  125. AddressFamily family = ANY_OK, bool expired_ok = false);
  126. /// \brief Return Address that corresponding to the index
  127. ///
  128. /// \param index The address index in the address vector
  129. /// \param family The address family, V4_ONLY or V6_ONLY
  130. asiolink::IOAddress getAddressAtIndex(size_t index,
  131. AddressFamily family) const;
  132. /// \brief Update RTT
  133. ///
  134. /// Updates the RTT for a particular address
  135. ///
  136. /// \param address Address to update
  137. /// \param rtt New RTT for the address
  138. void setAddressRTT(const asiolink::IOAddress& address, uint32_t rtt);
  139. /// \brief Update RTT of the address that corresponding to the index
  140. ///
  141. /// Shouldn't probably be used directly. Use corresponding
  142. /// NameserverAddress.
  143. /// \param rtt Round-Trip Time
  144. /// \param index The address's index in address vector
  145. /// \param family The address family, V4_ONLY or V6_ONLY
  146. void updateAddressRTTAtIndex(uint32_t rtt, size_t index,
  147. AddressFamily family);
  148. /**
  149. * \short Update RTT of an address.
  150. *
  151. * This is similar to updateAddressRTTAtIndex, but you pass the address,
  152. * not it's index. Passing the index might be unsafe, because the position
  153. * of the address or the cound of addresses may change in time.
  154. *
  155. * \param rtt Round-Trip Time
  156. * \param address The address whose RTT should be updated.
  157. * \param family The address family, V4_ONLY or V6_ONLY
  158. */
  159. void updateAddressRTT(uint32_t rtt, const asiolink::IOAddress& address,
  160. AddressFamily family);
  161. /// \brief Set Address Unreachable
  162. ///
  163. /// Sets the specified address to be unreachable
  164. ///
  165. /// \param address Address to update
  166. void setAddressUnreachable(const asiolink::IOAddress& address);
  167. /// \return Owner Name of RRset
  168. std::string getName() const {
  169. return name_;
  170. }
  171. /// \return Class of RRset
  172. const isc::dns::RRClass& getClass() const {
  173. return classCode_;
  174. }
  175. /// \return Hash Key of the Nameserver
  176. virtual HashKey hashKey() const {
  177. return HashKey(name_, classCode_);
  178. }
  179. /// \return Hash Key of the Nameserver
  180. /// \return Expiration Time of Data
  181. ///
  182. /// Returns the expiration time of addresses for this nameserver. For
  183. /// simplicity, this quantity is calculated as the minimum expiration time
  184. /// of the A and AAAA address records.
  185. time_t getExpiration() const {
  186. return expiration_;
  187. }
  188. /// \name Obtaining the IP addresses from resolver
  189. //@{
  190. /// \short A callback that some information here arrived (or are unavailable).
  191. struct Callback {
  192. virtual void operator()(boost::shared_ptr<NameserverEntry> self) = 0;
  193. /// \short Virtual destructor, so descendants are properly cleaned up
  194. virtual ~ Callback() {}
  195. };
  196. /**
  197. * \short Asks the resolver for IP address (or addresses).
  198. *
  199. * Adds a callback for given zone when they are ready or the information
  200. * is found unreachable.
  201. *
  202. * If it is not in NOT_ASKED or EXPIRED state, it does not ask the for the
  203. * IP address again, it just inserts the callback. It is up to the caller
  204. * not to insert one callback multiple times.
  205. *
  206. * The callback might be called directly from this function.
  207. *
  208. * \param resolver Who to ask.
  209. * \param callback The callback.
  210. * \param family Which addresses are interesting to the caller. This does
  211. * not change which adresses are requested, but the callback might
  212. * be executed when at last one requested type is available (eg. not
  213. * waiting for the other one).
  214. * \return The state the entry is currently in. It can return UNREACHABLE
  215. * even when there are addresses, if there are no addresses for this
  216. * family.
  217. */
  218. void askIP(isc::resolve::ResolverInterface* resolver,
  219. boost::shared_ptr<Callback> callback, AddressFamily family);
  220. //@}
  221. private:
  222. mutable isc::util::locks::recursive_mutex mutex_;///< Mutex protecting this object
  223. std::string name_; ///< Canonical name of the nameserver
  224. isc::dns::RRClass classCode_; ///< Class of the nameserver
  225. /**
  226. * \short Address lists.
  227. *
  228. * Only V4_ONLY and V6_ONLY is used, therefore we use the nearest larger
  229. * value as the size of the array.
  230. *
  231. * previous_addresses is kept until the data arrive again on re-fetch and
  232. * is used to pick up the RTTs from there.
  233. */
  234. std::vector<AddressEntry> addresses_[ANY_OK], previous_addresses_[ANY_OK];
  235. time_t expiration_; ///< Summary expiration time. 0 = unset
  236. // Do we have some addresses already? Do we expect some to come?
  237. // These are set after asking for IP, if NOT_ASKED, they are uninitialized
  238. bool has_address_[ADDR_REQ_MAX], expect_address_[ADDR_REQ_MAX];
  239. // Callbacks from resolver
  240. class ResolverCallback;
  241. friend class ResolverCallback;
  242. // Callbacks inserted into this object
  243. typedef std::pair<AddressFamily, boost::shared_ptr<Callback> >
  244. CallbackPair;
  245. std::vector<CallbackPair> callbacks_;
  246. /// \short Private version that does the actual asking of one address type
  247. ///
  248. /// Call unlocked.
  249. void askIP(isc::resolve::ResolverInterface* resolver,
  250. const isc::dns::RRType&, AddressFamily);
  251. };
  252. } // namespace dns
  253. } // namespace isc
  254. #endif // NAMESERVER_ENTRY_H