}
}
-int32_t MemRecursorCache::handleHit(MapCombo& map, MemRecursorCache::OrderedTagIterator_t& entry, const DNSName& qname, uint32_t& origTTL, vector<DNSRecord>* res, vector<std::shared_ptr<RRSIGRecordContent>>* signatures, std::vector<std::shared_ptr<DNSRecord>>* authorityRecs, bool* variable, boost::optional<vState>& state, bool* wasAuth, DNSName* fromAuthZone)
+time_t MemRecursorCache::handleHit(MapCombo& map, MemRecursorCache::OrderedTagIterator_t& entry, const DNSName& qname, uint32_t& origTTL, vector<DNSRecord>* res, vector<std::shared_ptr<RRSIGRecordContent>>* signatures, std::vector<std::shared_ptr<DNSRecord>>* authorityRecs, bool* variable, boost::optional<vState>& state, bool* wasAuth, DNSName* fromAuthZone)
{
// MUTEX SHOULD BE ACQUIRED
- int32_t ttd = entry->d_ttd;
+ time_t ttd = entry->d_ttd;
origTTL = entry->d_orig_ttl;
if (variable && (!entry->d_netmask.empty() || entry->d_rtag)) {
dr.d_type = entry->d_qtype;
dr.d_class = QClass::IN;
dr.d_content = k;
- dr.d_ttl = static_cast<uint32_t>(entry->d_ttd);
+ dr.d_ttl = static_cast<uint32_t>(entry->d_ttd); // XXX truncation
dr.d_place = DNSResourceRecord::ANSWER;
res->push_back(std::move(dr));
}
}
// Fake a cache miss if more than refreshTTLPerc of the original TTL has passed
-int32_t MemRecursorCache::fakeTTD(MemRecursorCache::OrderedTagIterator_t& entry, const DNSName& qname, uint16_t qtype, int32_t ret, time_t now, uint32_t origTTL, bool refresh)
+time_t MemRecursorCache::fakeTTD(MemRecursorCache::OrderedTagIterator_t& entry, const DNSName& qname, uint16_t qtype, time_t ret, time_t now, uint32_t origTTL, bool refresh)
{
- int32_t ttl = static_cast<int32_t>(ret - now);
+ time_t ttl = ret - now;
if (ttl > 0 && SyncRes::s_refresh_ttlperc > 0) {
const uint32_t deadline = origTTL * SyncRes::s_refresh_ttlperc / 100;
const bool almostExpired = static_cast<uint32_t>(ttl) <= deadline;
return ttl;
}
// returns -1 for no hits
-int32_t MemRecursorCache::get(time_t now, const DNSName &qname, const QType& qt, bool requireAuth, vector<DNSRecord>* res, const ComboAddress& who, bool refresh, const OptTag& routingTag, vector<std::shared_ptr<RRSIGRecordContent>>* signatures, std::vector<std::shared_ptr<DNSRecord>>* authorityRecs, bool* variable, vState* state, bool* wasAuth, DNSName* fromAuthZone)
+time_t MemRecursorCache::get(time_t now, const DNSName &qname, const QType& qt, bool requireAuth, vector<DNSRecord>* res, const ComboAddress& who, bool refresh, const OptTag& routingTag, vector<std::shared_ptr<RRSIGRecordContent>>* signatures, std::vector<std::shared_ptr<DNSRecord>>* authorityRecs, bool* variable, vState* state, bool* wasAuth, DNSName* fromAuthZone)
{
boost::optional<vState> cachedState{boost::none};
uint32_t origTTL;
to be able to use the nice d_cachecache hack. */
if (qtype != QType::ANY && !map.d_ecsIndex.empty() && !routingTag) {
if (qtype == QType::ADDR) {
- int32_t ret = -1;
+ time_t ret = -1;
auto entryA = getEntryUsingECSIndex(map, now, qname, QType::A, requireAuth, who);
if (entryA != map.d_map.end()) {
}
auto entryAAAA = getEntryUsingECSIndex(map, now, qname, QType::AAAA, requireAuth, who);
if (entryAAAA != map.d_map.end()) {
- int32_t ttdAAAA = handleHit(map, entryAAAA, qname, origTTL, res, signatures, authorityRecs, variable, cachedState, wasAuth, fromAuthZone);
+ time_t ttdAAAA = handleHit(map, entryAAAA, qname, origTTL, res, signatures, authorityRecs, variable, cachedState, wasAuth, fromAuthZone);
if (ret > 0) {
ret = std::min(ret, ttdAAAA);
} else {
*state = *cachedState;
}
- return ret > 0 ? static_cast<int32_t>(ret-now) : ret;
+ return ret > 0 ? (ret - now) : ret;
}
else {
auto entry = getEntryUsingECSIndex(map, now, qname, qtype, requireAuth, who);
if (entry != map.d_map.end()) {
- int32_t ret = handleHit(map, entry, qname, origTTL, res, signatures, authorityRecs, variable, cachedState, wasAuth, fromAuthZone);
+ time_t ret = handleHit(map, entry, qname, origTTL, res, signatures, authorityRecs, variable, cachedState, wasAuth, fromAuthZone);
if (state && cachedState) {
*state = *cachedState;
}
typedef boost::optional<std::string> OptTag;
-int32_t get(time_t, const DNSName &qname, const QType& qt, bool requireAuth, vector<DNSRecord>* res, const ComboAddress& who, bool refresh = false, const OptTag& routingTag = boost::none, vector<std::shared_ptr<RRSIGRecordContent>>* signatures=nullptr, std::vector<std::shared_ptr<DNSRecord>>* authorityRecs=nullptr, bool* variable=nullptr, vState* state=nullptr, bool* wasAuth=nullptr, DNSName* fromAuthZone=nullptr);
+time_t get(time_t, const DNSName &qname, const QType& qt, bool requireAuth, vector<DNSRecord>* res, const ComboAddress& who, bool refresh = false, const OptTag& routingTag = boost::none, vector<std::shared_ptr<RRSIGRecordContent>>* signatures=nullptr, std::vector<std::shared_ptr<DNSRecord>>* authorityRecs=nullptr, bool* variable=nullptr, vState* state=nullptr, bool* wasAuth=nullptr, DNSName* fromAuthZone=nullptr);
void replace(time_t, const DNSName &qname, const QType& qt, const vector<DNSRecord>& content, const vector<shared_ptr<RRSIGRecordContent>>& signatures, const std::vector<std::shared_ptr<DNSRecord>>& authorityRecs, bool auth, const DNSName& authZone, boost::optional<Netmask> ednsmask=boost::none, const OptTag& routingTag = boost::none, vState state=vState::Indeterminate, boost::optional<ComboAddress> from=boost::none);
return d_maps[qname.hash() % d_maps.size()];
}
- static int32_t fakeTTD(OrderedTagIterator_t& entry, const DNSName& qname, uint16_t qtype, int32_t ret, time_t now, uint32_t origTTL, bool refresh);
+ static time_t fakeTTD(OrderedTagIterator_t& entry, const DNSName& qname, uint16_t qtype, time_t ret, time_t now, uint32_t origTTL, bool refresh);
bool entryMatches(OrderedTagIterator_t& entry, uint16_t qt, bool requireAuth, const ComboAddress& who);
Entries getEntries(MapCombo& map, const DNSName &qname, const QType& qt, const OptTag& rtag);
cache_t::const_iterator getEntryUsingECSIndex(MapCombo& map, time_t now, const DNSName &qname, uint16_t qtype, bool requireAuth, const ComboAddress& who);
- int32_t handleHit(MapCombo& map, OrderedTagIterator_t& entry, const DNSName& qname, uint32_t& origTTL, vector<DNSRecord>* res, vector<std::shared_ptr<RRSIGRecordContent>>* signatures, std::vector<std::shared_ptr<DNSRecord>>* authorityRecs, bool* variable, boost::optional<vState>& state, bool* wasAuth, DNSName* authZone);
+ time_t handleHit(MapCombo& map, OrderedTagIterator_t& entry, const DNSName& qname, uint32_t& origTTL, vector<DNSRecord>* res, vector<std::shared_ptr<RRSIGRecordContent>>* signatures, std::vector<std::shared_ptr<DNSRecord>>* authorityRecs, bool* variable, boost::optional<vState>& state, bool* wasAuth, DNSName* authZone);
public:
struct lock {
BOOST_AUTO_TEST_SUITE(recursorcache_cc)
-BOOST_AUTO_TEST_CASE(test_RecursorCacheSimple)
+static void simple(time_t now)
{
MemRecursorCache MRC;
std::vector<std::shared_ptr<DNSRecord>> authRecords;
std::vector<std::shared_ptr<RRSIGRecordContent>> signatures;
const DNSName authZone(".");
- time_t now = INT_MAX - 15;
time_t ttd = now + 30;
DNSName power("powerdns.com.");
dr0.d_type = QType::AAAA;
dr0.d_class = QClass::IN;
dr0.d_content = std::make_shared<AAAARecordContent>(dr0Content);
- dr0.d_ttl = static_cast<uint32_t>(ttd);
+ dr0.d_ttl = static_cast<uint32_t>(ttd); // XXX truncation
dr0.d_place = DNSResourceRecord::ANSWER;
records.push_back(dr0);
dr1.d_type = QType::AAAA;
dr1.d_class = QClass::IN;
dr1.d_content = std::make_shared<AAAARecordContent>(dr1Content);
- dr1.d_ttl = static_cast<uint32_t>(ttd);
+ dr1.d_ttl = static_cast<uint32_t>(ttd); // XXX truncation
dr1.d_place = DNSResourceRecord::ANSWER;
DNSRecord dr2;
dr2.d_type = QType::A;
dr2.d_class = QClass::IN;
dr2.d_content = std::make_shared<ARecordContent>(dr2Content);
- dr2.d_ttl = static_cast<uint32_t>(ttd);
+ dr2.d_ttl = static_cast<uint32_t>(ttd); // XXX truncation
// the place should not matter to the cache
dr2.d_place = DNSResourceRecord::AUTHORITY;
dr3.d_type = QType::A;
dr3.d_class = QClass::IN;
dr3.d_content = std::make_shared<ARecordContent>(dr3Content);
- dr3.d_ttl = static_cast<uint32_t>(ttd + 100);
+ dr3.d_ttl = static_cast<uint32_t>(ttd + 100); // XXX truncation
// the place should not matter to the cache
dr3.d_place = DNSResourceRecord::AUTHORITY;
dr4.d_type = QType::A;
dr4.d_class = QClass::IN;
dr4.d_content = std::make_shared<ARecordContent>(dr4Content);
- dr4.d_ttl = static_cast<uint32_t>(ttd);
+ dr4.d_ttl = static_cast<uint32_t>(ttd); // XXX truncation
dr4.d_place = DNSResourceRecord::AUTHORITY;
// insert another entry but for 192.168.0.1/31
}
}
+BOOST_AUTO_TEST_CASE(test_RecursorCacheSimple)
+{
+ simple(time(nullptr));
+}
+
+BOOST_AUTO_TEST_CASE(test_RecursorCacheSimple2038)
+{
+ simple(INT_MAX - 15);
+}
+
+BOOST_AUTO_TEST_CASE(test_RecursorCacheSimple2038bis)
+{
+ simple(time_t(INT_MAX) + 10000);
+}
+
+#if 0
+BOOST_AUTO_TEST_CASE(test_RecursorCacheSimpleDistantFuture)
+{
+ // Fails due to using 32-bit ttl values in records for absolute time, see handleHit()
+ simple(2 * time_t(INT_MAX));
+}
+#endif
+
BOOST_AUTO_TEST_CASE(test_RecursorCacheGhost)
{
MemRecursorCache MRC;
ns1.d_type = QType::NS;
ns1.d_class = QClass::IN;
ns1.d_content = std::make_shared<NSRecordContent>(ns1Content);
- ns1.d_ttl = static_cast<uint32_t>(ttd);
+ ns1.d_ttl = static_cast<uint32_t>(ttd); // XXX truncation
ns1.d_place = DNSResourceRecord::ANSWER;
records.push_back(ns1);
MRC.replace(now, ns1.d_name, QType(ns1.d_type), records, signatures, authRecords, true, DNSName("powerdns.com."), boost::none);
/* try to raise the TTL, simulating the delegated authoritative server
raising the TTL so the zone stays alive */
records.clear();
- ns1.d_ttl = static_cast<uint32_t>(ttd + 3600);
+ ns1.d_ttl = static_cast<uint32_t>(ttd + 3600); // XXX truncation
records.push_back(ns1);
MRC.replace(now, ns1.d_name, QType(ns1.d_type), records, signatures, authRecords, true, DNSName("ghost.powerdns.com."), boost::none);
BOOST_CHECK_EQUAL(MRC.size(), 1U);
dr1.d_type = QType::AAAA;
dr1.d_class = QClass::IN;
dr1.d_content = std::make_shared<AAAARecordContent>(dr1Content);
- dr1.d_ttl = static_cast<uint32_t>(ttd);
+ dr1.d_ttl = static_cast<uint32_t>(ttd); // XXX truncation
dr1.d_place = DNSResourceRecord::ANSWER;
/* entry for power1, which expired 30 ago too */
dr2.d_type = QType::AAAA;
dr2.d_class = QClass::IN;
dr2.d_content = std::make_shared<AAAARecordContent>(dr2Content);
- dr2.d_ttl = static_cast<uint32_t>(ttd);
+ dr2.d_ttl = static_cast<uint32_t>(ttd); // XXX truncation
dr2.d_place = DNSResourceRecord::ANSWER;
/* insert both entries */