/* The software in this package is distributed under the GNU General Public License version 2 (with a special exception described below). A copy of GNU General Public License (GPL) is included in this distribution, in the file COPYING.GPL. As a special exception, if other files instantiate templates or use macros or inline functions from this file, or you compile this file and link it with other works to produce a work based on this file, this file does not by itself cause the resulting work to be covered by the GNU General Public License. However the source code for this file must still be made available in accordance with section (3) of the GNU General Public License. This exception does not invalidate any other reasons why a work based on this file might be covered by the GNU General Public License. */ #include "config/configuration.h" #include #include // for seeding random number generator #include #include #include #include #include #include "boost_assert_handler.h" using namespace std; using I2n::Logger::LogLevel; using I2n::Logger::GlobalLogger; typedef boost::uniform_int<> rand_dist_type; typedef boost::variate_generator rand_var_type; //----------------------------------------------------------------------------- // Configuration //----------------------------------------------------------------------------- Configuration::Configuration() : Daemon( false ), LoggingLevel( LogLevel::Error ), LoggingOutput( LogOutput_SYSLOG ), LogFileName( "" ), ConfigFileName( "" ), SourceNetworkInterface( "" ), NameServer( "" ), HostsDownLimit( 0 ), MinHostsDownLimit( 0 ), MaxHostsDownLimit( 50 ), PingFailLimit( 0 ), MinPingFailLimit( 0 ), MaxPingFailLimit( 100 ), StatusNotifierCmd( "" ), LinkUpIntervalInSec( 0 ), LinkDownIntervalInSec( 0 ), MinStableLinkIntervalInSec( 0 ), MaxStableLinkIntervalInSec( 3600 ), PingReplyTimeout( 30 ), MaxAddressResolutionAttempts( 10 ), ResolvedIpTtlThreshold( 10 ), MinTimeBetweenResolves( 10 ), DnsCacheFile(""), Hosts(), RatioRandomHosts( 1.0f ), PrintVersion( false ), RandomNumberGenerator( boost::numeric_cast(time(0)) ) { } Configuration::~Configuration() { } bool Configuration::get_daemon() const { return Daemon; } void Configuration::set_daemon( bool daemon ) { //lint !e578 Daemon = daemon; } LogLevel Configuration::get_log_level() const { return LoggingLevel; } void Configuration::set_log_level( const LogLevel &log_level ) { BOOST_ASSERT( (LogLevel::Emergency <= log_level) && (log_level <= LogLevel::Debug) ); this->LoggingLevel = log_level; } LogOutput Configuration::get_log_output() const { return LoggingOutput; } void Configuration::set_log_output( const LogOutput &log_output ) { BOOST_ASSERT( (LogOutput_First <= log_output) && (log_output <= LogOutput_Last) ); this->LoggingOutput = log_output; } string Configuration::get_log_file() const { return LogFileName; } void Configuration::set_log_file( const std::string &log_file ) { BOOST_ASSERT( !log_file.empty() ); this->LogFileName = log_file; } string Configuration::get_config_file_name() const { return ConfigFileName; } void Configuration::set_config_file_name( const string &config_file_name ) { BOOST_ASSERT( !config_file_name.empty() ); this->ConfigFileName = config_file_name; } string Configuration::get_nameserver() const { return NameServer; } void Configuration::set_nameserver( const string &nameserver ) { NameServer = nameserver; } string Configuration::get_source_network_interface() const { return SourceNetworkInterface; } void Configuration::set_source_network_interface( const string &source_network_interface ) { SourceNetworkInterface = source_network_interface; } int Configuration::get_hosts_down_limit() const { return HostsDownLimit; } void Configuration::set_hosts_down_limit( const int hosts_down_limit ) { BOOST_ASSERT( ( MinHostsDownLimit <= hosts_down_limit ) && ( hosts_down_limit <= MaxHostsDownLimit ) ); this->HostsDownLimit = hosts_down_limit; } int Configuration::get_ping_fail_limit() const { return PingFailLimit; } void Configuration::set_ping_fail_limit( const int ping_fail_limit ) { BOOST_ASSERT( ( MinPingFailLimit <= ping_fail_limit ) && ( ping_fail_limit <= MaxPingFailLimit ) ); PingFailLimit = ping_fail_limit; } string Configuration::get_status_notifier_cmd() const { return StatusNotifierCmd; } void Configuration::set_status_notifier_cmd( const string &status_notifier_cmd ) { BOOST_ASSERT( !status_notifier_cmd.empty() ); StatusNotifierCmd = status_notifier_cmd; } int Configuration::get_link_up_interval_in_sec() const { return LinkUpIntervalInSec; } void Configuration::set_link_up_interval_in_sec( const int link_up_interval_in_sec ) { BOOST_ASSERT( ( MinStableLinkIntervalInSec <= link_up_interval_in_sec ) && ( link_up_interval_in_sec <= MaxStableLinkIntervalInSec ) ); LinkUpIntervalInSec = link_up_interval_in_sec; } int Configuration::get_link_down_interval_in_sec() const { return LinkDownIntervalInSec; } void Configuration::set_link_down_interval_in_sec( const int link_down_interval_in_sec ) { BOOST_ASSERT( ( MinStableLinkIntervalInSec <= link_down_interval_in_sec ) && ( link_down_interval_in_sec <= MaxStableLinkIntervalInSec ) ); LinkDownIntervalInSec = link_down_interval_in_sec; } int Configuration::get_ping_reply_timeout() const { return PingReplyTimeout; } void Configuration::set_ping_reply_timeout( const int ping_reply_timeout ) { BOOST_ASSERT(ping_reply_timeout > 0 ); PingReplyTimeout = ping_reply_timeout; } int Configuration::get_max_address_resolution_attempts() const { return MaxAddressResolutionAttempts; } void Configuration::set_max_address_resolution_attempts( const int max_address_resolution_attempts ) { BOOST_ASSERT(max_address_resolution_attempts > 0 ); MaxAddressResolutionAttempts = max_address_resolution_attempts; } int Configuration::get_resolved_ip_ttl_threshold() const { return ResolvedIpTtlThreshold; } void Configuration::set_resolved_ip_ttl_threshold( const int resolved_ip_ttl_threshold ) { BOOST_ASSERT(resolved_ip_ttl_threshold >= 0 ); ResolvedIpTtlThreshold = resolved_ip_ttl_threshold; } int Configuration::get_min_time_between_resolves() const { return MinTimeBetweenResolves; } void Configuration::set_min_time_between_resolves( const int min_time_between_resolves ) { BOOST_ASSERT(min_time_between_resolves >= 0 ); MinTimeBetweenResolves = min_time_between_resolves; } void Configuration::set_dns_cache_file( const std::string &dns_cache_file) { BOOST_ASSERT( !dns_cache_file.empty() ); DnsCacheFile = dns_cache_file; } std::string Configuration::get_dns_cache_file() const { return DnsCacheFile; } float Configuration::get_ratio_random_hosts() const { return RatioRandomHosts; } void Configuration::set_ratio_random_hosts( const float ratio ) { BOOST_ASSERT( (ratio > 0.0f) && (ratio <= 1.0f) ); RatioRandomHosts = ratio; } HostList Configuration::get_hosts() const { return Hosts; } void Configuration::set_hosts( const HostList &hosts_list ) { Hosts = hosts_list; } bool Configuration::get_print_version() { return PrintVersion; } void Configuration::set_print_version( const bool do_print ) { PrintVersion = do_print; } int Configuration::get_random_number(const int lowest, const int highest) { rand_dist_type random_distribution(lowest, highest); rand_var_type random_variate(RandomNumberGenerator, random_distribution); return random_variate(); } /** * @brief select RatioRandomHosts of the hosts at random. * changes internal list of hosts * @returns false if could not randomize (e.g. only 1 host * available or ratio=1) */ bool Configuration::randomize_hosts() { // need this a few times unsigned int n_hosts = Hosts.size(); float n_hosts_float = boost::numeric_cast(n_hosts); // check if RatioRandomHosts == 1 if ((1. - RatioRandomHosts) < 0.5/n_hosts_float) return false; // determine number of hosts to keep unsigned int n_wanted = boost::math::iround(n_hosts_float * RatioRandomHosts); if (n_wanted == 0) n_wanted = 1; // want at least 1 host if (n_wanted == n_hosts) // e.g. always the case if only 1 host given return false; GlobalLogger.info() << "randomizing hosts: keeping " << n_wanted << " from overall " << n_hosts; BOOST_ASSERT(n_wanted <= n_hosts); // just to be sure // create new set of hosts (more efficient than removal from std::vector Hosts) std::set new_hosts; int take_idx; // add hosts at random until size is good rand_dist_type random_distribution(0, n_hosts-1); rand_var_type random_variate(RandomNumberGenerator, random_distribution); while (new_hosts.size() < n_wanted) { take_idx = random_variate(); new_hosts.insert( Hosts[take_idx] ); // does nothing if host is already in there } // convert from set to list HostList new_list; BOOST_FOREACH(HostItem host, new_hosts) new_list.push_back(host); this->Hosts = new_list; return true; }