summaryrefslogtreecommitdiff
path: root/modules/m_dns.cpp
diff options
context:
space:
mode:
authorAdam <Adam@anope.org>2013-08-11 15:46:59 -0400
committerAdam <Adam@anope.org>2013-08-11 15:48:46 -0400
commit812cb04fde10414ba1b13c88bde78f86e6701a5d (patch)
treefc96432c599f118f42642126bd88eaabac41e1d0 /modules/m_dns.cpp
parent1314d5b4f159a5a4964bf192b9e062b823ccdf62 (diff)
Add DNS Notify support
Diffstat (limited to 'modules/m_dns.cpp')
-rw-r--r--modules/m_dns.cpp110
1 files changed, 98 insertions, 12 deletions
diff --git a/modules/m_dns.cpp b/modules/m_dns.cpp
index 422d035b3..214e97cf4 100644
--- a/modules/m_dns.cpp
+++ b/modules/m_dns.cpp
@@ -612,6 +612,39 @@ class UDPSocket : public ReplySocket
}
};
+class NotifySocket : public Socket
+{
+ Packet *packet;
+ public:
+ NotifySocket(bool v6, Packet *p) : Socket(-1, v6, SOCK_DGRAM), packet(p)
+ {
+ SocketEngine::Change(this, false, SF_READABLE);
+ SocketEngine::Change(this, true, SF_WRITABLE);
+ }
+
+ bool ProcessWrite() anope_override
+ {
+ if (!packet)
+ return false;
+
+ Log(LOG_DEBUG_2) << "Resolver: Notifying slave " << packet->addr.addr();
+
+ try
+ {
+ unsigned char buffer[524];
+ unsigned short len = packet->Pack(buffer, sizeof(buffer));
+
+ sendto(this->GetFD(), reinterpret_cast<char *>(buffer), len, 0, &packet->addr.sa, packet->addr.size());
+ }
+ catch (const SocketException &) { }
+
+ delete packet;
+ packet = NULL;
+
+ return false;
+ }
+};
+
class MyManager : public Manager, public Timer
{
uint32_t serial;
@@ -624,6 +657,8 @@ class MyManager : public Manager, public Timer
bool listen;
sockaddrs addrs;
+
+ std::vector<std::pair<Anope::string, short> > notify;
public:
std::map<unsigned short, Request *> requests;
@@ -652,7 +687,7 @@ class MyManager : public Manager, public Timer
this->cache.clear();
}
- void SetIPPort(const Anope::string &nameserver, const Anope::string &ip, unsigned short port)
+ void SetIPPort(const Anope::string &nameserver, const Anope::string &ip, unsigned short port, std::vector<std::pair<Anope::string, short> > n)
{
delete udpsock;
delete tcpsock;
@@ -677,8 +712,26 @@ class MyManager : public Manager, public Timer
{
Log() << "Unable to bind dns to " << ip << ":" << port << ": " << ex.GetReason();
}
+
+ notify = n;
+ }
+
+ private:
+ unsigned short GetID()
+ {
+ if (this->udpsock->GetPackets().size() == 65535)
+ throw SocketException("DNS queue full");
+
+ static unsigned short cur_id = rand();
+
+ do
+ cur_id = (cur_id + 1) & 0xFFFF;
+ while (!cur_id || this->requests.count(cur_id));
+
+ return cur_id;
}
+ public:
void Process(Request *req) anope_override
{
Log(LOG_DEBUG_2) << "Resolver: Processing request to lookup " << req->name << ", of type " << req->type;
@@ -693,16 +746,7 @@ class MyManager : public Manager, public Timer
if (!this->udpsock)
throw SocketException("No dns socket");
- if (this->udpsock->GetPackets().size() == 65535)
- throw SocketException("DNS queue full");
-
- do
- {
- static unsigned short cur_id = rand();
- cur_id = req->id = (cur_id + 1) & 0xFFFF;
- }
- while (!req->id || this->requests.count(req->id));
-
+ req->id = GetID();
this->requests[req->id] = req;
req->SetSecs(timeout);
@@ -877,6 +921,37 @@ class MyManager : public Manager, public Timer
serial = Anope::CurTime;
}
+ void Notify(const Anope::string &zone) anope_override
+ {
+ /* notify slaves of the update */
+ for (unsigned i = 0; i < notify.size(); ++i)
+ {
+ const Anope::string &ip = notify[i].first;
+ short port = notify[i].second;
+
+ sockaddrs addr;
+ addr.pton(ip.find(':') != Anope::string::npos ? AF_INET6 : AF_INET, ip, port);
+ if (!addr.valid())
+ return;
+
+ Packet *packet = new Packet(this, &addr);
+ packet->flags = QUERYFLAGS_AA | QUERYFLAGS_OPCODE_NOTIFY;
+ try
+ {
+ packet->id = GetID();
+ }
+ catch (const SocketException &)
+ {
+ delete packet;
+ continue;
+ }
+
+ packet->questions.push_back(Question(zone, QUERY_SOA));
+
+ new NotifySocket(ip.find(':') != Anope::string::npos ? AF_INET6 : AF_INET, packet);
+ }
+ }
+
uint32_t GetSerial() const anope_override
{
return serial;
@@ -936,6 +1011,8 @@ class ModuleDNS : public Module
Anope::string ip;
int port;
+ std::vector<std::pair<Anope::string, short> > notify;
+
public:
ModuleDNS(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, EXTRA | VENDOR), manager(this)
{
@@ -954,6 +1031,15 @@ class ModuleDNS : public Module
nameservers = block->Get<const Anope::string>("nameservers", "ns1.example.com");
refresh = block->Get<int>("refresh", "3600");
+ for (int i = 0; i < block->CountBlock("notify"); ++i)
+ {
+ Configuration::Block *n = block->GetBlock("notify", i);
+ Anope::string nip = n->Get<Anope::string>("ip");
+ short nport = n->Get<short>("port");
+
+ notify.push_back(std::make_pair(nip, nport));
+ }
+
if (Anope::IsFile(nameserver))
{
std::ifstream f(nameserver.c_str());
@@ -991,7 +1077,7 @@ class ModuleDNS : public Module
try
{
- this->manager.SetIPPort(nameserver, ip, port);
+ this->manager.SetIPPort(nameserver, ip, port, notify);
}
catch (const SocketException &ex)
{