00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include "services.h"
00014 #include "anope.h"
00015 #include "dns.h"
00016 #include "sockets.h"
00017 #include "socketengine.h"
00018
00019 #ifndef _WIN32
00020 #include <sys/types.h>
00021 #include <sys/socket.h>
00022 #include <netdb.h>
00023 #endif
00024
00025 using namespace DNS;
00026
00027 Manager *DNS::Engine = NULL;
00028
00029 Question::Question()
00030 {
00031 this->type = QUERY_NONE;
00032 this->qclass = 0;
00033 }
00034
00035 Question::Question(const Anope::string &n, QueryType t, unsigned short q) : name(n), type(t), qclass(q)
00036 {
00037 }
00038
00039 ResourceRecord::ResourceRecord(const Anope::string &n, QueryType t, unsigned short q) : Question(n, t, q)
00040 {
00041 this->ttl = 0;
00042 this->created = Anope::CurTime;
00043 }
00044
00045 ResourceRecord::ResourceRecord(const Question &q) : Question(q)
00046 {
00047 this->ttl = 0;
00048 this->created = Anope::CurTime;
00049 }
00050
00051 Query::Query()
00052 {
00053 this->error = ERROR_NONE;
00054 }
00055
00056 Query::Query(const Question &q)
00057 {
00058 this->questions.push_back(q);
00059 this->error = ERROR_NONE;
00060 }
00061
00062 Request::Request(const Anope::string &addr, QueryType qt, bool cache, Module *c) : Timer(Config->DNSTimeout), Question(addr, qt), use_cache(cache), id(0), creator(c)
00063 {
00064 if (!DNS::Engine || !DNS::Engine->udpsock)
00065 throw SocketException("No DNS::Engine");
00066 if (DNS::Engine->udpsock->GetPackets().size() == 65535)
00067 throw SocketException("DNS queue full");
00068
00069 do
00070 {
00071 static unsigned short cur_id = rand();
00072 this->id = cur_id++;
00073 }
00074 while (DNS::Engine->requests.count(this->id));
00075
00076 DNS::Engine->requests[this->id] = this;
00077 }
00078
00079 Request::~Request()
00080 {
00081 DNS::Engine->requests.erase(this->id);
00082 }
00083
00084 void Request::Process()
00085 {
00086 Log(LOG_DEBUG_2) << "Resolver: Processing request to lookup " << this->name << ", of type " << this->type;
00087
00088 if (!DNS::Engine || !DNS::Engine->udpsock)
00089 throw SocketException("DNS::Engine has not been initialized");
00090
00091 if (this->use_cache && DNS::Engine->CheckCache(this))
00092 {
00093 Log(LOG_DEBUG_2) << "Resolver: Using cached result";
00094 delete this;
00095 return;
00096 }
00097
00098 Packet *p = new Packet(&DNS::Engine->addrs);
00099 p->flags = QUERYFLAGS_RD;
00100
00101 p->id = this->id;
00102 p->questions.push_back(*this);
00103 DNS::Engine->udpsock->Reply(p);
00104 }
00105
00106 void Request::OnError(const Query *r)
00107 {
00108 }
00109
00110 void Request::Tick(time_t)
00111 {
00112 Log(LOG_DEBUG_2) << "Resolver: timeout for query " << this->name;
00113 Query rr(*this);
00114 rr.error = ERROR_TIMEOUT;
00115 this->OnError(&rr);
00116 }
00117
00118 void Packet::PackName(unsigned char *output, unsigned short output_size, unsigned short &pos, const Anope::string &name)
00119 {
00120 if (name.length() + 2 > output_size)
00121 throw SocketException("Unable to pack name");
00122
00123 Log(LOG_DEBUG_2) << "Resolver: PackName packing " << name;
00124
00125 sepstream sep(name, '.');
00126 Anope::string token;
00127
00128 while (sep.GetToken(token))
00129 {
00130 output[pos++] = token.length();
00131 memcpy(&output[pos], token.c_str(), token.length());
00132 pos += token.length();
00133 }
00134
00135 output[pos++] = 0;
00136 }
00137
00138 Anope::string Packet::UnpackName(const unsigned char *input, unsigned short input_size, unsigned short &pos)
00139 {
00140 Anope::string name;
00141 unsigned short pos_ptr = pos, lowest_ptr = input_size;
00142 bool compressed = false;
00143
00144 if (pos_ptr >= input_size)
00145 throw SocketException("Unable to unpack name - no input");
00146
00147 while (input[pos_ptr] > 0)
00148 {
00149 unsigned short offset = input[pos_ptr];
00150
00151 if (offset & POINTER)
00152 {
00153 if ((offset & POINTER) != POINTER)
00154 throw SocketException("Unable to unpack name - bogus compression header");
00155 if (pos_ptr + 1 >= input_size)
00156 throw SocketException("Unable to unpack name - bogus compression header");
00157
00158
00159 if (compressed == false)
00160 {
00161 ++pos;
00162 compressed = true;
00163 }
00164
00165 pos_ptr = (offset & LABEL) << 8 | input[pos_ptr + 1];
00166
00167
00168 if (pos_ptr >= lowest_ptr)
00169 throw SocketException("Unable to unpack name - bogus compression pointer");
00170 lowest_ptr = pos_ptr;
00171 }
00172 else
00173 {
00174 if (pos_ptr + offset + 1 >= input_size)
00175 throw SocketException("Unable to unpack name - offset too large");
00176 if (!name.empty())
00177 name += ".";
00178 for (unsigned i = 1; i <= offset; ++i)
00179 name += input[pos_ptr + i];
00180
00181 pos_ptr += offset + 1;
00182 if (compressed == false)
00183
00184 pos = pos_ptr;
00185 }
00186 }
00187
00188
00189 ++pos;
00190
00191 Log(LOG_DEBUG_2) << "Resolver: UnpackName successfully unpacked " << name;
00192
00193 return name;
00194 }
00195
00196 Question Packet::UnpackQuestion(const unsigned char *input, unsigned short input_size, unsigned short &pos)
00197 {
00198 Question question;
00199
00200 question.name = this->UnpackName(input, input_size, pos);
00201
00202 if (pos + 4 > input_size)
00203 throw SocketException("Unable to unpack question");
00204
00205 question.type = static_cast<QueryType>(input[pos] << 8 | input[pos + 1]);
00206 pos += 2;
00207
00208 question.qclass = input[pos] << 8 | input[pos + 1];
00209 pos += 2;
00210
00211 return question;
00212 }
00213
00214 ResourceRecord Packet::UnpackResourceRecord(const unsigned char *input, unsigned short input_size, unsigned short &pos)
00215 {
00216 ResourceRecord record = static_cast<ResourceRecord>(this->UnpackQuestion(input, input_size, pos));
00217
00218 if (pos + 6 > input_size)
00219 throw SocketException("Unable to unpack resource record");
00220
00221 record.ttl = (input[pos] << 24) | (input[pos + 1] << 16) | (input[pos + 2] << 8) | input[pos + 3];
00222 pos += 4;
00223
00224
00225 pos += 2;
00226
00227 switch (record.type)
00228 {
00229 case QUERY_A:
00230 {
00231 if (pos + 4 > input_size)
00232 throw SocketException("Unable to unpack resource record");
00233
00234 in_addr a;
00235 a.s_addr = input[pos] | (input[pos + 1] << 8) | (input[pos + 2] << 16) | (input[pos + 3] << 24);
00236 pos += 4;
00237
00238 sockaddrs addrs;
00239 addrs.ntop(AF_INET, &a);
00240
00241 record.rdata = addrs.addr();
00242 break;
00243 }
00244 case QUERY_AAAA:
00245 {
00246 if (pos + 16 > input_size)
00247 throw SocketException("Unable to unpack resource record");
00248
00249 in6_addr a;
00250 for (int j = 0; j < 16; ++j)
00251 a.s6_addr[j] = input[pos + j];
00252 pos += 16;
00253
00254 sockaddrs addrs;
00255 addrs.ntop(AF_INET6, &a);
00256
00257 record.rdata = addrs.addr();
00258 break;
00259 }
00260 case QUERY_CNAME:
00261 case QUERY_PTR:
00262 {
00263 record.rdata = this->UnpackName(input, input_size, pos);
00264 break;
00265 }
00266 default:
00267 break;
00268 }
00269
00270 Log(LOG_DEBUG_2) << "Resolver: " << record.name << " -> " << record.rdata;
00271
00272 return record;
00273 }
00274
00275 Packet::Packet(sockaddrs *a) : Query(), id(0), flags(0)
00276 {
00277 if (a)
00278 addr = *a;
00279 }
00280
00281 void Packet::Fill(const unsigned char *input, const unsigned short len)
00282 {
00283 if (len < Packet::HEADER_LENGTH)
00284 throw SocketException("Unable to fill packet");
00285
00286 unsigned short packet_pos = 0;
00287
00288 this->id = (input[packet_pos] << 8) | input[packet_pos + 1];
00289 packet_pos += 2;
00290
00291 this->flags = (input[packet_pos] << 8) | input[packet_pos + 1];
00292 packet_pos += 2;
00293
00294 unsigned short qdcount = (input[packet_pos] << 8) | input[packet_pos + 1];
00295 packet_pos += 2;
00296
00297 unsigned short ancount = (input[packet_pos] << 8) | input[packet_pos + 1];
00298 packet_pos += 2;
00299
00300 unsigned short nscount = (input[packet_pos] << 8) | input[packet_pos + 1];
00301 packet_pos += 2;
00302
00303 unsigned short arcount = (input[packet_pos] << 8) | input[packet_pos + 1];
00304 packet_pos += 2;
00305
00306 Log(LOG_DEBUG_2) << "Resolver: qdcount: " << qdcount << " ancount: " << ancount << " nscount: " << nscount << " arcount: " << arcount;
00307
00308 for (unsigned i = 0; i < qdcount; ++i)
00309 this->questions.push_back(this->UnpackQuestion(input, len, packet_pos));
00310
00311 for (unsigned i = 0; i < ancount; ++i)
00312 this->answers.push_back(this->UnpackResourceRecord(input, len, packet_pos));
00313
00314 for (unsigned i = 0; i < nscount; ++i)
00315 this->authorities.push_back(this->UnpackResourceRecord(input, len, packet_pos));
00316
00317 for (unsigned i = 0; i < arcount; ++i)
00318 this->additional.push_back(this->UnpackResourceRecord(input, len, packet_pos));
00319 }
00320
00321 unsigned short Packet::Pack(unsigned char *output, unsigned short output_size)
00322 {
00323 if (output_size < Packet::HEADER_LENGTH)
00324 throw SocketException("Unable to pack packet");
00325
00326 unsigned short pos = 0;
00327
00328 output[pos++] = this->id >> 8;
00329 output[pos++] = this->id & 0xFF;
00330 output[pos++] = this->flags >> 8;
00331 output[pos++] = this->flags & 0xFF;
00332 output[pos++] = this->questions.size() >> 8;
00333 output[pos++] = this->questions.size() & 0xFF;
00334 output[pos++] = this->answers.size() >> 8;
00335 output[pos++] = this->answers.size() & 0xFF;
00336 output[pos++] = this->authorities.size() >> 8;
00337 output[pos++] = this->authorities.size() & 0xFF;
00338 output[pos++] = this->additional.size() >> 8;
00339 output[pos++] = this->additional.size() & 0xFF;
00340
00341 for (unsigned i = 0; i < this->questions.size(); ++i)
00342 {
00343 Question &q = this->questions[i];
00344
00345 if (q.type == QUERY_PTR)
00346 {
00347 sockaddrs ip(q.name);
00348
00349 if (q.name.find(':') != Anope::string::npos)
00350 {
00351 static const char *const hex = "0123456789abcdef";
00352 char reverse_ip[128];
00353 unsigned reverse_ip_count = 0;
00354 for (int j = 15; j >= 0; --j)
00355 {
00356 reverse_ip[reverse_ip_count++] = hex[ip.sa6.sin6_addr.s6_addr[j] & 0xF];
00357 reverse_ip[reverse_ip_count++] = '.';
00358 reverse_ip[reverse_ip_count++] = hex[ip.sa6.sin6_addr.s6_addr[j] >> 4];
00359 reverse_ip[reverse_ip_count++] = '.';
00360 }
00361 reverse_ip[reverse_ip_count++] = 0;
00362
00363 q.name = reverse_ip;
00364 q.name += "ip6.arpa";
00365 }
00366 else
00367 {
00368 unsigned long forward = ip.sa4.sin_addr.s_addr;
00369 in_addr reverse;
00370 reverse.s_addr = forward << 24 | (forward & 0xFF00) << 8 | (forward & 0xFF0000) >> 8 | forward >> 24;
00371
00372 ip.ntop(AF_INET, &reverse);
00373
00374 q.name = ip.addr() + ".in-addr.arpa";
00375 }
00376 }
00377
00378 this->PackName(output, output_size, pos, q.name);
00379
00380 if (pos + 4 >= output_size)
00381 throw SocketException("Unable to pack packet");
00382
00383 short s = htons(q.type);
00384 memcpy(&output[pos], &s, 2);
00385 pos += 2;
00386
00387 s = htons(q.qclass);
00388 memcpy(&output[pos], &s, 2);
00389 pos += 2;
00390 }
00391
00392 std::vector<ResourceRecord> types[] = { this->answers, this->authorities, this->additional };
00393 for (int i = 0; i < 3; ++i)
00394 for (unsigned j = 0; j < types[i].size(); ++j)
00395 {
00396 ResourceRecord &rr = types[i][j];
00397
00398 this->PackName(output, output_size, pos, rr.name);
00399
00400 if (pos + 8 >= output_size)
00401 throw SocketException("Unable to pack packet");
00402
00403 short s = htons(rr.type);
00404 memcpy(&output[pos], &s, 2);
00405 pos += 2;
00406
00407 s = htons(rr.qclass);
00408 memcpy(&output[pos], &s, 2);
00409 pos += 2;
00410
00411 long l = htonl(rr.ttl);
00412 memcpy(&output[pos], &l, 4);
00413 pos += 4;
00414
00415 switch (rr.type)
00416 {
00417 case QUERY_A:
00418 {
00419 if (pos + 6 > output_size)
00420 throw SocketException("Unable to pack packet");
00421
00422 sockaddrs a(rr.rdata);
00423
00424 s = htons(4);
00425 memcpy(&output[pos], &s, 2);
00426 pos += 2;
00427
00428 memcpy(&output[pos], &a.sa4.sin_addr, 4);
00429 pos += 4;
00430 break;
00431 }
00432 case QUERY_AAAA:
00433 {
00434 if (pos + 18 > output_size)
00435 throw SocketException("Unable to pack packet");
00436
00437 sockaddrs a(rr.rdata);
00438
00439 s = htons(16);
00440 memcpy(&output[pos], &s, 2);
00441 pos += 2;
00442
00443 memcpy(&output[pos], &a.sa6.sin6_addr, 16);
00444 pos += 16;
00445 break;
00446 }
00447 case QUERY_NS:
00448 case QUERY_CNAME:
00449 case QUERY_PTR:
00450 {
00451 if (pos + 2 >= output_size)
00452 throw SocketException("Unable to pack packet");
00453
00454 unsigned short packet_pos_save = pos;
00455 pos += 2;
00456
00457 this->PackName(output, output_size, pos, rr.rdata);
00458
00459 s = htons(pos - packet_pos_save - 2);
00460 memcpy(&output[packet_pos_save], &s, 2);
00461 break;
00462 }
00463 case QUERY_SOA:
00464 {
00465 if (pos + 2 >= output_size)
00466 throw SocketException("Unable to pack packet");
00467
00468 unsigned short packet_pos_save = pos;
00469 pos += 2;
00470
00471 std::vector<Anope::string> nameservers;
00472 spacesepstream(Config->DNSSOANS).GetTokens(nameservers);
00473 this->PackName(output, output_size, pos, !nameservers.empty() ? nameservers[0] : "");
00474 this->PackName(output, output_size, pos, Config->DNSSOAAdmin.replace_all_cs('@', '.'));
00475
00476 if (pos + 20 >= output_size)
00477 throw SocketException("Unable to pack SOA");
00478
00479 l = htonl(DNS::Engine->GetSerial());
00480 memcpy(&output[pos], &l, 4);
00481 pos += 4;
00482
00483 l = htonl(Config->DNSSOARefresh);
00484 memcpy(&output[pos], &l, 4);
00485 pos += 4;
00486
00487 l = htonl(Config->DNSSOARefresh);
00488 memcpy(&output[pos], &l, 4);
00489 pos += 4;
00490
00491 l = htonl(604800);
00492 memcpy(&output[pos], &l, 4);
00493 pos += 4;
00494
00495 l = htonl(0);
00496 memcpy(&output[pos], &l, 4);
00497 pos += 4;
00498
00499 s = htons(pos - packet_pos_save - 2);
00500 memcpy(&output[packet_pos_save], &s, 2);
00501
00502 break;
00503 }
00504 default:
00505 break;
00506 }
00507 }
00508
00509 return pos;
00510 }
00511
00512 Manager::TCPSocket::Client::Client(TCPSocket *l, int fd, const sockaddrs &addr) : Socket(fd, l->IsIPv6()), ClientSocket(l, addr), Timer(5), tcpsock(l), packet(NULL), length(0)
00513 {
00514 Log(LOG_DEBUG_2) << "Resolver: New client from " << addr.addr();
00515 }
00516
00517 Manager::TCPSocket::Client::~Client()
00518 {
00519 Log(LOG_DEBUG_2) << "Resolver: Exiting client from " << clientaddr.addr();
00520 delete packet;
00521 }
00522
00523 void Manager::TCPSocket::Client::Reply(Packet *p)
00524 {
00525 delete packet;
00526 packet = p;
00527 SocketEngine::Change(this, true, SF_WRITABLE);
00528 }
00529
00530 bool Manager::TCPSocket::Client::ProcessRead()
00531 {
00532 Log(LOG_DEBUG_2) << "Resolver: Reading from DNS TCP socket";
00533
00534 int i = recv(this->GetFD(), reinterpret_cast<char *>(packet_buffer) + length, sizeof(packet_buffer) - length, 0);
00535 if (i <= 0)
00536 return false;
00537
00538 length += i;
00539
00540 unsigned short want_len = packet_buffer[0] << 8 | packet_buffer[1];
00541 if (length >= want_len + 2)
00542 {
00543 int len = length - 2;
00544 length -= want_len + 2;
00545 return DNS::Engine->HandlePacket(this, packet_buffer + 2, len, NULL);
00546 }
00547 return true;
00548 }
00549
00550 bool Manager::TCPSocket::Client::ProcessWrite()
00551 {
00552 Log(LOG_DEBUG_2) << "Resolver: Writing to DNS TCP socket";
00553
00554 if (packet != NULL)
00555 {
00556 try
00557 {
00558 unsigned char buffer[65535];
00559 unsigned short len = packet->Pack(buffer + 2, sizeof(buffer) - 2);
00560
00561 short s = htons(len);
00562 memcpy(buffer, &s, 2);
00563 len += 2;
00564
00565 send(this->GetFD(), reinterpret_cast<char *>(buffer), len, 0);
00566 }
00567 catch (const SocketException &) { }
00568
00569 delete packet;
00570 packet = NULL;
00571 }
00572
00573 SocketEngine::Change(this, false, SF_WRITABLE);
00574 return true;
00575 }
00576
00577 Manager::TCPSocket::TCPSocket(const Anope::string &ip, int port) : Socket(-1, ip.find(':') != Anope::string::npos), ListenSocket(ip, port, ip.find(':') != Anope::string::npos)
00578 {
00579 }
00580
00581 ClientSocket *Manager::TCPSocket::OnAccept(int fd, const sockaddrs &addr)
00582 {
00583 return new Client(this, fd, addr);
00584 }
00585
00586 Manager::UDPSocket::UDPSocket(const Anope::string &ip, int port) : Socket(-1, ip.find(':') != Anope::string::npos, SOCK_DGRAM)
00587 {
00588 }
00589
00590 Manager::UDPSocket::~UDPSocket()
00591 {
00592 for (unsigned i = 0; i < packets.size(); ++i)
00593 delete packets[i];
00594 }
00595
00596 void Manager::UDPSocket::Reply(Packet *p)
00597 {
00598 packets.push_back(p);
00599 SocketEngine::Change(this, true, SF_WRITABLE);
00600 }
00601
00602 bool Manager::UDPSocket::ProcessRead()
00603 {
00604 Log(LOG_DEBUG_2) << "Resolver: Reading from DNS UDP socket";
00605
00606 unsigned char packet_buffer[524];
00607 sockaddrs from_server;
00608 socklen_t x = sizeof(from_server);
00609 int length = recvfrom(this->GetFD(), reinterpret_cast<char *>(&packet_buffer), sizeof(packet_buffer), 0, &from_server.sa, &x);
00610 return DNS::Engine->HandlePacket(this, packet_buffer, length, &from_server);
00611 }
00612
00613 bool Manager::UDPSocket::ProcessWrite()
00614 {
00615 Log(LOG_DEBUG_2) << "Resolver: Writing to DNS UDP socket";
00616
00617 Packet *r = !packets.empty() ? packets.front() : NULL;
00618 if (r != NULL)
00619 {
00620 try
00621 {
00622 unsigned char buffer[524];
00623 unsigned short len = r->Pack(buffer, sizeof(buffer));
00624
00625 sendto(this->GetFD(), reinterpret_cast<char *>(buffer), len, 0, &r->addr.sa, r->addr.size());
00626 }
00627 catch (const SocketException &) { }
00628
00629 delete r;
00630 packets.pop_front();
00631 }
00632
00633 if (packets.empty())
00634 SocketEngine::Change(this, false, SF_WRITABLE);
00635
00636 return true;
00637 }
00638
00639 Manager::Manager(const Anope::string &nameserver, const Anope::string &ip, int port) : Timer(300, Anope::CurTime, true), listen(false), serial(0), tcpsock(NULL), udpsock(NULL)
00640 {
00641 this->addrs.pton(nameserver.find(':') != Anope::string::npos ? AF_INET6 : AF_INET, nameserver, port);
00642
00643 try
00644 {
00645 udpsock = new UDPSocket(ip, port);
00646 }
00647 catch (const SocketException &ex)
00648 {
00649 Log() << "Unable to create socket for Manager: " << ex.GetReason();
00650 }
00651
00652 try
00653 {
00654 udpsock->Bind(ip, port);
00655 tcpsock = new TCPSocket(ip, port);
00656 listen = true;
00657 }
00658 catch (const SocketException &ex)
00659 {
00660
00661 Log(LOG_DEBUG) << "Unable to bind Manager to port " << port << ": " << ex.GetReason();
00662 }
00663
00664 this->UpdateSerial();
00665 }
00666
00667 Manager::~Manager()
00668 {
00669 delete udpsock;
00670 delete tcpsock;
00671
00672 for (std::map<unsigned short, Request *>::iterator it = this->requests.begin(), it_end = this->requests.end(); it != it_end; ++it)
00673 {
00674 Request *request = it->second;
00675
00676 Query rr(*request);
00677 rr.error = ERROR_UNKNOWN;
00678 request->OnError(&rr);
00679
00680 delete request;
00681 }
00682 this->requests.clear();
00683
00684 this->cache.clear();
00685
00686 DNS::Engine = NULL;
00687 }
00688
00689 bool Manager::HandlePacket(ReplySocket *s, const unsigned char *const packet_buffer, int length, sockaddrs *from)
00690 {
00691 if (length < Packet::HEADER_LENGTH)
00692 return true;
00693
00694 Packet recv_packet(from);
00695
00696 try
00697 {
00698 recv_packet.Fill(packet_buffer, length);
00699 }
00700 catch (const SocketException &ex)
00701 {
00702 Log(LOG_DEBUG_2) << ex.GetReason();
00703 return true;
00704 }
00705
00706 if (!(recv_packet.flags & QUERYFLAGS_QR))
00707 {
00708 if (!listen)
00709 return true;
00710 else if (recv_packet.questions.empty())
00711 {
00712 Log(LOG_DEBUG_2) << "Resolver: Received a question with no questions?";
00713 return true;
00714 }
00715
00716 Packet *packet = new Packet(recv_packet);
00717 packet->flags |= QUERYFLAGS_QR;
00718 packet->flags |= QUERYFLAGS_AA;
00719
00720 packet->answers.clear();
00721 packet->authorities.clear();
00722 packet->additional.clear();
00723
00724 for (unsigned i = 0; i < recv_packet.questions.size(); ++i)
00725 {
00726 const Question& q = recv_packet.questions[i];
00727
00728 if (q.type == QUERY_AXFR || q.type == QUERY_SOA)
00729 {
00730 ResourceRecord rr(q.name, QUERY_SOA);
00731 packet->answers.push_back(rr);
00732
00733 if (q.type == QUERY_AXFR)
00734 {
00735 Anope::string token;
00736 spacesepstream sep(Config->DNSSOANS);
00737 while (sep.GetToken(token))
00738 {
00739 ResourceRecord rr2(q.name, QUERY_NS);
00740 rr2.rdata = token;
00741 packet->answers.push_back(rr2);
00742 }
00743 }
00744 break;
00745 }
00746 }
00747
00748 FOREACH_MOD(I_OnDnsRequest, OnDnsRequest(recv_packet, packet));
00749
00750 for (unsigned i = 0; i < recv_packet.questions.size(); ++i)
00751 {
00752 const Question& q = recv_packet.questions[i];
00753
00754 if (q.type == QUERY_AXFR)
00755 {
00756 ResourceRecord rr(q.name, QUERY_SOA);
00757 packet->answers.push_back(rr);
00758 break;
00759 }
00760 }
00761
00762 s->Reply(packet);
00763 return true;
00764 }
00765
00766 if (from == NULL)
00767 {
00768 Log(LOG_DEBUG_2) << "Resolver: Received an answer over TCP. This is not supported.";
00769 return true;
00770 }
00771 else if (this->addrs != *from)
00772 {
00773 Log(LOG_DEBUG_2) << "Resolver: Received an answer from the wrong nameserver, Bad NAT or DNS forging attempt? '" << this->addrs.addr() << "' != '" << from->addr() << "'";
00774 return true;
00775 }
00776
00777 std::map<unsigned short, Request *>::iterator it = DNS::Engine->requests.find(recv_packet.id);
00778 if (it == DNS::Engine->requests.end())
00779 {
00780 Log(LOG_DEBUG_2) << "Resolver: Received an answer for something we didn't request";
00781 return true;
00782 }
00783 Request *request = it->second;
00784
00785 if (recv_packet.flags & QUERYFLAGS_OPCODE)
00786 {
00787 Log(LOG_DEBUG_2) << "Resolver: Received a nonstandard query";
00788 recv_packet.error = ERROR_NONSTANDARD_QUERY;
00789 request->OnError(&recv_packet);
00790 }
00791 else if (recv_packet.flags & QUERYFLAGS_RCODE)
00792 {
00793 Error error = ERROR_UNKNOWN;
00794
00795 switch (recv_packet.flags & QUERYFLAGS_RCODE)
00796 {
00797 case 1:
00798 Log(LOG_DEBUG_2) << "Resolver: format error";
00799 error = ERROR_FORMAT_ERROR;
00800 break;
00801 case 2:
00802 Log(LOG_DEBUG_2) << "Resolver: server error";
00803 error = ERROR_SERVER_FAILURE;
00804 break;
00805 case 3:
00806 Log(LOG_DEBUG_2) << "Resolver: domain not found";
00807 error = ERROR_DOMAIN_NOT_FOUND;
00808 break;
00809 case 4:
00810 Log(LOG_DEBUG_2) << "Resolver: not implemented";
00811 error = ERROR_NOT_IMPLEMENTED;
00812 break;
00813 case 5:
00814 Log(LOG_DEBUG_2) << "Resolver: refused";
00815 error = ERROR_REFUSED;
00816 break;
00817 default:
00818 break;
00819 }
00820
00821 recv_packet.error = error;
00822 request->OnError(&recv_packet);
00823 }
00824 else if (recv_packet.answers.empty())
00825 {
00826 Log(LOG_DEBUG_2) << "Resolver: No resource records returned";
00827 recv_packet.error = ERROR_NO_RECORDS;
00828 request->OnError(&recv_packet);
00829 }
00830 else
00831 {
00832 Log(LOG_DEBUG_2) << "Resolver: Lookup complete for " << request->name;
00833 request->OnLookupComplete(&recv_packet);
00834 DNS::Engine->AddCache(recv_packet);
00835 }
00836
00837 delete request;
00838 return true;
00839 }
00840
00841 void Manager::AddCache(Query &r)
00842 {
00843 for (unsigned i = 0; i < r.answers.size(); ++i)
00844 {
00845 ResourceRecord &rr = r.answers[i];
00846 Log(LOG_DEBUG_3) << "Resolver cache: added cache for " << rr.name << " -> " << rr.rdata << ", ttl: " << rr.ttl;
00847 this->cache.insert(std::make_pair(rr.name, rr));
00848 }
00849 }
00850
00851 bool Manager::CheckCache(Request *request)
00852 {
00853 cache_map::iterator it = this->cache.find(request->name);
00854 if (it != this->cache.end())
00855 {
00856 Query record(*request);
00857
00858 for (cache_map::iterator it_end = this->cache.upper_bound(request->name); it != it_end; ++it)
00859 {
00860 ResourceRecord &rec = it->second;
00861 if (rec.created + static_cast<time_t>(rec.ttl) >= Anope::CurTime)
00862 record.answers.push_back(rec);
00863 }
00864
00865 if (!record.answers.empty())
00866 {
00867 Log(LOG_DEBUG_3) << "Resolver: Using cached result for " << request->name;
00868 request->OnLookupComplete(&record);
00869 return true;
00870 }
00871 }
00872
00873 return false;
00874 }
00875
00876 void Manager::Tick(time_t now)
00877 {
00878 Log(LOG_DEBUG_2) << "Resolver: Purging DNS cache";
00879
00880 for (cache_map::iterator it = this->cache.begin(), it_next; it != this->cache.end(); it = it_next)
00881 {
00882 ResourceRecord &req = it->second;
00883 it_next = it;
00884 ++it_next;
00885
00886 if (req.created + static_cast<time_t>(req.ttl) < now)
00887 this->cache.erase(it);
00888 }
00889 }
00890
00891 void Manager::Cleanup(Module *mod)
00892 {
00893 for (std::map<unsigned short, Request *>::iterator it = this->requests.begin(), it_end = this->requests.end(); it != it_end;)
00894 {
00895 unsigned short id = it->first;
00896 Request *req = it->second;
00897 ++it;
00898
00899 if (req->creator && req->creator == mod)
00900 {
00901 Query rr(*req);
00902 rr.error = ERROR_UNLOADED;
00903 req->OnError(&rr);
00904
00905 delete req;
00906 this->requests.erase(id);
00907 }
00908 }
00909 }
00910
00911 void Manager::UpdateSerial()
00912 {
00913 serial = Anope::CurTime;
00914 }
00915
00916 uint32_t Manager::GetSerial() const
00917 {
00918 return serial;
00919 }
00920
00921 Query Manager::BlockingQuery(const Anope::string &mask, QueryType qt)
00922 {
00923 Question question(mask, qt);
00924 Query result(question);
00925
00926 int type = AF_UNSPEC;
00927 if (qt == QUERY_A)
00928 type = AF_INET;
00929 else if (qt == QUERY_AAAA)
00930 type = AF_INET6;
00931
00932 addrinfo hints;
00933 memset(&hints, 0, sizeof(hints));
00934 hints.ai_family = type;
00935
00936 Log(LOG_DEBUG_2) << "Resolver: BlockingQuery: Looking up " << mask;
00937
00938 addrinfo *addrresult;
00939 if (getaddrinfo(mask.c_str(), NULL, &hints, &addrresult) == 0)
00940 {
00941 for (addrinfo *cur = addrresult; cur; cur = cur->ai_next)
00942 {
00943 sockaddrs addr;
00944 memcpy(&addr, addrresult->ai_addr, addrresult->ai_addrlen);
00945 try
00946 {
00947 ResourceRecord rr(mask, qt);
00948 rr.rdata = addr.addr();
00949 result.answers.push_back(rr);
00950
00951 Log(LOG_DEBUG_2) << "Resolver: BlockingQuery: " << mask << " -> " << rr.rdata;
00952 }
00953 catch (const SocketException &) { }
00954 }
00955
00956 freeaddrinfo(addrresult);
00957 }
00958
00959 return result;
00960 }
00961
00962
00963