return ret;
}
-int32_t MemRecursorCache::handleHit(MapCombo& map, MemRecursorCache::OrderedTagIterator_t& entry, const DNSName& qname, vector<DNSRecord>* res, vector<std::shared_ptr<RRSIGRecordContent>>* signatures, std::vector<std::shared_ptr<DNSRecord>>* authorityRecs, bool* variable, vState* state, bool* wasAuth)
+static void updateDNSSECValidationStateFromCache(boost::optional<vState>& state, const vState stateUpdate)
+{
+ // if there was no state it's easy */
+ if (state == boost::none) {
+ state = stateUpdate;
+ return;
+ }
+
+ if (stateUpdate == vState::TA) {
+ state = vState::Secure;
+ }
+ else if (stateUpdate == vState::NTA) {
+ state = vState::Insecure;
+ }
+ else if (stateUpdate == vState::Bogus) {
+ state = stateUpdate;
+ }
+ else if (stateUpdate == vState::Indeterminate) {
+ state = stateUpdate;
+ }
+ else if (stateUpdate == vState::Insecure) {
+ if (*state != vState::Bogus && *state != vState::Indeterminate) {
+ state = stateUpdate;
+ }
+ }
+ else if (stateUpdate == vState::Secure) {
+ if (*state != vState::Bogus && *state != vState::Indeterminate) {
+ state = stateUpdate;
+ }
+ }
+}
+
+int32_t MemRecursorCache::handleHit(MapCombo& map, MemRecursorCache::OrderedTagIterator_t& entry, const DNSName& qname, vector<DNSRecord>* res, vector<std::shared_ptr<RRSIGRecordContent>>* signatures, std::vector<std::shared_ptr<DNSRecord>>* authorityRecs, bool* variable, boost::optional<vState>& state, bool* wasAuth)
{
// MUTEX SHOULD BE ACQUIRED
int32_t ttd = entry->d_ttd;
authorityRecs->insert(authorityRecs->end(), entry->d_authorityRecs.begin(), entry->d_authorityRecs.end());
}
- if (state) {
- updateDNSSECValidationState(*state, entry->d_state);
- }
+ updateDNSSECValidationStateFromCache(state, entry->d_state);
if (wasAuth) {
*wasAuth = *wasAuth && entry->d_auth;
// 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, const OptTag& routingTag, vector<std::shared_ptr<RRSIGRecordContent>>* signatures, std::vector<std::shared_ptr<DNSRecord>>* authorityRecs, bool* variable, vState* state, bool* wasAuth)
{
+ boost::optional<vState> cachedState{boost::none};
time_t ttd=0;
// cerr<<"looking up "<< qname<<"|"+qt.getName()<<"\n";
if(res) {
// so it will be set to false if at least one entry is not auth
*wasAuth = true;
}
- if (state) {
- *state = vState::Indeterminate;
- }
auto& map = getMap(qname);
const lock l(map);
auto entryA = getEntryUsingECSIndex(map, now, qname, QType::A, requireAuth, who);
if (entryA != map.d_map.end()) {
- ret = handleHit(map, entryA, qname, res, signatures, authorityRecs, variable, state, wasAuth);
+ ret = handleHit(map, entryA, qname, res, signatures, authorityRecs, variable, cachedState, wasAuth);
}
auto entryAAAA = getEntryUsingECSIndex(map, now, qname, QType::AAAA, requireAuth, who);
if (entryAAAA != map.d_map.end()) {
- int32_t ttdAAAA = handleHit(map, entryAAAA, qname, res, signatures, authorityRecs, variable, state, wasAuth);
+ int32_t ttdAAAA = handleHit(map, entryAAAA, qname, res, signatures, authorityRecs, variable, cachedState, wasAuth);
if (ret > 0) {
ret = std::min(ret, ttdAAAA);
} else {
ret = ttdAAAA;
}
}
+
+ if (state && cachedState) {
+ *state = *cachedState;
+ }
+
return ret > 0 ? static_cast<int32_t>(ret-now) : ret;
}
else {
auto entry = getEntryUsingECSIndex(map, now, qname, qtype, requireAuth, who);
if (entry != map.d_map.end()) {
- return static_cast<int32_t>(handleHit(map, entry, qname, res, signatures, authorityRecs, variable, state, wasAuth) - now);
+ int32_t ret = handleHit(map, entry, qname, res, signatures, authorityRecs, variable, cachedState, wasAuth);
+ if (state && cachedState) {
+ *state = *cachedState;
+ }
+ return static_cast<int32_t>(ret-now);
}
return -1;
}
continue;
}
- ttd = handleHit(map, firstIndexIterator, qname, res, signatures, authorityRecs, variable, state, wasAuth);
+ ttd = handleHit(map, firstIndexIterator, qname, res, signatures, authorityRecs, variable, cachedState, wasAuth);
if (qt.getCode() != QType::ANY && qt.getCode() != QType::ADDR) { // normally if we have a hit, we are done
break;
}
}
+ if (state && cachedState) {
+ *state = *cachedState;
+ }
return static_cast<int32_t>(ttd-now);
}
}
continue;
}
- ttd = handleHit(map, firstIndexIterator, qname, res, signatures, authorityRecs, variable, state, wasAuth);
+ ttd = handleHit(map, firstIndexIterator, qname, res, signatures, authorityRecs, variable, cachedState, wasAuth);
if (qt.getCode() != QType::ANY && qt.getCode() != QType::ADDR) { // normally if we have a hit, we are done
break;
}
}
+ if (state && cachedState) {
+ *state = *cachedState;
+ }
return static_cast<int32_t>(ttd-now);
}
return -1;
}
}
+static void reapRecordsForValidation(std::map<uint16_t, CacheEntry>& entries, const vector<DNSRecord>& records)
+{
+ for (const auto& rec : records) {
+ entries[rec.d_type].records.push_back(rec);
+ }
+}
+
+static void reapSignaturesForValidation(std::map<uint16_t, CacheEntry>& entries, const vector<std::shared_ptr<RRSIGRecordContent>>& signatures)
+{
+ for (const auto& sig : signatures) {
+ entries[sig->d_type].signatures.push_back(sig);
+ }
+}
+
/*!
* Convenience function to push the records from records into ret with a new TTL
*
cachedState = validateDNSKeys(sqname, cset, signatures, depth);
}
else {
- cachedState = SyncRes::validateRecordsWithSigs(depth, sqname, sqt, sqname, cset, signatures);
+ if (sqt == QType::ANY) {
+ std::map<uint16_t, CacheEntry> types;
+ reapRecordsForValidation(types, cset);
+ reapSignaturesForValidation(types, signatures);
+
+ for (const auto& type : types) {
+ vState cachedRecordState;
+ if (type.first == QType::DNSKEY) {
+ cachedRecordState = validateDNSKeys(sqname, type.second.records, type.second.signatures, depth);
+ }
+ else {
+ cachedRecordState = SyncRes::validateRecordsWithSigs(depth, sqname, QType(type.first), sqname, type.second.records, type.second.signatures);
+ }
+ updateDNSSECValidationState(cachedState, cachedRecordState);
+ }
+ }
+ else {
+ cachedState = SyncRes::validateRecordsWithSigs(depth, sqname, sqt, sqname, cset, signatures);
+ }
}
}
else {
recordcontents.insert(record.d_content);
}
- LOG(d_prefix<<"Going to validate "<<recordcontents.size()<< " record contents with "<<signatures.size()<<" sigs and "<<keys.size()<<" keys for "<<name<<endl);
+ LOG(d_prefix<<"Going to validate "<<recordcontents.size()<< " record contents with "<<signatures.size()<<" sigs and "<<keys.size()<<" keys for "<<name<<"|"<<qtype.getName()<<endl);
if (validateWithKeySet(d_now.tv_sec, name, recordcontents, signatures, keys, false)) {
LOG(d_prefix<<"Secure!"<<endl);
return vState::Secure;