Anope IRC Services  Version 2.0
os_dns.cpp
Go to the documentation of this file.
1 /*
2  * (C) 2003-2014 Anope Team
3  * Contact us at team@anope.org
4  *
5  * Please read COPYING and README for further details.
6  */
7 
8 #include "module.h"
9 #include "modules/dns.h"
10 
11 static ServiceReference<DNS::Manager> dnsmanager("DNS::Manager", "dns/manager");
12 
13 struct DNSZone;
14 class DNSServer;
15 
18 
19 static std::map<Anope::string, std::list<time_t> > server_quit_times;
20 
22 {
24  std::set<Anope::string, ci::less> servers;
25 
26  DNSZone(const Anope::string &n) : Serializable("DNSZone"), name(n)
27  {
28  zones->push_back(this);
29  }
30 
32  {
33  std::vector<DNSZone *>::iterator it = std::find(zones->begin(), zones->end(), this);
34  if (it != zones->end())
35  zones->erase(it);
36  }
37 
39  {
40  data["name"] << name;
41  unsigned count = 0;
42  for (std::set<Anope::string, ci::less>::iterator it = servers.begin(), it_end = servers.end(); it != it_end; ++it)
43  data["server" + stringify(count++)] << *it;
44  }
45 
47  {
48  DNSZone *zone;
49  Anope::string zone_name;
50 
51  data["name"] >> zone_name;
52 
53  if (obj)
54  {
55  zone = anope_dynamic_static_cast<DNSZone *>(obj);
56  data["name"] >> zone->name;
57  }
58  else
59  zone = new DNSZone(zone_name);
60 
61  zone->servers.clear();
62  for (unsigned count = 0; true; ++count)
63  {
64  Anope::string server_str;
65  data["server" + stringify(count)] >> server_str;
66  if (server_str.empty())
67  break;
68  zone->servers.insert(server_str);
69  }
70 
71  return zone;
72  }
73 
74  static DNSZone *Find(const Anope::string &name)
75  {
76  for (unsigned i = 0; i < zones->size(); ++i)
77  if (zones->at(i)->name.equals_ci(name))
78  {
79  DNSZone *z = zones->at(i);
80  z->QueueUpdate();
81  return z;
82  }
83  return NULL;
84  }
85 };
86 
87 class DNSServer : public Serializable
88 {
90  std::vector<Anope::string> ips;
91  unsigned limit;
92  /* wants to be in the pool */
93  bool pooled;
94  /* is actually in the pool */
95  bool active;
96 
97  public:
98  std::set<Anope::string, ci::less> zones;
99  time_t repool;
100 
101  DNSServer(const Anope::string &sn) : Serializable("DNSServer"), server_name(sn), limit(0), pooled(false), active(false), repool(0)
102  {
103  dns_servers->push_back(this);
104  }
105 
107  {
108  std::vector<DNSServer *>::iterator it = std::find(dns_servers->begin(), dns_servers->end(), this);
109  if (it != dns_servers->end())
110  dns_servers->erase(it);
111  }
112 
113  const Anope::string &GetName() const { return server_name; }
114  std::vector<Anope::string> &GetIPs() { return ips; }
115  unsigned GetLimit() const { return limit; }
116  void SetLimit(unsigned l) { limit = l; }
117 
118  bool Pooled() const { return pooled; }
119  void Pool(bool p)
120  {
121  if (!p)
122  this->SetActive(p);
123  pooled = p;
124  }
125 
126  bool Active() const { return pooled && active; }
127  void SetActive(bool p)
128  {
129  if (p)
130  this->Pool(p);
131  active = p;
132 
133  if (dnsmanager)
134  {
135  dnsmanager->UpdateSerial();
136  for (std::set<Anope::string, ci::less>::iterator it = zones.begin(), it_end = zones.end(); it != it_end; ++it)
137  dnsmanager->Notify(*it);
138  }
139  }
140 
142  {
143  data["server_name"] << server_name;
144  for (unsigned i = 0; i < ips.size(); ++i)
145  data["ip" + stringify(i)] << ips[i];
146  data["limit"] << limit;
147  data["pooled"] << pooled;
148  unsigned count = 0;
149  for (std::set<Anope::string, ci::less>::iterator it = zones.begin(), it_end = zones.end(); it != it_end; ++it)
150  data["zone" + stringify(count++)] << *it;
151  }
152 
154  {
155  DNSServer *req;
157 
158  data["server_name"] >> server_name;
159 
160  if (obj)
161  {
162  req = anope_dynamic_static_cast<DNSServer *>(obj);
163  req->server_name = server_name;
164  }
165  else
166  req = new DNSServer(server_name);
167 
168  for (unsigned i = 0; true; ++i)
169  {
170  Anope::string ip_str;
171  data["ip" + stringify(i)] >> ip_str;
172  if (ip_str.empty())
173  break;
174  req->ips.push_back(ip_str);
175  }
176 
177  data["limit"] >> req->limit;
178  data["pooled"] >> req->pooled;
179 
180  req->zones.clear();
181  for (unsigned i = 0; true; ++i)
182  {
183  Anope::string zone_str;
184  data["zone" + stringify(i)] >> zone_str;
185  if (zone_str.empty())
186  break;
187  req->zones.insert(zone_str);
188  }
189 
190  return req;
191  }
192 
193  static DNSServer *Find(const Anope::string &s)
194  {
195  for (unsigned i = 0; i < dns_servers->size(); ++i)
196  if (dns_servers->at(i)->GetName().equals_ci(s))
197  {
198  DNSServer *serv = dns_servers->at(i);
199  serv->QueueUpdate();
200  return serv;
201  }
202  return NULL;
203  }
204 };
205 
206 class CommandOSDNS : public Command
207 {
209  {
210  if (dns_servers->empty())
211  {
212  source.Reply(_("There are no configured servers."));
213  return;
214  }
215 
216  ListFormatter lf(source.GetAccount());
217  lf.AddColumn(_("Server")).AddColumn(_("IP")).AddColumn(_("Limit")).AddColumn(_("State"));
218  for (unsigned i = 0; i < dns_servers->size(); ++i)
219  {
220  DNSServer *s = dns_servers->at(i);
221  Server *srv = Server::Find(s->GetName(), true);
222 
224  entry["Server"] = s->GetName();
225  entry["Limit"] = s->GetLimit() ? stringify(s->GetLimit()) : Language::Translate(source.GetAccount(), _("None"));
226 
227  Anope::string ip_str;
228  for (unsigned j = 0; j < s->GetIPs().size(); ++j)
229  ip_str += s->GetIPs()[j] + " ";
230  ip_str.trim();
231  if (ip_str.empty())
232  ip_str = "None";
233  entry["IP"] = ip_str;
234 
235  if (s->Active())
236  entry["State"] = Language::Translate(source.GetAccount(), _("Pooled/Active"));
237  else if (s->Pooled())
238  entry["State"] = Language::Translate(source.GetAccount(), _("Pooled/Not Active"));
239  else
240  entry["State"] = Language::Translate(source.GetAccount(), _("Unpooled"));
241 
242  if (!srv)
243  entry["State"] += Anope::string(" ") + Language::Translate(source.GetAccount(), _("(Split)"));
244 
245  lf.AddEntry(entry);
246  }
247 
248  std::vector<Anope::string> replies;
249  lf.Process(replies);
250 
251  if (!zones->empty())
252  {
253  ListFormatter lf2(source.GetAccount());
254  lf2.AddColumn(_("Zone")).AddColumn(_("Servers"));
255 
256  for (unsigned i = 0; i < zones->size(); ++i)
257  {
258  const DNSZone *z = zones->at(i);
259 
261  entry["Zone"] = z->name;
262 
263  Anope::string server_str;
264  for (std::set<Anope::string, ci::less>::iterator it = z->servers.begin(), it_end = z->servers.end(); it != it_end; ++it)
265  server_str += *it + " ";
266  server_str.trim();
267 
268  if (server_str.empty())
269  server_str = "None";
270 
271  entry["Servers"] = server_str;
272 
273  lf2.AddEntry(entry);
274  }
275 
276  lf2.Process(replies);
277  }
278 
279  for (unsigned i = 0; i < replies.size(); ++i)
280  source.Reply(replies[i]);
281  }
282 
283  void AddZone(CommandSource &source, const std::vector<Anope::string> &params)
284  {
285  const Anope::string &zone = params[1];
286 
287  if (DNSZone::Find(zone))
288  {
289  source.Reply(_("Zone %s already exists."), zone.c_str());
290  return;
291  }
292 
293  if (Anope::ReadOnly)
294  source.Reply(READ_ONLY_MODE);
295 
296  Log(LOG_ADMIN, source, this) << "to add zone " << zone;
297 
298  new DNSZone(zone);
299  source.Reply(_("Added zone %s."), zone.c_str());
300  }
301 
302  void DelZone(CommandSource &source, const std::vector<Anope::string> &params)
303  {
304  const Anope::string &zone = params[1];
305 
306  DNSZone *z = DNSZone::Find(zone);
307  if (!z)
308  {
309  source.Reply(_("Zone %s does not exist."), zone.c_str());
310  return;
311  }
312 
313  if (Anope::ReadOnly)
314  source.Reply(READ_ONLY_MODE);
315 
316  Log(LOG_ADMIN, source, this) << "to delete zone " << z->name;
317 
318  for (std::set<Anope::string, ci::less>::iterator it = z->servers.begin(), it_end = z->servers.end(); it != it_end; ++it)
319  {
320  DNSServer *s = DNSServer::Find(*it);
321  if (s)
322  s->zones.erase(z->name);
323  }
324 
325  if (dnsmanager)
326  {
327  dnsmanager->UpdateSerial();
328  dnsmanager->Notify(z->name);
329  }
330 
331  source.Reply(_("Zone %s removed."), z->name.c_str());
332  delete z;
333  }
334 
335  void AddServer(CommandSource &source, const std::vector<Anope::string> &params)
336  {
337  DNSServer *s = DNSServer::Find(params[1]);
338  const Anope::string &zone = params.size() > 2 ? params[2] : "";
339 
340  if (s)
341  {
342  if (zone.empty())
343  {
344  source.Reply(_("Server %s already exists."), s->GetName().c_str());
345  }
346  else
347  {
348  DNSZone *z = DNSZone::Find(zone);
349  if (!z)
350  {
351  source.Reply(_("Zone %s does not exist."), zone.c_str());
352  return;
353  }
354  else if (z->servers.count(s->GetName()))
355  {
356  source.Reply(_("Server %s is already in zone %s."), s->GetName().c_str(), z->name.c_str());
357  return;
358  }
359 
360  if (Anope::ReadOnly)
361  source.Reply(READ_ONLY_MODE);
362 
363  z->servers.insert(s->GetName());
364  s->zones.insert(zone);
365 
366  if (dnsmanager)
367  {
368  dnsmanager->UpdateSerial();
369  dnsmanager->Notify(zone);
370  }
371 
372  Log(LOG_ADMIN, source, this) << "to add server " << s->GetName() << " to zone " << z->name;
373 
374  source.Reply(_("Server %s added to zone %s."), s->GetName().c_str(), z->name.c_str());
375  }
376 
377  return;
378  }
379 
380  Server *serv = Server::Find(params[1], true);
381  if (!serv || serv == Me || serv->IsJuped())
382  {
383  source.Reply(_("Server %s is not linked to the network."), params[1].c_str());
384  return;
385  }
386 
387  s = new DNSServer(params[1]);
388  if (zone.empty())
389  {
390  if (Anope::ReadOnly)
391  source.Reply(READ_ONLY_MODE);
392 
393  Log(LOG_ADMIN, source, this) << "to add server " << s->GetName();
394  source.Reply(_("Added server %s."), s->GetName().c_str());
395  }
396  else
397  {
398  DNSZone *z = DNSZone::Find(zone);
399  if (!z)
400  {
401  source.Reply(_("Zone %s does not exist."), zone.c_str());
402  delete s;
403  return;
404  }
405 
406  if (Anope::ReadOnly)
407  source.Reply(READ_ONLY_MODE);
408 
409  Log(LOG_ADMIN, source, this) << "to add server " << s->GetName() << " to zone " << zone;
410 
411  z->servers.insert(s->GetName());
412  s->zones.insert(z->name);
413 
414  if (dnsmanager)
415  {
416  dnsmanager->UpdateSerial();
417  dnsmanager->Notify(z->name);
418  }
419  }
420  }
421 
422  void DelServer(CommandSource &source, const std::vector<Anope::string> &params)
423  {
424  DNSServer *s = DNSServer::Find(params[1]);
425  const Anope::string &zone = params.size() > 2 ? params[2] : "";
426 
427  if (!s)
428  {
429  source.Reply(_("Server %s does not exist."), params[1].c_str());
430  return;
431  }
432  else if (!zone.empty())
433  {
434  DNSZone *z = DNSZone::Find(zone);
435  if (!z)
436  {
437  source.Reply(_("Zone %s does not exist."), zone.c_str());
438  return;
439  }
440  else if (!z->servers.count(s->GetName()))
441  {
442  source.Reply(_("Server %s is not in zone %s."), s->GetName().c_str(), z->name.c_str());
443  return;
444  }
445 
446  if (Anope::ReadOnly)
447  source.Reply(READ_ONLY_MODE);
448 
449  Log(LOG_ADMIN, source, this) << "to remove server " << s->GetName() << " from zone " << z->name;
450 
451  if (dnsmanager)
452  {
453  dnsmanager->UpdateSerial();
454  dnsmanager->Notify(z->name);
455  }
456 
457  z->servers.erase(s->GetName());
458  source.Reply(_("Removed server %s from zone %s."), s->GetName().c_str(), z->name.c_str());
459  return;
460  }
461  else if (Server::Find(s->GetName(), true))
462  {
463  source.Reply(_("Server %s must be quit before it can be deleted."), s->GetName().c_str());
464  return;
465  }
466 
467  for (std::set<Anope::string, ci::less>::iterator it = s->zones.begin(), it_end = s->zones.end(); it != it_end; ++it)
468  {
469  DNSZone *z = DNSZone::Find(*it);
470  if (z)
471  z->servers.erase(s->GetName());
472  }
473 
474  if (Anope::ReadOnly)
475  source.Reply(READ_ONLY_MODE);
476 
477  if (dnsmanager)
478  dnsmanager->UpdateSerial();
479 
480  Log(LOG_ADMIN, source, this) << "to delete server " << s->GetName();
481  source.Reply(_("Removed server %s."), s->GetName().c_str());
482  delete s;
483  }
484 
485  void AddIP(CommandSource &source, const std::vector<Anope::string> &params)
486  {
487  DNSServer *s = DNSServer::Find(params[1]);
488 
489  if (!s)
490  {
491  source.Reply(_("Server %s does not exist."), params[1].c_str());
492  return;
493  }
494 
495  for (unsigned i = 0; i < s->GetIPs().size(); ++i)
496  if (params[2].equals_ci(s->GetIPs()[i]))
497  {
498  source.Reply(_("IP %s already exists for %s."), s->GetIPs()[i].c_str(), s->GetName().c_str());
499  return;
500  }
501 
502  sockaddrs addr(params[2]);
503  if (!addr.valid())
504  {
505  source.Reply(_("%s is not a valid IP address."), params[2].c_str());
506  return;
507  }
508 
509  if (Anope::ReadOnly)
510  source.Reply(READ_ONLY_MODE);
511 
512  s->GetIPs().push_back(params[2]);
513  source.Reply(_("Added IP %s to %s."), params[2].c_str(), s->GetName().c_str());
514  Log(LOG_ADMIN, source, this) << "to add IP " << params[2] << " to " << s->GetName();
515 
516  if (s->Active() && dnsmanager)
517  {
518  dnsmanager->UpdateSerial();
519  for (std::set<Anope::string, ci::less>::iterator it = s->zones.begin(), it_end = s->zones.end(); it != it_end; ++it)
520  dnsmanager->Notify(*it);
521  }
522  }
523 
524  void DelIP(CommandSource &source, const std::vector<Anope::string> &params)
525  {
526  DNSServer *s = DNSServer::Find(params[1]);
527 
528  if (!s)
529  {
530  source.Reply(_("Server %s does not exist."), params[1].c_str());
531  return;
532  }
533 
534  if (Anope::ReadOnly)
535  source.Reply(READ_ONLY_MODE);
536 
537  for (unsigned i = 0; i < s->GetIPs().size(); ++i)
538  if (params[2].equals_ci(s->GetIPs()[i]))
539  {
540  s->GetIPs().erase(s->GetIPs().begin() + i);
541  source.Reply(_("Removed IP %s from %s."), params[2].c_str(), s->GetName().c_str());
542  Log(LOG_ADMIN, source, this) << "to remove IP " << params[2] << " from " << s->GetName();
543 
544  if (s->GetIPs().empty())
545  {
546  s->repool = 0;
547  s->Pool(false);
548  }
549 
550  if (s->Active() && dnsmanager)
551  {
552  dnsmanager->UpdateSerial();
553  for (std::set<Anope::string, ci::less>::iterator it = s->zones.begin(), it_end = s->zones.end(); it != it_end; ++it)
554  dnsmanager->Notify(*it);
555  }
556 
557  return;
558  }
559 
560  source.Reply(_("IP %s does not exist for %s."), params[2].c_str(), s->GetName().c_str());
561  }
562 
563  void OnSet(CommandSource &source, const std::vector<Anope::string> &params)
564  {
565  DNSServer *s = DNSServer::Find(params[1]);
566 
567  if (!s)
568  {
569  source.Reply(_("Server %s does not exist."), params[1].c_str());
570  return;
571  }
572 
573  if (Anope::ReadOnly)
574  source.Reply(READ_ONLY_MODE);
575 
576  if (params[2].equals_ci("LIMIT"))
577  {
578  try
579  {
580  unsigned l = convertTo<unsigned>(params[3]);
581  s->SetLimit(l);
582  if (l)
583  source.Reply(_("User limit for %s set to %d."), s->GetName().c_str(), l);
584  else
585  source.Reply(_("User limit for %s removed."), s->GetName().c_str());
586  }
587  catch (const ConvertException &ex)
588  {
589  source.Reply(_("Invalid value for LIMIT. Must be numerical."));
590  }
591  }
592  else
593  source.Reply(_("Unknown SET option."));
594  }
595 
596  void OnPool(CommandSource &source, const std::vector<Anope::string> &params)
597  {
598  DNSServer *s = DNSServer::Find(params[1]);
599 
600  if (!s)
601  {
602  source.Reply(_("Server %s does not exist."), params[1].c_str());
603  return;
604  }
605  else if (!Server::Find(s->GetName(), true))
606  {
607  source.Reply(_("Server %s is not currently linked."), s->GetName().c_str());
608  return;
609  }
610  else if (s->Pooled())
611  {
612  source.Reply(_("Server %s is already pooled."), s->GetName().c_str());
613  return;
614  }
615  else if (s->GetIPs().empty())
616  {
617  source.Reply(_("Server %s has no configured IPs."), s->GetName().c_str());
618  return;
619  }
620 
621  if (Anope::ReadOnly)
622  source.Reply(READ_ONLY_MODE);
623 
624  s->SetActive(true);
625 
626  source.Reply(_("Pooled %s."), s->GetName().c_str());
627  Log(LOG_ADMIN, source, this) << "to pool " << s->GetName();
628  }
629 
630 
631  void OnDepool(CommandSource &source, const std::vector<Anope::string> &params)
632  {
633  DNSServer *s = DNSServer::Find(params[1]);
634 
635  if (!s)
636  {
637  source.Reply(_("Server %s does not exist."), params[1].c_str());
638  return;
639  }
640  else if (!s->Pooled())
641  {
642  source.Reply(_("Server %s is not pooled."), s->GetName().c_str());
643  return;
644  }
645 
646  if (Anope::ReadOnly)
647  source.Reply(READ_ONLY_MODE);
648 
649  s->Pool(false);
650 
651  source.Reply(_("Depooled %s."), s->GetName().c_str());
652  Log(LOG_ADMIN, source, this) << "to depool " << s->GetName();
653  }
654 
655  public:
656  CommandOSDNS(Module *creator) : Command(creator, "operserv/dns", 0, 4)
657  {
658  this->SetDesc(_("Manage DNS zones for this network"));
659  this->SetSyntax(_("ADDZONE \037zone.name\037"));
660  this->SetSyntax(_("DELZONE \037zone.name\037"));
661  this->SetSyntax(_("ADDSERVER \037server.name\037 [\037zone.name\037]"));
662  this->SetSyntax(_("DELSERVER \037server.name\037 [\037zone.name\037]"));
663  this->SetSyntax(_("ADDIP \037server.name\037 \037ip\037"));
664  this->SetSyntax(_("DELIP \037server.name\037 \037ip\037"));
665  this->SetSyntax(_("SET \037server.name\037 \037option\037 \037value\037"));
666  this->SetSyntax(_("POOL \037server.name\037"));
667  this->SetSyntax(_("DEPOOL \037server.name\037"));
668  }
669 
670  void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
671  {
672  if (params.empty())
673  this->DisplayPoolState(source);
674  else if (params[0].equals_ci("ADDZONE") && params.size() > 1)
675  this->AddZone(source, params);
676  else if (params[0].equals_ci("DELZONE") && params.size() > 1)
677  this->DelZone(source, params);
678  else if (params[0].equals_ci("ADDSERVER") && params.size() > 1)
679  this->AddServer(source, params);
680  else if (params[0].equals_ci("DELSERVER") && params.size() > 1)
681  this->DelServer(source, params);
682  else if (params[0].equals_ci("ADDIP") && params.size() > 2)
683  this->AddIP(source, params);
684  else if (params[0].equals_ci("DELIP") && params.size() > 2)
685  this->DelIP(source, params);
686  else if (params[0].equals_ci("SET") && params.size() > 3)
687  this->OnSet(source, params);
688  else if (params[0].equals_ci("POOL") && params.size() > 1)
689  this->OnPool(source, params);
690  else if (params[0].equals_ci("DEPOOL") && params.size() > 1)
691  this->OnDepool(source, params);
692  else
693  this->OnSyntaxError(source, "");
694  }
695 
696  bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
697  {
698  this->SendSyntax(source);
699  source.Reply(" ");
700  source.Reply(_("This command allows managing DNS zones used for controlling what servers users\n"
701  "are directed to when connecting. Omitting all parameters prints out the status of\n"
702  "the DNS zone.\n"
703  " \n"
704  "\002ADDZONE\002 adds a zone, eg us.yournetwork.tld. Servers can then be added to this\n"
705  "zone with the \002ADDSERVER\002 command.\n"
706  " \n"
707  "The \002ADDSERVER\002 command adds a server to the given zone. When a query is done, the\n"
708  "zone in question is served if it exists, else all servers in all zones are served.\n"
709  "A server may be in more than one zone.\n"
710  " \n"
711  "The \002ADDIP\002 command associates an IP with a server.\n"
712  " \n"
713  "The \002POOL\002 and \002DEPOOL\002 commands actually add and remove servers to their given zones."));
714  return true;
715  }
716 };
717 
718 class ModuleDNS : public Module
719 {
722 
723  time_t ttl;
729 
730  time_t last_warn;
731 
732  public:
733  ModuleDNS(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, EXTRA | VENDOR),
734  zone_type("DNSZone", DNSZone::Unserialize), dns_type("DNSServer", DNSServer::Unserialize), commandosdns(this),
735  last_warn(0)
736  {
737 
738 
739  for (unsigned j = 0; j < dns_servers->size(); ++j)
740  {
741  DNSServer *s = dns_servers->at(j);
742  if (s->Pooled() && Server::Find(s->GetName(), true))
743  s->SetActive(true);
744  }
745  }
746 
748  {
749  for (unsigned i = zones->size(); i > 0; --i)
750  delete zones->at(i - 1);
751  for (unsigned i = dns_servers->size(); i > 0; --i)
752  delete dns_servers->at(i - 1);
753  }
754 
756  {
757  Configuration::Block *block = conf->GetModule(this);
758  this->ttl = block->Get<time_t>("ttl");
759  this->user_drop_mark = block->Get<int>("user_drop_mark");
760  this->user_drop_time = block->Get<time_t>("user_drop_time");
761  this->user_drop_readd_time = block->Get<time_t>("user_drop_readd_time");
762  this->remove_split_servers = block->Get<bool>("remove_split_servers");
763  this->readd_connected_servers = block->Get<bool>("readd_connected_servers");
764  }
765 
767  {
768  if (s == Me || s->IsJuped())
769  return;
770  if (!Me->IsSynced() || this->readd_connected_servers)
771  {
772  DNSServer *dns = DNSServer::Find(s->GetName());
773  if (dns && dns->Pooled() && !dns->Active() && !dns->GetIPs().empty())
774  {
775  dns->SetActive(true);
776  Log(this) << "Pooling server " << s->GetName();
777  }
778  }
779  }
780 
782  {
783  DNSServer *dns = DNSServer::Find(s->GetName());
784  if (remove_split_servers && dns && dns->Pooled() && dns->Active())
785  {
786  if (readd_connected_servers)
787  dns->SetActive(false); // Will be reactivated when it comes back
788  else
789  dns->Pool(false); // Otherwise permanently pull this
790  Log(this) << "Depooling delinked server " << s->GetName();
791  }
792  }
793 
794  void OnUserConnect(User *u, bool &exempt) anope_override
795  {
796  if (!u->Quitting() && u->server)
797  {
798  DNSServer *s = DNSServer::Find(u->server->GetName());
799  /* Check for user limit reached */
800  if (s && s->Pooled() && s->Active() && s->GetLimit() && u->server->users >= s->GetLimit())
801  {
802  Log(this) << "Depooling full server " << s->GetName() << ": " << u->server->users << " users";
803  s->SetActive(false);
804  }
805  }
806  }
807 
809  {
810  if (u && u->server)
811  {
812  DNSServer *s = DNSServer::Find(u->server->GetName());
813  if (!s || !s->Pooled())
814  return;
815 
816  /* Check for dropping under userlimit */
817  if (s->GetLimit() && !s->Active() && s->GetLimit() > u->server->users)
818  {
819  Log(this) << "Pooling server " << s->GetName();
820  s->SetActive(true);
821  }
822 
823  if (this->user_drop_mark > 0)
824  {
825  std::list<time_t>& times = server_quit_times[u->server->GetName()];
826  times.push_back(Anope::CurTime);
827  if (times.size() > static_cast<unsigned>(this->user_drop_mark))
828  times.pop_front();
829 
830  if (times.size() == static_cast<unsigned>(this->user_drop_mark))
831  {
832  time_t diff = Anope::CurTime - *times.begin();
833 
834  /* Check for very fast user drops */
835  if (s->Active() && diff <= this->user_drop_time)
836  {
837  Log(this) << "Depooling server " << s->GetName() << ": dropped " << this->user_drop_mark << " users in " << diff << " seconds";
839  s->SetActive(false);
840  }
841  /* Check for needing to re-pool a server that dropped users */
842  else if (!s->Active() && s->repool && s->repool <= Anope::CurTime)
843  {
844  s->SetActive(true);
845  s->repool = 0;
846  Log(this) << "Pooling server " << s->GetName();
847  }
848  }
849  }
850  }
851  }
852 
854  {
855  if (req.questions.empty())
856  return;
857  /* Currently we reply to any QR for A/AAAA */
858  const DNS::Question& q = req.questions[0];
859  if (q.type != DNS::QUERY_A && q.type != DNS::QUERY_AAAA && q.type != DNS::QUERY_AXFR && q.type != DNS::QUERY_ANY)
860  return;
861 
862  DNSZone *zone = DNSZone::Find(q.name);
863  size_t answer_size = packet->answers.size();
864  if (zone)
865  {
866  for (std::set<Anope::string, ci::less>::iterator it = zone->servers.begin(), it_end = zone->servers.end(); it != it_end; ++it)
867  {
868  DNSServer *s = DNSServer::Find(*it);
869  if (!s || !s->Active())
870  continue;
871 
872  for (unsigned j = 0; j < s->GetIPs().size(); ++j)
873  {
874  DNS::QueryType q_type = s->GetIPs()[j].find(':') != Anope::string::npos ? DNS::QUERY_AAAA : DNS::QUERY_A;
875 
876  if (q.type == DNS::QUERY_AXFR || q.type == DNS::QUERY_ANY || q_type == q.type)
877  {
878  DNS::ResourceRecord rr(q.name, q_type);
879  rr.ttl = this->ttl;
880  rr.rdata = s->GetIPs()[j];
881  packet->answers.push_back(rr);
882  }
883  }
884  }
885  }
886 
887  if (packet->answers.size() == answer_size)
888  {
889  /* Default zone */
890  for (unsigned i = 0; i < dns_servers->size(); ++i)
891  {
892  DNSServer *s = dns_servers->at(i);
893  if (!s->Active())
894  continue;
895 
896  for (unsigned j = 0; j < s->GetIPs().size(); ++j)
897  {
898  DNS::QueryType q_type = s->GetIPs()[j].find(':') != Anope::string::npos ? DNS::QUERY_AAAA : DNS::QUERY_A;
899 
900  if (q.type == DNS::QUERY_AXFR || q.type == DNS::QUERY_ANY || q_type == q.type)
901  {
902  DNS::ResourceRecord rr(q.name, q_type);
903  rr.ttl = this->ttl;
904  rr.rdata = s->GetIPs()[j];
905  packet->answers.push_back(rr);
906  }
907  }
908  }
909  }
910 
911  if (packet->answers.size() == answer_size)
912  {
913  if (last_warn + 60 < Anope::CurTime)
914  {
915  last_warn = Anope::CurTime;
916  Log(this) << "Warning! There are no pooled servers!";
917  }
918 
919  /* Something messed up, just return them all and hope one is available */
920  for (unsigned i = 0; i < dns_servers->size(); ++i)
921  {
922  DNSServer *s = dns_servers->at(i);
923 
924  for (unsigned j = 0; j < s->GetIPs().size(); ++j)
925  {
926  DNS::QueryType q_type = s->GetIPs()[j].find(':') != Anope::string::npos ? DNS::QUERY_AAAA : DNS::QUERY_A;
927 
928  if (q.type == DNS::QUERY_AXFR || q.type == DNS::QUERY_ANY || q_type == q.type)
929  {
930  DNS::ResourceRecord rr(q.name, q_type);
931  rr.ttl = this->ttl;
932  rr.rdata = s->GetIPs()[j];
933  packet->answers.push_back(rr);
934  }
935  }
936  }
937 
938  if (packet->answers.size() == answer_size)
939  {
940  Log(this) << "Error! There are no servers with any IPs of type " << q.type;
941  /* Send back an empty answer anyway */
942  }
943  }
944  }
945 };
946 
void SetActive(bool p)
Definition: os_dns.cpp:127
CoreExport bool ReadOnly
Definition: main.cpp:28
void OnDnsRequest(DNS::Query &req, DNS::Query *packet) anope_override
Definition: os_dns.cpp:853
static Serialize::Checker< std::vector< DNSZone * > > zones("DNSZone")
Definition: servers.h:42
void Serialize(Serialize::Data &data) const anope_override
Definition: os_dns.cpp:38
void OnServerQuit(Server *s) anope_override
Definition: os_dns.cpp:781
void DisplayPoolState(CommandSource &source)
Definition: os_dns.cpp:208
std::set< Anope::string, ci::less > zones
Definition: os_dns.cpp:98
~ModuleDNS()
Definition: os_dns.cpp:747
void DelZone(CommandSource &source, const std::vector< Anope::string > &params)
Definition: os_dns.cpp:302
bool IsSynced() const
Definition: servers.cpp:298
void Pool(bool p)
Definition: os_dns.cpp:119
bool readd_connected_servers
Definition: os_dns.cpp:728
static Serialize::Checker< std::vector< DNSServer * > > dns_servers("DNSServer")
static Serializable * Unserialize(Serializable *obj, Serialize::Data &data)
Definition: os_dns.cpp:153
bool pooled
Definition: os_dns.cpp:93
DNSServer(const Anope::string &sn)
Definition: os_dns.cpp:101
void OnDepool(CommandSource &source, const std::vector< Anope::string > &params)
Definition: os_dns.cpp:631
void AddZone(CommandSource &source, const std::vector< Anope::string > &params)
Definition: os_dns.cpp:283
void OnNewServer(Server *s) anope_override
Definition: os_dns.cpp:766
void QueueUpdate()
Definition: serialize.cpp:83
Definition: users.h:34
Anope::string name
Definition: os_dns.cpp:23
Anope::string rdata
Definition: dns.h:96
time_t last_warn
Definition: os_dns.cpp:730
static Serializable * Unserialize(Serializable *obj, Serialize::Data &data)
Definition: os_dns.cpp:46
bool IsJuped() const
Definition: servers.cpp:319
unsigned int ttl
Definition: dns.h:95
CommandOSDNS(Module *creator)
Definition: os_dns.cpp:656
#define READ_ONLY_MODE
Definition: language.h:71
time_t ttl
Definition: os_dns.cpp:723
void SetDesc(const Anope::string &d)
Definition: command.cpp:130
Anope::string server_name
Definition: os_dns.cpp:89
bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
Definition: os_dns.cpp:696
CommandOSDNS commandosdns
Definition: os_dns.cpp:721
CoreExport time_t CurTime
Definition: main.cpp:41
bool Pooled() const
Definition: os_dns.cpp:118
Serialize::Type dns_type
Definition: os_dns.cpp:720
bool remove_split_servers
Definition: os_dns.cpp:727
bool Active() const
Definition: os_dns.cpp:126
void AddIP(CommandSource &source, const std::vector< Anope::string > &params)
Definition: os_dns.cpp:485
static DNSServer * Find(const Anope::string &s)
Definition: os_dns.cpp:193
Serialize::Type zone_type
Definition: os_dns.cpp:720
std::map< Anope::string, Anope::string > ListEntry
Definition: lists.h:68
void AddServer(CommandSource &source, const std::vector< Anope::string > &params)
Definition: os_dns.cpp:335
time_t user_drop_time
Definition: os_dns.cpp:725
unsigned limit
Definition: os_dns.cpp:91
bool valid() const
Definition: sockets.cpp:99
void OnPreUserLogoff(User *u) anope_override
Definition: os_dns.cpp:808
virtual void OnSyntaxError(CommandSource &source, const Anope::string &subcommand)
Definition: command.cpp:191
void DelServer(CommandSource &source, const std::vector< Anope::string > &params)
Definition: os_dns.cpp:422
~DNSServer()
Definition: os_dns.cpp:106
static const size_type npos
Definition: anope.h:44
void Reply(const char *message,...)
Definition: command.cpp:96
time_t repool
Definition: os_dns.cpp:99
void Execute(CommandSource &source, const std::vector< Anope::string > &params) anope_override
Definition: os_dns.cpp:670
string & trim(const Anope::string &what=" \t\r\n")
Definition: anope.h:177
std::vector< Anope::string > & GetIPs()
Definition: os_dns.cpp:114
#define anope_override
Definition: services.h:56
bool empty() const
Definition: anope.h:126
unsigned GetLimit() const
Definition: os_dns.cpp:115
static Server * Find(const Anope::string &name, bool name_only=false)
Definition: servers.cpp:337
void SetLimit(unsigned l)
Definition: os_dns.cpp:116
std::vector< Anope::string > ips
Definition: os_dns.cpp:90
std::basic_string< char, ci_char_traits, std::allocator< char > > string
Definition: hashcomp.h:133
#define MODULE_INIT(x)
Definition: modules.h:45
CoreExport const char * Translate(const char *string)
Definition: language.cpp:59
bool active
Definition: os_dns.cpp:95
static std::map< Anope::string, std::list< time_t > > server_quit_times
Definition: os_dns.cpp:19
void OnPool(CommandSource &source, const std::vector< Anope::string > &params)
Definition: os_dns.cpp:596
void SetSyntax(const Anope::string &s)
Definition: command.cpp:140
static ServiceReference< DNS::Manager > dnsmanager("DNS::Manager","dns/manager")
Anope::string stringify(const T &x)
Definition: anope.h:710
void DelIP(CommandSource &source, const std::vector< Anope::string > &params)
Definition: os_dns.cpp:524
QueryType
Definition: dns.h:20
QueryType type
Definition: dns.h:77
void OnSet(CommandSource &source, const std::vector< Anope::string > &params)
Definition: os_dns.cpp:563
static DNSZone * Find(const Anope::string &name)
Definition: os_dns.cpp:74
int user_drop_mark
Definition: os_dns.cpp:724
T anope_dynamic_static_cast(O ptr)
Definition: anope.h:774
CoreExport Server * Me
Definition: servers.cpp:24
void SendSyntax(CommandSource &)
Definition: command.cpp:145
time_t user_drop_readd_time
Definition: os_dns.cpp:726
NickCore * GetAccount()
Definition: command.cpp:36
Anope::string name
Definition: dns.h:76
const char * c_str() const
Definition: anope.h:117
Definition: logger.h:53
T Get(const Anope::string &tag)
Definition: config.h:44
void OnUserConnect(User *u, bool &exempt) anope_override
Definition: os_dns.cpp:794
ModuleDNS(const Anope::string &modname, const Anope::string &creator)
Definition: os_dns.cpp:733
std::set< Anope::string, ci::less > servers
Definition: os_dns.cpp:24
DNSZone(const Anope::string &n)
Definition: os_dns.cpp:26
void Serialize(Serialize::Data &data) const anope_override
Definition: os_dns.cpp:141
#define _(x)
Definition: services.h:50
ListFormatter & AddColumn(const Anope::string &name)
Definition: misc.cpp:128
Type(const Anope::string &n, unserialize_func f, Module *owner=NULL)
~DNSZone()
Definition: os_dns.cpp:31
const Anope::string & GetName() const
Definition: os_dns.cpp:113
Definition: modules.h:163
void OnReload(Configuration::Conf *conf) anope_override
Definition: os_dns.cpp:755