if(t_pdl && t_pdl->d_gettag) {
try {
- dc->d_tag = t_pdl->gettag(conn->d_remote, dc->d_ednssubnet.source, dest, qname, qtype, &dc->d_policyTags, dc->d_data, ednsOptionsn true, requestorId);
+ dc->d_tag = t_pdl->gettag(conn->d_remote, dc->d_ednssubnet.source, dest, qname, qtype, &dc->d_policyTags, dc->d_data, ednsOptions, true, requestorId);
}
catch(std::exception& e) {
if(g_logCommonErrors)
t_RC->doPrune(); // this function is local to a thread, so fine anyhow
t_packetCache->doPruneTo(::arg().asNum("max-packetcache-entries") / g_numWorkerThreads);
- t_sstorage->negcache.prune(::arg().asNum("max-cache-entries") / (g_numWorkerThreads * 10));
+ SyncRes::pruneNegCache(::arg().asNum("max-cache-entries") / (g_numWorkerThreads * 10));
if(!((cleanCounter++)%40)) { // this is a full scan!
time_t limit=now.tv_sec-300;
- for(SyncRes::nsspeeds_t::iterator i = t_sstorage->nsSpeeds.begin() ; i!= t_sstorage->nsSpeeds.end(); )
- if(i->second.stale(limit))
- i = t_sstorage->nsSpeeds.erase(i);
- else
- ++i;
+ SyncRes::pruneNSSpeeds(limit);
}
last_prune=time(0);
}
{
t_id=(int) (long) ptr;
SyncRes tmp(g_now); // make sure it allocates tsstorage before we do anything, like primeHints or so..
- t_sstorage->domainmap = g_initialDomainMap;
+ SyncRes::setDomainMap(g_initialDomainMap);
t_allowFrom = g_initialAllowFrom;
t_udpclientsocks = std::unique_ptr<UDPClientSocks>(new UDPClientSocks());
t_tcpClientCounts = std::unique_ptr<tcpClientCounts_t>(new tcpClientCounts_t());
static uint64_t* pleaseDump(int fd)
{
- return new uint64_t(t_RC->doDump(fd) + dumpNegCache(t_sstorage->negcache, fd) + t_packetCache->doDump(fd));
+ return new uint64_t(t_RC->doDump(fd) + dumpNegCache(SyncRes::t_sstorage.negcache, fd) + t_packetCache->doDump(fd));
}
static uint64_t* pleaseDumpNSSpeeds(int fd)
uint64_t* pleaseWipeAndCountNegCache(const DNSName& canon, bool subtree)
{
- uint64_t ret = t_sstorage->negcache.wipe(canon, subtree);
+ uint64_t ret = SyncRes::wipeNegCache(canon, subtree);
return new uint64_t(ret);
}
uint64_t* pleaseGetThrottleSize()
{
- return new uint64_t(t_sstorage ? t_sstorage->throttle.size() : 0);
+ return new uint64_t(SyncRes::getThrottledServersSize());
}
static uint64_t getThrottleSize()
uint64_t* pleaseGetNegCacheSize()
{
- uint64_t tmp=(t_sstorage ? t_sstorage->negcache.size() : 0);
+ uint64_t tmp=(SyncRes::getNegCacheSize());
return new uint64_t(tmp);
}
uint64_t* pleaseGetFailedHostsSize()
{
- uint64_t tmp=(t_sstorage ? t_sstorage->fails.size() : 0);
+ uint64_t tmp=(SyncRes::getThrottledServersSize());
return new uint64_t(tmp);
}
uint64_t getFailedHostsSize()
uint64_t* pleaseGetNsSpeedsSize()
{
- return new uint64_t(t_sstorage ? t_sstorage->nsSpeeds.size() : 0);
+ return new uint64_t(SyncRes::getNSSpeedsSize());
}
uint64_t getNsSpeedsSize()
SyncRes::clearDelegationOnly();
SyncRes::clearDontQuery();
+ SyncRes::clearNSSpeeds();
+ SyncRes::clearEDNSStatuses();
+ SyncRes::clearThrottle();
+ SyncRes::clearFailedServers();
+
auto luaconfsCopy = g_luaconfs.getCopy();
luaconfsCopy.dfe.clear();
g_luaconfs.setState(luaconfsCopy);
sr->setDoEDNS0(edns0);
sr->setDoDNSSEC(dnssec);
sr->setLogMode(lm);
- t_sstorage->domainmap = std::make_shared<SyncRes::domainmap_t>();
- t_sstorage->negcache.clear();
- t_sstorage->nsSpeeds.clear();
- t_sstorage->ednsstatus.clear();
- t_sstorage->throttle.clear();
- t_sstorage->fails.clear();
- t_sstorage->dnssecmap.clear();
+ SyncRes::setDomainMap(std::make_shared<SyncRes::domainmap_t>());
+ SyncRes::clearNegCache();
}
static void setLWResult(LWResult* res, int rcode, bool aa=false, bool tc=false, bool edns=false)
BOOST_CHECK(downServers.size() > 0);
/* we explicitly refuse to mark the root servers down */
for (const auto& server : downServers) {
- BOOST_CHECK_EQUAL(t_sstorage->fails.value(server), 0);
+ BOOST_CHECK_EQUAL(SyncRes::getServerFailsCount(server), 0);
}
}
BOOST_CHECK_EQUAL(ret.size(), 1);
BOOST_CHECK_EQUAL(queriesWithEDNS, 1);
BOOST_CHECK_EQUAL(queriesWithoutEDNS, 1);
- BOOST_CHECK_EQUAL(t_sstorage->ednsstatus.size(), 1);
- BOOST_CHECK_EQUAL(t_sstorage->ednsstatus[noEDNSServer].mode, SyncRes::EDNSStatus::NOEDNS);
+ BOOST_CHECK_EQUAL(SyncRes::getEDNSStatusesSize(), 1);
+ BOOST_CHECK_EQUAL(SyncRes::getEDNSStatus(noEDNSServer), SyncRes::EDNSStatus::NOEDNS);
}
BOOST_AUTO_TEST_CASE(test_edns_notimp_fallback) {
BOOST_CHECK_EQUAL(downServers.size(), 4);
for (const auto& server : downServers) {
- BOOST_CHECK_EQUAL(t_sstorage->fails.value(server), 1);
- BOOST_CHECK(t_sstorage->throttle.shouldThrottle(time(nullptr), boost::make_tuple(server, target, QType::A)));
+ BOOST_CHECK_EQUAL(SyncRes::getServerFailsCount(server), 1);
+ BOOST_CHECK(SyncRes::isThrottled(time(nullptr), server, target, QType::A));
}
}
BOOST_CHECK_EQUAL(downServers.size(), 4);
for (const auto& server : downServers) {
- BOOST_CHECK_EQUAL(t_sstorage->fails.value(server), 1);
- BOOST_CHECK(t_sstorage->throttle.shouldThrottle(time(nullptr), boost::make_tuple(server, target, QType::A)));
+ BOOST_CHECK_EQUAL(SyncRes::getServerFailsCount(server), 1);
+ BOOST_CHECK(SyncRes::isThrottled(time(nullptr), server, target, QType::A));
+;
}
}
/* Error is reported as "OS limit error" (-2) so the servers should _NOT_ be marked down */
for (const auto& server : downServers) {
- BOOST_CHECK_EQUAL(t_sstorage->fails.value(server), 0);
- BOOST_CHECK(!t_sstorage->throttle.shouldThrottle(time(nullptr), boost::make_tuple(server, target, QType::A)));
+ BOOST_CHECK_EQUAL(SyncRes::getServerFailsCount(server), 0);
+ BOOST_CHECK(!SyncRes::isThrottled(time(nullptr), server, target, QType::A));
}
}
});
/* mark ns as down */
- t_sstorage->throttle.throttle(time(nullptr), boost::make_tuple(ns, "", 0), SyncRes::s_serverdownthrottletime, 10000);
+ SyncRes::doThrottle(time(nullptr), ns, SyncRes::s_serverdownthrottletime, 10000);
vector<DNSRecord> ret;
int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
const size_t blocks = 10;
/* mark ns as down for 'blocks' queries */
- t_sstorage->throttle.throttle(time(nullptr), boost::make_tuple(ns, "", 0), SyncRes::s_serverdownthrottletime, blocks);
+ SyncRes::doThrottle(time(nullptr), ns, SyncRes::s_serverdownthrottletime, blocks);
for (size_t idx = 0; idx < blocks; idx++) {
- BOOST_CHECK(t_sstorage->throttle.shouldThrottle(time(nullptr), boost::make_tuple(ns, "", 0)));
+ BOOST_CHECK(SyncRes::isThrottled(time(nullptr), ns));
}
/* we have been throttled 'blocks' times, we should not be throttled anymore */
- BOOST_CHECK(!t_sstorage->throttle.shouldThrottle(time(nullptr), boost::make_tuple(ns, "", 0)));
+ BOOST_CHECK(!SyncRes::isThrottled(time(nullptr), ns));
}
BOOST_AUTO_TEST_CASE(test_throttled_server_time) {
const size_t seconds = 1;
/* mark ns as down for 'seconds' seconds */
- t_sstorage->throttle.throttle(time(nullptr), boost::make_tuple(ns, "", 0), seconds, 10000);
- BOOST_CHECK(t_sstorage->throttle.shouldThrottle(time(nullptr), boost::make_tuple(ns, "", 0)));
+ SyncRes::doThrottle(time(nullptr), ns, seconds, 10000);
+
+ BOOST_CHECK(SyncRes::isThrottled(time(nullptr), ns));
sleep(seconds + 1);
/* we should not be throttled anymore */
- BOOST_CHECK(!t_sstorage->throttle.shouldThrottle(time(nullptr), boost::make_tuple(ns, "", 0)));
+ BOOST_CHECK(!SyncRes::isThrottled(time(nullptr), ns));
}
BOOST_AUTO_TEST_CASE(test_dont_query_server) {
BOOST_CHECK_EQUAL(res, RCode::NXDomain);
BOOST_CHECK_EQUAL(ret.size(), 1);
/* one for target1 and one for the entire TLD */
- BOOST_CHECK_EQUAL(t_sstorage->negcache.size(), 2);
+ BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 2);
ret.clear();
res = sr->beginResolve(target2, QType(QType::A), QClass::IN, ret);
BOOST_CHECK_EQUAL(res, RCode::NXDomain);
BOOST_CHECK_EQUAL(ret.size(), 1);
/* one for target1 and one for the entire TLD */
- BOOST_CHECK_EQUAL(t_sstorage->negcache.size(), 2);
+ BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 2);
/* we should have sent only one query */
BOOST_CHECK_EQUAL(queriesCount, 1);
/* even with root-nx-trust on and a NX answer from the root,
we should not have cached the entire TLD this time. */
- BOOST_CHECK_EQUAL(t_sstorage->negcache.size(), 1);
+ BOOST_CHECK_EQUAL(SyncRes::t_sstorage.negcache.size(), 1);
ret.clear();
res = sr->beginResolve(target2, QType(QType::A), QClass::IN, ret);
BOOST_CHECK_EQUAL(ret[0].d_name, target2);
BOOST_CHECK(getRR<ARecordContent>(ret[0])->getCA() == ComboAddress("192.0.2.2"));
- BOOST_CHECK_EQUAL(t_sstorage->negcache.size(), 1);
+ BOOST_CHECK_EQUAL(SyncRes::t_sstorage.negcache.size(), 1);
BOOST_CHECK_EQUAL(queriesCount, 3);
}
BOOST_CHECK_EQUAL(res, RCode::NXDomain);
BOOST_CHECK_EQUAL(ret.size(), 1);
/* one for target1 */
- BOOST_CHECK_EQUAL(t_sstorage->negcache.size(), 1);
+ BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 1);
ret.clear();
res = sr->beginResolve(target2, QType(QType::A), QClass::IN, ret);
BOOST_CHECK_EQUAL(res, 0);
BOOST_CHECK_EQUAL(ret.size(), 1);
/* one for target1 */
- BOOST_CHECK_EQUAL(t_sstorage->negcache.size(), 1);
+ BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 1);
/* we should have sent three queries */
BOOST_CHECK_EQUAL(queriesCount, 3);
BOOST_CHECK_EQUAL(res, RCode::NXDomain);
BOOST_CHECK_EQUAL(ret.size(), 2);
/* no negative cache entry because the response was variable */
- BOOST_CHECK_EQUAL(t_sstorage->negcache.size(), 0);
+ BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 0);
}
BOOST_AUTO_TEST_CASE(test_ns_speed) {
/* make pdns-public-ns2.powerdns.com. the fastest NS, with its IPv6 address faster than the IPV4 one,
then pdns-public-ns1.powerdns.com. on IPv4 */
- t_sstorage->nsSpeeds[DNSName("pdns-public-ns1.powerdns.com.")].submit(ComboAddress("192.0.2.1:53"), 100, &now);
- t_sstorage->nsSpeeds[DNSName("pdns-public-ns1.powerdns.com.")].submit(ComboAddress("[2001:DB8::1]:53"), 10000, &now);
- t_sstorage->nsSpeeds[DNSName("pdns-public-ns2.powerdns.com.")].submit(ComboAddress("192.0.2.2:53"), 10, &now);
- t_sstorage->nsSpeeds[DNSName("pdns-public-ns2.powerdns.com.")].submit(ComboAddress("[2001:DB8::2]:53"), 1, &now);
- t_sstorage->nsSpeeds[DNSName("pdns-public-ns3.powerdns.com.")].submit(ComboAddress("192.0.2.3:53"), 10000, &now);
- t_sstorage->nsSpeeds[DNSName("pdns-public-ns3.powerdns.com.")].submit(ComboAddress("[2001:DB8::3]:53"), 10000, &now);
+ SyncRes::submitNSSpeed(DNSName("pdns-public-ns1.powerdns.com."), ComboAddress("192.0.2.1:53"), 100, &now);
+ SyncRes::submitNSSpeed(DNSName("pdns-public-ns1.powerdns.com."), ComboAddress("[2001:DB8::1]:53"), 10000, &now);
+ SyncRes::submitNSSpeed(DNSName("pdns-public-ns2.powerdns.com."), ComboAddress("192.0.2.2:53"), 10, &now);
+ SyncRes::submitNSSpeed(DNSName("pdns-public-ns2.powerdns.com."), ComboAddress("[2001:DB8::2]:53"), 1, &now);
+ SyncRes::submitNSSpeed(DNSName("pdns-public-ns3.powerdns.com."), ComboAddress("192.0.2.3:53"), 10000, &now);
+ SyncRes::submitNSSpeed(DNSName("pdns-public-ns3.powerdns.com."), ComboAddress("[2001:DB8::3]:53"), 10000, &now);
vector<DNSRecord> ret;
int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
SyncRes::AuthDomain ad;
ad.d_rdForward = false;
ad.d_servers.push_back(forwardedNS);
- (*t_sstorage->domainmap)[target] = ad;
+ (*SyncRes::t_sstorage.domainmap)[target] = ad;
sr->setAsyncCallback([forwardedNS](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, std::shared_ptr<RemoteLogger> outgoingLogger, LWResult* res) {
SyncRes::AuthDomain ad;
ad.d_rdForward = false;
ad.d_servers.push_back(forwardedNS);
- (*t_sstorage->domainmap)[target] = ad;
+ (*SyncRes::t_sstorage.domainmap)[target] = ad;
sr->setAsyncCallback([forwardedNS](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, std::shared_ptr<RemoteLogger> outgoingLogger, LWResult* res) {
SyncRes::AuthDomain ad;
ad.d_rdForward = true;
ad.d_servers.push_back(forwardedNS);
- (*t_sstorage->domainmap)[target] = ad;
+ (*SyncRes::t_sstorage.domainmap)[target] = ad;
sr->setAsyncCallback([forwardedNS](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, std::shared_ptr<RemoteLogger> outgoingLogger, LWResult* res) {
SyncRes::AuthDomain ad;
ad.d_rdForward = true;
ad.d_servers.push_back(forwardedNS);
- (*t_sstorage->domainmap)[target] = ad;
+ (*SyncRes::t_sstorage.domainmap)[target] = ad;
sr->setAsyncCallback([forwardedNS](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, std::shared_ptr<RemoteLogger> outgoingLogger, LWResult* res) {
dr.d_content = std::make_shared<ARecordContent>(nsAddr);
ad.d_records.insert(dr);
- (*t_sstorage->domainmap)[authZone] = ad;
+ (*SyncRes::t_sstorage.domainmap)[authZone] = ad;
sr->setAsyncCallback([&queriesCount,nsAddr,target,targetAddr](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, std::shared_ptr<RemoteLogger> outgoingLogger, LWResult* res) {
queriesCount++;
void* pleaseWipeNegCache()
{
- t_sstorage->negcache.clear();
+ SyncRes::clearNegCache();
return 0;
}
void* pleaseUseNewSDomainsMap(std::shared_ptr<SyncRes::domainmap_t> newmap)
{
- t_sstorage->domainmap = newmap;
+ SyncRes::setDomainMap(newmap);
return 0;
}
string reloadAuthAndForwards()
{
- std::shared_ptr<SyncRes::domainmap_t> original=t_sstorage->domainmap;
+ std::shared_ptr<SyncRes::domainmap_t> original=SyncRes::getDomainMap();
try {
L<<Logger::Warning<<"Reloading zones, purging data from cache"<<endl;
-
- for(const auto& i : *t_sstorage->domainmap) {
- for(const auto& j : i.second.d_records)
- broadcastAccFunction<uint64_t>(boost::bind(pleaseWipeCache, j.d_name, false));
+
+ if (original) {
+ for(const auto& i : *original) {
+ for(const auto& j : i.second.d_records)
+ broadcastAccFunction<uint64_t>(boost::bind(pleaseWipeCache, j.d_name, false));
+ }
}
string configname=::arg()["config-dir"]+"/recursor.conf";
#include "ednssubnet.hh"
#include "cachecleaner.hh"
#include "rec-lua-conf.hh"
-thread_local std::unique_ptr<SyncRes::StaticStorage> t_sstorage;
+thread_local SyncRes::ThreadLocalStorage SyncRes::t_sstorage;
unsigned int SyncRes::s_maxnegttl;
unsigned int SyncRes::s_maxcachettl;
d_cacheonly(false), d_nocache(false), d_doDNSSEC(false), d_doEDNS0(false), d_lm(s_lm)
{
- if(!t_sstorage) {
- t_sstorage = std::unique_ptr<StaticStorage>(new StaticStorage());
- }
}
/** everything begins here - this is the entry point just after receiving a packet */
DNSName authdomain(qname);
domainmap_t::const_iterator iter=getBestAuthZone(&authdomain);
- if(iter==t_sstorage->domainmap->end()) {
+ if(iter==t_sstorage.domainmap->end()) {
LOG(prefix<<qname<<": auth storage has no zone for this query!"<<endl);
return false;
}
return;
}
fprintf(fp,"IP Address\tMode\tMode last updated at\n");
- for(const auto& eds : t_sstorage->ednsstatus) {
+ for(const auto& eds : t_sstorage.ednsstatus) {
fprintf(fp, "%s\t%d\t%s", eds.first.toString().c_str(), (int)eds.second.mode, ctime(&eds.second.modeSetAt));
}
fprintf(fp, "; nsspeed dump from thread follows\n;\n");
uint64_t count=0;
- for(const auto& i : t_sstorage->nsSpeeds)
+ for(const auto& i : t_sstorage.nsSpeeds)
{
count++;
fprintf(fp, "%s -> ", i.first.toString().c_str());
*/
SyncRes::EDNSStatus* ednsstatus;
- ednsstatus = &t_sstorage->ednsstatus[ip]; // does this include port? YES
+ ednsstatus = &t_sstorage.ednsstatus[ip]; // does this include port? YES
if(ednsstatus->modeSetAt && ednsstatus->modeSetAt + 3600 < d_now.tv_sec) {
*ednsstatus=SyncRes::EDNSStatus();
LOG(prefix<<qname<<": Recursion not requested for '"<<qname<<"|"<<qtype.getName()<<"', peeking at auth/forward zones"<<endl);
DNSName authname(qname);
domainmap_t::const_iterator iter=getBestAuthZone(&authname);
- if(iter != t_sstorage->domainmap->end()) {
+ if(iter != t_sstorage.domainmap->end()) {
const vector<ComboAddress>& servers = iter->second.d_servers;
if(servers.empty()) {
ret.clear();
random_shuffle(ret.begin(), ret.end(), dns_random);
// move 'best' address for this nameserver name up front
- nsspeeds_t::iterator best = t_sstorage->nsSpeeds.find(qname);
+ nsspeeds_t::iterator best = t_sstorage.nsSpeeds.find(qname);
- if(best != t_sstorage->nsSpeeds.end())
+ if(best != t_sstorage.nsSpeeds.end())
for(ret_t::iterator i=ret.begin(); i != ret.end(); ++i) {
if(*i==best->second.d_best) { // got the fastest one
if(i!=ret.begin()) {
{
SyncRes::domainmap_t::const_iterator ret;
do {
- ret=t_sstorage->domainmap->find(*qname);
- if(ret!=t_sstorage->domainmap->end())
+ ret=t_sstorage.domainmap->find(*qname);
+ if(ret!=t_sstorage.domainmap->end())
break;
}while(qname->chopOff());
return ret;
DNSName authdomain(qname);
domainmap_t::const_iterator iter=getBestAuthZone(&authdomain);
- if(iter!=t_sstorage->domainmap->end()) {
+ if(iter!=t_sstorage.domainmap->end()) {
if( iter->second.d_servers.empty() )
// this gets picked up in doResolveAt, the empty DNSName, combined with the
// empty vector means 'we are auth for this zone'
bool wasForwardedOrAuth = false;
bool wasAuth = false;
domainmap_t::const_iterator iter=getBestAuthZone(&authname);
- if(iter != t_sstorage->domainmap->end()) {
+ if(iter != t_sstorage.domainmap->end()) {
wasForwardedOrAuth = true;
const vector<ComboAddress>& servers = iter->second.d_servers;
if(servers.empty()) {
NegCache::NegCacheEntry ne;
if(s_rootNXTrust &&
- t_sstorage->negcache.getRootNXTrust(qname, d_now, ne) &&
+ t_sstorage.negcache.getRootNXTrust(qname, d_now, ne) &&
ne.d_auth.isRoot() &&
!(wasForwardedOrAuth && !authname.isRoot())) { // when forwarding, the root may only neg-cache if it was forwarded to.
sttl = ne.d_ttd - d_now.tv_sec;
res = RCode::NXDomain;
giveNegative = true;
}
- else if (t_sstorage->negcache.get(qname, qtype, d_now, ne) &&
+ else if (t_sstorage.negcache.get(qname, qtype, d_now, ne) &&
!(wasForwardedOrAuth && ne.d_auth != authname)) { // Only the authname nameserver can neg cache entries
res = 0;
sttl = ne.d_ttd - d_now.tv_sec;
for(const auto& val: rnameservers) {
double speed;
- speed=t_sstorage->nsSpeeds[val].get(&d_now);
+ speed=t_sstorage.nsSpeeds[val].get(&d_now);
speeds[val]=speed;
}
random_shuffle(rnameservers.begin(),rnameservers.end(), dns_random);
bool SyncRes::throttledOrBlocked(const std::string& prefix, const ComboAddress& remoteIP, const DNSName& qname, const QType& qtype, bool pierceDontQuery)
{
- if(t_sstorage->throttle.shouldThrottle(d_now.tv_sec, boost::make_tuple(remoteIP, "", 0))) {
+ if(t_sstorage.throttle.shouldThrottle(d_now.tv_sec, boost::make_tuple(remoteIP, "", 0))) {
LOG(prefix<<qname<<": server throttled "<<endl);
s_throttledqueries++; d_throttledqueries++;
return true;
}
- else if(t_sstorage->throttle.shouldThrottle(d_now.tv_sec, boost::make_tuple(remoteIP, qname, qtype.getCode()))) {
+ else if(t_sstorage.throttle.shouldThrottle(d_now.tv_sec, boost::make_tuple(remoteIP, qname, qtype.getCode()))) {
LOG(prefix<<qname<<": query throttled "<<endl);
s_throttledqueries++; d_throttledqueries++;
return true;
}
else {
bool haveLogged = false;
- if (!t_sstorage->domainmap->empty()) {
+ if (!t_sstorage.domainmap->empty()) {
// Check if we are authoritative for a zone in this answer
DNSName tmp_qname(rec.d_name);
auto auth_domain_iter=getBestAuthZone(&tmp_qname);
- if(auth_domain_iter!=t_sstorage->domainmap->end() &&
+ if(auth_domain_iter!=t_sstorage.domainmap->end() &&
auth.countLabels() <= auth_domain_iter->first.countLabels()) {
if (auth_domain_iter->first != auth) {
LOG("NO! - we are authoritative for the zone "<<auth_domain_iter->first<<endl);
ne.d_qtype = QType(0); // this encodes 'whole record'
ne.d_auth = rec.d_name;
harvestNXRecords(lwr.d_records, ne);
- t_sstorage->negcache.add(ne);
+ t_sstorage.negcache.add(ne);
if(s_rootNXTrust && ne.d_auth.isRoot() && auth.isRoot()) {
ne.d_name = ne.d_name.getLastLabel();
- t_sstorage->negcache.add(ne);
+ t_sstorage.negcache.add(ne);
}
}
ne.d_qtype = qtype;
harvestNXRecords(lwr.d_records, ne);
if(qtype.getCode()) { // prevents us from blacking out a whole domain
- t_sstorage->negcache.add(ne);
+ t_sstorage.negcache.add(ne);
}
}
negindic=true;
}
if(resolveret!=-2) { // don't account for resource limits, they are our own fault
- t_sstorage->nsSpeeds[*tns].submit(*remoteIP, 1000000, &d_now); // 1 sec
+ t_sstorage.nsSpeeds[*tns].submit(*remoteIP, 1000000, &d_now); // 1 sec
// code below makes sure we don't filter COM or the root
- if (s_serverdownmaxfails > 0 && (auth != g_rootdnsname) && t_sstorage->fails.incr(*remoteIP) >= s_serverdownmaxfails) {
+ if (s_serverdownmaxfails > 0 && (auth != g_rootdnsname) && t_sstorage.fails.incr(*remoteIP) >= s_serverdownmaxfails) {
LOG(prefix<<qname<<": Max fails reached resolving on "<< remoteIP->toString() <<". Going full throttle for "<< s_serverdownthrottletime <<" seconds" <<endl);
- t_sstorage->throttle.throttle(d_now.tv_sec, boost::make_tuple(*remoteIP, "", 0), s_serverdownthrottletime, 10000); // mark server as down
+ t_sstorage.throttle.throttle(d_now.tv_sec, boost::make_tuple(*remoteIP, "", 0), s_serverdownthrottletime, 10000); // mark server as down
} else if(resolveret==-1)
- t_sstorage->throttle.throttle(d_now.tv_sec, boost::make_tuple(*remoteIP, qname, qtype.getCode()), 60, 100); // unreachable, 1 minute or 100 queries
+ t_sstorage.throttle.throttle(d_now.tv_sec, boost::make_tuple(*remoteIP, qname, qtype.getCode()), 60, 100); // unreachable, 1 minute or 100 queries
else
- t_sstorage->throttle.throttle(d_now.tv_sec, boost::make_tuple(*remoteIP, qname, qtype.getCode()), 10, 5); // timeout
+ t_sstorage.throttle.throttle(d_now.tv_sec, boost::make_tuple(*remoteIP, qname, qtype.getCode()), 10, 5); // timeout
}
continue;
}
if(lwr.d_rcode==RCode::ServFail || lwr.d_rcode==RCode::Refused) {
LOG(prefix<<qname<<": "<<*tns<<" ("<<remoteIP->toString()<<") returned a "<< (lwr.d_rcode==RCode::ServFail ? "ServFail" : "Refused") << ", trying sibling IP or NS"<<endl);
- t_sstorage->throttle.throttle(d_now.tv_sec,boost::make_tuple(*remoteIP, qname, qtype.getCode()),60,3); // servfail or refused
+ t_sstorage.throttle.throttle(d_now.tv_sec,boost::make_tuple(*remoteIP, qname, qtype.getCode()),60,3); // servfail or refused
continue;
}
if(s_serverdownmaxfails > 0)
- t_sstorage->fails.clear(*remoteIP);
+ t_sstorage.fails.clear(*remoteIP);
break; // this IP address worked!
wasLame:; // well, it didn't
LOG(prefix<<qname<<": status=NS "<<*tns<<" ("<< remoteIP->toString() <<") is lame for '"<<auth<<"', trying sibling IP or NS"<<endl);
- t_sstorage->throttle.throttle(d_now.tv_sec, boost::make_tuple(*remoteIP, qname, qtype.getCode()), 60, 100); // lame
+ t_sstorage.throttle.throttle(d_now.tv_sec, boost::make_tuple(*remoteIP, qname, qtype.getCode()), 60, 100); // lame
}
}
*/
// cout<<"msec: "<<lwr.d_usec/1000.0<<", "<<g_avgLatency/1000.0<<'\n';
- t_sstorage->nsSpeeds[*tns].submit(*remoteIP, lwr.d_usec, &d_now);
+ t_sstorage.nsSpeeds[*tns].submit(*remoteIP, lwr.d_usec, &d_now);
}
if(s_minimumTTL) {
else if(realreferral) {
LOG(prefix<<qname<<": status=did not resolve, got "<<(unsigned int)nsset.size()<<" NS, ");
if(sawDS) {
- t_sstorage->dnssecmap[newauth]=true;
- /* for(const auto& e : t_sstorage->dnssecmap)
+ //s_dnssecmap[newauth]=true;
+ /* for(const auto& e : s_dnssecmap)
cout<<e.first<<' ';
cout<<endl;*/
}
{
}
- struct timeval getOrMakeTime(struct timeval* tv)
+ void submit(int val, const struct timeval* tv)
{
- if(tv)
- return *tv;
- else {
- struct timeval ret;
- Utility::gettimeofday(&ret, 0);
- return ret;
- }
- }
-
- void submit(int val, struct timeval* tv)
- {
- struct timeval now=getOrMakeTime(tv);
+ struct timeval now=*tv;
if(d_needinit) {
d_last=now;
}
}
- double get(struct timeval* tv)
+ double get(const struct timeval* tv)
{
- struct timeval now=getOrMakeTime(tv);
+ struct timeval now=*tv;
float diff=makeFloat(d_lastget-now);
d_lastget=now;
float factor=exp(diff/60.0f); // is 1.0 or less
enum LogMode { LogNone, Log, Store};
typedef std::function<int(const ComboAddress& ip, const DNSName& qdomain, int qtype, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, std::shared_ptr<RemoteLogger> outgoingLogger, LWResult *lwr)> asyncresolve_t;
+ struct EDNSStatus
+ {
+ EDNSStatus() : mode(UNKNOWN), modeSetAt(0) {}
+ enum EDNSMode { UNKNOWN=0, EDNSOK=1, EDNSIGNORANT=2, NOEDNS=3 } mode;
+ time_t modeSetAt;
+ };
+
+ //! This represents a number of decaying Ewmas, used to store performance per nameserver-name.
+ /** Modelled to work mostly like the underlying DecayingEwma. After you've called get,
+ d_best is filled out with the best address for this collection */
+ struct DecayingEwmaCollection
+ {
+ void submit(const ComboAddress& remote, int usecs, const struct timeval* now)
+ {
+ collection_t::iterator pos;
+ for(pos=d_collection.begin(); pos != d_collection.end(); ++pos)
+ if(pos->first==remote)
+ break;
+ if(pos!=d_collection.end()) {
+ pos->second.submit(usecs, now);
+ }
+ else {
+ DecayingEwma de;
+ de.submit(usecs, now);
+ d_collection.push_back(make_pair(remote, de));
+ }
+ }
+
+ double get(const struct timeval* now)
+ {
+ if(d_collection.empty())
+ return 0;
+ double ret=std::numeric_limits<double>::max();
+ double tmp;
+ for(collection_t::iterator pos=d_collection.begin(); pos != d_collection.end(); ++pos) {
+ if((tmp=pos->second.get(now)) < ret) {
+ ret=tmp;
+ d_best=pos->first;
+ }
+ }
+
+ return ret;
+ }
+
+ bool stale(time_t limit) const
+ {
+ for(collection_t::const_iterator pos=d_collection.begin(); pos != d_collection.end(); ++pos)
+ if(!pos->second.stale(limit))
+ return false;
+ return true;
+ }
+
+ typedef vector<pair<ComboAddress, DecayingEwma> > collection_t;
+ collection_t d_collection;
+ ComboAddress d_best;
+ };
+
+ typedef map<DNSName, DecayingEwmaCollection> nsspeeds_t;
+ typedef map<ComboAddress, EDNSStatus> ednsstatus_t;
+
+ struct AuthDomain
+ {
+ vector<ComboAddress> d_servers;
+ bool d_rdForward;
+ typedef multi_index_container <
+ DNSRecord,
+ indexed_by <
+ ordered_non_unique<
+ composite_key< DNSRecord,
+ member<DNSRecord, DNSName, &DNSRecord::d_name>,
+ member<DNSRecord, uint16_t, &DNSRecord::d_type>
+ >,
+ composite_key_compare<std::less<DNSName>, std::less<uint16_t> >
+ >
+ >
+ > records_t;
+ records_t d_records;
+ };
+
+ typedef map<DNSName, AuthDomain> domainmap_t;
+ typedef Throttle<boost::tuple<ComboAddress,DNSName,uint16_t> > throttle_t;
+ typedef Counters<ComboAddress> fails_t;
+
+ struct ThreadLocalStorage {
+ NegCache negcache;
+ nsspeeds_t nsSpeeds;
+ throttle_t throttle;
+ ednsstatus_t ednsstatus;
+ fails_t fails;
+ std::shared_ptr<domainmap_t> domainmap;
+ };
+
static void setDefaultLogMode(LogMode lm)
{
s_lm = lm;
{
s_ednsdomains = SuffixMatchNode();
}
+ static void pruneNSSpeeds(time_t limit)
+ {
+ for(auto i = t_sstorage.nsSpeeds.begin(), end = t_sstorage.nsSpeeds.end(); i != end; ) {
+ if(i->second.stale(limit)) {
+ i = t_sstorage.nsSpeeds.erase(i);
+ }
+ else {
+ ++i;
+ }
+ }
+ }
+ static uint64_t getNSSpeedsSize()
+ {
+ return t_sstorage.nsSpeeds.size();
+ }
+ static void submitNSSpeed(const DNSName& server, const ComboAddress& ca, uint32_t usec, const struct timeval* now)
+ {
+ t_sstorage.nsSpeeds[server].submit(ca, usec, now);
+ }
+ static void clearNSSpeeds()
+ {
+ t_sstorage.nsSpeeds.clear();
+ }
+ static EDNSStatus::EDNSMode getEDNSStatus(const ComboAddress& server)
+ {
+ const auto& it = t_sstorage.ednsstatus.find(server);
+ if (it == t_sstorage.ednsstatus.end())
+ return EDNSStatus::UNKNOWN;
+
+ return it->second.mode;
+ }
+ static uint64_t getEDNSStatusesSize()
+ {
+ return t_sstorage.ednsstatus.size();
+ }
+ static void clearEDNSStatuses()
+ {
+ t_sstorage.ednsstatus.clear();
+ }
+ static uint64_t getThrottledServersSize()
+ {
+ return t_sstorage.throttle.size();
+ }
+ static void clearThrottle()
+ {
+ t_sstorage.throttle.clear();
+ }
+ static bool isThrottled(time_t now, const ComboAddress& server, const DNSName& target, uint16_t qtype)
+ {
+ return t_sstorage.throttle.shouldThrottle(now, boost::make_tuple(server, target, qtype));
+ }
+ static bool isThrottled(time_t now, const ComboAddress& server)
+ {
+ return t_sstorage.throttle.shouldThrottle(now, boost::make_tuple(server, "", 0));
+ }
+ static void doThrottle(time_t now, const ComboAddress& server, time_t duration, unsigned int tries)
+ {
+ t_sstorage.throttle.throttle(now, boost::make_tuple(server, "", 0), duration, tries);
+ }
+ static uint64_t getFailedServersSize()
+ {
+ return t_sstorage.fails.size();
+ }
+ static void clearFailedServers()
+ {
+ t_sstorage.fails.clear();
+ }
+ static unsigned long getServerFailsCount(const ComboAddress& server)
+ {
+ return t_sstorage.fails.value(server);
+ }
+
+ static void clearNegCache()
+ {
+ t_sstorage.negcache.clear();
+ }
+
+ static uint64_t getNegCacheSize()
+ {
+ return t_sstorage.negcache.size();
+ }
+
+ static void pruneNegCache(unsigned int maxEntries)
+ {
+ t_sstorage.negcache.prune(maxEntries);
+ }
+
+ static uint64_t wipeNegCache(const DNSName& name, bool subtree = false)
+ {
+ return t_sstorage.negcache.wipe(name, subtree);
+ }
+
+ static void setDomainMap(std::shared_ptr<domainmap_t> newMap)
+ {
+ t_sstorage.domainmap = newMap;
+ }
+
+ static const std::shared_ptr<domainmap_t> getDomainMap()
+ {
+ return t_sstorage.domainmap;
+ }
explicit SyncRes(const struct timeval& now);
d_asyncResolve = func;
}
+ static thread_local ThreadLocalStorage t_sstorage;
+
static std::atomic<uint64_t> s_queries;
static std::atomic<uint64_t> s_outgoingtimeouts;
static std::atomic<uint64_t> s_outgoing4timeouts;
static std::atomic<uint64_t> s_nodelegated;
static std::atomic<uint64_t> s_unreachables;
- std::unordered_map<std::string,bool> d_discardedPolicies;
- DNSFilterEngine::Policy d_appliedPolicy;
- unsigned int d_outqueries;
- unsigned int d_tcpoutqueries;
- unsigned int d_throttledqueries;
- unsigned int d_timeouts;
- unsigned int d_unreachables;
- unsigned int d_totUsec;
- ComboAddress d_requestor;
-
- //! This represents a number of decaying Ewmas, used to store performance per nameserver-name.
- /** Modelled to work mostly like the underlying DecayingEwma. After you've called get,
- d_best is filled out with the best address for this collection */
- struct DecayingEwmaCollection
- {
- void submit(const ComboAddress& remote, int usecs, struct timeval* now)
- {
- collection_t::iterator pos;
- for(pos=d_collection.begin(); pos != d_collection.end(); ++pos)
- if(pos->first==remote)
- break;
- if(pos!=d_collection.end()) {
- pos->second.submit(usecs, now);
- }
- else {
- DecayingEwma de;
- de.submit(usecs, now);
- d_collection.push_back(make_pair(remote, de));
- }
- }
-
- double get(struct timeval* now)
- {
- if(d_collection.empty())
- return 0;
- double ret=std::numeric_limits<double>::max();
- double tmp;
- for(collection_t::iterator pos=d_collection.begin(); pos != d_collection.end(); ++pos) {
- if((tmp=pos->second.get(now)) < ret) {
- ret=tmp;
- d_best=pos->first;
- }
- }
-
- return ret;
- }
-
- bool stale(time_t limit) const
- {
- for(collection_t::const_iterator pos=d_collection.begin(); pos != d_collection.end(); ++pos)
- if(!pos->second.stale(limit))
- return false;
- return true;
- }
-
- typedef vector<pair<ComboAddress, DecayingEwma> > collection_t;
- collection_t d_collection;
- ComboAddress d_best;
- };
-
- typedef map<DNSName, DecayingEwmaCollection> nsspeeds_t;
-
- struct EDNSStatus
- {
- EDNSStatus() : mode(UNKNOWN), modeSetAt(0) {}
- enum EDNSMode { UNKNOWN=0, EDNSOK=1, EDNSIGNORANT=2, NOEDNS=3 } mode;
- time_t modeSetAt;
- };
-
- typedef map<ComboAddress, EDNSStatus> ednsstatus_t;
-
- struct AuthDomain
- {
- vector<ComboAddress> d_servers;
- bool d_rdForward;
- typedef multi_index_container <
- DNSRecord,
- indexed_by <
- ordered_non_unique<
- composite_key< DNSRecord,
- member<DNSRecord, DNSName, &DNSRecord::d_name>,
- member<DNSRecord, uint16_t, &DNSRecord::d_type>
- >,
- composite_key_compare<std::less<DNSName>, std::less<uint16_t> >
- >
- >
- > records_t;
- records_t d_records;
- };
-
-
- typedef map<DNSName, AuthDomain> domainmap_t;
-
- typedef Throttle<boost::tuple<ComboAddress,DNSName,uint16_t> > throttle_t;
-
- typedef Counters<ComboAddress> fails_t;
-
static string s_serverID;
static unsigned int s_minimumTTL;
static unsigned int s_maxqperq;
static bool s_rootNXTrust;
static bool s_nopacketcache;
- struct StaticStorage {
- nsspeeds_t nsSpeeds;
- ednsstatus_t ednsstatus;
- throttle_t throttle;
- fails_t fails;
- std::shared_ptr<domainmap_t> domainmap;
- map<DNSName, bool> dnssecmap;
- NegCache negcache;
- };
+ std::unordered_map<std::string,bool> d_discardedPolicies;
+ DNSFilterEngine::Policy d_appliedPolicy;
+ unsigned int d_outqueries;
+ unsigned int d_tcpoutqueries;
+ unsigned int d_throttledqueries;
+ unsigned int d_timeouts;
+ unsigned int d_unreachables;
+ unsigned int d_totUsec;
+ ComboAddress d_requestor;
private:
+
static std::unordered_set<DNSName> s_delegationOnly;
static NetmaskGroup s_ednssubnets;
static SuffixMatchNode s_ednsdomains;
LogMode d_lm;
};
-extern thread_local std::unique_ptr<SyncRes::StaticStorage> t_sstorage;
class Socket;
/* external functions, opaque to us */
static void fillZone(const DNSName& zonename, HttpResponse* resp)
{
- auto iter = t_sstorage->domainmap->find(zonename);
- if (iter == t_sstorage->domainmap->end())
+ auto iter = SyncRes::t_sstorage.domainmap->find(zonename);
+ if (iter == SyncRes::t_sstorage.domainmap->end())
throw ApiException("Could not find domain '"+zonename.toString()+"'");
const SyncRes::AuthDomain& zone = iter->second;
DNSName zonename = apiNameToDNSName(stringFromJson(document, "name"));
- auto iter = t_sstorage->domainmap->find(zonename);
- if (iter != t_sstorage->domainmap->end())
+ auto iter = SyncRes::t_sstorage.domainmap->find(zonename);
+ if (iter != SyncRes::t_sstorage.domainmap->end())
throw ApiException("Zone already exists");
doCreateZone(document);
throw HttpMethodNotAllowedException();
Json::array doc;
- for(const SyncRes::domainmap_t::value_type& val : *t_sstorage->domainmap) {
+ for(const SyncRes::domainmap_t::value_type& val : *SyncRes::t_sstorage.domainmap) {
const SyncRes::AuthDomain& zone = val.second;
Json::array servers;
for(const ComboAddress& server : zone.d_servers) {
{
DNSName zonename = apiZoneIdToName(req->parameters["id"]);
- SyncRes::domainmap_t::const_iterator iter = t_sstorage->domainmap->find(zonename);
- if (iter == t_sstorage->domainmap->end())
+ SyncRes::domainmap_t::const_iterator iter = SyncRes::t_sstorage.domainmap->find(zonename);
+ if (iter == SyncRes::t_sstorage.domainmap->end())
throw ApiException("Could not find domain '"+zonename.toString()+"'");
if(req->method == "PUT" && !::arg().mustDo("api-readonly")) {
throw ApiException("Query q can't be blank");
Json::array doc;
- for(const SyncRes::domainmap_t::value_type& val : *t_sstorage->domainmap) {
+ for(const SyncRes::domainmap_t::value_type& val : *SyncRes::t_sstorage.domainmap) {
string zoneId = apiZoneNameToId(val.first);
string zoneName = val.first.toString();
if (pdns_ci_find(zoneName, q) != string::npos) {