ensured LogPrefix is used in DNS and PingScheduler; shortened lines; remove vim end...
[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,
42 const int max_address_resolution_attempts,
43 const std::string &cache_file)
36ad976b 44{
c1abff61 45 GlobalLogger.info() << "DnsMaster: Creating cache";
8d26221d
CH
46 DnsCacheItem cache( new DnsCache(io_serv, cache_file) );
47 create_master(io_serv, default_name_server, resolved_ip_ttl_threshold,
48 max_address_resolution_attempts, cache);
49}
50
51void DnsMaster::create_master(const IoServiceItem &io_serv,
52 const boost::asio::ip::address &default_name_server,
53 const int resolved_ip_ttl_threshold,
54 const int max_address_resolution_attempts,
55 const DnsCacheItem &cache)
56{
36ad976b
CH
57 if (TheOnlyInstance)
58 {
c1abff61
CH
59 GlobalLogger.warning() << "DnsMaster: "
60 << "Blocking attempt to create another instance!";
96779587 61 return;
36ad976b
CH
62 }
63
c1abff61 64 GlobalLogger.info() << "DNS Master: creating instance";
923626c0 65 TheOnlyInstance.reset( new DnsMaster(io_serv,
ad83004d 66 default_name_server,
923626c0
CH
67 resolved_ip_ttl_threshold,
68 max_address_resolution_attempts,
69 cache)
70 );
36ad976b
CH
71}
72
36ad976b 73DnsMaster::DnsMaster(const IoServiceItem &io_serv,
ad83004d 74 const boost::asio::ip::address &default_name_server,
923626c0
CH
75 const int resolved_ip_ttl_threshold,
76 const int max_address_resolution_attempts,
96779587 77 const DnsCacheItem &cache)
36ad976b 78 : IoService( io_serv )
ad83004d 79 , DefaultNameServer( default_name_server )
923626c0
CH
80 , ResolvedIpTtlThreshold( resolved_ip_ttl_threshold )
81 , MaxAddressResolutionAttempts( max_address_resolution_attempts )
96779587 82 , Cache(cache)
4e7b6ff9 83 , ResolverMap()
36ad976b 84{
36ad976b
CH
85}
86
87
88DnsMasterItem& DnsMaster::get_instance()
89{
90 if ( !TheOnlyInstance )
c1abff61
CH
91 GlobalLogger.error() << "DnsMaster: "
92 << "Request to return instance before creating it!";
36ad976b
CH
93 return TheOnlyInstance;
94}
95
c5b4902d
CH
96DnsMaster::~DnsMaster()
97{
c1abff61 98 GlobalLogger.info() << "DnsMaster: being destructed";
c5b4902d
CH
99
100 if (DnsMaster::TheOnlyInstance)
26b0f687
CH
101 { // apparently, this static variable still exists while itself is
102 // destructed...
c1abff61 103 //GlobalLogger.warning() << "DnsMaster: being destructed but not "
26b0f687 104 // << "singleton instance TheOnlyInstance!";
c5b4902d
CH
105 DnsMaster::TheOnlyInstance.reset();
106 }
107
108 // Items in ResolverMap and the DnsCache might still be referenced by
109 // Resolvers and are smart pointers, anyway --> nothing to do here
110}
111
36ad976b
CH
112
113
923626c0
CH
114ResolverItem& DnsMaster::get_resolver_for( const std::string &hostname,
115 const PingProtocol &ping_protocol )
116{
117 // find suitable DnsIpProtocol for ping protocol
dbe986b9 118 DnsIpProtocol protocol = ping2dns_protocol(ping_protocol);
923626c0
CH
119 return get_resolver_for(hostname, protocol);
120}
121
122
ad83004d 123ResolverItem& DnsMaster::get_resolver_for(const std::string &hostname,
e18c1337 124 const DnsIpProtocol &protocol)
36ad976b 125{
923626c0
CH
126 // create key to ResolverMap
127 resolver_key_type key(hostname, protocol);
dbe986b9 128 if ( ResolverMap.count(key) == 0 )
36ad976b
CH
129 { // need to create a resolver
130
131 // check if it is an ip address, so can create a simple pseudo resolver
dbe986b9 132 if ( is_ip(hostname) )
36ad976b 133 {
923626c0
CH
134 boost::asio::ip::address ip
135 = boost::asio::ip::address::from_string(hostname);
136 if ( (protocol == DNS_IPv4 && !ip.is_v4()) ||
137 (protocol == DNS_IPv6 && !ip.is_v6()) )
c1abff61
CH
138 GlobalLogger.warning() << "DnsMaster:"
139 << "Asked to create a DNS resolver "
923626c0
CH
140 << "for wrong IP protocol: v4 != v6! "
141 << "We will comply.";
c1abff61
CH
142 GlobalLogger.info() << "DnsMaster: Creating PseudoResolver for IP "
143 << ip;
4e7b6ff9
CH
144 ResolverItem new_resolver( new IpPseudoResolver(IoService,
145 hostname,
146 Cache) );
dbe986b9 147 ResolverMap[key] = new_resolver;
36ad976b
CH
148 }
149 else
150 {
dbe986b9
CH
151 GlobalLogger.info() << "DnsMaster: Creating Resolver for host "
152 << hostname << " and protocol " << to_string(protocol);
4e7b6ff9
CH
153 ResolverItem new_resolver( new DnsResolver(IoService,
154 hostname,
923626c0 155 protocol,
4e7b6ff9 156 Cache,
ad83004d 157 DefaultNameServer) );
dbe986b9 158 ResolverMap[key] = new_resolver;
36ad976b
CH
159 }
160 }
dbe986b9 161 return ResolverMap[key];
36ad976b
CH
162}
163
164/**
165 * return true if given hostname string actually is an IP
166 *
96779587 167 * delegates decision to boost::asio::ip::address::from_string
36ad976b
CH
168 */
169bool DnsMaster::is_ip(const std::string &hostname) const
170{
171 try
172 {
96779587
CH
173 boost::asio::ip::address ip = boost::asio::ip::address::from_string(
174 hostname);
36ad976b
CH
175 return ip.is_v4() || ip.is_v6();
176 }
177 catch ( const std::exception &ex )
178 {
179 return false;
180 }
181}
182
923626c0
CH
183
184DnsIpProtocol DnsMaster::ping2dns_protocol(const PingProtocol& pprot)
185{
186 switch (pprot)
187 {
188 case PingProtocol_ICMP: return DNS_IPv4; break;
189 case PingProtocol_ICMPv6: return DNS_IPv6; break;
190 case PingProtocol_TCP: return DNS_IPv4; break;
191 case PingProtocol_TCP_IPv6: return DNS_IPv6; break;
192 default:
c1abff61 193 GlobalLogger.warning() << "DnsMaster: Unexpected ping protocol: "
923626c0
CH
194 << static_cast<int>(pprot);
195 return DNS_IPALL;
196 break;
197 }
198}
199
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
e18c1337
CH
215std::string to_string(const DnsIpProtocol &protocol)
216{
217 switch (protocol)
218 {
219 case DNS_IPv4: return "IPv4"; break;
220 case DNS_IPv6: return "IPv6"; break;
221 case DNS_IPALL: return "IPv4/6"; break;
222 default: GlobalLogger.warning() << "Unexpected protocol in to_string!";
223 return "Unexpected Protocol"; break;
224 }
225}