improved information content of logs: in LinkAnalyzer messages add cname chain
[pingcheck] / src / dns / dnsmaster.cpp
CommitLineData
36ad976b
CH
1/*
2 The software in this package is distributed under the GNU General
3 Public License version 2 (with a special exception described below).
4
5 A copy of GNU General Public License (GPL) is included in this distribution,
6 in the file COPYING.GPL.
7
8 As a special exception, if other files instantiate templates or use macros
9 or inline functions from this file, or you compile this file and link it
10 with other works to produce a work based on this file, this file
11 does not by itself cause the resulting work to be covered
12 by the GNU General Public License.
13
14 However the source code for this file must still be made available
15 in accordance with section (3) of the GNU General Public License.
16
17 This exception does not invalidate any other reasons why a work based
18 on this file might be covered by the GNU General Public License.
19
20 Christian Herdtweck, Intra2net AG 2015
21 */
22
c5b4902d 23#include "dns/dnsmaster.h"
36ad976b
CH
24
25#include <logfunc.hpp>
26#include <boost/bind.hpp>
36ad976b
CH
27#include <boost/asio/placeholders.hpp>
28
c5b4902d
CH
29#include "dns/ippseudoresolver.h"
30#include "dns/dnsresolver.h"
96779587 31
36ad976b 32using boost::bind;
36ad976b
CH
33using I2n::Logger::GlobalLogger;
34
96779587 35
36ad976b
CH
36DnsMasterItem DnsMaster::TheOnlyInstance;
37
8d26221d 38// just delegates work to other create_master function
96779587 39void DnsMaster::create_master(const IoServiceItem &io_serv,
ad83004d
CH
40 const boost::asio::ip::address &default_name_server,
41 const int resolved_ip_ttl_threshold,
f833126b 42 const int min_time_between_resolves,
ad83004d 43 const int max_address_resolution_attempts,
cd71d095 44 const int max_recursion_count,
ad83004d 45 const std::string &cache_file)
36ad976b 46{
c1abff61 47 GlobalLogger.info() << "DnsMaster: Creating cache";
f833126b
CH
48 DnsCacheItem cache(
49 new DnsCache(io_serv,
50 cache_file,
51 static_cast<uint32_t>(min_time_between_resolves)
52 )
53 );
54 create_master(io_serv,
55 default_name_server,
56 resolved_ip_ttl_threshold,
57 max_address_resolution_attempts,
cd71d095 58 max_recursion_count,
f833126b 59 cache);
8d26221d
CH
60}
61
62void DnsMaster::create_master(const IoServiceItem &io_serv,
63 const boost::asio::ip::address &default_name_server,
64 const int resolved_ip_ttl_threshold,
65 const int max_address_resolution_attempts,
cd71d095 66 const int max_recursion_count,
8d26221d
CH
67 const DnsCacheItem &cache)
68{
36ad976b
CH
69 if (TheOnlyInstance)
70 {
c1abff61
CH
71 GlobalLogger.warning() << "DnsMaster: "
72 << "Blocking attempt to create another instance!";
96779587 73 return;
36ad976b
CH
74 }
75
c1abff61 76 GlobalLogger.info() << "DNS Master: creating instance";
923626c0 77 TheOnlyInstance.reset( new DnsMaster(io_serv,
ad83004d 78 default_name_server,
923626c0
CH
79 resolved_ip_ttl_threshold,
80 max_address_resolution_attempts,
cd71d095 81 max_recursion_count,
923626c0
CH
82 cache)
83 );
36ad976b
CH
84}
85
36ad976b 86DnsMaster::DnsMaster(const IoServiceItem &io_serv,
ad83004d 87 const boost::asio::ip::address &default_name_server,
923626c0
CH
88 const int resolved_ip_ttl_threshold,
89 const int max_address_resolution_attempts,
cd71d095 90 const int max_recursion_count,
96779587 91 const DnsCacheItem &cache)
36ad976b 92 : IoService( io_serv )
ad83004d 93 , DefaultNameServer( default_name_server )
923626c0
CH
94 , ResolvedIpTtlThreshold( resolved_ip_ttl_threshold )
95 , MaxAddressResolutionAttempts( max_address_resolution_attempts )
cd71d095 96 , MaxRecursionCount( max_recursion_count )
96779587 97 , Cache(cache)
4e7b6ff9 98 , ResolverMap()
36ad976b 99{
36ad976b
CH
100}
101
102
103DnsMasterItem& DnsMaster::get_instance()
104{
105 if ( !TheOnlyInstance )
c1abff61
CH
106 GlobalLogger.error() << "DnsMaster: "
107 << "Request to return instance before creating it!";
36ad976b
CH
108 return TheOnlyInstance;
109}
110
c5b4902d
CH
111DnsMaster::~DnsMaster()
112{
c1abff61 113 GlobalLogger.info() << "DnsMaster: being destructed";
c5b4902d
CH
114
115 if (DnsMaster::TheOnlyInstance)
26b0f687
CH
116 { // apparently, this static variable still exists while itself is
117 // destructed...
c1abff61 118 //GlobalLogger.warning() << "DnsMaster: being destructed but not "
26b0f687 119 // << "singleton instance TheOnlyInstance!";
c5b4902d
CH
120 DnsMaster::TheOnlyInstance.reset();
121 }
122
123 // Items in ResolverMap and the DnsCache might still be referenced by
124 // Resolvers and are smart pointers, anyway --> nothing to do here
125}
126
36ad976b
CH
127
128
923626c0
CH
129ResolverItem& DnsMaster::get_resolver_for( const std::string &hostname,
130 const PingProtocol &ping_protocol )
131{
132 // find suitable DnsIpProtocol for ping protocol
dbe986b9 133 DnsIpProtocol protocol = ping2dns_protocol(ping_protocol);
923626c0
CH
134 return get_resolver_for(hostname, protocol);
135}
136
137
ad83004d 138ResolverItem& DnsMaster::get_resolver_for(const std::string &hostname,
e18c1337 139 const DnsIpProtocol &protocol)
36ad976b 140{
923626c0
CH
141 // create key to ResolverMap
142 resolver_key_type key(hostname, protocol);
dbe986b9 143 if ( ResolverMap.count(key) == 0 )
36ad976b
CH
144 { // need to create a resolver
145
146 // check if it is an ip address, so can create a simple pseudo resolver
dbe986b9 147 if ( is_ip(hostname) )
36ad976b 148 {
923626c0
CH
149 boost::asio::ip::address ip
150 = boost::asio::ip::address::from_string(hostname);
151 if ( (protocol == DNS_IPv4 && !ip.is_v4()) ||
152 (protocol == DNS_IPv6 && !ip.is_v6()) )
c1abff61
CH
153 GlobalLogger.warning() << "DnsMaster:"
154 << "Asked to create a DNS resolver "
923626c0
CH
155 << "for wrong IP protocol: v4 != v6! "
156 << "We will comply.";
c1abff61
CH
157 GlobalLogger.info() << "DnsMaster: Creating PseudoResolver for IP "
158 << ip;
4e7b6ff9
CH
159 ResolverItem new_resolver( new IpPseudoResolver(IoService,
160 hostname,
8f00b3df 161 protocol,
4e7b6ff9 162 Cache) );
dbe986b9 163 ResolverMap[key] = new_resolver;
36ad976b
CH
164 }
165 else
166 {
dbe986b9
CH
167 GlobalLogger.info() << "DnsMaster: Creating Resolver for host "
168 << hostname << " and protocol " << to_string(protocol);
4e7b6ff9
CH
169 ResolverItem new_resolver( new DnsResolver(IoService,
170 hostname,
923626c0 171 protocol,
4e7b6ff9 172 Cache,
ad83004d 173 DefaultNameServer) );
dbe986b9 174 ResolverMap[key] = new_resolver;
36ad976b
CH
175 }
176 }
dbe986b9 177 return ResolverMap[key];
36ad976b
CH
178}
179
180/**
181 * return true if given hostname string actually is an IP
182 *
96779587 183 * delegates decision to boost::asio::ip::address::from_string
36ad976b
CH
184 */
185bool DnsMaster::is_ip(const std::string &hostname) const
186{
187 try
188 {
96779587
CH
189 boost::asio::ip::address ip = boost::asio::ip::address::from_string(
190 hostname);
36ad976b
CH
191 return ip.is_v4() || ip.is_v6();
192 }
193 catch ( const std::exception &ex )
194 {
195 return false;
196 }
197}
198
923626c0 199
923626c0
CH
200/*boost::asio::ip::address &DnsMaster::get_name_server() const
201{
202 return NameServer;
203}*/
204
205int DnsMaster::get_resolved_ip_ttl_threshold() const
206{
207 return ResolvedIpTtlThreshold;
208}
209
210int DnsMaster::get_max_address_resolution_attempts() const
96779587 211{
923626c0 212 return MaxAddressResolutionAttempts;
96779587
CH
213}
214
cd71d095
CH
215int DnsMaster::get_max_recursion_count() const
216{
217 return MaxRecursionCount;
218}
219
e638894d
CH
220std::string DnsMaster::get_cname_chain_str(const std::string &hostname)
221{
222 DnsMasterItem master = get_instance();
223 if (master)
224 return master->Cache->get_cname_chain_str(hostname);
225 else
226 return hostname;
227}