// 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);
}
}