00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #ifndef WIN32
00027 #include <sys/types.h>
00028 #include <sys/socket.h>
00029 #include <errno.h>
00030 #include <netinet/in.h>
00031 #include <arpa/inet.h>
00032 #else
00033 #include "inspircd_win32wrapper.h"
00034 #include "inspircd_se_config.h"
00035 #endif
00036
00037 #include "dns.h"
00038 #include "inspircd.h"
00039 #include "socketengine.h"
00040 #include "configreader.h"
00041 #include "socket.h"
00042
00043 using irc::sockets::insp_inaddr;
00044 using irc::sockets::insp_ntoa;
00045 using irc::sockets::insp_aton;
00046 using irc::sockets::OpenTCPSocket;
00047
00050 enum QueryInfo
00051 {
00052 ERROR_MASK = 0x10000
00053 };
00054
00057 enum QueryFlags
00058 {
00059 FLAGS_MASK_RD = 0x01,
00060 FLAGS_MASK_TC = 0x02,
00061 FLAGS_MASK_AA = 0x04,
00062 FLAGS_MASK_OPCODE = 0x78,
00063 FLAGS_MASK_QR = 0x80,
00064 FLAGS_MASK_RCODE = 0x0F,
00065 FLAGS_MASK_Z = 0x70,
00066 FLAGS_MASK_RA = 0x80
00067 };
00068
00069
00072 struct ResourceRecord
00073 {
00074 QueryType type;
00075 unsigned int rr_class;
00076 unsigned long ttl;
00077 unsigned int rdlength;
00078 };
00079
00082 class DNSHeader
00083 {
00084 public:
00085 unsigned char id[2];
00086 unsigned int flags1;
00087 unsigned int flags2;
00088 unsigned int qdcount;
00089 unsigned int ancount;
00090 unsigned int nscount;
00091 unsigned int arcount;
00092 unsigned char payload[512];
00093 };
00094
00095 class DNSRequest
00096 {
00097 public:
00098 unsigned char id[2];
00099 unsigned char* res;
00100 unsigned int rr_class;
00101 QueryType type;
00102 DNS* dnsobj;
00103 unsigned long ttl;
00104 std::string orig;
00105 InspIRCd* ServerInstance;
00106
00107 DNSRequest(InspIRCd* Instance, DNS* dns, int id, const std::string &original);
00108 ~DNSRequest();
00109 DNSInfo ResultIsReady(DNSHeader &h, int length, int result_we_want);
00110 int SendRequests(const DNSHeader *header, const int length, QueryType qt);
00111 };
00112
00113 class CacheTimer : public Timer
00114 {
00115 private:
00116 InspIRCd* ServerInstance;
00117 DNS* dns;
00118 public:
00119 CacheTimer(InspIRCd* Instance, DNS* thisdns)
00120 : Timer(3600, Instance->Time(), true), ServerInstance(Instance), dns(thisdns) { }
00121
00122 virtual void Tick(time_t)
00123 {
00124 dns->PruneCache();
00125 }
00126 };
00127
00128 class RequestTimeout : public Timer
00129 {
00130 InspIRCd* ServerInstance;
00131 DNSRequest* watch;
00132 int watchid;
00133 public:
00134 RequestTimeout(unsigned long n, InspIRCd* SI, DNSRequest* watching, int id) : Timer(n, time(NULL)), ServerInstance(SI), watch(watching), watchid(id)
00135 {
00136 }
00137
00138 void Tick(time_t)
00139 {
00140 if (ServerInstance->Res->requests[watchid] == watch)
00141 {
00142
00143 if (ServerInstance->Res->Classes[watchid])
00144 {
00145 ServerInstance->Res->Classes[watchid]->OnError(RESOLVER_TIMEOUT, "Request timed out");
00146 delete ServerInstance->Res->Classes[watchid];
00147 ServerInstance->Res->Classes[watchid] = NULL;
00148 }
00149 ServerInstance->Res->requests[watchid] = NULL;
00150 delete watch;
00151 return;
00152 }
00153 }
00154 };
00155
00156
00157 DNSRequest::DNSRequest(InspIRCd* Instance, DNS* dns, int rid, const std::string &original) : dnsobj(dns), ServerInstance(Instance)
00158 {
00159 res = new unsigned char[512];
00160 *res = 0;
00161 orig = original;
00162 RequestTimeout* RT = new RequestTimeout(Instance->Config->dns_timeout ? Instance->Config->dns_timeout : 5, Instance, this, rid);
00163 Instance->Timers->AddTimer(RT);
00164 }
00165
00166
00167 DNSRequest::~DNSRequest()
00168 {
00169 delete[] res;
00170 }
00171
00173 inline void DNS::FillResourceRecord(ResourceRecord* rr, const unsigned char *input)
00174 {
00175 rr->type = (QueryType)((input[0] << 8) + input[1]);
00176 rr->rr_class = (input[2] << 8) + input[3];
00177 rr->ttl = (input[4] << 24) + (input[5] << 16) + (input[6] << 8) + input[7];
00178 rr->rdlength = (input[8] << 8) + input[9];
00179 }
00180
00182 inline void DNS::FillHeader(DNSHeader *header, const unsigned char *input, const int length)
00183 {
00184 header->id[0] = input[0];
00185 header->id[1] = input[1];
00186 header->flags1 = input[2];
00187 header->flags2 = input[3];
00188 header->qdcount = (input[4] << 8) + input[5];
00189 header->ancount = (input[6] << 8) + input[7];
00190 header->nscount = (input[8] << 8) + input[9];
00191 header->arcount = (input[10] << 8) + input[11];
00192 memcpy(header->payload,&input[12],length);
00193 }
00194
00196 inline void DNS::EmptyHeader(unsigned char *output, const DNSHeader *header, const int length)
00197 {
00198 output[0] = header->id[0];
00199 output[1] = header->id[1];
00200 output[2] = header->flags1;
00201 output[3] = header->flags2;
00202 output[4] = header->qdcount >> 8;
00203 output[5] = header->qdcount & 0xFF;
00204 output[6] = header->ancount >> 8;
00205 output[7] = header->ancount & 0xFF;
00206 output[8] = header->nscount >> 8;
00207 output[9] = header->nscount & 0xFF;
00208 output[10] = header->arcount >> 8;
00209 output[11] = header->arcount & 0xFF;
00210 memcpy(&output[12],header->payload,length);
00211 }
00212
00214 int DNSRequest::SendRequests(const DNSHeader *header, const int length, QueryType qt)
00215 {
00216 ServerInstance->Logs->Log("RESOLVER", DEBUG,"DNSRequest::SendRequests");
00217
00218 unsigned char payload[sizeof(DNSHeader)];
00219
00220 this->rr_class = 1;
00221 this->type = qt;
00222
00223 DNS::EmptyHeader(payload,header,length);
00224
00225 #ifdef IPV6
00226 if (this->dnsobj->socketfamily == AF_INET6)
00227 {
00228 sockaddr_in6 addr;
00229 memset(&addr,0,sizeof(addr));
00230 memcpy(&addr.sin6_addr,&dnsobj->myserver6,sizeof(addr.sin6_addr));
00231 addr.sin6_family = AF_INET6;
00232 addr.sin6_port = htons(DNS::QUERY_PORT);
00233 if (ServerInstance->SE->SendTo(dnsobj, payload, length + 12, 0, (sockaddr *) &addr, sizeof(addr)) != length+12)
00234 return -1;
00235 }
00236 else
00237 #endif
00238 {
00239 sockaddr_in addr;
00240 memset(&addr,0,sizeof(addr));
00241 memcpy(&addr.sin_addr.s_addr,&dnsobj->myserver4,sizeof(addr.sin_addr));
00242 addr.sin_family = AF_INET;
00243 addr.sin_port = htons(DNS::QUERY_PORT);
00244 if (ServerInstance->SE->SendTo(dnsobj, (const char*)payload, length + 12, 0, (sockaddr *) &addr, sizeof(addr)) != length+12)
00245 return -1;
00246 }
00247
00248 ServerInstance->Logs->Log("RESOLVER",DEBUG,"Sent OK");
00249 return 0;
00250 }
00251
00253 DNSRequest* DNS::AddQuery(DNSHeader *header, int &id, const char* original)
00254 {
00255
00256 if (this->GetFd() == -1)
00257 return NULL;
00258
00259
00260 id = this->PRNG() & DNS::MAX_REQUEST_ID;
00261
00262
00263 while (requests[id])
00264 id = this->PRNG() & DNS::MAX_REQUEST_ID;
00265
00266 DNSRequest* req = new DNSRequest(ServerInstance, this, id, original);
00267
00268 header->id[0] = req->id[0] = id >> 8;
00269 header->id[1] = req->id[1] = id & 0xFF;
00270 header->flags1 = FLAGS_MASK_RD;
00271 header->flags2 = 0;
00272 header->qdcount = 1;
00273 header->ancount = 0;
00274 header->nscount = 0;
00275 header->arcount = 0;
00276
00277
00278
00279
00280 requests[id] = req;
00281
00282
00283 return req;
00284 }
00285
00286 int DNS::ClearCache()
00287 {
00288
00289 int rv = this->cache->size();
00290 delete this->cache;
00291 this->cache = new dnscache();
00292 return rv;
00293 }
00294
00295 int DNS::PruneCache()
00296 {
00297 int n = 0;
00298 dnscache* newcache = new dnscache();
00299 for (dnscache::iterator i = this->cache->begin(); i != this->cache->end(); i++)
00300
00301 if (i->second.CalcTTLRemaining())
00302 newcache->insert(*i);
00303 else
00304 n++;
00305
00306 delete this->cache;
00307 this->cache = newcache;
00308 return n;
00309 }
00310
00311 void DNS::Rehash()
00312 {
00313 ip6munge = false;
00314 int portpass = 0;
00315
00316 if (this->GetFd() > -1)
00317 {
00318 if (ServerInstance && ServerInstance->SE)
00319 ServerInstance->SE->DelFd(this);
00320 ServerInstance->SE->Shutdown(this, 2);
00321 ServerInstance->SE->Close(this);
00322 this->SetFd(-1);
00323
00324
00325 this->PruneCache();
00326 }
00327 else
00328 {
00329
00330 this->cache = new dnscache();
00331 }
00332
00333 if ((strstr(ServerInstance->Config->DNSServer,"::ffff:") == (char*)&ServerInstance->Config->DNSServer) || (strstr(ServerInstance->Config->DNSServer,"::FFFF:") == (char*)&ServerInstance->Config->DNSServer))
00334 {
00335 ServerInstance->Logs->Log("RESOLVER",DEFAULT,"WARNING: Using IPv4 addresses over IPv6 forces some DNS checks to be disabled.");
00336 ServerInstance->Logs->Log("RESOLVER",DEFAULT," This should not cause a problem, however it is recommended you migrate");
00337 ServerInstance->Logs->Log("RESOLVER",DEFAULT," to a true IPv6 environment.");
00338 this->ip6munge = true;
00339 }
00340
00341 this->socketfamily = AF_INET;
00342 #ifdef IPV6
00343 if (strchr(ServerInstance->Config->DNSServer,':'))
00344 {
00345 this->socketfamily = AF_INET6;
00346 inet_pton(AF_INET6, ServerInstance->Config->DNSServer, &this->myserver6);
00347 }
00348 else
00349 {
00350 inet_aton(ServerInstance->Config->DNSServer, &this->myserver4);
00351 portpass = -1;
00352 }
00353 #else
00354 inet_aton(ServerInstance->Config->DNSServer, &this->myserver4);
00355 #endif
00356
00357
00358 int s = OpenTCPSocket(ServerInstance->Config->DNSServer, SOCK_DGRAM);
00359 this->SetFd(s);
00360 ServerInstance->SE->NonBlocking(this->GetFd());
00361
00362
00363 if (this->GetFd() != -1)
00364 {
00365
00366 if (!ServerInstance->BindSocket(this->GetFd(), portpass, "", false))
00367 {
00368
00369 ServerInstance->Logs->Log("RESOLVER",DEBUG,"Error binding dns socket");
00370 ServerInstance->SE->Shutdown(this, 2);
00371 ServerInstance->SE->Close(this);
00372 this->SetFd(-1);
00373 }
00374
00375 if (this->GetFd() >= 0)
00376 {
00377
00378 if (ServerInstance && ServerInstance->SE)
00379 {
00380 if (!ServerInstance->SE->AddFd(this))
00381 {
00382 ServerInstance->Logs->Log("RESOLVER",DEFAULT,"Internal error starting DNS - hostnames will NOT resolve.");
00383 ServerInstance->SE->Shutdown(this, 2);
00384 ServerInstance->SE->Close(this);
00385 this->SetFd(-1);
00386 }
00387 }
00388 }
00389 }
00390 else
00391 {
00392 ServerInstance->Logs->Log("RESOLVER",DEBUG,"Error creating dns socket");
00393 }
00394 }
00395
00397 DNS::DNS(InspIRCd* Instance) : ServerInstance(Instance)
00398 {
00399 ServerInstance->Logs->Log("RESOLVER",DEBUG,"DNS::DNS");
00400
00401 memset(Classes,0,sizeof(Classes));
00402
00403
00404 memset(requests,0,sizeof(requests));
00405
00406
00407
00408 currid = 0;
00409
00410
00411
00412 this->cache = NULL;
00413
00414
00415
00416
00417 this->SetFd(-1);
00418
00419
00420
00421 this->Rehash();
00422
00423 this->PruneTimer = new CacheTimer(ServerInstance, this);
00424
00425 ServerInstance->Timers->AddTimer(this->PruneTimer);
00426 }
00427
00429 int DNS::MakePayload(const char * const name, const QueryType rr, const unsigned short rr_class, unsigned char * const payload)
00430 {
00431 short payloadpos = 0;
00432 const char* tempchr, *tempchr2 = name;
00433 unsigned short length;
00434
00435
00436 while ((tempchr = strchr(tempchr2,'.')) != NULL)
00437 {
00438 length = tempchr - tempchr2;
00439 if (payloadpos + length + 1 > 507)
00440 return -1;
00441 payload[payloadpos++] = length;
00442 memcpy(&payload[payloadpos],tempchr2,length);
00443 payloadpos += length;
00444 tempchr2 = &tempchr[1];
00445 }
00446 length = strlen(tempchr2);
00447 if (length)
00448 {
00449 if (payloadpos + length + 2 > 507)
00450 return -1;
00451 payload[payloadpos++] = length;
00452 memcpy(&payload[payloadpos],tempchr2,length);
00453 payloadpos += length;
00454 payload[payloadpos++] = 0;
00455 }
00456 if (payloadpos > 508)
00457 return -1;
00458 length = htons(rr);
00459 memcpy(&payload[payloadpos],&length,2);
00460 length = htons(rr_class);
00461 memcpy(&payload[payloadpos + 2],&length,2);
00462 return payloadpos + 4;
00463 }
00464
00466 int DNS::GetIP(const char *name)
00467 {
00468 DNSHeader h;
00469 int id;
00470 int length;
00471
00472 if ((length = this->MakePayload(name, DNS_QUERY_A, 1, (unsigned char*)&h.payload)) == -1)
00473 return -1;
00474
00475 DNSRequest* req = this->AddQuery(&h, id, name);
00476
00477 if ((!req) || (req->SendRequests(&h, length, DNS_QUERY_A) == -1))
00478 return -1;
00479
00480 return id;
00481 }
00482
00484 int DNS::GetIP6(const char *name)
00485 {
00486 DNSHeader h;
00487 int id;
00488 int length;
00489
00490 if ((length = this->MakePayload(name, DNS_QUERY_AAAA, 1, (unsigned char*)&h.payload)) == -1)
00491 return -1;
00492
00493 DNSRequest* req = this->AddQuery(&h, id, name);
00494
00495 if ((!req) || (req->SendRequests(&h, length, DNS_QUERY_AAAA) == -1))
00496 return -1;
00497
00498 return id;
00499 }
00500
00502 int DNS::GetCName(const char *alias)
00503 {
00504 DNSHeader h;
00505 int id;
00506 int length;
00507
00508 if ((length = this->MakePayload(alias, DNS_QUERY_CNAME, 1, (unsigned char*)&h.payload)) == -1)
00509 return -1;
00510
00511 DNSRequest* req = this->AddQuery(&h, id, alias);
00512
00513 if ((!req) || (req->SendRequests(&h, length, DNS_QUERY_CNAME) == -1))
00514 return -1;
00515
00516 return id;
00517 }
00518
00520 int DNS::GetName(const insp_inaddr *ip)
00521 {
00522 char query[128];
00523 DNSHeader h;
00524 int id;
00525 int length;
00526
00527 #ifdef IPV6
00528 unsigned char* c = (unsigned char*)&ip->s6_addr;
00529 if (c[0] == 0 && c[1] == 0 && c[2] == 0 && c[3] == 0 &&
00530 c[4] == 0 && c[5] == 0 && c[6] == 0 && c[7] == 0 &&
00531 c[8] == 0 && c[9] == 0 && c[10] == 0xFF && c[11] == 0xFF)
00532 sprintf(query,"%d.%d.%d.%d.in-addr.arpa",c[15],c[14],c[13],c[12]);
00533 else
00534 DNS::MakeIP6Int(query, (in6_addr*)ip);
00535 #else
00536 unsigned char* c = (unsigned char*)&ip->s_addr;
00537 sprintf(query,"%d.%d.%d.%d.in-addr.arpa",c[3],c[2],c[1],c[0]);
00538 #endif
00539
00540 if ((length = this->MakePayload(query, DNS_QUERY_PTR, 1, (unsigned char*)&h.payload)) == -1)
00541 return -1;
00542
00543 DNSRequest* req = this->AddQuery(&h, id, insp_ntoa(*ip));
00544
00545 if ((!req) || (req->SendRequests(&h, length, DNS_QUERY_PTR) == -1))
00546 return -1;
00547
00548 return id;
00549 }
00550
00552 int DNS::GetNameForce(const char *ip, ForceProtocol fp)
00553 {
00554 char query[128];
00555 DNSHeader h;
00556 int id;
00557 int length;
00558 #ifdef SUPPORT_IP6LINKS
00559 if (fp == PROTOCOL_IPV6)
00560 {
00561 in6_addr i;
00562 if (inet_pton(AF_INET6, ip, &i) > 0)
00563 {
00564 DNS::MakeIP6Int(query, &i);
00565 }
00566 else
00567
00568 return -1;
00569 }
00570 else
00571 #endif
00572 {
00573 in_addr i;
00574 if (inet_aton(ip, &i))
00575 {
00576 unsigned char* c = (unsigned char*)&i.s_addr;
00577 sprintf(query,"%d.%d.%d.%d.in-addr.arpa",c[3],c[2],c[1],c[0]);
00578 }
00579 else
00580
00581 return -1;
00582 }
00583
00584 if ((length = this->MakePayload(query, DNS_QUERY_PTR, 1, (unsigned char*)&h.payload)) == -1)
00585 return -1;
00586
00587 DNSRequest* req = this->AddQuery(&h, id, ip);
00588
00589 if ((!req) || (req->SendRequests(&h, length, DNS_QUERY_PTR) == -1))
00590 return -1;
00591
00592 return id;
00593 }
00594
00597 void DNS::MakeIP6Int(char* query, const in6_addr *ip)
00598 {
00599 #ifdef SUPPORT_IP6LINKS
00600 const char* hex = "0123456789abcdef";
00601 for (int index = 31; index >= 0; index--)
00602 {
00603 if (index % 2)
00604
00605 *query++ = hex[ip->s6_addr[index / 2] & 0x0F];
00606 else
00607
00608 *query++ = hex[(ip->s6_addr[index / 2] & 0xF0) >> 4];
00609 *query++ = '.';
00610 }
00611 strcpy(query,"ip6.arpa");
00612 #else
00613 *query = 0;
00614 #endif
00615 }
00616
00618 DNSResult DNS::GetResult(int resultnum)
00619 {
00620
00621 DNSHeader header;
00622 DNSRequest *req;
00623 unsigned char buffer[sizeof(DNSHeader)];
00624 sockaddr* from = new sockaddr[2];
00625 #ifdef IPV6
00626 socklen_t x = this->socketfamily == AF_INET ? sizeof(sockaddr_in) : sizeof(sockaddr_in6);
00627 #else
00628 socklen_t x = sizeof(sockaddr_in);
00629 #endif
00630 const char* ipaddr_from;
00631 unsigned short int port_from = 0;
00632
00633 int length = ServerInstance->SE->RecvFrom(this, (char*)buffer, sizeof(DNSHeader), 0, from, &x);
00634
00635
00636 if (length < 12)
00637 {
00638
00639 delete[] from;
00640 return DNSResult(-1,"",0,"");
00641 }
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652 #ifdef IPV6
00653 char nbuf[MAXBUF];
00654 if (this->socketfamily == AF_INET6)
00655 {
00656 ipaddr_from = inet_ntop(AF_INET6, &((sockaddr_in6*)from)->sin6_addr, nbuf, sizeof(nbuf));
00657 port_from = ntohs(((sockaddr_in6*)from)->sin6_port);
00658 }
00659 else
00660 #endif
00661 {
00662 ipaddr_from = inet_ntoa(((sockaddr_in*)from)->sin_addr);
00663 port_from = ntohs(((sockaddr_in*)from)->sin_port);
00664 }
00665
00666 delete[] from;
00667
00668
00669
00670
00671 if (!ip6munge)
00672 {
00673 if ((port_from != DNS::QUERY_PORT) || (strcasecmp(ipaddr_from, ServerInstance->Config->DNSServer)))
00674 {
00675 return DNSResult(-1,"",0,"");
00676 }
00677 }
00678
00679
00680 DNS::FillHeader(&header,buffer,length - 12);
00681
00682
00683
00684
00685
00686 unsigned long this_id = header.id[1] + (header.id[0] << 8);
00687
00688
00689 if (!requests[this_id])
00690 {
00691
00692 return DNSResult(-1,"",0,"");
00693 }
00694 else
00695 {
00696
00697 req = requests[this_id];
00698 requests[this_id] = NULL;
00699 }
00700
00701
00702
00703
00704
00705 DNSInfo data = req->ResultIsReady(header, length, resultnum);
00706 std::string resultstr;
00707
00708
00709 if (data.first == NULL)
00710 {
00711
00712
00713
00714
00715
00716
00717 std::string ro = req->orig;
00718 delete req;
00719 return DNSResult(this_id | ERROR_MASK, data.second, 0, ro);
00720 }
00721 else
00722 {
00723 unsigned long ttl = req->ttl;
00724 char formatted[128];
00725
00726
00727 switch (req->type)
00728 {
00729 case DNS_QUERY_A:
00730 snprintf(formatted,16,"%u.%u.%u.%u",data.first[0],data.first[1],data.first[2],data.first[3]);
00731 resultstr = formatted;
00732 break;
00733
00734 case DNS_QUERY_AAAA:
00735 {
00736 inet_ntop(AF_INET6, data.first, formatted, sizeof(formatted));
00737 char* c = strstr(formatted,":0:");
00738 if (c != NULL)
00739 {
00740 memmove(c+1,c+2,strlen(c+2) + 1);
00741 c += 2;
00742 while (memcmp(c,"0:",2) == 0)
00743 memmove(c,c+2,strlen(c+2) + 1);
00744 if (memcmp(c,"0",2) == 0)
00745 *c = 0;
00746 if (memcmp(formatted,"0::",3) == 0)
00747 memmove(formatted,formatted + 1, strlen(formatted + 1) + 1);
00748 }
00749 resultstr = formatted;
00750
00751
00752
00753
00754
00755
00756 if (*formatted == ':')
00757 resultstr.insert(0, "0");
00758 }
00759 break;
00760
00761 case DNS_QUERY_CNAME:
00762
00763
00764 case DNS_QUERY_PTR:
00765
00766 resultstr = std::string((const char*)data.first);
00767 break;
00768
00769 default:
00770 break;
00771
00772 }
00773
00774
00775 std::string ro = req->orig;
00776 delete req;
00777 return DNSResult(this_id,resultstr,ttl,ro);
00778 }
00779 }
00780
00782 DNSInfo DNSRequest::ResultIsReady(DNSHeader &header, int length, int result_we_want)
00783 {
00784 int i = 0;
00785 int q = 0;
00786 int curanswer, o;
00787 ResourceRecord rr;
00788 unsigned short ptr;
00789
00790
00791 rr.type = DNS_QUERY_NONE;
00792 rr.rdlength = 0;
00793 rr.ttl = 1;
00794 rr.rr_class = 0;
00795
00796 if (!(header.flags1 & FLAGS_MASK_QR))
00797 return std::make_pair((unsigned char*)NULL,"Not a query result");
00798
00799 if (header.flags1 & FLAGS_MASK_OPCODE)
00800 return std::make_pair((unsigned char*)NULL,"Unexpected value in DNS reply packet");
00801
00802 if (header.flags2 & FLAGS_MASK_RCODE)
00803 return std::make_pair((unsigned char*)NULL,"Domain name not found");
00804
00805 if (header.ancount < 1)
00806 return std::make_pair((unsigned char*)NULL,"No resource records returned");
00807
00808
00809 length -= 12;
00810
00811 while ((unsigned int)q < header.qdcount && i < length)
00812 {
00813 if (header.payload[i] > 63)
00814 {
00815 i += 6;
00816 q++;
00817 }
00818 else
00819 {
00820 if (header.payload[i] == 0)
00821 {
00822 q++;
00823 i += 5;
00824 }
00825 else i += header.payload[i] + 1;
00826 }
00827 }
00828 curanswer = 0;
00829 while ((unsigned)curanswer < header.ancount)
00830 {
00831 q = 0;
00832 while (q == 0 && i < length)
00833 {
00834 if (header.payload[i] > 63)
00835 {
00836 i += 2;
00837 q = 1;
00838 }
00839 else
00840 {
00841 if (header.payload[i] == 0)
00842 {
00843 i++;
00844 q = 1;
00845 }
00846 else i += header.payload[i] + 1;
00847 }
00848 }
00849 if (length - i < 10)
00850 return std::make_pair((unsigned char*)NULL,"Incorrectly sized DNS reply");
00851
00852
00853 if (curanswer == result_we_want)
00854 DNS::FillResourceRecord(&rr,&header.payload[i]);
00855
00856 i += 10;
00857 if (rr.type != this->type)
00858 {
00859 curanswer++;
00860 i += rr.rdlength;
00861 continue;
00862 }
00863 if (rr.rr_class != this->rr_class)
00864 {
00865 curanswer++;
00866 i += rr.rdlength;
00867 continue;
00868 }
00869 break;
00870 }
00871 if ((unsigned int)curanswer == header.ancount)
00872 return std::make_pair((unsigned char*)NULL,"No more answers (" + ConvToStr(header.ancount) + " answers, wanted #" + ConvToStr(result_we_want) + ")");
00873
00874 if (i + rr.rdlength > (unsigned int)length)
00875 return std::make_pair((unsigned char*)NULL,"Resource record larger than stated");
00876
00877 if (rr.rdlength > 1023)
00878 return std::make_pair((unsigned char*)NULL,"Resource record too large");
00879
00880 this->ttl = rr.ttl;
00881
00882 switch (rr.type)
00883 {
00884 case DNS_QUERY_CNAME:
00885
00886 case DNS_QUERY_PTR:
00887 o = 0;
00888 q = 0;
00889 while (q == 0 && i < length && o + 256 < 1023)
00890 {
00891 if (header.payload[i] > 63)
00892 {
00893 memcpy(&ptr,&header.payload[i],2);
00894 i = ntohs(ptr) - 0xC000 - 12;
00895 }
00896 else
00897 {
00898 if (header.payload[i] == 0)
00899 {
00900 q = 1;
00901 }
00902 else
00903 {
00904 res[o] = 0;
00905 if (o != 0)
00906 res[o++] = '.';
00907 memcpy(&res[o],&header.payload[i + 1],header.payload[i]);
00908 o += header.payload[i];
00909 i += header.payload[i] + 1;
00910 }
00911 }
00912 }
00913 res[o] = 0;
00914 break;
00915 case DNS_QUERY_AAAA:
00916 memcpy(res,&header.payload[i],rr.rdlength);
00917 res[rr.rdlength] = 0;
00918 break;
00919 case DNS_QUERY_A:
00920 memcpy(res,&header.payload[i],rr.rdlength);
00921 res[rr.rdlength] = 0;
00922 break;
00923 default:
00924 memcpy(res,&header.payload[i],rr.rdlength);
00925 res[rr.rdlength] = 0;
00926 break;
00927 }
00928 return std::make_pair(res,"No error");
00929 }
00930
00932 DNS::~DNS()
00933 {
00934 ServerInstance->SE->Shutdown(this, 2);
00935 ServerInstance->SE->Close(this);
00936 ServerInstance->Timers->DelTimer(this->PruneTimer);
00937 }
00938
00939 CachedQuery* DNS::GetCache(const std::string &source)
00940 {
00941 dnscache::iterator x = cache->find(source.c_str());
00942 if (x != cache->end())
00943 return &(x->second);
00944 else
00945 return NULL;
00946 }
00947
00948 void DNS::DelCache(const std::string &source)
00949 {
00950 cache->erase(source.c_str());
00951 }
00952
00953 void Resolver::TriggerCachedResult()
00954 {
00955 if (CQ)
00956 OnLookupComplete(CQ->data, time_left, true, 0);
00957 }
00958
00960 Resolver::Resolver(InspIRCd* Instance, const std::string &source, QueryType qt, bool &cached, Module* creator) : ServerInstance(Instance), Creator(creator), input(source), querytype(qt)
00961 {
00962 ServerInstance->Logs->Log("RESOLVER",DEBUG,"Resolver::Resolver");
00963 cached = false;
00964
00965 CQ = ServerInstance->Res->GetCache(source);
00966 if (CQ)
00967 {
00968 time_left = CQ->CalcTTLRemaining();
00969 if (!time_left)
00970 {
00971 ServerInstance->Res->DelCache(source);
00972 }
00973 else
00974 {
00975 cached = true;
00976 return;
00977 }
00978 }
00979
00980 insp_inaddr binip;
00981
00982 switch (querytype)
00983 {
00984 case DNS_QUERY_A:
00985 this->myid = ServerInstance->Res->GetIP(source.c_str());
00986 break;
00987
00988 case DNS_QUERY_PTR:
00989 if (insp_aton(source.c_str(), &binip) > 0)
00990 {
00991
00992 this->myid = ServerInstance->Res->GetName(&binip);
00993 }
00994 else
00995 {
00996 this->OnError(RESOLVER_BADIP, "Bad IP address for reverse lookup");
00997 throw ModuleException("Resolver: Bad IP address");
00998 return;
00999 }
01000 break;
01001
01002 case DNS_QUERY_PTR4:
01003 querytype = DNS_QUERY_PTR;
01004 this->myid = ServerInstance->Res->