2 * This file is part of PowerDNS or dnsdist.
3 * Copyright -- PowerDNS.COM B.V. and its contributors
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
9 * In addition, for the avoidance of any doubt, permission is granted to
10 * link this program with OpenSSL and to (re)distribute the binaries
11 * produced as the result of such linking.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
28 #include <boost/utility.hpp>
30 #include "packetcache.hh"
32 #include "communicator.hh"
33 #include "dnsbackend.hh"
34 #include "ueberbackend.hh"
35 #include "packethandler.hh"
38 #include "arguments.hh"
39 #include "packetcache.hh"
40 #include "threadname.hh"
42 // there can be MANY OF THESE
43 void CommunicatorClass::retrievalLoopThread()
45 setThreadName("pdns/comm-retre");
50 auto data
= d_data
.lock();
51 if (data
->d_suckdomains
.empty()) {
55 auto firstItem
= data
->d_suckdomains
.begin();
58 data
->d_suckdomains
.erase(firstItem
);
59 if (data
->d_suckdomains
.empty()) {
60 data
->d_sorthelper
= 0;
63 suck(sr
.domain
, sr
.primary
, sr
.force
);
67 void CommunicatorClass::loadArgsIntoSet(const char* listname
, set
<string
>& listset
)
70 stringtok(parts
, ::arg()[listname
], ", \t");
71 for (const auto& part
: parts
) {
73 ComboAddress
caIp(part
, 53);
74 listset
.insert(caIp
.toStringWithPort());
76 catch (PDNSException
& e
) {
77 g_log
<< Logger::Error
<< "Unparseable IP in " << listname
<< ". Error: " << e
.reason
<< endl
;
83 void CommunicatorClass::go()
86 PacketHandler::s_allowNotifyFrom
.toMasks(::arg()["allow-notify-from"]);
88 catch (PDNSException
& e
) {
89 g_log
<< Logger::Error
<< "Unparseable IP in allow-notify-from. Error: " << e
.reason
<< endl
;
93 std::thread
mainT([this]() { mainloop(); });
96 for (int nthreads
= 0; nthreads
< ::arg().asNum("retrieval-threads", 1); ++nthreads
) {
97 std::thread
retrieve([this]() { retrievalLoopThread(); });
101 d_preventSelfNotification
= ::arg().mustDo("prevent-self-notification");
103 auto delay
= ::arg().asNum("delay-notifications");
105 d_delayNotifications
= static_cast<time_t>(delay
);
109 d_onlyNotify
.toMasks(::arg()["only-notify"]);
111 catch (PDNSException
& e
) {
112 g_log
<< Logger::Error
<< "Unparseable IP in only-notify. Error: " << e
.reason
<< endl
;
116 loadArgsIntoSet("also-notify", d_alsoNotify
);
118 loadArgsIntoSet("forward-notify", PacketHandler::s_forwardNotify
);
121 void CommunicatorClass::mainloop()
124 setThreadName("pdns/comm-main");
125 signal(SIGPIPE
, SIG_IGN
);
126 g_log
<< Logger::Warning
<< "Primary/secondary communicator launching" << endl
;
128 d_tickinterval
= ::arg().asNum("xfr-cycle-interval");
137 secondaryRefresh(&P
);
138 primaryUpdateCheck(&P
);
139 doNotifications(&P
); // this processes any notification acknowledgements and actually send out our own notifications
141 next
= time(nullptr) + d_tickinterval
;
143 while (time(nullptr) < next
) {
144 rc
= d_any_sem
.tryWait();
147 bool extraSecondaryRefresh
= false;
150 auto data
= d_data
.lock();
151 if (data
->d_tocheck
.size()) {
152 extraSecondaryRefresh
= true;
155 if (extraSecondaryRefresh
)
156 secondaryRefresh(&P
);
159 // eat up extra posts to avoid busy looping if many posts were done
160 while (d_any_sem
.tryWait() == 0) {
162 break; // something happened
164 // this gets executed about once per second
169 catch (PDNSException
& ae
) {
170 g_log
<< Logger::Error
<< "Exiting because communicator thread died with error: " << ae
.reason
<< endl
;
174 catch (std::exception
& e
) {
175 g_log
<< Logger::Error
<< "Exiting because communicator thread died with STL error: " << e
.what() << endl
;
179 g_log
<< Logger::Error
<< "Exiting because communicator caught unknown exception." << endl
;