Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

auth: add a configurable delay for notifications #13649

Merged
merged 4 commits into from Jan 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 0 additions & 2 deletions .not-formatted
Expand Up @@ -26,8 +26,6 @@
./pdns/cdb.hh
./pdns/comfun.cc
./pdns/comment.hh
./pdns/communicator.cc
./pdns/communicator.hh
./pdns/dbdnsseckeeper.cc
./pdns/delaypipe.cc
./pdns/delaypipe.hh
Expand Down
18 changes: 14 additions & 4 deletions docs/settings.rst
Expand Up @@ -547,6 +547,16 @@ to enable DNSSEC. Must be one of:
The default keysize for the ZSK generated with :doc:`pdnsutil secure-zone <dnssec/pdnsutil>`.
Only relevant for algorithms with non-fixed keysizes (like RSA).

.. _setting-delay-notifications:

``delay-notifications``
-----------------------

- Integer
- Default: 0 (no delay, send them directly)

Configure a delay to send out notifications, no delay by default.

.. _setting-direct-dnskey:

``direct-dnskey``
Expand Down Expand Up @@ -1051,7 +1061,7 @@ Setting this to any value less than or equal to 0 will set no limit.

.. deprecated:: 4.5.0
Renamed to :ref:`setting-primary`.

- Boolean
- Default: no

Expand Down Expand Up @@ -1858,11 +1868,11 @@ Enable for testing PowerDNS upgrades, without changing stored records.
Enable for upgrading record content on secondaries, or when using the API (see :doc:`upgrade notes <../upgrading>`).
Disable after record contents have been upgraded.

This option is supported by the bind and Generic SQL backends.
This option is supported by the bind and Generic SQL backends.

.. note::
When using a generic SQL backend, records with an unknown record type (see :doc:`../appendices/types`) can be identified with the following SQL query::

SELECT * from records where type like 'TYPE%';

.. _setting-version-string:
Expand Down Expand Up @@ -1956,7 +1966,7 @@ When set to "detailed", all information about the request and response are logge
[webserver] e235780e-a5cf-415e-9326-9d33383e739e Content-Length: 49
[webserver] e235780e-a5cf-415e-9326-9d33383e739e Content-Type: text/html; charset=utf-8
[webserver] e235780e-a5cf-415e-9326-9d33383e739e Server: PowerDNS/0.0.15896.0.gaba8bab3ab
[webserver] e235780e-a5cf-415e-9326-9d33383e739e Full body:
[webserver] e235780e-a5cf-415e-9326-9d33383e739e Full body:
[webserver] e235780e-a5cf-415e-9326-9d33383e739e <!html><title>Not Found</title><h1>Not Found</h1>
[webserver] e235780e-a5cf-415e-9326-9d33383e739e 127.0.0.1:55376 "GET /api/v1/servers/localhost/bla HTTP/1.1" 404 196

Expand Down
2 changes: 2 additions & 0 deletions pdns/auth-main.cc
Expand Up @@ -228,6 +228,7 @@ static void declareArguments()
::arg().setSwitch("prevent-self-notification", "Don't send notifications to what we think is ourself") = "yes";
::arg().setSwitch("any-to-tcp", "Answer ANY queries with tc=1, shunting to TCP") = "yes";
::arg().setSwitch("edns-subnet-processing", "If we should act on EDNS Subnet options") = "no";
::arg().set("delay-notifications", "Configure a delay to send out notifications, no delay by default") = "0";

::arg().set("edns-cookie-secret", "When set, set a server cookie when responding to a query with a Client cookie (in hex)") = "";

Expand Down Expand Up @@ -326,6 +327,7 @@ static void declareArguments()
::arg().set("rng", "Specify the random number generator to use. Valid values are auto,sodium,openssl,getrandom,arc4random,urandom.") = "auto";

::arg().set("default-catalog-zone", "Catalog zone to assign newly created primary zones (via the API) to") = "";

#ifdef ENABLE_GSS_TSIG
::arg().setSwitch("enable-gss-tsig", "Enable GSS TSIG processing") = "no";
#endif
Expand Down
4 changes: 2 additions & 2 deletions pdns/auth-primarycommunicator.cc
Expand Up @@ -75,7 +75,7 @@ void CommunicatorClass::queueNotifyDomain(const DomainInfo& di, UeberBackend* B)

