]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - src/dns.cpp
Removed a pointless check in ./configure --clean that made it only work with one...
[user/henk/code/inspircd.git] / src / dns.cpp
index ca08b93ba8063e0a902ab72f86a44bb208722b6a..756c2d5dc12c6cfdc442f1fd585e8881d7171d38 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;
@@ -94,14 +88,14 @@ class DNSHeader
 class DNSRequest
 {
  public:
-       unsigned char   id[2];          /* Request id */
-       unsigned char*  res;            /* Result processing buffer */
+       unsigned char   id[2];          /* Request id */
+       unsigned char*  res;            /* Result processing buffer */
        unsigned int    rr_class;       /* Request class */
-       QueryType       type;           /* Request type */
+       QueryType       type;           /* Request type */
        insp_inaddr     myserver;       /* DNS server address*/
-       DNS*            dnsobj;         /* DNS caller (where we get our FD from) */
+       DNS*            dnsobj;         /* DNS caller (where we get our FD from) */
 
-       DNSRequest(InspIRCd* Instance, DNS* dns, insp_inaddr server, int id, requestlist &requests);
+       DNSRequest(InspIRCd* Instance, DNS* dns, insp_inaddr server, int id);
        ~DNSRequest();
        DNSInfo ResultIsReady(DNSHeader &h, int length);
        int SendRequests(const DNSHeader *header, const int length, QueryType qt);
@@ -112,25 +106,26 @@ class RequestTimeout : public InspTimer
        InspIRCd* ServerInstance;
        DNSRequest* watch;
        int watchid;
-       requestlist &rl;
  public:
-       RequestTimeout(InspIRCd* SI, DNSRequest* watching, int id, requestlist &requests) : InspTimer(2, time(NULL)), ServerInstance(SI), watch(watching), watchid(id), rl(requests)
+       RequestTimeout(unsigned long n, InspIRCd* SI, DNSRequest* watching, int id) : InspTimer(n, time(NULL)), ServerInstance(SI), watch(watching), watchid(id)
        {
                ServerInstance->Log(DEBUG, "New DNS timeout set on %08x", watching);
        }
 
        void Tick(time_t TIME)
        {
-               if (rl.find(watchid) != rl.end())
+               if (ServerInstance->Res->requests[watchid] == watch)
                {
                        /* Still exists, whack it */
-                       if (rl.find(watchid)->second == watch)
+                       if (ServerInstance->Res->Classes[watchid])
                        {
-                               watch->OnError(RESOLVER_TIMEOUT, "Request timed out");
-                               rl.erase(rl.find(watchid));
-                               delete watch;
-                               ServerInstance->Log(DEBUG, "DNS timeout on %08x squished pointer", watch);
+                               ServerInstance->Res->Classes[watchid]->OnError(RESOLVER_TIMEOUT, "Request timed out");
+                               delete ServerInstance->Res->Classes[watchid];
+                               ServerInstance->Res->Classes[watchid] = NULL;
                        }
+                       ServerInstance->Res->requests[watchid] = NULL;
+                       delete watch;
+                       ServerInstance->Log(DEBUG, "DNS timeout on %08x squished pointer", watch);
                        return;
                }
                ServerInstance->Log(DEBUG, "DNS timeout on %08x: result already received!", watch);
@@ -138,12 +133,12 @@ class RequestTimeout : public InspTimer
 };
 
 /* Allocate the processing buffer */
-DNSRequest::DNSRequest(InspIRCd* Instance, DNS* dns, insp_inaddr server, int id, requestlist &requests) : dnsobj(dns)
+DNSRequest::DNSRequest(InspIRCd* Instance, DNS* dns, insp_inaddr server, int id) : dnsobj(dns)
 {
        res = new unsigned char[512];
        *res = 0;
        memcpy(&myserver, &server, sizeof(insp_inaddr));
-       RequestTimeout* RT = new RequestTimeout(Instance, this, id, requests);
+       RequestTimeout* RT = new RequestTimeout(Instance->Config->dns_timeout ? Instance->Config->dns_timeout : 5, Instance, this, id);
        Instance->Timers->AddTimer(RT); /* The timer manager frees this */
 }
 
@@ -227,19 +222,15 @@ DNSRequest* DNS::AddQuery(DNSHeader *header, int &id)
        /* Is the DNS connection down? */
        if (this->GetFd() == -1)
                return NULL;
-
-       /* Are there already the max number of requests on the go? */
-       if (requests.size() == DNS::MAX_REQUEST_ID + 1)
-               return NULL;
        
        /* Create an id */
        id = this->PRNG() & DNS::MAX_REQUEST_ID;
 
        /* If this id is already 'in flight', pick another. */
-       while (requests.find(id) != requests.end())
+       while (requests[id])
                id = this->PRNG() & DNS::MAX_REQUEST_ID;
 
-       DNSRequest* req = new DNSRequest(ServerInstance, this, this->myserver, id, requests);
+       DNSRequest* req = new DNSRequest(ServerInstance, this, this->myserver, id);
 
        header->id[0] = req->id[0] = id >> 8;
        header->id[1] = req->id[1] = id & 0xFF;
@@ -269,6 +260,9 @@ DNS::DNS(InspIRCd* Instance) : ServerInstance(Instance)
        /* Clear the Resolver class table */
        memset(Classes,0,sizeof(Classes));
 
+       /* Clear the requests class table */
+       memset(requests,0,sizeof(requests));
+
        /* Set the id of the next request to 0
         */
        currid = 0;
@@ -463,10 +457,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
 
@@ -613,8 +612,7 @@ DNSResult DNS::GetResult()
        unsigned long this_id = header.id[1] + (header.id[0] << 8);
 
        /* Do we have a pending request matching this id? */
-       requestlist_iter n_iter = requests.find(this_id);
-       if (n_iter == requests.end())
+       if (!requests[this_id])
        {
                /* Somehow we got a DNS response for a request we never made... */
                ServerInstance->Log(DEBUG,"DNS: got a response for a query we didnt send with fd=%d queryid=%d",this->GetFd(),this_id);
@@ -623,8 +621,8 @@ DNSResult DNS::GetResult()
        else
        {
                /* Remove the query from the list of pending queries */
-               req = (DNSRequest*)n_iter->second;
-               requests.erase(n_iter);
+               req = requests[this_id];
+               requests[this_id] = NULL;
        }
 
        /* Inform the DNSRequest class that it has a result to be read.
@@ -721,7 +719,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");
 
@@ -860,7 +862,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);
 
@@ -938,10 +940,14 @@ 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 */
        DNSResult res = this->GetResult();
        /* Is there a usable request id? */
@@ -1015,6 +1021,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()
 {