]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - src/dns.cpp
Make irc::spacify take 'const char*' instead of 'char*'
[user/henk/code/inspircd.git] / src / dns.cpp
index e5c1388f6ecb662c9cbcf82e2ad5347d555deffb..54032bf2ef206e6823c32f47450c1bde708b6ef2 100644 (file)
@@ -2,14 +2,11 @@
  *       | Inspire Internet Relay Chat Daemon |
  *       +------------------------------------+
  *
- *  InspIRCd is copyright (C) 2002-2006 ChatSpike-Dev.
- *                    E-mail:
- *             <brain@chatspike.net>
- *             <Craig@chatspike.net>
- *     
- * Written by Craig Edwards, Craig McLure, and others.
+ *  InspIRCd: (C) 2002-2007 InspIRCd Development Team
+ * See: http://www.inspircd.org/wiki/index.php/Credits
+ *
  * This program is free but copyrighted software; see
- *         the file COPYING for details.
+ *            the file COPYING for details.
  *
  * ---------------------------------------------------
  */
@@ -24,8 +21,6 @@ Please do not assume that firedns works like this,
 looks like this, walks like this or tastes like this.
 */
 
-using namespace std;
-
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <errno.h>
@@ -37,7 +32,6 @@ using namespace std;
 #include "configreader.h"
 #include "socket.h"
 
-using namespace std;
 using irc::sockets::insp_sockaddr;
 using irc::sockets::insp_inaddr;
 using irc::sockets::insp_ntoa;
@@ -91,39 +85,72 @@ class DNSHeader
        unsigned char   payload[512];   /* Packet payload */
 };
 
-/** Represents a request 'on the wire' with routing information relating to
- * where to call when we get a result
- */
 class DNSRequest
 {
  public:
        unsigned char   id[2];          /* Request id */
-       unsigned char*  res;            /* Result processing buffer */
-       unsigned int    rr_class;       /* Request class */
+       unsigned char*  res;            /* Result processing buffer */
+       unsigned int    rr_class;       /* Request class */
        QueryType       type;           /* Request type */
-       insp_inaddr     myserver;       /* DNS server address*/
-       DNS*            dnsobj;         /* DNS caller (where we get our FD from) */
+       insp_inaddr     myserver;       /* DNS server address*/
+       DNS*            dnsobj;         /* DNS caller (where we get our FD from) */
+
+       DNSRequest(InspIRCd* Instance, DNS* dns, insp_inaddr server, int id, requestlist &requests);
+       ~DNSRequest();
+       DNSInfo ResultIsReady(DNSHeader &h, int length);
+       int SendRequests(const DNSHeader *header, const int length, QueryType qt);
+};
 
-       /* Allocate the processing buffer */
-       DNSRequest(DNS* dns, insp_inaddr server) : dnsobj(dns)
+class RequestTimeout : public InspTimer
+{
+       InspIRCd* ServerInstance;
+       DNSRequest* watch;
+       int watchid;
+       requestlist &rl;
+ public:
+       RequestTimeout(unsigned long n, InspIRCd* SI, DNSRequest* watching, int id, requestlist &requests) : InspTimer(n, time(NULL)), ServerInstance(SI), watch(watching), watchid(id), rl(requests)
        {
-               res = new unsigned char[512];
-               *res = 0;
-               memcpy(&myserver, &server, sizeof(insp_inaddr));
+               ServerInstance->Log(DEBUG, "New DNS timeout set on %08x", watching);
        }
 
-       /* Deallocate the processing buffer */
-       ~DNSRequest()
+       void Tick(time_t TIME)
        {
-               delete[] res;
+               if (rl.find(watchid) != rl.end())
+               {
+                       /* Still exists, whack it */
+                       if (rl.find(watchid)->second == watch)
+                       {
+                               if (ServerInstance->Res->Classes[watchid])
+                               {
+                                       ServerInstance->Res->Classes[watchid]->OnError(RESOLVER_TIMEOUT, "Request timed out");
+                                       delete ServerInstance->Res->Classes[watchid];
+                                       ServerInstance->Res->Classes[watchid] = NULL;
+                               }
+                               rl.erase(rl.find(watchid));
+                               delete watch;
+                               ServerInstance->Log(DEBUG, "DNS timeout on %08x squished pointer", watch);
+                       }
+                       return;
+               }
+               ServerInstance->Log(DEBUG, "DNS timeout on %08x: result already received!", watch);
        }
+};
 
