also added test for this and updated cache test for future cases of cache structure changes
<edge id="n0::e29" source="n0::n84" target="n0::n44">
<data key="d10">
<y:QuadCurveEdge straightness="0.1">
- <y:Path sx="0.0" sy="21.423017741544847" tx="0.0" ty="0.0"/>
+ <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
</y:QuadCurveEdge>
</y:SplineEdge>
</data>
</edge>
+ <edge id="n0::e96" source="n0::n39" target="n0::n84">
+ <data key="d9"/>
+ <data key="d10">
+ <y:SplineEdge>
+ <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0">
+ <y:Point x="-152.3464868738588" y="2260.694553272394"/>
+ </y:Path>
+ <y:LineStyle color="#000000" type="dotted" width="1.0"/>
+ <y:Arrows source="none" target="standard"/>
+ </y:SplineEdge>
+ </data>
+ </edge>
+ <edge id="n0::e97" source="n0::n23" target="n0::n83">
+ <data key="d9"/>
+ <data key="d10">
+ <y:SplineEdge>
+ <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+ <y:LineStyle color="#000000" type="dotted" width="1.0"/>
+ <y:Arrows source="none" target="standard"/>
+ </y:SplineEdge>
+ </data>
+ </edge>
</graph>
<data key="d7">
<y:Resources/>
config/option/dnscachefileoption.cpp
dns/timetolive.cpp
dns/hostaddress.cpp
+ dns/dnsipprotocol.cpp
dns/dnscache.cpp
dns/resolverbase.cpp
dns/dnsresolver.cpp
// UPDATE
// -----------------------------------------------------------------------------
-// warn if hostname is empty and remove trailing dot
-std::string DnsCache::key_for_hostname(const std::string &hostname) const
+/*
+ * warn if hostname is empty and remove trailing dot
+ * also warn if protocol is neither IPv4 nor IPv6
+ */
+ip_map_key_type DnsCache::key_for_ips(const std::string &hostname,
+ const DnsIpProtocol &protocol) const
{
if (hostname.empty())
{
GlobalLogger.info() << "DnsCache: empty host!";
- return "";
+ return ip_map_key_type("", DNS_IPALL);
+ }
+ if (protocol == DNS_IPALL)
+ {
+ GlobalLogger.info() << "DnsCache: neither IPv4 nor v6!";
+ return ip_map_key_type("", DNS_IPALL);
}
// check whether last character is a dot
if (hostname.rfind('.') == hostname.length()-1)
- return hostname.substr(0, hostname.length()-1);
+ return ip_map_key_type( hostname.substr(0, hostname.length()-1),
+ protocol );
else
- return hostname;
+ return ip_map_key_type( hostname,
+ protocol );
}
void DnsCache::update(const std::string &hostname,
+ const DnsIpProtocol &protocol,
const HostAddressVec &new_ips)
{
- std::string key = key_for_hostname(hostname);
+ // check for valid input arguments
+ ip_map_key_type key = key_for_ips(hostname, protocol);
+ if ( key.first.empty() )
+ return;
+
+ // ensure that there is never IP and CNAME for the same host
if ( !get_cname(hostname).Host.empty() )
- { // ensure that there is never IP and CNAME for the same host
- GlobalLogger.info() << "DnsCache: Saving IPs for " << key
+ {
+ GlobalLogger.info() << "DnsCache: Saving IPs for " << key.first
<< " 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 "
+ << key.first << " from " << addr.get_ttl().get_value() << "s to "
<< MinTimeBetweenResolves << "s because was too short";
ips_checked.push_back( HostAddress( addr.get_ip(),
MinTimeBetweenResolves) );
ips_checked.push_back(addr);
}
+ // write IPs into one log line
stringstream log_temp;
- log_temp << "DnsCache: update IPs for " << key << " to "
+ log_temp << "DnsCache: update IPs for " << key.first << " to "
<< ips_checked.size() << "-list: ";
BOOST_FOREACH( const HostAddress &ip, ips_checked )
log_temp << ip.get_ip() << ", ";
}
+/*
+ * warn if hostname is empty and remove trailing dot
+ */
+cname_map_key_type DnsCache::key_for_cname(const std::string &hostname) const
+{
+ if (hostname.empty())
+ {
+ GlobalLogger.info() << "DnsCache: empty host!";
+ return "";
+ }
+
+ // check whether last character is a dot
+ if (hostname.rfind('.') == hostname.length()-1)
+ return hostname.substr(0, hostname.length()-1);
+ else
+ return hostname;
+}
+
+
void DnsCache::update(const std::string &hostname,
const Cname &cname)
{
- std::string key = key_for_hostname(hostname);
- if ( !get_ips(hostname).empty() )
- { // ensure that there is never IP and CNAME for the same host
+ // check for valid input arguments
+ cname_map_key_type key = key_for_cname(hostname);
+ if ( key.empty() )
+ return;
+
+ // ensure that there is never IP and CNAME for the same host
+ int n_ips = get_ips(hostname, DNS_IPv4).size()
+ + get_ips(hostname, DNS_IPv6).size();
+ if ( n_ips > 0 )
+ {
+ GlobalLogger.info() << "DnsCache: Saving IPs for " << key
+ << " removes CNAME to " << get_cname(hostname).Host << "!";
GlobalLogger.info() << "DnsCache: Saving CNAME for " << key
- << " removes " << get_ips(hostname).size() << " IPs for same host!";
- update(hostname, HostAddressVec()); // overwrite with empty IP list
+ << " removes " << n_ips << " IPs for same host!";
+ update(hostname, DNS_IPv4, HostAddressVec());
+ update(hostname, DNS_IPv6, HostAddressVec());
}
- // remove possible trailing dot from cname
- Cname to_save = Cname(key_for_hostname(cname.Host),
+ // remove possible trailing dot from cname's target host
+ Cname to_save = Cname(key_for_cname(cname.Host), // implicit cast to string
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 "
+ << key << " from " << to_save.Ttl.get_value() << "s to "
<< MinTimeBetweenResolves << "s because was too short";
to_save.Ttl = TimeToLive(MinTimeBetweenResolves);
}
GlobalLogger.notice() << "DnsCache: update CNAME for " << key
- << " to " << to_save.Host;
+ << " to " << to_save.Host;
CnameCache[key] = to_save;
HasChanged = true;
}
* @returns empty list if no (up to date) ips for hostname in cache
*/
HostAddressVec DnsCache::get_ips(const std::string &hostname,
+ const DnsIpProtocol &protocol,
const bool check_up_to_date)
{
- std::string key = key_for_hostname(hostname);
+ ip_map_key_type key = key_for_ips(hostname, protocol);
HostAddressVec result = IpCache[key];
if (check_up_to_date)
{
}
result = result_up_to_date;
}
- /*GlobalLogger.debug() << "DnsCache: request IPs for " << key
+ /*GlobalLogger.debug() << "DnsCache: request IPs for " << key.first
<< " --> " << result.size() << "-list";
BOOST_FOREACH( const HostAddress &addr, result )
GlobalLogger.debug() << "DnsCache: " << addr.get_ip().to_string()
Cname DnsCache::get_cname(const std::string &hostname,
const bool check_up_to_date)
{
- std::string key = key_for_hostname(hostname);
+ cname_map_key_type key = key_for_cname(hostname);
Cname result_obj = CnameCache[key];
/*GlobalLogger.debug() << "DnsCache: request CNAME for " << key
<< " --> \"" << result_obj.Host << "\" (TTL "
// underlying assumption in this function: for a hostname, the cache has either
// a list of IPs saved or a cname saved, but never both
HostAddressVec DnsCache::get_ips_recursive(const std::string &hostname,
+ const DnsIpProtocol &protocol,
const bool check_up_to_date)
{
std::string current_host = hostname;
Cname current_cname;
- HostAddressVec result = get_ips(current_host, check_up_to_date);
+ HostAddressVec result = get_ips(current_host, protocol, check_up_to_date);
int n_recursions = 0;
uint32_t min_cname_ttl = 0xffff; // largest possible unsigned 4-byte value
int max_recursion_count = DnsMaster::get_instance()
{
current_cname = get_cname(current_host, check_up_to_date);
if (current_cname.Host.empty())
- break;
+ break; // no ips (since result.empty()) and no cname
+ // --> will return empty result
- current_host = key_for_hostname(current_cname.Host);
+ current_host = current_cname.Host;
if (++n_recursions >= max_recursion_count)
{
GlobalLogger.info() << "DnsCache: reached recursion limit of "
{
min_cname_ttl = min(min_cname_ttl,
current_cname.Ttl.get_updated_value());
- result = get_ips(current_host, check_up_to_date);
+ result = get_ips(current_host, protocol, check_up_to_date);
}
}
#include <boost/archive/xml_iarchive.hpp>
#include "host/pinger.h" // for IoserviceItem
+#include "dns/dnsipprotocol.h"
#include "dns/hostaddress.h"
#include "dns/cname.h"
typedef std::vector<HostAddress> HostAddressVec;
-typedef std::map<std::string, HostAddressVec> ip_map_type;
-typedef std::map<std::string, Cname> cname_map_type;
+typedef std::pair<std::string, DnsIpProtocol> ip_map_key_type;
+typedef std::map<ip_map_key_type, HostAddressVec> ip_map_type;
+typedef std::string cname_map_key_type;
+typedef std::map<cname_map_key_type, Cname> cname_map_type;
// -----------------------------------------------------------------------------
// DnsCache
~DnsCache();
// accessed from ResolverBase subclasses
- void update(const std::string &hostname, const HostAddressVec &new_ips);
- void update(const std::string &hostname, const Cname &cname);
+ void update(const std::string &hostname,
+ const DnsIpProtocol &protocol,
+ const HostAddressVec &new_ips);
+ void update(const std::string &hostname,
+ const Cname &cname);
// retrieval
HostAddressVec get_ips(const std::string &hostname,
+ const DnsIpProtocol &protocol,
const bool check_up_to_date=false);
Cname get_cname(const std::string &hostname,
- const bool check_up_to_date=false);
+ const bool check_up_to_date=false);
HostAddressVec get_ips_recursive(const std::string &hostname,
+ const DnsIpProtocol &protocol,
const bool check_up_to_date=false);
std::string get_first_outdated_cname(const std::string &hostname,
const uint32_t ttl_thresh);
void schedule_save(const boost::system::error_code &error);
void save_to_cachefile();
void load_from_cachefile();
- std::string key_for_hostname(const std::string &hostname) const;
+ ip_map_key_type key_for_ips(const std::string &hostname,
+ const DnsIpProtocol &protocol) const;
+ cname_map_key_type key_for_cname(const std::string &hostname) const;
};
--- /dev/null
+/*
+ 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.
+
+ Christian Herdtweck, Intra2net AG 2015
+ */
+
+#include "dns/dnsipprotocol.h"
+
+#include <logfunc.hpp>
+
+using I2n::Logger::GlobalLogger;
+
+
+std::string to_string(const DnsIpProtocol &protocol)
+{
+ switch (protocol)
+ {
+ case DNS_IPv4: return "IPv4"; break;
+ case DNS_IPv6: return "IPv6"; break;
+ case DNS_IPALL: return "IPv4/6"; break;
+ default: GlobalLogger.warning() << "Unexpected protocol in to_string!";
+ return "Unexpected Protocol"; break;
+ }
+}
+
+DnsIpProtocol ping2dns_protocol(const PingProtocol& pprot)
+{
+ switch (pprot)
+ {
+ case PingProtocol_ICMP: return DNS_IPv4; break;
+ case PingProtocol_ICMPv6: return DNS_IPv6; break;
+ case PingProtocol_TCP: return DNS_IPv4; break;
+ case PingProtocol_TCP_IPv6: return DNS_IPv6; break;
+ default:
+ GlobalLogger.warning()
+ << "Unexpected ping protocol in ping2dns_protocol: "
+ << static_cast<int>(pprot);
+ return DNS_IPALL;
+ break;
+ }
+}
+
+
--- /dev/null
+/*
+ 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.
+
+ Christian Herdtweck, Intra2net AG 2015
+ */
+
+#ifndef DNS_IP_PROTOCOL_H
+#define DNS_IP_PROTOCOL_H
+
+#include <boost/net/dns.hpp>
+#include "host/pingprotocol.h"
+
+typedef boost::net::dns::type_t DnsIpProtocol;
+const DnsIpProtocol DNS_IPv4 = boost::net::dns::type_a;
+const DnsIpProtocol DNS_IPv6 = boost::net::dns::type_a6;
+const DnsIpProtocol DNS_IPALL = boost::net::dns::type_all;
+
+std::string to_string(const DnsIpProtocol &protocol);
+DnsIpProtocol ping2dns_protocol(const PingProtocol& pprot);
+
+#endif
<< ip;
ResolverItem new_resolver( new IpPseudoResolver(IoService,
hostname,
+ protocol,
Cache) );
ResolverMap[key] = new_resolver;
}
}
-DnsIpProtocol DnsMaster::ping2dns_protocol(const PingProtocol& pprot)
-{
- switch (pprot)
- {
- case PingProtocol_ICMP: return DNS_IPv4; break;
- case PingProtocol_ICMPv6: return DNS_IPv6; break;
- case PingProtocol_TCP: return DNS_IPv4; break;
- case PingProtocol_TCP_IPv6: return DNS_IPv6; break;
- default:
- GlobalLogger.warning() << "DnsMaster: Unexpected ping protocol: "
- << static_cast<int>(pprot);
- return DNS_IPALL;
- break;
- }
-}
-
/*boost::asio::ip::address &DnsMaster::get_name_server() const
{
return NameServer;
return MaxRecursionCount;
}
-std::string to_string(const DnsIpProtocol &protocol)
-{
- switch (protocol)
- {
- case DNS_IPv4: return "IPv4"; break;
- case DNS_IPv6: return "IPv6"; break;
- case DNS_IPALL: return "IPv4/6"; break;
- default: GlobalLogger.warning() << "Unexpected protocol in to_string!";
- return "Unexpected Protocol"; break;
- }
-}
#include "host/pinger.h" // for IoserviceItem
#include "host/pingprotocol.h"
+#include "dns/dnsipprotocol.h"
#include "dns/dnscache.h"
#include "dns/resolverbase.h"
typedef boost::shared_ptr<DnsMaster> DnsMasterItem;
-typedef boost::net::dns::type_t DnsIpProtocol;
-const DnsIpProtocol DNS_IPv4 = boost::net::dns::type_a;
-const DnsIpProtocol DNS_IPv6 = boost::net::dns::type_a6;
-const DnsIpProtocol DNS_IPALL = boost::net::dns::type_all;
-
typedef std::pair<std::string, DnsIpProtocol> resolver_key_type;
typedef std::map<resolver_key_type, ResolverItem> resolver_map_type;
-std::string to_string(const DnsIpProtocol &protocol);
-
/**
* Factory and Cache of DNS resolvers
*
// internal helper functions
private:
bool is_ip(const std::string &hostname) const;
- static DnsIpProtocol ping2dns_protocol(const PingProtocol& pprot);
};
#endif
const DnsIpProtocol &protocol,
const DnsCacheItem cache,
const boost::asio::ip::address &name_server)
- : ResolverBase( io_serv, hostname, cache )
+ : ResolverBase( io_serv, hostname, protocol, cache )
, Socket( *io_serv, ip::udp::endpoint(ip::udp::v4(), 0))
// just connect to anything, will specify sender/receiver later
, ReceiveBuffer()
, RequestBuffer()
- , Protocol( protocol )
, NameServer( name_server, Config::DNS_PORT )
, ResolveTimeoutTimer( *io_serv )
, PauseBeforeRetryTimer( *io_serv )
else
{ // check cache for IP for this cname
bool check_up_to_date = true;
- HostAddressVec cached_data = Cache->get_ips_recursive(last_cname,
+ HostAddressVec cached_data = get_cached_ips_recursively(last_cname,
check_up_to_date);
if ( !cached_data.empty() )
{
boost::asio::ip::udp::socket Socket;
boost::net::dns_buffer_t ReceiveBuffer;
boost::net::dns_buffer_t RequestBuffer;
- DnsIpProtocol Protocol;
boost::asio::ip::udp::endpoint NameServer;
boost::asio::deadline_timer ResolveTimeoutTimer;
boost::asio::deadline_timer PauseBeforeRetryTimer;
private:
IpPseudoResolver(const IoServiceItem io_serv,
const std::string &ip_string,
+ const DnsIpProtocol &protocol,
const DnsCacheItem &cache )
- : ResolverBase( io_serv, ip_string, cache )
+ : ResolverBase( io_serv, ip_string, protocol, cache )
, IpAddress( boost::asio::ip::address::from_string(ip_string),
Config::DefaultTtl )
{}
ResolverBase::ResolverBase(const IoServiceItem &io_serv,
const std::string &hostname,
+ const DnsIpProtocol &protocol,
const DnsCacheItem &cache )
: IoService( io_serv )
, Hostname( hostname )
+ , Protocol( protocol )
, Cache( cache )
, CallbackList()
{}
void ResolverBase::update_cache( const std::string &hostname,
const HostAddressVec &new_ips ) const
-{ Cache->update( hostname, new_ips ); }
+{ Cache->update( hostname, Protocol, new_ips ); }
void ResolverBase::update_cache( const std::string &hostname,
const Cname &cname ) const
{ Cache->update( hostname, cname ); }
void ResolverBase::update_cache( const HostAddressVec &new_ips ) const
-{ Cache->update( Hostname, new_ips ); }
+{ Cache->update( Hostname, Protocol, new_ips ); }
void ResolverBase::update_cache( const Cname &cname ) const
{ Cache->update( Hostname, cname ); }
+/**
+ * @brief get IPs like a "real" resolver, i.e. recursively going through CNAMEs
+ *
+ * if host is empty, will use this Resolver's Hostname and Protocol
+ *
+ * just calls DnsCache::get_ips_recursive
+ */
HostAddressVec ResolverBase::get_cached_ips_recursively(const std::string host,
bool check_up_to_date) const
{
if (host.empty())
- return Cache->get_ips_recursive(Hostname, check_up_to_date);
+ return Cache->get_ips_recursive(Hostname, Protocol, check_up_to_date);
else
- return Cache->get_ips_recursive(host, check_up_to_date);
+ return Cache->get_ips_recursive(host, Protocol, check_up_to_date);
}
void ResolverBase::schedule_callbacks(const bool was_success,
#include <queue>
#include "host/pinger.h"
+#include "dns/dnsipprotocol.h"
#include "dns/hostaddress.h"
#include "dns/dnscache.h"
protected:
ResolverBase(const IoServiceItem &io_serv,
const std::string &hostname,
+ const DnsIpProtocol &protocol,
const DnsCacheItem &cache );
// variables
protected:
IoServiceItem IoService;
const std::string Hostname;
+ const DnsIpProtocol Protocol;
DnsCacheItem Cache;
callback_list_type CallbackList;
{
// Raw sockets are locked down by Unix operating systems to prevent
// malware and security holes, thus it requires root access to use it.
- GlobalLogger.error() << "Pingcheck must run as root (" << ex.what() << ")" << endl;
+ GlobalLogger.error() << "Error creating Pinger: " << ex.what()
+ << " (you may have to run pingcheck as root)" << endl;
exit( EXIT_FAILURE );
}
return protocol;
}
+
+std::string ping_protocol_to_string( const PingProtocol &protocol)
+{
+ switch(protocol)
+ {
+ case PingProtocol_ICMP: return "ICMPv4"; break;
+ case PingProtocol_ICMPv6: return "ICMPv6"; break;
+ case PingProtocol_TCP: return "TCPv4"; break;
+ case PingProtocol_TCP_IPv6: return "TCPv6"; break;
+ default:
+ BOOST_ASSERT(
+ !"unexpected PingProtocol in ping_protocol_to_string!" );
+ break;
+ }
+}
};
PingProtocol get_ping_protocol_from_string( const std::string & protocol_string );
+std::string ping_protocol_to_string( const PingProtocol &protocol);
//-----------------------------------------------------------------------------
// PingProtocolList
void PingScheduler::get_next_ping_protocol()
{
+ if (Ping)
+ {
+ Ping->stop_pinging();
+ Ping.reset();
+ }
+
GlobalLogger.debug() << LogPrefix
<< "------------------------------------------------------------------";
++ProtocolIter;
// --> ProtocolIter still points to currently used protocol which is
// required in dns_resolve_callback
- if (Ping)
- Ping->stop_pinging();
-
Ping = PingerFactory::createPinger(ping_protocol, IoService,
NetworkInterfaceName, PingReplyTimeout);
{
// get distributor
IcmpPacketDistributorItem distributor = IcmpPacketDistributor::get_distributor(
- icmp::v4(), source_network_interface, io_serv);
+ protocol, source_network_interface, io_serv);
// create pinger
IcmpPinger *ptr = new IcmpPinger(io_serv, protocol, echo_reply_timeout_in_sec, distributor);
// check if there is an instance for this protocol and interface
if ( Instances.count(identifier) == 0 )
{ // need to create an instance for this protocol and network interface
+ std::string protocol_str;
+ if (protocol == icmp::v4())
+ protocol_str = "ICMPv4";
+ else if (protocol == icmp::v6())
+ protocol_str = "ICMPv6";
+ else
+ protocol_str = "unknown protocol!";
+
GlobalLogger.info() << "Creating IcmpPacketDistributor for interface "
- << network_interface << std::endl;
+ << network_interface << " and protocol "
+ << protocol_str << std::endl;
IcmpPacketDistributorItem new_instance( new IcmpPacketDistributor(
protocol, network_interface, io_serv ) );
Instances[identifier] = new_instance;
${CMAKE_SOURCE_DIR}/src/host/pinger.cpp
${CMAKE_SOURCE_DIR}/src/dns/hostaddress.cpp
${CMAKE_SOURCE_DIR}/src/dns/timetolive.cpp
+ ${CMAKE_SOURCE_DIR}/src/dns/dnsipprotocol.cpp
${CMAKE_SOURCE_DIR}/src/dns/dnsmaster.cpp
${CMAKE_SOURCE_DIR}/src/dns/dnscache.cpp
${CMAKE_SOURCE_DIR}/src/dns/resolverbase.cpp
configure_file(icmp_echoreply.pcap ${CMAKE_CURRENT_BINARY_DIR}/icmp_echoreply.pcap COPYONLY)
configure_file(icmp_timeexceeded.pcap ${CMAKE_CURRENT_BINARY_DIR}/icmp_timeexceeded.pcap COPYONLY)
configure_file(icmp_destinationunreachable.pcap ${CMAKE_CURRENT_BINARY_DIR}/icmp_destinationunreachable.pcap COPYONLY)
-configure_file(dns_cache_example.xml ${CMAKE_CURRENT_BINARY_DIR}/dns_cache_example.xml COPYONLY)
+configure_file(dns_cache_compatibility_test.xml ${CMAKE_CURRENT_BINARY_DIR}/dns_cache_compatibility_test.xml COPYONLY)
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<!DOCTYPE boost_serialization>
+<boost_serialization signature="serialization::archive" version="7">
+<IpCache class_id="0" tracking_level="0" version="0">
+ <count>3</count>
+ <item_version>0</item_version>
+ <item class_id="1" tracking_level="0" version="0">
+ <first class_id="2" tracking_level="0" version="0">
+ <first>abc.xyz</first>
+ <second>1</second>
+ </first>
+ <second class_id="3" tracking_level="0" version="0">
+ <count>1</count>
+ <item_version>0</item_version>
+ <item class_id="4" tracking_level="0" version="0">
+ <ip_str>11.22.33.44</ip_str>
+ <Ttl class_id="5" tracking_level="0" version="0">
+ <Ttl>567</Ttl>
+ <ttl_creation_time>20150522T072136.957424</ttl_creation_time>
+ </Ttl>
+ </item>
+ </second>
+ </item>
+ <item>
+ <first>
+ <first>cname1.xyz</first>
+ <second>1</second>
+ </first>
+ <second>
+ <count>0</count>
+ <item_version>0</item_version>
+ </second>
+ </item>
+ <item>
+ <first>
+ <first>cname1.xyz</first>
+ <second>28</second>
+ </first>
+ <second>
+ <count>0</count>
+ <item_version>0</item_version>
+ </second>
+ </item>
+</IpCache>
+<CnameCache class_id="6" tracking_level="0" version="0">
+ <count>2</count>
+ <item_version>0</item_version>
+ <item class_id="7" tracking_level="0" version="0">
+ <first>abc.xyz</first>
+ <second class_id="8" tracking_level="0" version="0">
+ <Host></Host>
+ <Ttl>
+ <Ttl>0</Ttl>
+ <ttl_creation_time>20150522T072136.957426</ttl_creation_time>
+ </Ttl>
+ </second>
+ </item>
+ <item>
+ <first>cname1.xyz</first>
+ <second>
+ <Host>abc.xyz</Host>
+ <Ttl>
+ <Ttl>27</Ttl>
+ <ttl_creation_time>20150522T072136.957467</ttl_creation_time>
+ </Ttl>
+ </second>
+ </item>
+</CnameCache>
+</boost_serialization>
+
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
-<!DOCTYPE boost_serialization>
-<boost_serialization signature="serialization::archive" version="7">
-<IpCache class_id="0" tracking_level="0" version="0">
- <count>4</count>
- <item_version>0</item_version>
- <item class_id="1" tracking_level="0" version="0">
- <first>abc.xyz</first>
- <second class_id="2" tracking_level="0" version="0">
- <count>1</count>
- <item_version>0</item_version>
- <item class_id="3" tracking_level="0" version="0">
- <ip_str>11.22.33.44</ip_str>
- <Ttl class_id="4" tracking_level="0" version="0">
- <Ttl>567</Ttl>
- <ttl_creation_time>20150429T140512.609565</ttl_creation_time>
- </Ttl>
- </item>
- </second>
- </item>
- <item>
- <first>cname1.xyz</first>
- <second>
- <count>0</count>
- <item_version>0</item_version>
- </second>
- </item>
- <item>
- <first>cname2.xyz</first>
- <second>
- <count>0</count>
- <item_version>0</item_version>
- </second>
- </item>
- <item>
- <first>cname3.xyz</first>
- <second>
- <count>0</count>
- <item_version>0</item_version>
- </second>
- </item>
-</IpCache>
-<CnameCache class_id="5" tracking_level="0" version="0">
- <count>4</count>
- <item_version>0</item_version>
- <item class_id="6" tracking_level="0" version="0">
- <first>abc.xyz</first>
- <second class_id="7" tracking_level="0" version="0">
- <Host></Host>
- <Ttl>
- <Ttl>0</Ttl>
- <ttl_creation_time>20150429T131654.312043</ttl_creation_time>
- </Ttl>
- </second>
- </item>
- <item>
- <first>cname1.xyz</first>
- <second>
- <Host>abc.xyz</Host>
- <Ttl>
- <Ttl>27</Ttl>
- <ttl_creation_time>20150429T140512.609555</ttl_creation_time>
- </Ttl>
- </second>
- </item>
- <item>
- <first>cname2.xyz</first>
- <second>
- <Host>cname1.xyz</Host>
- <Ttl>
- <Ttl>207</Ttl>
- <ttl_creation_time>20150429T140512.609545</ttl_creation_time>
- </Ttl>
- </second>
- </item>
- <item>
- <first>cname3.xyz</first>
- <second>
- <Host>cname2.xyz</Host>
- <Ttl>
- <Ttl>87</Ttl>
- <ttl_creation_time>20150429T140512.609533</ttl_creation_time>
- </Ttl>
- </second>
- </item>
-</CnameCache>
-</boost_serialization>
-
#include <boost/bind.hpp>
#include <logfunc.hpp>
+#include <filefunc.hxx>
#include "host/pingprotocol.h"
#include "dns/hostaddress.h"
+#include "dns/dnsipprotocol.h"
#include "dns/dnsmaster.h"
#include "dns/dnscache.h"
#include "dns/resolverbase.h"
HostAddress ip(address::from_string("192.168.42.1"), 61);
HostAddressVec ips;
ips.push_back(ip);
- Cache->update("host1.test", ips);
+ Cache->update("host1.test", DNS_IPv4, ips);
}
{
HostAddressVec ips;
ips.push_back(ip1);
ips.push_back(ip2);
- Cache->update("host2_3.test", ips);
+ Cache->update("host2_3.test", DNS_IPv4, ips);
}
{
resolved_ip_ttl_threshold ) );
ips.push_back( HostAddress( address::from_string("192.168.42.7"),
resolved_ip_ttl_threshold+1 ) );
- Cache->update("host_outdated.test", ips);
+ Cache->update("host_outdated.test", DNS_IPv4, ips);
Cache->update( "cname_outdated.test",
Cname("host_outdated.test", resolved_ip_ttl_threshold) );
HostAddressVec ips;
ips.push_back( HostAddress( address::from_string("192.128.42.8"),
1 ) );
- Cache->update("host_ttl_below_thresh.test", ips);
+ Cache->update("host_ttl_below_thresh.test", DNS_IPv4, ips);
Cache->update( "cname_ttl_below_thresh.test",
Cname("host_ttl_below_thresh.test", 2) );
Cache->update( "cname_loop3.test", Cname("cname_loop1.test", 60) );
}
+ { // create IPv4 and IPv6 for same host
+ HostAddressVec ips;
+ ips.push_back( HostAddress( address::from_string("192.168.42.8"),
+ 432 ) );
+ Cache->update("host_v4_and_v6.test", DNS_IPv4, ips);
+ ips.clear();
+ ips.push_back( HostAddress(
+ address::from_string("2a00:1450:4001:808::1004"),
+ 543 ) );
+ Cache->update("host_v4_and_v6.test", DNS_IPv6, ips);
+ }
+
BOOST_TEST_MESSAGE( "Done filling cache." );
}
BOOST_AUTO_TEST_CASE( cache_retrieve_ip1 )
{
- HostAddressVec ips = Cache->get_ips("host1.test");
+ HostAddressVec ips = Cache->get_ips("host1.test", DNS_IPv4);
BOOST_REQUIRE_EQUAL( ips.size(), 1 );
HostAddress ip = ips.front();
BOOST_CHECK( ip.is_valid() );
BOOST_AUTO_TEST_CASE( cache_retrieve_ip2 )
{
- HostAddressVec ips = Cache->get_ips("host2_3.test");
+ HostAddressVec ips = Cache->get_ips("host2_3.test", DNS_IPv4);
BOOST_CHECK_EQUAL( ips.size(), 2 );
HostAddress ip = ips[0];
BOOST_CHECK( ip.is_valid() );
BOOST_AUTO_TEST_CASE( cache_retrieve_cname )
{
- HostAddressVec ips = Cache->get_ips("cname.test");
+ HostAddressVec ips = Cache->get_ips("cname.test", DNS_IPv4);
BOOST_CHECK( ips.empty() );
Cname cname = Cache->get_cname("cname.test");
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");
+ HostAddressVec ips = Cache->get_ips_recursive("cname.test", DNS_IPv4);
BOOST_REQUIRE_EQUAL( ips.size(), 1 );
HostAddress ip = ips.front();
BOOST_CHECK( ip.is_valid() );
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");
+ HostAddressVec ips = Cache->get_ips_recursive("cname3.test", DNS_IPv4);
BOOST_REQUIRE_EQUAL( ips.size(), 1 );
HostAddress ip = ips.front();
BOOST_CHECK( ip.is_valid() );
HostAddressVec ips;
ips.push_back( HostAddress( address::from_string("192.168.42.100"),
ttl4 ) );
- cache->update("skip_chain_fourth.test", ips);
+ cache->update("skip_chain_fourth.test", DNS_IPv4, ips);
}
// normal recursive call should give nothing since one cname is outdated
bool check_up_to_date = true;
HostAddressVec ips = cache->get_ips_recursive("skip_chain_first.test",
+ DNS_IPv4,
check_up_to_date);
bool one_is_out_of_date = (ttl1 < 5) || (ttl2 < 5)
|| (ttl3 < 5) || (ttl4 < 5);
BOOST_CHECK_EQUAL( Cache->get_first_outdated_cname("host1.test", 5), "" );
}
-BOOST_AUTO_TEST_CASE( cache_load_test )
+
+void create_cache(const std::string &file_name, IoServiceItem io_serv)
{
- 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(),
+ BOOST_TEST_MESSAGE( "creating cache for file " << file_name );
+ if ( I2n::file_exists(file_name) )
+ BOOST_CHECK( I2n::unlink(file_name) ); // try to remove
+ DnsCache save_cache( io_serv, file_name, min_time_between_resolves );
+
+ HostAddressVec ips;
+ ips.push_back( HostAddress(address::from_string("11.22.33.44"), 567) );
+ save_cache.update("abc.xyz", DNS_IPv4, ips);
+
+ save_cache.update("cname1.xyz", Cname("abc.xyz", 27));
+
+ // is saved when destructed
+}
+
+
+void test_cache(const std::string &file_name, IoServiceItem io_serv)
+{
+ BOOST_TEST_MESSAGE( "loading cache from file " << file_name );
+ DnsCache loaded_cache( io_serv,
+ file_name,
min_time_between_resolves );
- HostAddressVec ips = loaded_cache.get_ips("abc.xyz");
- 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 );
- BOOST_CHECK_EQUAL( ip.get_ttl().get_updated_value(), 0 );
+ HostAddressVec ips = loaded_cache.get_ips("abc.xyz", DNS_IPv4);
+ BOOST_CHECK_EQUAL( ips.size(), 1 );
+ if (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 );
+ //BOOST_CHECK_EQUAL( ip.get_ttl().get_updated_value(), 0 );
+ }
Cname cname = loaded_cache.get_cname("cname1.xyz");
BOOST_CHECK_EQUAL( cname.Host, "abc.xyz" );
BOOST_CHECK_EQUAL( cname.Ttl.get_value(), 27 );
- BOOST_CHECK_EQUAL( cname.Ttl.get_updated_value(), 0 );
+ //BOOST_CHECK_EQUAL( cname.Ttl.get_updated_value(), 0 );
// not testing Ttl set time since is private
}
+
+BOOST_AUTO_TEST_CASE( cache_save_and_load_test )
+{
+ std::stringstream file_name_temp;
+ file_name_temp << DATA_DIR_STRING << "/" << "dns_cache_save_load_test.xml";
+ std::string file_name = file_name_temp.str();
+
+ // create and save
+ create_cache( file_name, IoService );
+
+ // now load and test
+ test_cache( file_name, IoService );
+
+}
+
+BOOST_AUTO_TEST_CASE( cache_load_compatibility_test )
+{
+ std::stringstream file_name;
+ file_name << DATA_DIR_STRING << "/" << "dns_cache_compatibility_test.xml";
+ test_cache( file_name.str(), IoService );
+
+ // If this test fails because the cache structure was changed,
+ // you can overwrite the dns_cache_compatibility_test.xml by uncommenting
+ // the following code line.
+ //create_cache( file_name.str(), IoService );
+ //
+ // Run test again with arg --log_level=MESSAGE and look out for message
+ // "create cache for file [...]dns_cache_compatibility_test.xml"
+ // You should then copy the dns_cache_compatibility_test.xml to test/data
+ // in git and commit together with the new cache structure code
+}
+
BOOST_AUTO_TEST_CASE( cache_outdated_test )
{
bool check_up_to_date = false;
- HostAddressVec ips = Cache->get_ips("host_outdated.test", check_up_to_date);
+ HostAddressVec ips = Cache->get_ips("host_outdated.test", DNS_IPv4,
+ check_up_to_date);
BOOST_CHECK_EQUAL( ips.size(), 4 );
- ips = Cache->get_ips_recursive("host_outdated.test", check_up_to_date);
+ ips = Cache->get_ips_recursive("host_outdated.test", DNS_IPv4,
+ check_up_to_date);
BOOST_CHECK_EQUAL( ips.size(), 4 );
Cname cname = Cache->get_cname("cname_outdated.test", check_up_to_date);
BOOST_CHECK( !cname.Host.empty() );
- ips = Cache->get_ips_recursive("cname_outdated.test", check_up_to_date);
+ ips = Cache->get_ips_recursive("cname_outdated.test", DNS_IPv4,
+ check_up_to_date);
BOOST_CHECK_EQUAL( ips.size(), 4 );
- ips = Cache->get_ips_recursive("cname_up_to_date.test", check_up_to_date);
+ ips = Cache->get_ips_recursive("cname_up_to_date.test", DNS_IPv4,
+ check_up_to_date);
BOOST_CHECK_EQUAL( ips.size(), 4 );
check_up_to_date = true;
- ips = Cache->get_ips( "host_outdated.test", check_up_to_date );
+ ips = Cache->get_ips( "host_outdated.test", DNS_IPv4, check_up_to_date );
BOOST_CHECK_EQUAL( ips.size(), 1 );
- ips = Cache->get_ips_recursive("host_outdated.test", check_up_to_date);
+ ips = Cache->get_ips_recursive("host_outdated.test", DNS_IPv4,
+ check_up_to_date);
BOOST_CHECK_EQUAL( ips.size(), 1 );
cname = Cache->get_cname("cname_outdated.test", check_up_to_date);
BOOST_CHECK( cname.Host.empty() );
- ips = Cache->get_ips_recursive("cname_outdated.test", check_up_to_date);
+ ips = Cache->get_ips_recursive("cname_outdated.test", DNS_IPv4,
+ check_up_to_date);
BOOST_CHECK_EQUAL( ips.size(), 0 );
- ips = Cache->get_ips_recursive("cname_up_to_date.test", check_up_to_date);
+ ips = Cache->get_ips_recursive("cname_up_to_date.test", DNS_IPv4,
+ check_up_to_date);
BOOST_CHECK_EQUAL( ips.size(), 1 );
}
BOOST_AUTO_TEST_CASE( cache_ttl_below_thresh_test )
{
- HostAddressVec ips = Cache->get_ips("host_ttl_below_thresh.test", false);
+ HostAddressVec ips = Cache->get_ips("host_ttl_below_thresh.test", DNS_IPv4,
+ false);
BOOST_REQUIRE_EQUAL( ips.size(), 1 );
HostAddress ip = ips.front();
BOOST_CHECK_EQUAL( ip.get_ttl().get_value(), min_time_between_resolves );
BOOST_AUTO_TEST_CASE( cache_retrieve_loop )
{
- BOOST_CHECK_EQUAL( Cache->get_ips_recursive("cname_loop1.test").size(), 0 );
- BOOST_CHECK_EQUAL( Cache->get_ips_recursive("cname_loop2.test").size(), 0 );
- BOOST_CHECK_EQUAL( Cache->get_ips_recursive("cname_loop3.test").size(), 0 );
+ BOOST_CHECK_EQUAL(
+ Cache->get_ips_recursive("cname_loop1.test", DNS_IPv4).size(), 0 );
+ BOOST_CHECK_EQUAL(
+ Cache->get_ips_recursive("cname_loop2.test", DNS_IPv4).size(), 0 );
+ BOOST_CHECK_EQUAL(
+ Cache->get_ips_recursive("cname_loop3.test", DNS_IPv4).size(), 0 );
+}
+
+
+BOOST_AUTO_TEST_CASE( cache_IPv6 )
+{
+ HostAddressVec ips = Cache->get_ips("host_v4_and_v6.test", DNS_IPv4);
+ 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.8" );
+ BOOST_CHECK_EQUAL( ip.get_ttl().get_value(), 432 );
+
+ ips = Cache->get_ips("host_v4_and_v6.test", DNS_IPv6);
+ BOOST_REQUIRE_EQUAL( ips.size(), 1 );
+ ip = ips.front();
+ BOOST_CHECK( ip.is_valid() );
+ BOOST_CHECK_EQUAL( ip.get_ip().to_string(), "2a00:1450:4001:808::1004" );
+ BOOST_CHECK_EQUAL( ip.get_ttl().get_value(), 543 );
}