Commit | Line | Data |
---|---|---|
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 | 32 | using boost::bind; |
36ad976b CH |
33 | using I2n::Logger::GlobalLogger; |
34 | ||
96779587 | 35 | |
36ad976b CH |
36 | DnsMasterItem DnsMaster::TheOnlyInstance; |
37 | ||
96779587 | 38 | void DnsMaster::create_master(const IoServiceItem &io_serv, |
ad83004d CH |
39 | const boost::asio::ip::address &default_name_server, |
40 | const int resolved_ip_ttl_threshold, | |
41 | const int max_address_resolution_attempts, | |
42 | const std::string &cache_file) | |
36ad976b CH |
43 | { |
44 | if (TheOnlyInstance) | |
45 | { | |
46 | GlobalLogger.warning() | |
96779587 CH |
47 | << "Blocking attempt to create another DnsMaster instance!"; |
48 | return; | |
36ad976b CH |
49 | } |
50 | ||
923626c0 | 51 | GlobalLogger.info() << "Creating DNS Cache and Master"; |
96779587 | 52 | DnsCacheItem cache( new DnsCache(io_serv, cache_file) ); |
923626c0 | 53 | TheOnlyInstance.reset( new DnsMaster(io_serv, |
ad83004d | 54 | default_name_server, |
923626c0 CH |
55 | resolved_ip_ttl_threshold, |
56 | max_address_resolution_attempts, | |
57 | cache) | |
58 | ); | |
36ad976b CH |
59 | } |
60 | ||
61 | ||
62 | DnsMaster::DnsMaster(const IoServiceItem &io_serv, | |
ad83004d | 63 | const boost::asio::ip::address &default_name_server, |
923626c0 CH |
64 | const int resolved_ip_ttl_threshold, |
65 | const int max_address_resolution_attempts, | |
96779587 | 66 | const DnsCacheItem &cache) |
36ad976b | 67 | : IoService( io_serv ) |
ad83004d | 68 | , DefaultNameServer( default_name_server ) |
923626c0 CH |
69 | , ResolvedIpTtlThreshold( resolved_ip_ttl_threshold ) |
70 | , MaxAddressResolutionAttempts( max_address_resolution_attempts ) | |
96779587 | 71 | , Cache(cache) |
4e7b6ff9 | 72 | , ResolverMap() |
36ad976b | 73 | { |
36ad976b CH |
74 | } |
75 | ||
76 | ||
77 | DnsMasterItem& DnsMaster::get_instance() | |
78 | { | |
79 | if ( !TheOnlyInstance ) | |
80 | GlobalLogger.error() | |
81 | << "Request to return DnsMaster instance before creating it!"; | |
82 | return TheOnlyInstance; | |
83 | } | |
84 | ||
c5b4902d CH |
85 | DnsMaster::~DnsMaster() |
86 | { | |
87 | GlobalLogger.info() << "DnsMaster is being destructed"; | |
88 | ||
89 | if (DnsMaster::TheOnlyInstance) | |
90 | { // just to be sure ... | |
91 | GlobalLogger.warning() << "DnsMaster is being destructed that is not " | |
92 | << "singleton instance TheOnlyInstance!"; | |
93 | DnsMaster::TheOnlyInstance.reset(); | |
94 | } | |
95 | ||
96 | // Items in ResolverMap and the DnsCache might still be referenced by | |
97 | // Resolvers and are smart pointers, anyway --> nothing to do here | |
98 | } | |
99 | ||
36ad976b CH |
100 | |
101 | ||
923626c0 CH |
102 | ResolverItem& DnsMaster::get_resolver_for( const std::string &hostname, |
103 | const PingProtocol &ping_protocol ) | |
104 | { | |
105 | // find suitable DnsIpProtocol for ping protocol | |
106 | DnsIpProtocol protocol = DnsMaster::ping2dns_protocol(ping_protocol); | |
107 | return get_resolver_for(hostname, protocol); | |
108 | } | |
109 | ||
110 | ||
ad83004d CH |
111 | ResolverItem& DnsMaster::get_resolver_for(const std::string &hostname, |
112 | const DnsIpProtocol &protocol) | |
36ad976b CH |
113 | { |
114 | DnsMasterItem master = get_instance(); | |
923626c0 CH |
115 | |
116 | // create key to ResolverMap | |
117 | resolver_key_type key(hostname, protocol); | |
118 | if ( master->ResolverMap.count(key) == 0 ) | |
36ad976b CH |
119 | { // need to create a resolver |
120 | ||
121 | // check if it is an ip address, so can create a simple pseudo resolver | |
122 | if ( master->is_ip(hostname) ) | |
123 | { | |
923626c0 CH |
124 | boost::asio::ip::address ip |
125 | = boost::asio::ip::address::from_string(hostname); | |
126 | if ( (protocol == DNS_IPv4 && !ip.is_v4()) || | |
127 | (protocol == DNS_IPv6 && !ip.is_v6()) ) | |
128 | GlobalLogger.warning() << "Asked to create a DNS resolver " | |
129 | << "for wrong IP protocol: v4 != v6! " | |
130 | << "We will comply."; | |
131 | GlobalLogger.info() << "Creating PseudoResolver for IP " << ip; | |
4e7b6ff9 CH |
132 | ResolverItem new_resolver( new IpPseudoResolver(IoService, |
133 | hostname, | |
134 | Cache) ); | |
923626c0 | 135 | master->ResolverMap[key] = new_resolver; |
36ad976b CH |
136 | } |
137 | else | |
138 | { | |
96779587 | 139 | GlobalLogger.info() << "Creating Resolver for host " << hostname; |
4e7b6ff9 CH |
140 | ResolverItem new_resolver( new DnsResolver(IoService, |
141 | hostname, | |
923626c0 | 142 | protocol, |
4e7b6ff9 | 143 | Cache, |
ad83004d | 144 | DefaultNameServer) ); |
923626c0 | 145 | master->ResolverMap[key] = new_resolver; |
36ad976b CH |
146 | } |
147 | } | |
923626c0 | 148 | return master->ResolverMap[key]; |
36ad976b CH |
149 | } |
150 | ||
ad83004d CH |
151 | // create resolver but do not remember it in ResolverMap |
152 | ResolverItem DnsMaster::get_recursor_for(const std::string &hostname, | |
153 | const DnsIpProtocol &protocol, | |
154 | const boost::asio::ip::address &name_server) | |
155 | { | |
156 | ResolverItem new_resolver( new DnsResolver(IoService, | |
157 | hostname, | |
158 | protocol, | |
159 | Cache, | |
160 | name_server) ); | |
161 | return new_resolver; | |
162 | } | |
163 | ||
36ad976b CH |
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 | */ |
169 | bool 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 | |
184 | DnsIpProtocol 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: | |
193 | GlobalLogger.warning() << "Unexpected ping protocol: " | |
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 | ||
205 | int DnsMaster::get_resolved_ip_ttl_threshold() const | |
206 | { | |
207 | return ResolvedIpTtlThreshold; | |
208 | } | |
209 | ||
210 | int DnsMaster::get_max_address_resolution_attempts() const | |
96779587 | 211 | { |
923626c0 | 212 | return MaxAddressResolutionAttempts; |
96779587 CH |
213 | } |
214 | ||
36ad976b CH |
215 | // (created using vim -- the world's best text editor) |
216 |