-       /* Called when a result is ready to be processed which matches this id */
-       DNSInfo ResultIsReady(DNSHeader &h, int length);
+/* Allocate the processing buffer */
+DNSRequest::DNSRequest(InspIRCd* Instance, DNS* dns, insp_inaddr server, int id, requestlist &requests) : dnsobj(dns)
+{
+       res = new unsigned char[512];
+       *res = 0;
+       memcpy(&myserver, &server, sizeof(insp_inaddr));
+       RequestTimeout* RT = new RequestTimeout(Instance->Config->dns_timeout ? Instance->Config->dns_timeout : 5, Instance, this, id, requests);
+       Instance->Timers->AddTimer(RT); /* The timer manager frees this */
+}
 
-       /* Called when there are requests to be sent out */
-       int SendRequests(const DNSHeader *header, const int length, QueryType qt);
-};
+/* Deallocate the processing buffer */
+DNSRequest::~DNSRequest()
+{
+       delete[] res;
+}
 
 /** Fill a ResourceRecord class based on raw data input */
 inline void DNS::FillResourceRecord(ResourceRecord* rr, const unsigned char *input)
@@ -211,7 +238,7 @@ DNSRequest* DNS::AddQuery(DNSHeader *header, int &id)
        while (requests.find(id) != requests.end())
                id = this->PRNG() & DNS::MAX_REQUEST_ID;
 
-       DNSRequest* req = new DNSRequest(this, this->myserver);
+       DNSRequest* req = new DNSRequest(ServerInstance, this, this->myserver, id, requests);
 
        header->id[0] = req->id[0] = id >> 8;
        header->id[1] = req->id[1] = id & 0xFF;
@@ -435,10 +462,15 @@ int DNS::GetName(const insp_inaddr *ip)
        int length;
 
 #ifdef IPV6
-       DNS::MakeIP6Int(query, (in6_addr*)ip);
+       unsigned char* c = (unsigned char*)&ip->s6_addr;
+       if (c[0] == 0 && c[1] == 0 && c[2] == 0 && c[3] == 0 &&
+           c[4] == 0 && c[5] == 0 && c[6] == 0 && c[7] == 0 &&
+           c[8] == 0 && c[9] == 0 && c[10] == 0xFF && c[11] == 0xFF)
+               sprintf(query,"%d.%d.%d.%d.in-addr.arpa",c[15],c[14],c[13],c[12]);
+       else
+               DNS::MakeIP6Int(query, (in6_addr*)ip);
 #else
        unsigned char* c = (unsigned char*)&ip->s_addr;
-
        sprintf(query,"%d.%d.%d.%d.in-addr.arpa",c[3],c[2],c[1],c[0]);
 #endif
 
@@ -693,7 +725,11 @@ DNSInfo DNSRequest::ResultIsReady(DNSHeader &header, int length)
        int curanswer, o;
        ResourceRecord rr;
        unsigned short ptr;
-                       
+
+       /* This is just to keep _FORTIFY_SOURCE happy */
+       rr.type = DNS_QUERY_NONE;
+       rr.rdlength = 0;
+
        if (!(header.flags1 & FLAGS_MASK_QR))
                return std::make_pair((unsigned char*)NULL,"Not a query result");
 
@@ -832,7 +868,7 @@ DNS::~DNS()
 }
 
 /** High level abstraction of dns used by application at large */
-Resolver::Resolver(InspIRCd* Instance, const std::string &source, QueryType qt) : ServerInstance(Instance), input(source), querytype(qt)
+Resolver::Resolver(InspIRCd* Instance, const std::string &source, QueryType qt, Module* creator) : ServerInstance(Instance), Creator(creator), input(source), querytype(qt)
 {
        ServerInstance->Log(DEBUG,"Instance: %08x %08x",Instance, ServerInstance);
 
@@ -910,8 +946,13 @@ int Resolver::GetId()
        return this->myid;
 }
 
+Module* Resolver::GetCreator()
+{
+       return this->Creator;
+}
+
 /** Process a socket read event */
-void DNS::HandleEvent(EventType et)
+void DNS::HandleEvent(EventType et, int errornum)
 {
        ServerInstance->Log(DEBUG,"Marshall reads: %d",this->GetFd());
        /* Fetch the id and result of the next available packet */
@@ -987,6 +1028,22 @@ bool DNS::AddResolverClass(Resolver* r)
        }
 }
 
+void DNS::CleanResolvers(Module* module)
+{
+       for (int i = 0; i < MAX_REQUEST_ID; i++)
+       {
+               if (Classes[i])
+               {
+                       if (Classes[i]->GetCreator() == module)
+                       {
+                               Classes[i]->OnError(RESLOVER_FORCEUNLOAD, "Parent module is unloading");
+                               delete Classes[i];
+                               Classes[i] = NULL;
+                       }
+               }
+       }
+}
+
 /** Generate pseudo-random number */
 unsigned long DNS::PRNG()
 {