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