tested new DNS with internal server, make more robust against caching; works nicely now
[pingcheck] / src / config / configuration.cpp
CommitLineData
91fcc471
TJ
1/*
2The software in this package is distributed under the GNU General
3Public License version 2 (with a special exception described below).
4
5A copy of GNU General Public License (GPL) is included in this distribution,
6in the file COPYING.GPL.
7
8As a special exception, if other files instantiate templates or use macros
9or inline functions from this file, or you compile this file and link it
10with other works to produce a work based on this file, this file
11does not by itself cause the resulting work to be covered
12by the GNU General Public License.
13
14However the source code for this file must still be made available
15in accordance with section (3) of the GNU General Public License.
16
17This exception does not invalidate any other reasons why a work based
18on this file might be covered by the GNU General Public License.
19*/
9c55ecd3 20#include "config/configuration.h"
8c3f445c 21
096b06ef
CH
22#include <set>
23#include <ctime> // for seeding random number generator
096b06ef
CH
24#include <boost/math/special_functions/round.hpp>
25#include <boost/numeric/conversion/cast.hpp>
26#include <boost/foreach.hpp>
27#include <boost/random/uniform_int.hpp>
28#include <boost/random/variate_generator.hpp>
ced28dc7 29
780b0bca
CH
30#include "boost_assert_handler.h"
31
aa48371a 32using namespace std;
f3c09c5a 33using I2n::Logger::LogLevel;
096b06ef
CH
34using I2n::Logger::GlobalLogger;
35
36typedef boost::uniform_int<> rand_dist_type;
37typedef boost::variate_generator<rand_gen_type&, rand_dist_type> rand_var_type;
14d14bd7
GMF
38
39//-----------------------------------------------------------------------------
40// Configuration
41//-----------------------------------------------------------------------------
aa48371a
GMF
42
43Configuration::Configuration() :
8ef29e4a 44 Daemon( false ),
f3c09c5a 45 LoggingLevel( LogLevel::Error ),
5ba17410 46 LoggingOutput( LogOutput_SYSLOG ),
33f408b1 47 ConfigFileName( "" ),
abb06ac2 48 SourceNetworkInterface( "" ),
61e224f8 49 NameServer( "" ),
a341119a
GMF
50 HostsDownLimit( 0 ),
51 MinHostsDownLimit( 0 ),
52 MaxHostsDownLimit( 50 ),
53 PingFailLimit( 0 ),
54 MinPingFailLimit( 0 ),
55 MaxPingFailLimit( 100 ),
d52d036a 56 StatusNotifierCmd( "" ),
4d6ab0f3 57 LinkUpIntervalInMin( 0 ),
1634f2a1 58 LinkDownIntervalInMin( 0 ),
4d6ab0f3
GMF
59 MinStableLinkIntervalInMin( 0 ),
60 MaxStableLinkIntervalInMin( 60 ),
079d19ab
CH
61 PingReplyTimeout( 30 ),
62 MaxAddressResolutionAttempts( 10 ),
63 ResolvedIpTtlThreshold( 10 ),
a901aed6 64 DnsCacheFile(""),
096b06ef
CH
65 Hosts(),
66 RatioRandomHosts( 1.0f ),
bfec40a6 67 PrintVersion( false ),
096b06ef 68 RandomNumberGenerator( boost::numeric_cast<unsigned int>(time(0)) )
ced28dc7
GMF
69{
70}
71
72Configuration::~Configuration()
73{
74}
aa48371a 75
8ef29e4a
GMF
76bool Configuration::get_daemon() const
77{
78 return Daemon;
79}
80
81void Configuration::set_daemon( bool daemon )
529e5587 82{ //lint !e578
8ef29e4a
GMF
83 Daemon = daemon;
84}
85
2c40f493
GMF
86LogLevel Configuration::get_log_level() const
87{
88 return LoggingLevel;
89}
90
91void Configuration::set_log_level( const LogLevel &log_level )
92{
f3c09c5a 93 BOOST_ASSERT( (LogLevel::Emergency <= log_level) && (log_level <= LogLevel::Debug) );
2c40f493
GMF
94
95 this->LoggingLevel = log_level;
96}
97
5ba17410
GMF
98LogOutput Configuration::get_log_output() const
99{
100 return LoggingOutput;
101}
102
103void Configuration::set_log_output( const LogOutput &log_output )
104{
105 BOOST_ASSERT( (LogOutput_First <= log_output) && (log_output <= LogOutput_Last) );
106
107 this->LoggingOutput = log_output;
108}
109
14d14bd7 110string Configuration::get_config_file_name() const
aa48371a 111{
33f408b1 112 return ConfigFileName;
14d14bd7 113}
aa48371a 114
e15b9466 115void Configuration::set_config_file_name( const string &config_file_name )
14d14bd7 116{
8c3f445c
GMF
117 BOOST_ASSERT( !config_file_name.empty() );
118
33f408b1 119 this->ConfigFileName = config_file_name;
aa48371a
GMF
120}
121
e15b9466 122string Configuration::get_nameserver() const
61e224f8
GMF
123{
124 return NameServer;
125}
126
e15b9466 127void Configuration::set_nameserver( const string &nameserver )
61e224f8
GMF
128{
129 NameServer = nameserver;
130}
131
abb06ac2
GMF
132string Configuration::get_source_network_interface() const
133{
134 return SourceNetworkInterface;
135}
136
137void Configuration::set_source_network_interface(
138 const string &source_network_interface
139)
140{
141 SourceNetworkInterface = source_network_interface;
142}
143
a341119a 144int Configuration::get_hosts_down_limit() const
aa48371a 145{
a341119a 146 return HostsDownLimit;
aa48371a
GMF
147}
148
a341119a 149void Configuration::set_hosts_down_limit( const int hosts_down_limit )
aa48371a 150{
f75a2748 151 BOOST_ASSERT( ( MinHostsDownLimit <= hosts_down_limit ) && ( hosts_down_limit <= MaxHostsDownLimit ) );
8c3f445c 152
a341119a 153 this->HostsDownLimit = hosts_down_limit;
aa48371a 154}
ad8eb8ab 155
a341119a 156int Configuration::get_ping_fail_limit() const
c5e4bfa1 157{
a341119a 158 return PingFailLimit;
c5e4bfa1
GMF
159}
160
a341119a 161void Configuration::set_ping_fail_limit( const int ping_fail_limit )
c5e4bfa1 162{
f75a2748
GMF
163 BOOST_ASSERT( ( MinPingFailLimit <= ping_fail_limit ) && ( ping_fail_limit <= MaxPingFailLimit ) );
164
a341119a 165 PingFailLimit = ping_fail_limit;
c5e4bfa1
GMF
166}
167
d52d036a
GMF
168string Configuration::get_status_notifier_cmd() const
169{
170 return StatusNotifierCmd;
171}
172
173void Configuration::set_status_notifier_cmd( const string &status_notifier_cmd )
174{
175 BOOST_ASSERT( !status_notifier_cmd.empty() );
176
177 StatusNotifierCmd = status_notifier_cmd;
178}
179
4d6ab0f3 180int Configuration::get_link_up_interval_in_min() const
fb09230d 181{
4d6ab0f3 182 return LinkUpIntervalInMin;
fb09230d
GMF
183}
184
7028b80b
GMF
185void Configuration::set_link_up_interval_in_min(
186 const int link_up_interval_in_min
187)
fb09230d 188{
4d6ab0f3 189 BOOST_ASSERT( ( MinStableLinkIntervalInMin <= link_up_interval_in_min ) && ( link_up_interval_in_min <= MaxStableLinkIntervalInMin ) );
f75a2748 190
4d6ab0f3 191 LinkUpIntervalInMin = link_up_interval_in_min;
fb09230d
GMF
192}
193
1634f2a1
GMF
194int Configuration::get_link_down_interval_in_min() const
195{
196 return LinkDownIntervalInMin;
197}
198
7028b80b
GMF
199void Configuration::set_link_down_interval_in_min(
200 const int link_down_interval_in_min
201)
1634f2a1
GMF
202{
203 BOOST_ASSERT( ( MinStableLinkIntervalInMin <= link_down_interval_in_min ) && ( link_down_interval_in_min <= MaxStableLinkIntervalInMin ) );
204
205 LinkDownIntervalInMin = link_down_interval_in_min;
206}
207
079d19ab
CH
208int Configuration::get_ping_reply_timeout() const
209{
210 return PingReplyTimeout;
211}
212void Configuration::set_ping_reply_timeout( const int ping_reply_timeout )
213{
214 BOOST_ASSERT(ping_reply_timeout > 0 );
215 PingReplyTimeout = ping_reply_timeout;
216}
217
218int Configuration::get_max_address_resolution_attempts() const
219{
220 return MaxAddressResolutionAttempts;
221}
222void Configuration::set_max_address_resolution_attempts( const int max_address_resolution_attempts )
223{
224 BOOST_ASSERT(max_address_resolution_attempts > 0 );
225 MaxAddressResolutionAttempts = max_address_resolution_attempts;
226}
227
228int Configuration::get_resolved_ip_ttl_threshold() const
229{
230 return ResolvedIpTtlThreshold;
231}
232void Configuration::set_resolved_ip_ttl_threshold( const int resolved_ip_ttl_threshold )
233{
fd62d09f 234 BOOST_ASSERT(resolved_ip_ttl_threshold >= 0 );
079d19ab
CH
235 ResolvedIpTtlThreshold = resolved_ip_ttl_threshold;
236}
237
a901aed6
CH
238void Configuration::set_dns_cache_file( const std::string &dns_cache_file)
239{
240 BOOST_ASSERT( !dns_cache_file.empty() );
241 DnsCacheFile = dns_cache_file;
242}
243
244std::string Configuration::get_dns_cache_file() const
245{
246 return DnsCacheFile;
247}
248
096b06ef
CH
249float Configuration::get_ratio_random_hosts() const
250{
251 return RatioRandomHosts;
252}
253
254void Configuration::set_ratio_random_hosts( const float ratio )
255{
256 BOOST_ASSERT( (ratio > 0.0f) && (ratio <= 1.0f) );
bfec40a6 257 RatioRandomHosts = ratio;
096b06ef
CH
258}
259
dbe36b16 260HostList Configuration::get_hosts() const
ad8eb8ab 261{
8739a651 262 return Hosts;
ad8eb8ab
GMF
263}
264
dbe36b16 265void Configuration::set_hosts( const HostList &hosts_list )
ad8eb8ab 266{
bfec40a6
CH
267 Hosts = hosts_list;
268}
269
270bool Configuration::get_print_version()
271{
272 return PrintVersion;
273}
274
275void Configuration::set_print_version( const bool do_print )
276{
277 PrintVersion = do_print;
ad8eb8ab
GMF
278}
279
096b06ef
CH
280int Configuration::get_random_number(const int lowest, const int highest)
281{
282 rand_dist_type random_distribution(lowest, highest);
283 rand_var_type random_variate(RandomNumberGenerator, random_distribution);
284 return random_variate();
285}
286
287/**
288 * @brief select RatioRandomHosts of the hosts at random.
289 * changes internal list of hosts
290 * @returns false if could not randomize (e.g. only 1 host
291 * available or ratio=1)
292 */
293bool Configuration::randomize_hosts()
294{
295 // need this a few times
296 unsigned int n_hosts = Hosts.size();
297 float n_hosts_float = boost::numeric_cast<float>(n_hosts);
298
299 // check if RatioRandomHosts == 1
300 if ((1. - RatioRandomHosts) < 0.5/n_hosts_float)
301 return false;
302
303 // determine number of hosts to keep
304 unsigned int n_wanted = boost::math::iround(n_hosts_float * RatioRandomHosts);
305 if (n_wanted == 0)
306 n_wanted = 1; // want at least 1 host
307 if (n_wanted == n_hosts) // e.g. always the case if only 1 host given
308 return false;
309
310 GlobalLogger.info() << "randomizing hosts: keeping "
311 << n_wanted << " from overall " << n_hosts;
312
313 BOOST_ASSERT(n_wanted <= n_hosts); // just to be sure
314
315 // create new set of hosts (more efficient than removal from std::vector Hosts)
316 std::set<HostItem> new_hosts;
317 int take_idx;
318
319 // add hosts at random until size is good
320 rand_dist_type random_distribution(0, n_hosts-1);
321 rand_var_type random_variate(RandomNumberGenerator, random_distribution);
322 while (new_hosts.size() < n_wanted)
323 {
324 take_idx = random_variate();
325 new_hosts.insert( Hosts[take_idx] ); // does nothing if host is already in there
326 }
327
328 // convert from set to list
329 HostList new_list;
330 BOOST_FOREACH(HostItem host, new_hosts)
331 new_list.push_back(host);
332
333 this->Hosts = new_list;
334
335 return true;
336}
337