]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/communicator.hh
Merge pull request #4711 from thusoy/pgsql-extra-connection-args
[thirdparty/pdns.git] / pdns / communicator.hh
CommitLineData
12c86877 1/*
12471842
PL
2 * This file is part of PowerDNS or dnsdist.
3 * Copyright -- PowerDNS.COM B.V. and its contributors
4 *
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.
8 *
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.
12 *
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.
17 *
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.
21 */
12c86877
BH
22#ifndef PDNS_COMMUNICATOR_HH
23#define PDNS_COMMUNICATOR_HH
24
25#include <pthread.h>
26#include <string>
27#include <semaphore.h>
28#include <queue>
29#include <list>
f1a8bee5 30#include <limits>
dbcb3066
BH
31#include <boost/multi_index_container.hpp>
32#include <boost/multi_index/identity.hpp>
33#include <boost/multi_index/sequenced_index.hpp>
3e7dcee6 34#include <boost/scoped_ptr.hpp>
dbcb3066 35using namespace boost::multi_index;
1258abe0 36
76473b92
KM
37#include <unistd.h>
38#include <fcntl.h>
39#include <netdb.h>
1258abe0 40
12c86877
BH
41#include "lock.hh"
42#include "packethandler.hh"
43
10f4eea8 44#include "namespaces.hh"
d2116c15 45#include "dns_random.hh"
12c86877
BH
46
47struct SuckRequest
48{
5fca2e23 49 DNSName domain;
12c86877 50 string master;
dbcb3066
BH
51 bool operator<(const SuckRequest& b) const
52 {
53 return tie(domain, master) < tie(b.domain, b.master);
54 }
12c86877
BH
55};
56
dbcb3066
BH
57struct IDTag{};
58
59typedef multi_index_container<
60 SuckRequest,
61 indexed_by<
62 sequenced<>,
63 ordered_unique<tag<IDTag>, identity<SuckRequest> >
64 >
65> UniQueue;
a71bee29 66typedef UniQueue::index<IDTag>::type domains_by_name_t;
dbcb3066 67
12c86877
BH
68class NotificationQueue
69{
70public:
5fca2e23 71 void add(const DNSName &domain, const string &ip)
12c86877 72 {
3c8a7112
KM
73 const ComboAddress caIp(ip);
74
1258abe0
BH
75 NotificationRequest nr;
76 nr.domain = domain;
3c8a7112 77 nr.ip = caIp.toStringWithPort();
1258abe0 78 nr.attempts = 0;
d2116c15 79 nr.id = dns_random(0xffff);
1258abe0 80 nr.next = time(0);
12c86877
BH
81
82 d_nqueue.push_back(nr);
83 }
3c8a7112 84
5fca2e23 85 bool removeIf(const string &remote, uint16_t id, const DNSName &domain)
12c86877 86 {
3c8a7112
KM
87 ServiceTuple stRemote, stQueued;
88 parseService(remote, stRemote);
89
a71bee29 90 for(d_nqueue_t::iterator i=d_nqueue.begin(); i!=d_nqueue.end(); ++i) {
3c8a7112
KM
91 parseService(i->ip, stQueued);
92 if(i->id==id && stQueued.host == stRemote.host && i->domain==domain) {
4957a608
BH
93 d_nqueue.erase(i);
94 return true;
12c86877
BH
95 }
96 }
97 return false;
98 }
99
5fca2e23 100 bool getOne(DNSName &domain, string &ip, uint16_t *id, bool &purged)
12c86877
BH
101 {
102 for(d_nqueue_t::iterator i=d_nqueue.begin();i!=d_nqueue.end();++i)
103 if(i->next <= time(0)) {
4957a608
BH
104 i->attempts++;
105 purged=false;
106 i->next=time(0)+1+(1<<i->attempts);
107 domain=i->domain;
108 ip=i->ip;
109 *id=i->id;
110 purged=false;
111 if(i->attempts>4) {
112 purged=true;
113 d_nqueue.erase(i);
114 }
115 return true;
12c86877
BH
116 }
117 return false;
118 }
3c8a7112 119
12c86877
BH
120 time_t earliest()
121 {
10f4eea8 122 time_t early=std::numeric_limits<time_t>::max() - 1;
12c86877
BH
123 for(d_nqueue_t::const_iterator i=d_nqueue.begin();i!=d_nqueue.end();++i)
124 early=min(early,i->next);
125 return early-time(0);
126 }
3c8a7112 127
2d00c43d 128 void dump();
3c8a7112 129
12c86877
BH
130private:
131 struct NotificationRequest
132 {
5fca2e23 133 DNSName domain;
12c86877 134 string ip;
1c514700 135 time_t next;
12c86877 136 int attempts;
092f210a 137 uint16_t id;
12c86877
BH
138 };
139
a71bee29 140 typedef std::list<NotificationRequest> d_nqueue_t;
12c86877
BH
141 d_nqueue_t d_nqueue;
142
143};
144
3e7dcee6 145struct ZoneStatus;
146
12c86877
BH
147/** this class contains a thread that communicates with other nameserver and does housekeeping.
148 Initially, it is notified only of zones that need to be pulled in because they have been updated. */
149
150class CommunicatorClass
151{
152public:
153 CommunicatorClass()
154 {
155 pthread_mutex_init(&d_lock,0);
156 pthread_mutex_init(&d_holelock,0);
dbcb3066 157
12c86877 158 d_tickinterval=60;
bd11bd1d 159 d_masterschanged=d_slaveschanged=true;
50d471ea
AT
160 d_nsock4 = -1;
161 d_nsock6 = -1;
162 d_havepriosuckrequest = false;
163 d_preventSelfNotification = false;
12c86877 164 }
88c0425a 165 time_t doNotifications();
dbcb3066
BH
166 void go();
167
168
5fca2e23
PD
169 void drillHole(const DNSName &domain, const string &ip);
170 bool justNotified(const DNSName &domain, const string &ip);
d3ee36f2 171 void addSuckRequest(const DNSName &domain, const string &master);
7f3d870e 172 void addSlaveCheckRequest(const DomainInfo& di, const ComboAddress& remote);
7108e055 173 void addTrySuperMasterRequest(DNSPacket *p);
5fca2e23 174 void notify(const DNSName &domain, const string &ip);
12c86877 175 void mainloop();
dbcb3066 176 void retrievalLoopThread();
5fca2e23 177 void sendNotification(int sock, const DNSName &domain, const ComboAddress& remote, uint16_t id);
a71bee29 178
12c86877
BH
179 static void *launchhelper(void *p)
180 {
181 static_cast<CommunicatorClass *>(p)->mainloop();
182 return 0;
183 }
dbcb3066
BH
184 static void *retrieveLaunchhelper(void *p)
185 {
186 static_cast<CommunicatorClass *>(p)->retrievalLoopThread();
187 return 0;
188 }
5fca2e23 189 bool notifyDomain(const DNSName &domain);
12c86877 190private:
0c01dd7c 191 void makeNotifySockets();
5fca2e23 192 void queueNotifyDomain(const DNSName &domain, UeberBackend *B);
0c01dd7c 193 int d_nsock4, d_nsock6;
675fa24c 194 map<pair<DNSName,string>,time_t>d_holes;
12c86877 195 pthread_mutex_t d_holelock;
dbcb3066 196 void launchRetrievalThreads();
d3ee36f2 197 void suck(const DNSName &domain, const string &remote);
3e7dcee6 198 void ixfrSuck(const DNSName &domain, const TSIGTriplet& tt, const ComboAddress& laddr, const ComboAddress& remote, boost::scoped_ptr<AuthLua>& pdl,
199 ZoneStatus& zs, vector<DNSRecord>* axfr);
cd189f24 200
12c86877
BH
201 void slaveRefresh(PacketHandler *P);
202 void masterUpdateCheck(PacketHandler *P);
203 pthread_mutex_t d_lock;
dbcb3066
BH
204
205 UniQueue d_suckdomains;
3e7dcee6 206 set<DNSName> d_inprogress;
dbcb3066 207
12c86877
BH
208 Semaphore d_suck_sem;
209 Semaphore d_any_sem;
88c0425a 210 time_t d_tickinterval;
7f3d870e 211 set<DomainInfo> d_tocheck;
7108e055 212 vector<DNSPacket> d_potentialsupermasters;
24d3239e 213 set<string> d_alsoNotify;
cf58746e
PL
214 NotificationQueue d_nq;
215 NetmaskGroup d_onlyNotify;
216 bool d_havepriosuckrequest;
217 bool d_masterschanged, d_slaveschanged;
218 bool d_preventSelfNotification;
3e7dcee6 219
220 struct RemoveSentinel
221 {
222 explicit RemoveSentinel(const DNSName& dn, CommunicatorClass* cc) : d_dn(dn), d_cc(cc)
223 {}
224
225 ~RemoveSentinel()
226 {
227 Lock l(&d_cc->d_lock);
228 d_cc->d_inprogress.erase(d_dn);
229 }
230 DNSName d_dn;
231 CommunicatorClass* d_cc;
232};
233
12c86877
BH
234};
235
ef03cc09 236// class that one day might be more than a function to help you get IP addresses for a nameserver
237class FindNS
238{
239public:
240 vector<string> lookup(const DNSName &name, DNSBackend *b)
241 {
242 vector<string> addresses;
243
244 this->resolve_name(&addresses, name);
245
2a642697
PD
246 if(b) {
247 b->lookup(QType(QType::ANY),name);
248 DNSResourceRecord rr;
249 while(b->get(rr))
250 if(rr.qtype.getCode() == QType::A || rr.qtype.getCode()==QType::AAAA)
251 addresses.push_back(rr.content); // SOL if you have a CNAME for an NS
252 }
ef03cc09 253 return addresses;
254 }
255
256 vector<string> lookup(const DNSName &name, UeberBackend *b)
257 {
258 vector<string> addresses;
259
260 this->resolve_name(&addresses, name);
261
2a642697
PD
262 if(b) {
263 b->lookup(QType(QType::ANY),name);
264 DNSResourceRecord rr;
265 while(b->get(rr))
266 if(rr.qtype.getCode() == QType::A || rr.qtype.getCode()==QType::AAAA)
267 addresses.push_back(rr.content); // SOL if you have a CNAME for an NS
268 }
ef03cc09 269 return addresses;
270 }
271
272private:
273 void resolve_name(vector<string>* addresses, const DNSName& name)
274 {
275 struct addrinfo* res;
276 struct addrinfo hints;
277 memset(&hints, 0, sizeof(hints));
d259e496 278 hints.ai_socktype = SOCK_DGRAM; // otherwise we get everything in triplicate (!)
ef03cc09 279 for(int n = 0; n < 2; ++n) {
280 hints.ai_family = n ? AF_INET : AF_INET6;
281 ComboAddress remote;
282 remote.sin4.sin_family = AF_INET6;
283 if(!getaddrinfo(name.toString().c_str(), 0, &hints, &res)) {
284 struct addrinfo* address = res;
285 do {
a683e8bd
RG
286 if (address->ai_addrlen <= sizeof(remote)) {
287 memcpy(&remote, address->ai_addr, address->ai_addrlen);
288 addresses->push_back(remote.toString());
289 }
ef03cc09 290 } while((address = address->ai_next));
291 freeaddrinfo(res);
292 }
293 }
294 }
295};
296
297
12c86877 298#endif