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