From: Christian Herdtweck Date: Mon, 4 May 2015 08:47:53 +0000 (+0200) Subject: added option min-time-between-resolves-option and tests for it X-Git-Url: http://developer.intra2net.com/git/?p=pingcheck;a=commitdiff_plain;h=f833126b51898c1092d3f782924b24ec1c5ca4ae added option min-time-between-resolves-option and tests for it --- diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 68ab5db..efed741 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -59,6 +59,7 @@ set(SOURCES config/option/pingreplytimeoutoption.cpp config/option/maxaddressresolutionattemptsoption.cpp config/option/resolvedipttlthresholdoption.cpp + config/option/mintimebetweenresolvesoption.cpp config/option/dnscachefileoption.cpp dns/timetolive.cpp dns/hostaddress.cpp diff --git a/src/config/configuration.cpp b/src/config/configuration.cpp index 48971fd..c030e81 100644 --- a/src/config/configuration.cpp +++ b/src/config/configuration.cpp @@ -62,6 +62,7 @@ Configuration::Configuration() : PingReplyTimeout( 30 ), MaxAddressResolutionAttempts( 10 ), ResolvedIpTtlThreshold( 10 ), + MinTimeBetweenResolves( 10 ), DnsCacheFile(""), Hosts(), RatioRandomHosts( 1.0f ), @@ -248,6 +249,16 @@ void Configuration::set_resolved_ip_ttl_threshold( const int resolved_ip_ttl_thr 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() ); diff --git a/src/config/configuration.h b/src/config/configuration.h index ca0c5a7..32e9d13 100644 --- a/src/config/configuration.h +++ b/src/config/configuration.h @@ -98,6 +98,10 @@ public: void set_resolved_ip_ttl_threshold( const int resolved_ip_ttl_threshold ); + int get_min_time_between_resolves() const; + void set_min_time_between_resolves( + const int min_time_between_resolves ); + std::string get_dns_cache_file() const; void set_dns_cache_file(const std::string &dns_cache_file); @@ -136,6 +140,7 @@ private: int PingReplyTimeout; int MaxAddressResolutionAttempts; int ResolvedIpTtlThreshold; + int MinTimeBetweenResolves; std::string DnsCacheFile; HostList Hosts; float RatioRandomHosts; diff --git a/src/config/configurationoptions.cpp b/src/config/configurationoptions.cpp index 3c975eb..9e574dd 100644 --- a/src/config/configurationoptions.cpp +++ b/src/config/configurationoptions.cpp @@ -49,6 +49,7 @@ #include "config/option/pingreplytimeoutoption.h" #include "config/option/maxaddressresolutionattemptsoption.h" #include "config/option/resolvedipttlthresholdoption.h" +#include "config/option/mintimebetweenresolvesoption.h" #include "config/option/dnscachefileoption.h" using namespace std; @@ -121,6 +122,9 @@ ConfigurationOptions::ConfigurationOptions() : ConfigurationOptionItem resolved_ip_ttl_threshold( new ResolvedIpTtlThresholdOption ); ConfigOptions.push_back( resolved_ip_ttl_threshold ); + ConfigurationOptionItem min_time_between_resolves( new MinTimeBetweenResolvesOption ); + ConfigOptions.push_back( min_time_between_resolves ); + ConfigurationOptionItem ratio_random_hosts( new RatioRandomHostsOption ); ConfigOptions.push_back( ratio_random_hosts ); diff --git a/src/config/option/mintimebetweenresolvesoption.cpp b/src/config/option/mintimebetweenresolvesoption.cpp new file mode 100644 index 0000000..2f279fa --- /dev/null +++ b/src/config/option/mintimebetweenresolvesoption.cpp @@ -0,0 +1,65 @@ +/* + 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/option/mintimebetweenresolvesoption.h" + +#include + +using namespace std; +using boost::program_options::value; +using boost::program_options::variables_map; +using I2n::Logger::GlobalLogger; + +//----------------------------------------------------------------------------- +// MinTimeBetweenResolvesOption +//----------------------------------------------------------------------------- + +MinTimeBetweenResolvesOption::MinTimeBetweenResolvesOption() : + ConfigurationOption( + "min-time-between-resolves", + value()->default_value( 10 ), + "Minimum time in seconds between calls to DNS resolve of same address" + ) +{ +} + +MinTimeBetweenResolvesOption::~MinTimeBetweenResolvesOption() +{ +} + +bool MinTimeBetweenResolvesOption::parse( + const variables_map& vm, + Configuration *configuration +) +{ + // default-source-network-interface + if ( 1 <= vm.count( get_command_string() ) ) + { + int thresh = vm[ get_command_string() ].as (); + configuration->set_min_time_between_resolves( thresh ); + + GlobalLogger.info() << get_command_string() << "=" + << thresh << endl; + + return true; + } + + return false; +} diff --git a/src/config/option/mintimebetweenresolvesoption.h b/src/config/option/mintimebetweenresolvesoption.h new file mode 100644 index 0000000..4ab1f71 --- /dev/null +++ b/src/config/option/mintimebetweenresolvesoption.h @@ -0,0 +1,49 @@ +/* + 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. + */ + +#ifndef MIN_TIME_BETWEEN_RESOLVES_OPTION_H +#define MIN_TIME_BETWEEN_RESOLVES_OPTION_H + +#include + +#include "config/option/configurationoption.h" + +//----------------------------------------------------------------------------- +// MinTimeBetweenResolvesOption +//----------------------------------------------------------------------------- + +/** + * @brief This class represents the "min-time-between-resolves" + * configuration option. + */ +class MinTimeBetweenResolvesOption : public ConfigurationOption +{ +public: + MinTimeBetweenResolvesOption(); + virtual ~MinTimeBetweenResolvesOption(); + + virtual bool parse( + const boost::program_options::variables_map &vm, + Configuration *configuration + ); + +}; + +#endif // MIN_TIME_BETWEEN_RESOLVES_OPTION_H diff --git a/src/dns/dnscache.cpp b/src/dns/dnscache.cpp index c79ef83..4c524e7 100644 --- a/src/dns/dnscache.cpp +++ b/src/dns/dnscache.cpp @@ -49,6 +49,10 @@ namespace Config int MaxRetrievalRecursions = 10; } +// ----------------------------------------------------------------------------- +// Cname +// ----------------------------------------------------------------------------- + Cname::Cname() : Host() , Ttl() @@ -65,15 +69,21 @@ Cname::Cname(const std::string &host, const TimeToLive &ttl) {} +// ----------------------------------------------------------------------------- +// DNS Cache constructor / destructor +// ----------------------------------------------------------------------------- + const string DnsCache::DoNotUseCacheFile = "do not use cache file!"; DnsCache::DnsCache(const IoServiceItem &io_serv, - const std::string &cache_file) + const std::string &cache_file, + const uint32_t min_time_between_resolves) : IpCache() , CnameCache() , SaveTimer( *io_serv ) , CacheFile( cache_file ) , HasChanged( false ) + , MinTimeBetweenResolves( min_time_between_resolves ) { // load cache from file load_from_cachefile(); @@ -97,6 +107,10 @@ DnsCache::~DnsCache() } +// ----------------------------------------------------------------------------- +// LOAD / SAVE +// ----------------------------------------------------------------------------- + void DnsCache::schedule_save(const boost::system::error_code &error) { // just in case: ensure SaveTimer is cancelled @@ -190,6 +204,10 @@ void DnsCache::load_from_cachefile() } +// ----------------------------------------------------------------------------- +// UPDATE +// ----------------------------------------------------------------------------- + // warn if hostname is empty and remove trailing dot std::string DnsCache::key_for_hostname(const std::string &hostname) const { @@ -217,9 +235,26 @@ void DnsCache::update(const std::string &hostname, << " removes CNAME to " << get_cname(hostname).Host << "!"; update(hostname, Cname()); // overwrite with "empty" cname } + // ensure min ttl of MinTimeBetweenResolves + HostAddressVec ips_checked; + BOOST_FOREACH( const HostAddress &addr, new_ips ) + { + if ( addr.get_ttl().get_value() < MinTimeBetweenResolves ) + { + GlobalLogger.info() << "DnsCache: Correcting TTL of IP for " + << hostname << " from " << addr.get_ttl().get_value() << "s to " + << MinTimeBetweenResolves << "s because was too short"; + ips_checked.push_back( HostAddress( addr.get_ip(), + MinTimeBetweenResolves) ); + } + else + ips_checked.push_back(addr); + } + GlobalLogger.info() << "DnsCache: update IPs for " << key - << " to " << new_ips.size() << "-list"; - IpCache[key] = new_ips; + << " to " << ips_checked.size() << "-list"; + + IpCache[key] = ips_checked; HasChanged = true; } @@ -239,6 +274,15 @@ void DnsCache::update(const std::string &hostname, Cname to_save = Cname(key_for_hostname(cname.Host), cname.Ttl); + // ensure min ttl of MinTimeBetweenResolves + if ( to_save.Ttl.get_value() < MinTimeBetweenResolves ) + { + GlobalLogger.info() << "DnsCache: Correcting TTL of CNAME of " + << hostname << " from " << to_save.Ttl.get_value() << "s to " + << MinTimeBetweenResolves << "s because was too short"; + to_save.Ttl = TimeToLive(MinTimeBetweenResolves); + } + GlobalLogger.info() << "DnsCache: update CNAME for " << key << " to " << to_save.Host; CnameCache[key] = to_save; @@ -246,6 +290,10 @@ void DnsCache::update(const std::string &hostname, } +// ----------------------------------------------------------------------------- +// RETRIEVAL +// ----------------------------------------------------------------------------- + /** * @returns empty list if no (up to date) ips for hostname in cache */ diff --git a/src/dns/dnscache.h b/src/dns/dnscache.h index 3bc1758..c165c0d 100644 --- a/src/dns/dnscache.h +++ b/src/dns/dnscache.h @@ -51,7 +51,8 @@ public: static const std::string DoNotUseCacheFile; DnsCache( const IoServiceItem &io_serv, - const std::string &cache_file ); + const std::string &cache_file, + const uint32_t min_time_between_resolves ); ~DnsCache(); // accessed from ResolverBase subclasses @@ -75,6 +76,7 @@ private: boost::asio::deadline_timer SaveTimer; std::string CacheFile; bool HasChanged; + uint32_t MinTimeBetweenResolves; // internal functions private: diff --git a/src/dns/dnsmaster.cpp b/src/dns/dnsmaster.cpp index f25f09c..7235a1e 100644 --- a/src/dns/dnsmaster.cpp +++ b/src/dns/dnsmaster.cpp @@ -39,13 +39,22 @@ DnsMasterItem DnsMaster::TheOnlyInstance; void DnsMaster::create_master(const IoServiceItem &io_serv, const boost::asio::ip::address &default_name_server, const int resolved_ip_ttl_threshold, + const int min_time_between_resolves, const int max_address_resolution_attempts, const std::string &cache_file) { GlobalLogger.info() << "DnsMaster: Creating cache"; - DnsCacheItem cache( new DnsCache(io_serv, cache_file) ); - create_master(io_serv, default_name_server, resolved_ip_ttl_threshold, - max_address_resolution_attempts, cache); + DnsCacheItem cache( + new DnsCache(io_serv, + cache_file, + static_cast(min_time_between_resolves) + ) + ); + create_master(io_serv, + default_name_server, + resolved_ip_ttl_threshold, + max_address_resolution_attempts, + cache); } void DnsMaster::create_master(const IoServiceItem &io_serv, diff --git a/src/dns/dnsmaster.h b/src/dns/dnsmaster.h index 1976ba5..424d8ba 100644 --- a/src/dns/dnsmaster.h +++ b/src/dns/dnsmaster.h @@ -100,6 +100,7 @@ public: static void create_master(const IoServiceItem &io_serv, const boost::asio::ip::address &default_name_server, const int resolved_ip_ttl_threshold, + const int min_time_between_resolves, const int max_address_resolution_attempts, const std::string &cache_file); static void create_master(const IoServiceItem &io_serv, diff --git a/src/main.cpp b/src/main.cpp index 1463001..5fffb50 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -517,6 +517,7 @@ int main( int argc, const char *argv[] ) io_service, name_server_ip, configuration->get_resolved_ip_ttl_threshold(), + configuration->get_min_time_between_resolves(), configuration->get_max_address_resolution_attempts(), configuration->get_dns_cache_file() ); diff --git a/test/CMakeLists.test_configurationcommandline.txt b/test/CMakeLists.test_configurationcommandline.txt index 589996c..b8788eb 100644 --- a/test/CMakeLists.test_configurationcommandline.txt +++ b/test/CMakeLists.test_configurationcommandline.txt @@ -31,6 +31,7 @@ add_executable(test_configurationcommandline ${CMAKE_SOURCE_DIR}/src/config/option/pingreplytimeoutoption.cpp ${CMAKE_SOURCE_DIR}/src/config/option/maxaddressresolutionattemptsoption.cpp ${CMAKE_SOURCE_DIR}/src/config/option/resolvedipttlthresholdoption.cpp + ${CMAKE_SOURCE_DIR}/src/config/option/mintimebetweenresolvesoption.cpp ${CMAKE_SOURCE_DIR}/src/config/option/dnscachefileoption.cpp ${CMAKE_SOURCE_DIR}/src/host/loglevel.cpp ${CMAKE_SOURCE_DIR}/src/host/logoutput.cpp diff --git a/test/CMakeLists.test_configurationfile.txt b/test/CMakeLists.test_configurationfile.txt index a3fa1f7..522a18b 100644 --- a/test/CMakeLists.test_configurationfile.txt +++ b/test/CMakeLists.test_configurationfile.txt @@ -31,6 +31,7 @@ add_executable(test_configurationfile ${CMAKE_SOURCE_DIR}/src/config/option/pingreplytimeoutoption.cpp ${CMAKE_SOURCE_DIR}/src/config/option/maxaddressresolutionattemptsoption.cpp ${CMAKE_SOURCE_DIR}/src/config/option/resolvedipttlthresholdoption.cpp + ${CMAKE_SOURCE_DIR}/src/config/option/mintimebetweenresolvesoption.cpp ${CMAKE_SOURCE_DIR}/src/config/option/dnscachefileoption.cpp ${CMAKE_SOURCE_DIR}/src/host/loglevel.cpp ${CMAKE_SOURCE_DIR}/src/host/logoutput.cpp diff --git a/test/CMakeLists.test_configurationoptions.txt b/test/CMakeLists.test_configurationoptions.txt index b96956c..f2fea82 100644 --- a/test/CMakeLists.test_configurationoptions.txt +++ b/test/CMakeLists.test_configurationoptions.txt @@ -29,6 +29,7 @@ add_executable(test_configurationoptions ${CMAKE_SOURCE_DIR}/src/config/option/pingreplytimeoutoption.cpp ${CMAKE_SOURCE_DIR}/src/config/option/maxaddressresolutionattemptsoption.cpp ${CMAKE_SOURCE_DIR}/src/config/option/resolvedipttlthresholdoption.cpp + ${CMAKE_SOURCE_DIR}/src/config/option/mintimebetweenresolvesoption.cpp ${CMAKE_SOURCE_DIR}/src/config/option/dnscachefileoption.cpp ${CMAKE_SOURCE_DIR}/src/host/loglevel.cpp ${CMAKE_SOURCE_DIR}/src/host/logoutput.cpp diff --git a/test/test_configurationoptions.cpp b/test/test_configurationoptions.cpp index 86463bc..bf4e418 100644 --- a/test/test_configurationoptions.cpp +++ b/test/test_configurationoptions.cpp @@ -124,7 +124,7 @@ BOOST_AUTO_TEST_CASE( get_configuration_options ) // if this assert fails, you must add or remove one of the options in the // test below. Will probably find them all in // src/config/configurationoptions.cpp constructor - BOOST_CHECK_EQUAL( options.size(), 17 ); + BOOST_CHECK_EQUAL( options.size(), 18 ); BOOST_CHECK_EQUAL( option_present( options, "hosts-down-limit" ), true ); BOOST_CHECK_EQUAL( option_present( options, "link-down-interval" ), true ); @@ -136,6 +136,7 @@ BOOST_AUTO_TEST_CASE( get_configuration_options ) BOOST_CHECK_EQUAL( option_present( options, "ping-reply-timeout" ), true ); BOOST_CHECK_EQUAL( option_present( options, "max-address-resolution-attempts" ), true ); BOOST_CHECK_EQUAL( option_present( options, "resolved-ip-ttl-threshold" ), true ); + BOOST_CHECK_EQUAL( option_present( options, "min-time-between-resolves" ), true ); BOOST_CHECK_EQUAL( option_present( options, "dns-cache-file" ), true ); BOOST_CHECK_EQUAL( option_present( options, "ratio-random-hosts" ), true ); BOOST_CHECK_EQUAL( option_present( options, "host.name" ), true ); diff --git a/test/test_dns.cpp b/test/test_dns.cpp index 9c95577..8273aee 100644 --- a/test/test_dns.cpp +++ b/test/test_dns.cpp @@ -45,7 +45,8 @@ using boost::asio::ip::address; // constants for master address name_server = address::from_string("127.0.0.1"); -int resolved_ip_ttl_threshold = 3; +int resolved_ip_ttl_threshold = 5; +uint32_t min_time_between_resolves = 3; // should be < resolved_ip_ttl_threshold int max_address_resolution_attempts = 2; std::string cache_file = DnsCache::DoNotUseCacheFile; @@ -76,7 +77,7 @@ struct GlobalFixture // DNS Cache DnsCacheItem cache_temp = DnsCacheItem( - new DnsCache(IoService, cache_file) ); + new DnsCache(IoService, cache_file, min_time_between_resolves) ); cache_temp.swap( Cache ); cache_temp.reset(); fill_cache(); @@ -132,7 +133,7 @@ struct GlobalFixture Cache->update("cname3.test", Cname("cname2.test", 37) ); } - { + { // for cache_outdated_test HostAddressVec ips; ips.push_back( HostAddress( address::from_string("192.168.42.4"), 0 ) ); @@ -150,6 +151,17 @@ struct GlobalFixture Cname("host_outdated.test", resolved_ip_ttl_threshold+1)); } + { // for cache_ttl_below_thresh_test + // TTLs < min_time_between_resolves should be corrected + HostAddressVec ips; + ips.push_back( HostAddress( address::from_string("192.128.42.8"), + 1 ) ); + Cache->update("host_ttl_below_thresh.test", ips); + + Cache->update( "cname_ttl_below_thresh.test", + Cname("host_ttl_below_thresh.test", 2) ); + } + BOOST_TEST_MESSAGE( "Done filling cache." ); } @@ -211,7 +223,7 @@ BOOST_FIXTURE_TEST_SUITE( TestDnsCache, TestFixture ) BOOST_AUTO_TEST_CASE( cache_retrieve_ip1 ) { HostAddressVec ips = Cache->get_ips("host1.test"); - BOOST_CHECK_EQUAL( ips.size(), 1 ); + BOOST_REQUIRE_EQUAL( ips.size(), 1 ); HostAddress ip = ips.front(); BOOST_CHECK( ip.is_valid() ); BOOST_CHECK_EQUAL( ip.get_ip().to_string(), "192.168.42.1" ); @@ -247,7 +259,7 @@ BOOST_AUTO_TEST_CASE( cache_retrieve_recursive1 ) { // should get IP from host1 but ttl from cname since is smaller HostAddressVec ips = Cache->get_ips_recursive("cname.test"); - BOOST_CHECK_EQUAL( ips.size(), 1 ); + BOOST_REQUIRE_EQUAL( ips.size(), 1 ); HostAddress ip = ips.front(); BOOST_CHECK( ip.is_valid() ); BOOST_CHECK_EQUAL( ip.get_ip().to_string(), "192.168.42.1" ); @@ -258,7 +270,7 @@ BOOST_AUTO_TEST_CASE( cache_retrieve_recursive2 ) { // should get IP from host1 but ttl from cname2 since is smaller HostAddressVec ips = Cache->get_ips_recursive("cname3.test"); - BOOST_CHECK_EQUAL( ips.size(), 1 ); + BOOST_REQUIRE_EQUAL( ips.size(), 1 ); HostAddress ip = ips.front(); BOOST_CHECK( ip.is_valid() ); BOOST_CHECK_EQUAL( ip.get_ip().to_string(), "192.168.42.1" ); @@ -331,9 +343,11 @@ BOOST_AUTO_TEST_CASE( cache_load_test ) std::stringstream file_name; file_name << DATA_DIR_STRING << "/" << "dns_cache_example.xml"; BOOST_TEST_MESSAGE( "loading cache from file " << file_name.str() ); - DnsCache loaded_cache( IoService, file_name.str() ); + DnsCache loaded_cache( IoService, + file_name.str(), + min_time_between_resolves ); HostAddressVec ips = loaded_cache.get_ips("abc.xyz"); - BOOST_CHECK_EQUAL( ips.size(), 1 ); + BOOST_REQUIRE_EQUAL( ips.size(), 1 ); HostAddress ip = ips.front(); BOOST_CHECK_EQUAL( ip.get_ip().to_string(), "11.22.33.44" ); BOOST_CHECK_EQUAL( ip.get_ttl().get_value(), 567 ); @@ -374,7 +388,17 @@ BOOST_AUTO_TEST_CASE( cache_outdated_test ) BOOST_CHECK_EQUAL( ips.size(), 1 ); } +BOOST_AUTO_TEST_CASE( cache_ttl_below_thresh_test ) +{ + // in fill_cache, + HostAddressVec ips = Cache->get_ips("host_ttl_below_thresh.test", false); + BOOST_REQUIRE_EQUAL( ips.size(), 1 ); + HostAddress ip = ips.front(); + BOOST_CHECK_EQUAL( ip.get_ttl().get_value(), min_time_between_resolves ); + Cname cname = Cache->get_cname("cname_ttl_below_thresh.test", false); + BOOST_CHECK_EQUAL( cname.Ttl.get_value(), min_time_between_resolves ); +} BOOST_AUTO_TEST_SUITE_END() // of TestDnsCache