nameserver_entry.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  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 "address_entry.h"
  24. #include "asiolink.h"
  25. #include "nsas_types.h"
  26. #include "hash_key.h"
  27. #include "lru_list.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. /*
  96. * \brief Return Address
  97. *
  98. * Returns a vector of addresses corresponding to this nameserver.
  99. *
  100. * \param addresses Vector of address entries into which will be appended
  101. * addresses that match the specified criteria. (The reason for
  102. * choosing this signature is that addresses from more than one
  103. * nameserver may be retrieved, in which case appending to an existing
  104. * list of addresses is convenient.)
  105. * \param family The family of address that is requested.
  106. * \param expired_ok Return addresses even when expired. This is here
  107. * because an address with TTL 0 is expired at the exact time it
  108. * arrives. But when we call the callback, the owner of callback
  109. * is allowed to use them anyway so it should set expired_ok
  110. * to true.
  111. * \return The state this is currently in. If the TTL expires, it enters
  112. * the EXPIRED state by itself and passes no addresses. It may be
  113. * IN_PROGRESS and still return some addresses (when one address family
  114. * arrived and is is returned, but the other is still on the way).
  115. * \todo Should we sort out unreachable addresses as well?
  116. */
  117. Fetchable::State getAddresses(AddressVector& addresses,
  118. AddressFamily family = ANY_OK, bool expired_ok = false);
  119. /// \brief Return Address that corresponding to the index
  120. ///
  121. /// \param index The address index in the address vector
  122. /// \param family The address family, V4_ONLY or V6_ONLY
  123. asiolink::IOAddress getAddressAtIndex(size_t index,
  124. AddressFamily family) const;
  125. /// \brief Update RTT
  126. ///
  127. /// Updates the RTT for a particular address
  128. ///
  129. /// \param address Address to update
  130. /// \param RTT New RTT for the address
  131. void setAddressRTT(const asiolink::IOAddress& address, uint32_t rtt);
  132. /// \brief Update RTT of the address that corresponding to the index
  133. ///
  134. /// Shouldn't probably be used directly. Use corresponding
  135. /// NameserverAddress.
  136. /// \param rtt Round-Trip Time
  137. /// \param index The address's index in address vector
  138. /// \param family The address family, V4_ONLY or V6_ONLY
  139. void updateAddressRTTAtIndex(uint32_t rtt, size_t index,
  140. AddressFamily family);
  141. /**
  142. * \short Update RTT of an address.
  143. *
  144. * This is similar to updateAddressRTTAtIndex, but you pass the address,
  145. * not it's index. Passing the index might be unsafe, because the position
  146. * of the address or the cound of addresses may change in time.
  147. *
  148. * \param rtt Round-Trip Time
  149. * \param address The address whose RTT should be updated.
  150. * \param family The address family, V4_ONLY or V6_ONLY
  151. */
  152. void updateAddressRTT(uint32_t rtt, const asiolink::IOAddress& address,
  153. AddressFamily family);
  154. /// \brief Set Address Unreachable
  155. ///
  156. /// Sets the specified address to be unreachable
  157. ///
  158. /// \param address Address to update
  159. void setAddressUnreachable(const asiolink::IOAddress& address);
  160. /// \return Owner Name of RRset
  161. std::string getName() const {
  162. return name_;
  163. }
  164. /// \return Class of RRset
  165. const isc::dns::RRClass& getClass() const {
  166. return classCode_;
  167. }
  168. /// \return Hash Key of the Nameserver
  169. virtual HashKey hashKey() const {
  170. return HashKey(name_, classCode_);
  171. }
  172. /// \return Hash Key of the Nameserver
  173. /// \return Expiration Time of Data
  174. ///
  175. /// Returns the expiration time of addresses for this nameserver. For
  176. /// simplicity, this quantity is calculated as the minimum expiration time
  177. /// of the A and AAAA address records.
  178. time_t getExpiration() const {
  179. return expiration_;
  180. }
  181. /// \name Obtaining the IP addresses from resolver
  182. //@{
  183. /// \short A callback that some information here arrived (or are unavailable).
  184. struct Callback {
  185. virtual void operator()(boost::shared_ptr<NameserverEntry> self) = 0;
  186. /// \short Virtual destructor, so descendants are properly cleaned up
  187. virtual ~ Callback() {}
  188. };
  189. /**
  190. * \short Asks the resolver for IP address (or addresses).
  191. *
  192. * Adds a callback for given zone when they are ready or the information
  193. * is found unreachable.
  194. *
  195. * If it is not in NOT_ASKED or EXPIRED state, it does not ask the for the
  196. * IP address again, it just inserts the callback. It is up to the caller
  197. * not to insert one callback multiple times.
  198. *
  199. * The callback might be called directly from this function.
  200. *
  201. * \param resolver Who to ask.
  202. * \param callback The callback.
  203. * \param family Which addresses are interesting to the caller. This does
  204. * not change which adresses are requested, but the callback might
  205. * be executed when at last one requested type is available (eg. not
  206. * waiting for the other one).
  207. * \return The state the entry is currently in. It can return UNREACHABLE
  208. * even when there are addresses, if there are no addresses for this
  209. * family.
  210. */
  211. void askIP(boost::shared_ptr<isc::resolve::ResolverInterface> resolver,
  212. boost::shared_ptr<Callback> callback, AddressFamily family);
  213. //@}
  214. private:
  215. mutable isc::locks::recursive_mutex mutex_;///< Mutex protecting this object
  216. std::string name_; ///< Canonical name of the nameserver
  217. isc::dns::RRClass classCode_; ///< Class of the nameserver
  218. /**
  219. * \short Address lists.
  220. *
  221. * Only V4_ONLY and V6_ONLY is used, therefore we use the nearest larger
  222. * value as the size of the array.
  223. *
  224. * previous_addresses is kept until the data arrive again on re-fetch and
  225. * is used to pick up the RTTs from there.
  226. */
  227. std::vector<AddressEntry> addresses_[ANY_OK], previous_addresses_[ANY_OK];
  228. time_t expiration_; ///< Summary expiration time. 0 = unset
  229. // Do we have some addresses already? Do we expect some to come?
  230. // These are set after asking for IP, if NOT_ASKED, they are uninitialized
  231. bool has_address_[ADDR_REQ_MAX], expect_address_[ADDR_REQ_MAX];
  232. // Callbacks from resolver
  233. class ResolverCallback;
  234. friend class ResolverCallback;
  235. // Callbacks inserted into this object
  236. typedef std::pair<AddressFamily, boost::shared_ptr<Callback> >
  237. CallbackPair;
  238. std::vector<CallbackPair> callbacks_;
  239. /// \short Private version that does the actual asking of one address type
  240. ///
  241. /// Call unlocked.
  242. void askIP(boost::shared_ptr<isc::resolve::ResolverInterface> resolver,
  243. const isc::dns::RRType&, AddressFamily);
  244. };
  245. } // namespace dns
  246. } // namespace isc
  247. #endif // __NAMESERVER_ENTRY_H