From: Remi Gacogne Date: Thu, 20 May 2021 08:51:40 +0000 (+0200) Subject: auth: Convert the TCPNameserver to LockGuarded X-Git-Tag: dnsdist-1.7.0-alpha1~11^2~14 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=24fb57748b45171b0d1444d1cd164647c0844a6a;p=thirdparty%2Fpdns.git auth: Convert the TCPNameserver to LockGuarded --- diff --git a/pdns/tcpreceiver.cc b/pdns/tcpreceiver.cc index b9c619eb2d..716236febc 100644 --- a/pdns/tcpreceiver.cc +++ b/pdns/tcpreceiver.cc @@ -66,24 +66,22 @@ extern StatBag S; \brief This file implements the tcpreceiver that receives and answers questions over TCP/IP */ -std::mutex TCPNameserver::s_plock; std::unique_ptr TCPNameserver::d_connectionroom_sem{nullptr}; -std::unique_ptr TCPNameserver::s_P{nullptr}; +LockGuarded> TCPNameserver::s_P{nullptr}; unsigned int TCPNameserver::d_maxTCPConnections = 0; NetmaskGroup TCPNameserver::d_ng; size_t TCPNameserver::d_maxTransactionsPerConn; size_t TCPNameserver::d_maxConnectionsPerClient; unsigned int TCPNameserver::d_idleTimeout; unsigned int TCPNameserver::d_maxConnectionDuration; -std::mutex TCPNameserver::s_clientsCountMutex; -std::map TCPNameserver::s_clientsCount; +LockGuarded> TCPNameserver::s_clientsCount; void TCPNameserver::go() { g_log<reset(); try { - s_P=make_unique(); + *(s_P.lock()) = make_unique(); } catch(PDNSException &ae) { g_log< lock(s_clientsCountMutex); - s_clientsCount[remote]--; - if (s_clientsCount[remote] == 0) { - s_clientsCount.erase(remote); + auto count = s_clientsCount.lock(); + auto it = count->find(remote); + if (it == count->end()) { + // this is worrying, but nothing we can do at this point + return; + } + --it->second; + if (it->second == 0) { + count->erase(it); } } } @@ -334,13 +337,13 @@ void TCPNameserver::doConnection(int fd) } } { - std::lock_guard l(s_plock); - if(!s_P) { + auto packetHandler = s_P.lock(); + if (!*packetHandler) { g_log<(); + *packetHandler = make_unique(); } - reply= s_P->doQuestion(*packet); // we really need to ask the backend :-) + reply = (*packetHandler)->doQuestion(*packet); // we really need to ask the backend :-) } if(!reply) // unable to write an answer? @@ -350,8 +353,7 @@ void TCPNameserver::doConnection(int fd) } } catch(PDNSException &ae) { - std::lock_guard l(s_plock); - s_P.reset(); // on next call, backend will be recycled + s_P.lock()->reset(); // on next call, backend will be recycled g_log<& q, bool isAXFR) +bool TCPNameserver::canDoAXFR(std::unique_ptr& q, bool isAXFR, std::unique_ptr& packetHandler) { if(::arg().mustDo("disable-axfr")) return false; @@ -389,13 +390,13 @@ bool TCPNameserver::canDoAXFR(std::unique_ptr& q, bool isAXFR) TSIGRecordContent trc; DNSName keyname; string secret; - if(!q->checkForCorrectTSIG(s_P->getBackend(), &keyname, &secret, &trc)) { + if(!q->checkForCorrectTSIG(packetHandler->getBackend(), &keyname, &secret, &trc)) { return false; } else { getTSIGHashEnum(trc.d_algoName, q->d_tsig_algo); } - DNSSECKeeper dk(s_P->getBackend()); + DNSSECKeeper dk(packetHandler->getBackend()); if(!dk.TSIGGrantsAccess(q->qdomain, keyname)) { g_log<d_tsig_algo)<<"' does not grant access"<& q, bool isAXFR) // cerr<<"doing per-zone-axfr-acls"<getBackend()->getSOAUncached(q->qdomain,sd)) { + if(packetHandler->getBackend()->getSOAUncached(q->qdomain,sd)) { // cerr<<"got backend and SOA"< acl; - s_P->getBackend()->getDomainMetadata(q->qdomain, "ALLOW-AXFR-FROM", acl); + packetHandler->getBackend()->getDomainMetadata(q->qdomain, "ALLOW-AXFR-FROM", acl); for (const auto & i : acl) { // cerr<<"matching against "<<*i<& q, bool isAXFR) nsset.insert(DNSName(rr.content)); } for(const auto & j: nsset) { - vector nsips=fns.lookup(j, s_P->getBackend()); + vector nsips=fns.lookup(j, packetHandler->getBackend()); for(const auto & nsip : nsips) { // cerr<<"got "<<*k<<" from AUTO-NS"<getRemote().toString()) @@ -502,22 +503,22 @@ int TCPNameserver::doAXFR(const DNSName &target, std::unique_ptr& q, // determine if zone exists and AXFR is allowed using existing backend before spawning a new backend. SOAData sd; { - std::lock_guard l(s_plock); + auto packetHandler = s_P.lock(); DLOG(g_log<(); + *packetHandler = make_unique(); } // canDoAXFR does all the ACL checks, and has the if(disable-axfr) shortcut, call it first. - if (!canDoAXFR(q, true)) { + if (!canDoAXFR(q, true, *packetHandler)) { g_log<setRcode(RCode::NotAuth); sendPacket(outpacket,outsock); return 0; } - if(!s_P->getBackend()->getSOAUncached(target, sd)) { + if(!(*packetHandler)->getBackend()->getSOAUncached(target, sd)) { g_log<setRcode(RCode::NotAuth); sendPacket(outpacket,outsock); @@ -1067,22 +1068,22 @@ int TCPNameserver::doIXFR(std::unique_ptr& q, int outsock) bool securedZone; bool serialPermitsIXFR; { - std::lock_guard l(s_plock); + auto packetHandler = s_P.lock(); DLOG(g_log<(); + *packetHandler = make_unique(); } // canDoAXFR does all the ACL checks, and has the if(disable-axfr) shortcut, call it first. - if(!canDoAXFR(q, false) || !s_P->getBackend()->getSOAUncached(q->qdomain, sd)) { + if(!canDoAXFR(q, false, *packetHandler) || !(*packetHandler)->getBackend()->getSOAUncached(q->qdomain, sd)) { g_log<setRcode(RCode::NotAuth); sendPacket(outpacket,outsock); return 0; } - DNSSECKeeper dk(s_P->getBackend()); + DNSSECKeeper dk((*packetHandler)->getBackend()); DNSSECKeeper::clearCaches(q->qdomain); bool narrow; securedZone = dk.isSecuredZone(q->qdomain); @@ -1260,13 +1261,13 @@ void TCPNameserver::thread() } else { if (d_maxConnectionsPerClient) { - std::lock_guard lock(s_clientsCountMutex); - if (s_clientsCount[remote] >= d_maxConnectionsPerClient) { + auto clientsCount = s_clientsCount.lock(); + if ((*clientsCount)[remote] >= d_maxConnectionsPerClient) { g_log<wait(); // blocks if no connections are available diff --git a/pdns/tcpreceiver.hh b/pdns/tcpreceiver.hh index 366921a91e..e996adc1fe 100644 --- a/pdns/tcpreceiver.hh +++ b/pdns/tcpreceiver.hh @@ -25,7 +25,6 @@ #include "dnsbackend.hh" #include "packethandler.hh" #include -#include #include #include #include @@ -37,6 +36,7 @@ #include #include +#include "lock.hh" #include "namespaces.hh" class TCPNameserver @@ -53,14 +53,12 @@ private: static void getQuestion(int fd, char *mesg, int pktlen, const ComboAddress& remote, unsigned int totalTime); static int doAXFR(const DNSName &target, std::unique_ptr& q, int outsock); static int doIXFR(std::unique_ptr& q, int outsock); - static bool canDoAXFR(std::unique_ptr& q, bool isAXFR); + static bool canDoAXFR(std::unique_ptr& q, bool isAXFR, std::unique_ptr& packetHandler); static void doConnection(int fd); static void decrementClientCount(const ComboAddress& remote); void thread(void); - static std::mutex s_plock; - static std::mutex s_clientsCountMutex; - static std::map s_clientsCount; - static std::unique_ptr s_P; + static LockGuarded> s_clientsCount; + static LockGuarded> s_P; static std::unique_ptr d_connectionroom_sem; static unsigned int d_maxTCPConnections; static NetmaskGroup d_ng;