for (const auto& ip : ips) {
g_log << Logger::Notice << "Queued notification of domain '" << di.zone << "' to " << ip << endl;
d_nq.add(di.zone, ip);
d_nq.add(di.zone, ip, d_delayNotifications);
hasQueuedItem = true;
}
}
Expand All @@ -98,7 +98,7 @@ void CommunicatorClass::queueNotifyDomain(const DomainInfo& di, UeberBackend* B)
g_log << Logger::Notice << "Queued also-notification of domain '" << di.zone << "' to " << caIp.toStringWithPort() << endl;
if (!ips.count(caIp.toStringWithPort())) {
ips.insert(caIp.toStringWithPort());
d_nq.add(di.zone, caIp.toStringWithPort());
d_nq.add(di.zone, caIp.toStringWithPort(), d_delayNotifications);
}
hasQueuedItem = true;
}
Expand Down
56 changes: 30 additions & 26 deletions pdns/communicator.cc
Expand Up @@ -43,7 +43,7 @@
void CommunicatorClass::retrievalLoopThread()
{
setThreadName("pdns/comm-retre");
for(;;) {
for (;;) {
d_suck_sem.wait();
SuckRequest sr;
{
Expand All @@ -53,8 +53,8 @@ void CommunicatorClass::retrievalLoopThread()
}

auto firstItem = data->d_suckdomains.begin();
sr=*firstItem;

sr = *firstItem;
data->d_suckdomains.erase(firstItem);
if (data->d_suckdomains.empty()) {
data->d_sorthelper = 0;
Expand All @@ -64,17 +64,17 @@ void CommunicatorClass::retrievalLoopThread()
}
}

void CommunicatorClass::loadArgsIntoSet(const char *listname, set<string> &listset)
void CommunicatorClass::loadArgsIntoSet(const char* listname, set<string>& listset)
{
vector<string> parts;
stringtok(parts, ::arg()[listname], ", \t");
for (const auto & part : parts) {
for (const auto& part : parts) {
try {
ComboAddress caIp(part, 53);
listset.insert(caIp.toStringWithPort());
}
catch(PDNSException &e) {
g_log<<Logger::Error<<"Unparseable IP in "<<listname<<". Error: "<<e.reason<<endl;
catch (PDNSException& e) {
g_log << Logger::Error << "Unparseable IP in " << listname << ". Error: " << e.reason << endl;
_exit(1);
}
}
Expand All @@ -83,28 +83,33 @@ void CommunicatorClass::loadArgsIntoSet(const char *listname, set<string> &lists
void CommunicatorClass::go()
{
try {
PacketHandler::s_allowNotifyFrom.toMasks(::arg()["allow-notify-from"] );
PacketHandler::s_allowNotifyFrom.toMasks(::arg()["allow-notify-from"]);
}
catch(PDNSException &e) {
g_log<<Logger::Error<<"Unparseable IP in allow-notify-from. Error: "<<e.reason<<endl;
catch (PDNSException& e) {
g_log << Logger::Error << "Unparseable IP in allow-notify-from. Error: " << e.reason << endl;
_exit(1);
}

std::thread mainT([this](){mainloop();});
std::thread mainT([this]() { mainloop(); });
mainT.detach();

for(int n=0; n < ::arg().asNum("retrieval-threads", 1); ++n) {
std::thread retrieve([this](){retrievalLoopThread();});
for (int nthreads = 0; nthreads < ::arg().asNum("retrieval-threads", 1); ++nthreads) {
std::thread retrieve([this]() { retrievalLoopThread(); });
retrieve.detach();
}

d_preventSelfNotification = ::arg().mustDo("prevent-self-notification");

auto delay = ::arg().asNum("delay-notifications");
if (delay > 0) {
d_delayNotifications = static_cast<time_t>(delay);
}

try {
d_onlyNotify.toMasks(::arg()["only-notify"]);
}
catch(PDNSException &e) {
g_log<<Logger::Error<<"Unparseable IP in only-notify. Error: "<<e.reason<<endl;
catch (PDNSException& e) {
g_log << Logger::Error << "Unparseable IP in only-notify. Error: " << e.reason << endl;
_exit(1);
}

Expand All @@ -117,7 +122,7 @@ void CommunicatorClass::mainloop()
{
try {
setThreadName("pdns/comm-main");
signal(SIGPIPE,SIG_IGN);
signal(SIGPIPE, SIG_IGN);
g_log << Logger::Warning << "Primary/secondary communicator launching" << endl;

d_tickinterval = ::arg().asNum("xfr-cycle-interval");
Expand All @@ -128,17 +133,17 @@ void CommunicatorClass::mainloop()

makeNotifySockets();

for(;;) {
for (;;) {
secondaryRefresh(&P);
primaryUpdateCheck(&P);
doNotifications(&P); // this processes any notification acknowledgements and actually send out our own notifications

next = time(nullptr) + d_tickinterval;

while(time(nullptr) < next) {
rc=d_any_sem.tryWait();
while (time(nullptr) < next) {
rc = d_any_sem.tryWait();

if(rc) {
if (rc != 0) {
bool extraSecondaryRefresh = false;
Utility::sleep(1);
{
Expand All @@ -161,17 +166,16 @@ void CommunicatorClass::mainloop()
}
}
}
catch(PDNSException &ae) {
g_log<<Logger::Error<<"Exiting because communicator thread died with error: "<<ae.reason<<endl;
catch (PDNSException& ae) {
g_log << Logger::Error << "Exiting because communicator thread died with error: " << ae.reason << endl;
Utility::sleep(1);
_exit(1);
}
catch(std::exception &e) {
g_log<<Logger::Error<<"Exiting because communicator thread died with STL error: "<<e.what()<<endl;
catch (std::exception& e) {
g_log << Logger::Error << "Exiting because communicator thread died with STL error: " << e.what() << endl;
_exit(1);
}
catch( ... )
{
catch (...) {
g_log << Logger::Error << "Exiting because communicator caught unknown exception." << endl;
_exit(1);
}
Expand Down