summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbrain <brain@e03df62e-2008-0410-955e-edbf42e46eb7>2006-08-01 21:35:07 +0000
committerbrain <brain@e03df62e-2008-0410-955e-edbf42e46eb7>2006-08-01 21:35:07 +0000
commita5c9214743e76bd8bee1cb5f4d0d6dc3d1171c58 (patch)
tree2a520b22f9a7423924b4ad776b747fd9ba198ae9
parentcf2836550f864e162923b8db82d1758b7fb77175 (diff)
Removed threaded dns (it might make a comeback some day, but as it stands its incompatible with the new OO resolver)
Migrated to new OO resolver, removed as much firedns craq as is safe to do so, operates over one file descriptor now and keyed against request id. The only way to use the system is via class Resolver (so i'll need to migrate the rest of the ircd to use it) git-svn-id: http://svn.inspircd.org/repository/trunk/inspircd@4622 e03df62e-2008-0410-955e-edbf42e46eb7
-rw-r--r--include/dns.h71
-rw-r--r--include/inspsocket.h1
-rw-r--r--src/cmd_nick.cpp11
-rw-r--r--src/dns.cpp1422
-rw-r--r--src/dnsqueue.cpp273
-rw-r--r--src/inspircd.cpp26
-rw-r--r--src/inspsocket.cpp28
-rw-r--r--src/message.cpp19
8 files changed, 566 insertions, 1285 deletions
diff --git a/include/dns.h b/include/dns.h
index 5417d3c61..b9ba27e2e 100644
--- a/include/dns.h
+++ b/include/dns.h
@@ -50,67 +50,18 @@ enum ResolverError
*/
class DNS : public Extensible
{
-private:
+ private:
insp_inaddr *binip;
- char* result;
- char localbuf[1024];
+ unsigned char* result;
+ unsigned char localbuf[1024];
int t;
- void dns_init();
- int myfd;
- void dns_init_2(const char* dnsserver);
- insp_inaddr *dns_aton4(const char * const ipstring);
- int dns_getip4(const char * const name);
- int dns_getip4list(const char * const name);
- int dns_getname4(const insp_inaddr * const ip);
- char *dns_getresult(const int fd);
- insp_inaddr *dns_aton4_s(const char * const ipstring, insp_inaddr * const ip);
- char *dns_getresult_s(const int fd, char * const result);
- insp_inaddr *dns_aton4_r(const char * const ipstring);
- char *dns_getresult_r(const int fd);
-public:
- /** The default constructor uses dns addresses read from /etc/resolv.conf.
- * Please note that it will re-read /etc/resolv.conf for each copy of the
- * class you instantiate, causing disk access and slow lookups if you create
- * a lot of them. Consider passing the constructor a server address as a parameter
- * instead.
- */
+ int myid;
+ public:
+ int dns_getip4(const char* name);
+ int dns_getname4(const insp_inaddr* ip);
+ int dns_getresult();
DNS();
- /** This constructor accepts a dns server address. The address must be in dotted
- * decimal form, e.g. 1.2.3.4.
- */
- DNS(const std::string &dnsserver);
- /** The destructor frees all used structures.
- */
~DNS();
- /** This method will start the reverse lookup of an ip given in dotted decimal
- * format, e.g. 1.2.3.4, and returns true if the lookup was successfully
- * initiated.
- */
- bool ReverseLookup(const std::string &ip, bool ins);
- /** This method will start the forward lookup of a hostname, e.g. www.inspircd.org,
- * and returns true if the lookup was successfully initiated.
- */
- bool ForwardLookup(const std::string &host, bool ins);
- /** Used by modules to perform a dns lookup but have the socket engine poll a module, instead of the dns object directly.
- */
- bool ForwardLookupWithFD(const std::string &host, int &fd);
- /** This method will return true when the lookup is completed. It uses poll internally
- * to determine the status of the socket.
- */
- bool HasResult();
- /** This method will return true if the lookup's fd matches the one provided
- */
- bool HasResult(int fd);
- /** This method returns the result of your query as a string, depending upon wether you
- * called DNS::ReverseLookup() or DNS::ForwardLookup.
- */
- std::string GetResult();
- std::string GetResultIP();
- /** This method returns the file handle used by the dns query socket or zero if the
- * query is invalid for some reason, e.g. the dns server not responding.
- */
- int GetFD();
- void SetNS(const std::string &dnsserver);
};
/**
@@ -146,7 +97,7 @@ class Resolver : public Extensible
/**
* The file descriptor used for the DNS lookup
*/
- int fd;
+ int myid;
/**
* The output data, e.g. a hostname or an IP.
*/
@@ -197,7 +148,7 @@ class Resolver : public Extensible
* to determine where in various tables to place a pointer to your class, but it
* is safe to call and use this method.
*/
- int GetFd();
+ int GetId();
};
/**
@@ -213,8 +164,6 @@ void dns_deal_with_classes(int fd);
*/
bool dns_add_class(Resolver* r);
-void dns_close(int fd);
-
#ifdef THREADED_DNS
/** This is the handler function for multi-threaded DNS.
* It cannot be a class member as pthread will not let us
diff --git a/include/inspsocket.h b/include/inspsocket.h
index 4bd76788c..1b9947ef9 100644
--- a/include/inspsocket.h
+++ b/include/inspsocket.h
@@ -59,7 +59,6 @@ protected:
/**
* The resolver for this socket
*/
- DNS dns;
/**
* The hostname connected to
diff --git a/src/cmd_nick.cpp b/src/cmd_nick.cpp
index ab286bee4..ddcb04940 100644
--- a/src/cmd_nick.cpp
+++ b/src/cmd_nick.cpp
@@ -149,20 +149,9 @@ void cmd_nick::Handle (const char** parameters, int pcnt, userrec *user)
}
else
{
-#ifdef THREADED_DNS
- // initialize their dns lookup thread
- pthread_attr_t attribs;
- pthread_attr_init(&attribs);
- pthread_attr_setdetachstate(&attribs, PTHREAD_CREATE_DETACHED);
- if (pthread_create(&user->dnsthread, &attribs, dns_task, (void *)user) != 0)
- {
- log(DEBUG,"Failed to create DNS lookup thread for user %s: %s",user->nick, strerror(errno));
- }
-#else
user->dns_done = (!lookup_dns(user->nick));
if (user->dns_done)
log(DEBUG,"Aborting dns lookup of %s because dns server experienced a failure.",user->nick);
-#endif
}
}
if (user->registered == REG_NICKUSER)
diff --git a/src/dns.cpp b/src/dns.cpp
index eee1e0234..a8268aafc 100644
--- a/src/dns.cpp
+++ b/src/dns.cpp
@@ -3,13 +3,13 @@
* +------------------------------------+
*
* InspIRCd is copyright (C) 2002-2006 ChatSpike-Dev.
- * E-mail:
- * <brain@chatspike.net>
- * <Craig@chatspike.net>
+ * E-mail:
+ * <brain@chatspike.net>
+ * <Craig@chatspike.net>
*
* Written by Craig Edwards, Craig McLure, and others.
* This program is free but copyrighted software; see
- * the file COPYING for details.
+ * the file COPYING for details.
*
* ---------------------------------------------------
*/
@@ -53,10 +53,6 @@ using namespace std;
#include "socketengine.h"
#include "configreader.h"
-#ifdef THREADED_DNS
-pthread_mutex_t connmap_lock = PTHREAD_MUTEX_INITIALIZER;
-#endif
-
extern InspIRCd* ServerInstance;
extern ServerConfig* Config;
extern time_t TIME;
@@ -70,56 +66,70 @@ class s_connection;
typedef std::map<int,s_connection*> connlist;
typedef connlist::iterator connlist_iter;
+
+DNS* Res = NULL;
+
+/* As lookups are completed, they are pushed into this result_list */
+std::map<int, std::string> result_list;
connlist connections;
-Resolver* dns_classes[MAX_DESCRIPTORS];
+int master_socket = -1;
+
+Resolver* dns_classes[65536];
insp_inaddr servers[8];
int i4;
-int initdone = 0;
-int lastcreate = -1;
-class s_connection
+class s_rr_middle
{
public:
- unsigned char id[2];
- unsigned int _class;
- QueryType type;
- int want_list;
- int fd;
+ QueryType type;
+ unsigned int _class;
+ unsigned long ttl;
+ unsigned int rdlength;
};
-class s_rr_middle
+class s_header
{
public:
- QueryType type;
- unsigned int _class;
- unsigned long ttl;
- unsigned int rdlength;
+ unsigned char id[2];
+ unsigned int flags1;
+ unsigned int flags2;
+ unsigned int qdcount;
+ unsigned int ancount;
+ unsigned int nscount;
+ unsigned int arcount;
+ unsigned char payload[512];
};
-class s_header
+class s_connection
{
public:
- unsigned char id[2];
- unsigned int flags1;
- unsigned int flags2;
- unsigned int qdcount;
- unsigned int ancount;
- unsigned int nscount;
- unsigned int arcount;
- unsigned char payload[512];
+ unsigned char id[2];
+ unsigned char res[512];
+ unsigned int _class;
+ QueryType type;
+ int want_list;
+
+ s_connection()
+ {
+ *res = 0;
+ }
+
+ unsigned char* result_ready(s_header &h, int length);
+ int send_requests(const s_header *h, const int l);
};
+
void *dns_align(void *inp)
{
- char *p = (char*)inp;
- int offby = ((char *)p - (char *)0) % (sizeof(void *) > sizeof(long) ? sizeof(void *) : sizeof(long));
- if (offby != 0)
- return p + ((sizeof(void *) > sizeof(long) ? sizeof(void *) : sizeof(long)) - offby);
- else
- return p;
+ char *p = (char*)inp;
+ int offby = ((char *)p - (char *)0) % (sizeof(void *) > sizeof(long) ? sizeof(void *) : sizeof(long));
+ if (offby != 0)
+ return p + ((sizeof(void *) > sizeof(long) ? sizeof(void *) : sizeof(long)) - offby);
+ else
+ return p;
}
/*
@@ -131,352 +141,266 @@ void *dns_align(void *inp)
inline void dns_fill_rr(s_rr_middle* rr, const unsigned char *input)
{
- rr->type = (QueryType)((input[0] << 8) + input[1]);
- rr->_class = (input[2] << 8) + input[3];
- rr->ttl = (input[4] << 24) + (input[5] << 16) + (input[6] << 8) + input[7];
- rr->rdlength = (input[8] << 8) + input[9];
+ rr->type = (QueryType)((input[0] << 8) + input[1]);
+ rr->_class = (input[2] << 8) + input[3];
+ rr->ttl = (input[4] << 24) + (input[5] << 16) + (input[6] << 8) + input[7];
+ rr->rdlength = (input[8] << 8) + input[9];
}
inline void dns_fill_header(s_header *header, const unsigned char *input, const int l)
{
- header->id[0] = input[0];
- header->id[1] = input[1];
- header->flags1 = input[2];
- header->flags2 = input[3];
- header->qdcount = (input[4] << 8) + input[5];
- header->ancount = (input[6] << 8) + input[7];
- header->nscount = (input[8] << 8) + input[9];
- header->arcount = (input[10] << 8) + input[11];
- memcpy(header->payload,&input[12],l);
+ header->id[0] = input[0];
+ header->id[1] = input[1];
+ header->flags1 = input[2];
+ header->flags2 = input[3];
+ header->qdcount = (input[4] << 8) + input[5];
+ header->ancount = (input[6] << 8) + input[7];
+ header->nscount = (input[8] << 8) + input[9];
+ header->arcount = (input[10] << 8) + input[11];
+ memcpy(header->payload,&input[12],l);
}
inline void dns_empty_header(unsigned char *output, const s_header *header, const int l)
{
- output[0] = header->id[0];
- output[1] = header->id[1];
- output[2] = header->flags1;
- output[3] = header->flags2;
- output[4] = header->qdcount >> 8;
- output[5] = header->qdcount & 0xFF;
- output[6] = header->ancount >> 8;
- output[7] = header->ancount & 0xFF;
- output[8] = header->nscount >> 8;
- output[9] = header->nscount & 0xFF;
- output[10] = header->arcount >> 8;
- output[11] = header->arcount & 0xFF;
- memcpy(&output[12],header->payload,l);
+ output[0] = header->id[0];
+ output[1] = header->id[1];
+ output[2] = header->flags1;
+ output[3] = header->flags2;
+ output[4] = header->qdcount >> 8;
+ output[5] = header->qdcount & 0xFF;
+ output[6] = header->ancount >> 8;
+ output[7] = header->ancount & 0xFF;
+ output[8] = header->nscount >> 8;
+ output[9] = header->nscount & 0xFF;
+ output[10] = header->arcount >> 8;
+ output[11] = header->arcount & 0xFF;
+ memcpy(&output[12],header->payload,l);
}
-void dns_close(int fd)
-{
-#ifndef THREADED_DNS
- if (ServerInstance && ServerInstance->SE)
- ServerInstance->SE->DelFd(fd);
-#endif
- log(DEBUG,"DNS: dns_close on fd %d",fd);
- shutdown(fd,2);
- close(fd);
- return;
-}
-void DNS::dns_init()
+int s_connection::send_requests(const s_header *h, const int l)
{
- FILE *f;
- int i;
- insp_inaddr addr;
- char buf[1024];
- if (initdone == 1)
- return;
- i4 = 0;
-
- initdone = 1;
- srand((unsigned int) TIME);
- memset(servers,'\0',sizeof(insp_inaddr) * 8);
- f = fopen("/etc/resolv.conf","r");
- if (f == NULL)
- return;
- while (fgets(buf,1024,f) != NULL) {
- if (strncmp(buf,"nameserver",10) == 0)
- {
- i = 10;
- while (buf[i] == ' ' || buf[i] == '\t')
- i++;
- if (i4 < 8)
- {
- if (insp_aton(&buf[i],&addr) > 0)
- {
- log(DEBUG,"Add server %d, %s",i4,&buf[i]);
- memcpy(&servers[i4++],&addr,sizeof(insp_inaddr));
- }
- }
- }
- }
- fclose(f);
-}
+ insp_sockaddr addr;
+ unsigned char payload[sizeof(s_header)];
-void DNS::dns_init_2(const char* dnsserver)
-{
- log(DEBUG,"*************** DNS INIT 2 **************");
- insp_inaddr addr;
- i4 = 0;
- srand((unsigned int) TIME);
- memset(servers,'\0',sizeof(insp_inaddr) * 8);
- log(DEBUG,"ADD DNS: %s",dnsserver);
- if (insp_aton(dnsserver,&addr) > 0)
+ dns_empty_header(payload,h,l);
+
+ /* otherwise send via standard ipv4 boringness */
+ memset(&addr,0,sizeof(addr));
+#ifdef IPV6
+ memcpy(&addr.sin6_addr,&servers[0],sizeof(addr.sin6_addr));
+ addr.sin6_family = AF_FAMILY;
+ addr.sin6_port = htons(53);
+#else
+ memcpy(&addr.sin_addr.s_addr,&servers[0],sizeof(addr.sin_addr));
+ addr.sin_family = AF_FAMILY;
+ addr.sin_port = htons(53);
+#endif
+ if (sendto(master_socket, payload, l + 12, 0, (sockaddr *) &addr, sizeof(addr)) == -1)
{
- unsigned char* n = (unsigned char*)&addr;
- log(DEBUG,"***** Add server %d, %s: %d, %d, %d, %d",i4,dnsserver,n[0],n[1],n[2],n[3]);
- memcpy(&servers[i4++],&addr,sizeof(insp_inaddr));
+ log(DEBUG,"Error in sendto!");
+ return -1;
}
-}
+ return 0;
+}
-int dns_send_requests(const s_header *h, const s_connection *s, const int l)
+s_connection* dns_add_query(s_header *h, int &id)
{
- int i;
- insp_sockaddr addr;
- unsigned char payload[sizeof(s_header)];
- dns_empty_header(payload,h,l);
+ id = rand() % 65536;
+ s_connection * s = new s_connection();
-
- i = 0;
-
- /* otherwise send via standard ipv4 boringness */
- memset(&addr,0,sizeof(addr));
-#ifdef IPV6
- memcpy(&addr.sin6_addr,&servers[i],sizeof(addr.sin6_addr));
- addr.sin6_family = AF_FAMILY;
- addr.sin6_port = htons(53);
-#else
- memcpy(&addr.sin_addr.s_addr,&servers[i],sizeof(addr.sin_addr));
- addr.sin_family = AF_FAMILY;
- addr.sin_port = htons(53);
-#endif
- if (sendto(s->fd, payload, l + 12, 0, (sockaddr *) &addr, sizeof(addr)) == -1)
- {
- log(DEBUG,"Error in sendto!");
- return -1;
- }
-
- return 0;
+ /* set header flags */
+ h->id[0] = s->id[0] = id >> 8;
+ h->id[1] = s->id[1] = id & 0xFF;
+ h->flags1 = 0 | FLAGS1_MASK_RD;
+ h->flags2 = 0;
+ h->qdcount = 1;
+ h->ancount = 0;
+ h->nscount = 0;
+ h->arcount = 0;
+ s->want_list = 0;
+ if (connections.find(id) == connections.end())
+ connections[id] = s;
+ return s;
}
-s_connection *dns_add_query(s_header *h)
+void create_socket()
{
+ log(DEBUG,"---- BEGIN DNS INITIALIZATION, SERVER=%s ---",Config->DNSServer);
+ insp_inaddr addr;
+ i4 = 0;
+ srand((unsigned int) TIME);
+ memset(servers,'\0',sizeof(insp_inaddr) * 8);
+ if (insp_aton(Config->DNSServer,&addr) > 0)
+ memcpy(&servers[i4++],&addr,sizeof(insp_inaddr));
- s_connection * s = new s_connection;
- int id = rand() % 65536;
-
- /* set header flags */
- h->id[0] = s->id[0] = id >> 8; /* verified by dns_getresult_s() */
- h->id[1] = s->id[1] = id & 0xFF;
- h->flags1 = 0 | FLAGS1_MASK_RD;
- h->flags2 = 0;
- h->qdcount = 1;
- h->ancount = 0;
- h->nscount = 0;
- h->arcount = 0;
- s->want_list = 0;
- s->fd = socket(PF_PROTOCOL, SOCK_DGRAM, 0);
- if (s->fd != -1)
- {
- log(DEBUG,"Set query socket nonblock");
- if (fcntl(s->fd, F_SETFL, O_NONBLOCK) != 0)
- {
- shutdown(s->fd,2);
- close(s->fd);
- s->fd = -1;
- }
- }
- if (s->fd != -1)
- {
+ master_socket = socket(PF_PROTOCOL, SOCK_DGRAM, 0);
+ if (master_socket != -1)
+ {
+ log(DEBUG,"Set query socket nonblock");
+ if (fcntl(master_socket, F_SETFL, O_NONBLOCK) != 0)
+ {
+ shutdown(master_socket,2);
+ close(master_socket);
+ master_socket = -1;
+ }
+ }
+ if (master_socket != -1)
+ {
#ifdef IPV6
- insp_sockaddr addr;
- memset(&addr,0,sizeof(addr));
- addr.sin6_family = AF_FAMILY;
- addr.sin6_port = 0;
- memset(&addr.sin6_addr,255,sizeof(in6_addr));
+ insp_sockaddr addr;
+ memset(&addr,0,sizeof(addr));
+ addr.sin6_family = AF_FAMILY;
+ addr.sin6_port = 0;
+ memset(&addr.sin6_addr,255,sizeof(in6_addr));
#else
- insp_sockaddr addr;
- memset(&addr,0,sizeof(addr));
- addr.sin_family = AF_FAMILY;
- addr.sin_port = 0;
- addr.sin_addr.s_addr = INADDR_ANY;
- if (bind(s->fd,(sockaddr *)&addr,sizeof(addr)) != 0)
- {
- log(DEBUG,"Cant bind with source port = 0");
- shutdown(s->fd,2);
- close(s->fd);
- s->fd = -1;
- }
+ insp_sockaddr addr;
+ memset(&addr,0,sizeof(addr));
+ addr.sin_family = AF_FAMILY;
+ addr.sin_port = 0;
+ addr.sin_addr.s_addr = INADDR_ANY;
#endif
- }
- if (s->fd == -1)
- {
- DELETE(s);
- return NULL;
- }
- /* create new connection object, add to linked list */
-#ifdef THREADED_DNS
- pthread_mutex_lock(&connmap_lock);
-#endif
- if (connections.find(s->fd) == connections.end())
- connections[s->fd] = s;
-#ifdef THREADED_DNS
- pthread_mutex_unlock(&connmap_lock);
-#endif
-
- return s;
+ log(DEBUG,"Binding query port");
+ if (bind(master_socket,(sockaddr *)&addr,sizeof(addr)) != 0)
+ {
+ log(DEBUG,"Cant bind with source port = 0");
+ shutdown(master_socket,2);
+ close(master_socket);
+ master_socket = -1;
+ }
+
+ if (master_socket >= 0)
+ {
+ log(DEBUG,"Attach query port to socket engine");
+ if (ServerInstance && ServerInstance->SE)
+ ServerInstance->SE->AddFd(master_socket,true,X_ESTAB_DNS);
+ }
+ }
}
int dns_build_query_payload(const char * const name, const unsigned short rr, const unsigned short _class, unsigned char * const payload)
{
- short payloadpos;
- const char * tempchr, * tempchr2;
- unsigned short l;
-
- payloadpos = 0;
- tempchr2 = name;
-
- /* split name up into labels, create query */
- while ((tempchr = strchr(tempchr2,'.')) != NULL)
- {
- l = tempchr - tempchr2;
- if (payloadpos + l + 1 > 507)
- return -1;
- payload[payloadpos++] = l;
- memcpy(&payload[payloadpos],tempchr2,l);
- payloadpos += l;
- tempchr2 = &tempchr[1];
- }
- l = strlen(tempchr2);
- if (l)
- {
- if (payloadpos + l + 2 > 507)
- return -1;
- payload[payloadpos++] = l;
- memcpy(&payload[payloadpos],tempchr2,l);
- payloadpos += l;
- payload[payloadpos++] = '\0';
- }
- if (payloadpos > 508)
- return -1;
- l = htons(rr);
- memcpy(&payload[payloadpos],&l,2);
- l = htons(_class);
- memcpy(&payload[payloadpos + 2],&l,2);
- return payloadpos + 4;
-}
-
-int DNS::dns_getip4(const char *name) { /* build, add and send A query; retrieve result with dns_getresult() */
- s_header h;
- s_connection *s;
- int l;
+ short payloadpos;
+ const char * tempchr, * tempchr2;
+ unsigned short l;
- dns_init();
-
+ payloadpos = 0;
+ tempchr2 = name;
- l = dns_build_query_payload(name,DNS_QRY_A,1,(unsigned char *)&h.payload);
- if (l == -1)
- return -1;
- s = dns_add_query(&h);
- if (s == NULL)
- return -1;
- s->_class = 1;
- s->type = DNS_QRY_A;
- if (dns_send_requests(&h,s,l) == -1)
- return -1;
-
- return s->fd;
-}
-
-int DNS::dns_getip4list(const char *name) { /* build, add and send A query; retrieve result with dns_getresult() */
- s_header h;
- s_connection *s;
- int l;
-
- dns_init();
-
- l = dns_build_query_payload(name,DNS_QRY_A,1,(unsigned char *)&h.payload);
- if (l == -1)
- return -1;
- s = dns_add_query(&h);
- if (s == NULL)
- return -1;
- s->_class = 1;
- s->type = DNS_QRY_A;
- s->want_list = 1;
- if (dns_send_requests(&h,s,l) == -1)
- return -1;
-
- return s->fd;
+ /* split name up into labels, create query */
+ while ((tempchr = strchr(tempchr2,'.')) != NULL)
+ {
+ l = tempchr - tempchr2;
+ if (payloadpos + l + 1 > 507)
+ return -1;
+ payload[payloadpos++] = l;
+ memcpy(&payload[payloadpos],tempchr2,l);
+ payloadpos += l;
+ tempchr2 = &tempchr[1];
+ }
+ l = strlen(tempchr2);
+ if (l)
+ {
+ if (payloadpos + l + 2 > 507)
+ return -1;
+ payload[payloadpos++] = l;
+ memcpy(&payload[payloadpos],tempchr2,l);
+ payloadpos += l;
+ payload[payloadpos++] = '\0';
+ }
+ if (payloadpos > 508)
+ return -1;
+ l = htons(rr);
+ memcpy(&payload[payloadpos],&l,2);
+ l = htons(_class);
+ memcpy(&payload[payloadpos + 2],&l,2);
+ return payloadpos + 4;
+}
+
+int DNS::dns_getip4(const char *name)
+{
+ /* build, add and send A query; retrieve result with dns_getresult() */
+ s_header h;
+ s_connection *s;
+ int l;
+ int id;
+
+ l = dns_build_query_payload(name,DNS_QRY_A,1,(unsigned char *)&h.payload);
+ if (l == -1)
+ return -1;
+ s = dns_add_query(&h, id);
+ if (s == NULL)
+ return -1;
+ s->_class = 1;
+ s->type = DNS_QRY_A;
+ if (s->send_requests(&h,l) == -1)
+ return -1;
+
+ return id;
}
int DNS::dns_getname4(const insp_inaddr *ip)
{ /* build, add and send PTR query; retrieve result with dns_getresult() */
#ifdef IPV6
- return -1;
+ return -1;
#else
- log(DEBUG,"DNS::dns_getname4");
- char query[512];
- s_header h;
- s_connection * s;
- unsigned char *c;
- int l;
+ log(DEBUG,"DNS::dns_getname4");
+ char query[512];
+ s_header h;
+ s_connection * s;
+ unsigned char *c;
+ int l;
+ int id;
+
+ c = (unsigned char *)&ip->s_addr;
+
+ sprintf(query,"%d.%d.%d.%d.in-addr.arpa",c[3],c[2],c[1],c[0]);
+
+ l = dns_build_query_payload(query,DNS_QRY_PTR,1,(unsigned char *)&h.payload);
+ if (l == -1)
+ return -1;
+ s = dns_add_query(&h, id);
+ if (s == NULL)
+ return -1;
+ s->_class = 1;
+ s->type = DNS_QRY_PTR;
+ if (s->send_requests(&h,l) == -1)
+ return -1;
+
+ return id;
+#endif
+}
- c = (unsigned char *)&ip->s_addr;
+/* Return the next id which is ready.
+ * result_list[id] will have been populated with the result string.
+ */
+int DNS::dns_getresult()
+{
+ /* retrieve result of DNS query (buffered) */
+ s_header h;
+ s_connection *c;
+ int length;
+ unsigned char buffer[sizeof(s_header)];
- sprintf(query,"%d.%d.%d.%d.in-addr.arpa",c[3],c[2],c[1],c[0]);
+ length = recv(master_socket,buffer,sizeof(s_header),0);
- l = dns_build_query_payload(query,DNS_QRY_PTR,1,(unsigned char *)&h.payload);
- if (l == -1)
- return -1;
- s = dns_add_query(&h);
- if (s == NULL)
- return -1;
- s->_class = 1;
- s->type = DNS_QRY_PTR;
- if (dns_send_requests(&h,s,l) == -1)
- return -1;
+ if (length < 12)
+ return -1;
- return s->fd;
-#endif
-}
+ dns_fill_header(&h,buffer,length - 12);
-char* DNS::dns_getresult(const int cfd) { /* retrieve result of DNS query */
- log(DEBUG,"DNS: dns_getresult with cfd=%d",cfd);
- return dns_getresult_s(cfd,this->localbuf);
-}
+ // Get the id of this request
+ unsigned long this_id = h.id[1] + (h.id[0] << 8);
-char* DNS::dns_getresult_s(const int cfd, char *res) { /* retrieve result of DNS query (buffered) */
- s_header h;
- s_connection *c;
- int l, i, q, curanswer, o;
- s_rr_middle rr;
- unsigned char buffer[sizeof(s_header)];
- unsigned short p;
-
- if (res)
- *res = 0;
-
- /* FireDNS used a linked list for this. How ugly (and slow). */
-
-#ifdef THREADED_DNS
- /* XXX: STL really does NOT like being poked and prodded in more than
- * one orifice by threaded apps. Make sure we remain nice to it, and
- * lock a mutex around any access to the std::map.
- */
- pthread_mutex_lock(&connmap_lock);
-#endif
- connlist_iter n_iter = connections.find(cfd);
+ // Do we have a pending request for it?
+
+ connlist_iter n_iter = connections.find(this_id);
if (n_iter == connections.end())
{
- log(DEBUG,"DNS: got a response for a query we didnt send with fd=%d",cfd);
-#ifdef THREADED_DNS
- pthread_mutex_unlock(&connmap_lock);
-#endif
- return NULL;
+ log(DEBUG,"DNS: got a response for a query we didnt send with fd=%d queryid=%d",master_socket,this_id);
+ return -1;
}
else
{
@@ -485,543 +409,287 @@ char* DNS::dns_getresult_s(const int cfd, char *res) { /* retrieve result of DNS
/* We don't delete c here, because its done later when needed */
connections.erase(n_iter);
}
-#ifdef THREADED_DNS
- pthread_mutex_unlock(&connmap_lock);
-#endif
+ unsigned char* a = c->result_ready(h, length);
- l = recv(c->fd,buffer,sizeof(s_header),0);
- dns_close(c->fd);
- if (l < 12)
- {
- DELETE(c);
- return NULL;
- }
- dns_fill_header(&h,buffer,l - 12);
- if (c->id[0] != h.id[0] || c->id[1] != h.id[1])
- {
- log(DEBUG,"DNS: id mismatch on query");
- DELETE(c);
- return NULL; /* ID mismatch */
- }
- if ((h.flags1 & FLAGS1_MASK_QR) == 0)
- {
- log(DEBUG,"DNS: didnt get a query result");
- DELETE(c);
- return NULL;
- }
- if ((h.flags1 & FLAGS1_MASK_OPCODE) != 0)
- {
- log(DEBUG,"DNS: got an OPCODE and didnt want one");
- DELETE(c);
- return NULL;
- }
- if ((h.flags2 & FLAGS2_MASK_RCODE) != 0)
- {
- log(DEBUG,"DNS lookup failed due to SERVFAIL");
- DELETE(c);
- return NULL;
- }
- if (h.ancount < 1)
- {
- log(DEBUG,"DNS: no answers!");
- DELETE(c);
- return NULL;
- }
- i = 0;
- q = 0;
- l -= 12;
- while ((unsigned)q < h.qdcount && i < l)
- {
- if (h.payload[i] > 63)
- {
- i += 6;
- q++;
- }
- else
- {
- if (h.payload[i] == 0)
- {
- q++;
- i += 5;
- }
- else i += h.payload[i] + 1;
- }
- }
- curanswer = 0;
- while ((unsigned)curanswer < h.ancount)
- {
- q = 0;
- while (q == 0 && i < l)
- {
- if (h.payload[i] > 63)
- {
- i += 2;
- q = 1;
- }
- else
- {
- if (h.payload[i] == 0)
- {
- i++;
- q = 1;
- }
- else i += h.payload[i] + 1; /* skip length and label */
- }
- }
- if (l - i < 10)
- {
- DELETE(c);
- return NULL;
- }
- dns_fill_rr(&rr,&h.payload[i]);
- i += 10;
- if (rr.type != c->type)
- {
- curanswer++;
- i += rr.rdlength;
- continue;
- }
- if (rr._class != c->_class)
- {
- curanswer++;
- i += rr.rdlength;
- continue;
- }
- break;
- }
- if ((unsigned)curanswer == h.ancount)
- return NULL;
- if ((unsigned)i + rr.rdlength > (unsigned)l)
- return NULL;
- if (rr.rdlength > 1023)
- return NULL;
-
- switch (rr.type)
- {
- case DNS_QRY_PTR:
- log(DEBUG,"DNS: got a result of type DNS_QRY_PTR");
- o = 0;
- q = 0;
- while (q == 0 && i < l && o + 256 < 1023)
- {
- if (h.payload[i] > 63)
- {
- log(DEBUG,"DNS: h.payload[i] > 63");
- memcpy(&p,&h.payload[i],2);
- i = ntohs(p) - 0xC000 - 12;
- }
- else
- {
- if (h.payload[i] == 0)
- {
- q = 1;
- }
- else
- {
- res[o] = '\0';
- if (o != 0)
- res[o++] = '.';
- memcpy(&res[o],&h.payload[i + 1],h.payload[i]);
- o += h.payload[i];
- i += h.payload[i] + 1;
- }
- }
- }
- res[o] = '\0';
- break;
- case DNS_QRY_A:
- log(DEBUG,"DNS: got a result of type DNS_QRY_A");
- if (c->want_list)
- {
- dns_ip4list *alist = (dns_ip4list *) res; /* we have to trust that this is aligned */
- while ((char *)alist - (char *)res < 700)
- {
- if (rr.type != DNS_QRY_A)
- break;
- if (rr._class != 1)
- break;
- if (rr.rdlength != 4)
- {
- DELETE(c);
- return NULL;
- }
- memcpy(&alist->ip,&h.payload[i],4);
- if ((unsigned)++curanswer >= h.ancount)
- break;
- i += rr.rdlength;
- q = 0;
- while (q == 0 && i < l)
- {
- if (h.payload[i] > 63)
- {
- i += 2;
- q = 1;
- }
- else
- {
- if (h.payload[i] == 0)
- {
- i++;
- q = 1;
- }
- else i += h.payload[i] + 1;
- }
- }
- if (l - i < 10)
- {
- DELETE(c);
- return NULL;
- }
- dns_fill_rr(&rr,&h.payload[i]);
- i += 10;
- alist->next = (dns_ip4list *) dns_align(((char *) alist) + sizeof(dns_ip4list));
- alist = alist->next;
- alist->next = NULL;
- }
- alist->next = NULL;
- break;
- }
- memcpy(res,&h.payload[i],rr.rdlength);
- res[rr.rdlength] = '\0';
- break;
- default:
- memcpy(res,&h.payload[i],rr.rdlength);
- res[rr.rdlength] = '\0';
- break;
- }
- DELETE(c);
- return res;
-}
-
-DNS::DNS()
-{
- dns_init();
- log(DEBUG,"Create blank DNS");
-}
-
-DNS::DNS(const std::string &dnsserver)
-{
- dns_init_2(dnsserver.c_str());
- log(DEBUG,"Create DNS with server '%s'",dnsserver.c_str());
-}
-
-void DNS::SetNS(const std::string &dnsserver)
-{
- dns_init_2(dnsserver.c_str());
- log(DEBUG,"Set NS");
-}
-
-DNS::~DNS()
-{
-}
-
-bool DNS::ReverseLookup(const std::string &ip, bool ins)
-{
- if (ServerInstance && ServerInstance->stats)
- ServerInstance->stats->statsDns++;
- insp_inaddr binip;
- if (insp_aton(ip.c_str(), &binip) < 1)
- {
- return false;
- }
-
- this->myfd = dns_getname4(&binip);
- if (this->myfd == -1)
- {
- return false;
- }
- log(DEBUG,"DNS: ReverseLookup, fd=%d",this->myfd);
-#ifndef THREADED_DNS
- if (ins)
- {
- if (ServerInstance && ServerInstance->SE)
- ServerInstance->SE->AddFd(this->myfd,true,X_ESTAB_DNS);
- }
-#endif
- return true;
-}
-
-bool DNS::ForwardLookup(const std::string &host, bool ins)
-{
- if (ServerInstance && ServerInstance->stats)
- ServerInstance->stats->statsDns++;
- this->myfd = dns_getip4(host.c_str());
- if (this->myfd == -1)
- {
- return false;
- }
- log(DEBUG,"DNS: ForwardLookup, fd=%d",this->myfd);
-#ifndef THREADED_DNS
- if (ins)
- {
- if (ServerInstance && ServerInstance->SE)
- ServerInstance->SE->AddFd(this->myfd,true,X_ESTAB_DNS);
- }
-#endif
- return true;
-}
-
-bool DNS::ForwardLookupWithFD(const std::string &host, int &fd)
-{
- if (ServerInstance && ServerInstance->stats)
- ServerInstance->stats->statsDns++;
- this->myfd = dns_getip4(host.c_str());
- fd = this->myfd;
- if (this->myfd == -1)
- {
- return false;
- }
- log(DEBUG,"DNS: ForwardLookupWithFD, fd=%d",this->myfd);
- if (ServerInstance && ServerInstance->SE)
- ServerInstance->SE->AddFd(this->myfd,true,X_ESTAB_MODULE);
- return true;
-}
+ if (a == NULL)
+ {
+ result_list[this_id] = "";
+ }
+ else
+ {
+ if (c->type == DNS_QRY_A)
+ {
+ char formatted[1024];
+ snprintf(formatted,1024,"%u.%u.%u.%u",a[0],a[1],a[2],a[3]);
+ result_list[this_id] = std::string(formatted);
+ }
+ else
+ {
+ result_list[this_id] = std::string((const char*)a);
+ }
+ }
-bool DNS::HasResult(int fd)
-{
- return (fd == this->myfd);
+ delete c;
+ return this_id;
}
-/* Only the multithreaded dns uses this poll() based
- * check now. As its in another thread we dont have
- * to worry about its performance that much.
+/** A result is ready, process it
*/
-bool DNS::HasResult()
-{
- log(DEBUG,"DNS: HasResult, fd=%d",this->myfd);
- pollfd polls;
- polls.fd = this->myfd;
- polls.events = POLLIN;
- int ret = poll(&polls,1,1);
- log(DEBUG,"DNS: Hasresult returning %d",ret);
- return (ret > 0);
-}
-
-int DNS::GetFD()
+unsigned char* s_connection::result_ready(s_header &h, int length)
{
- return this->myfd;
-}
-
-std::string DNS::GetResult()
-{
- log(DEBUG,"DNS: GetResult()");
- result = dns_getresult(this->myfd);
- if (result)
- {
- if (ServerInstance && ServerInstance->stats)
- ServerInstance->stats->statsDnsGood++;
- dns_close(this->myfd);
- this->myfd = -1;
- return result;
- }
- else
- {
- if (ServerInstance && ServerInstance->stats)
- ServerInstance->stats->statsDnsBad++;
- if (this->myfd != -1)
- {
- dns_close(this->myfd);
- this->myfd = -1;
- }
- return "";
- }
+ int i, q, curanswer, o;
+ s_rr_middle rr;
+ unsigned short p;
+
+ if ((h.flags1 & FLAGS1_MASK_QR) == 0)
+ {
+ log(DEBUG,"DNS: didnt get a query result");
+ return NULL;
+ }
+ if ((h.flags1 & FLAGS1_MASK_OPCODE) != 0)
+ {
+ log(DEBUG,"DNS: got an OPCODE and didnt want one");
+ return NULL;
+ }
+ if ((h.flags2 & FLAGS2_MASK_RCODE) != 0)
+ {
+ log(DEBUG,"DNS lookup failed due to SERVFAIL");
+ return NULL;
+ }
+ if (h.ancount < 1)
+ {
+ log(DEBUG,"DNS: no answers!");
+ return NULL;
+ }
+ i = 0;
+ q = 0;
+ length -= 12;
+ while ((unsigned)q < h.qdcount && i < length)
+ {
+ if (h.payload[i] > 63)
+ {
+ i += 6;
+ q++;
+ }
+ else
+ {
+ if (h.payload[i] == 0)
+ {
+ q++;
+ i += 5;
+ }
+ else i += h.payload[i] + 1;
+ }
+ }
+ curanswer = 0;
+ while ((unsigned)curanswer < h.ancount)
+ {
+ q = 0;
+ while (q == 0 && i < length)
+ {
+ if (h.payload[i] > 63)
+ {
+ i += 2;
+ q = 1;
+ }
+ else
+ {
+ if (h.payload[i] == 0)
+ {
+ i++;
+ q = 1;
+ }
+ else i += h.payload[i] + 1; /* skip length and label */
+ }
+ }
+ if (length - i < 10)
+ {
+ return NULL;
+ }
+ dns_fill_rr(&rr,&h.payload[i]);
+ i += 10;
+ if (rr.type != this->type)
+ {
+ curanswer++;
+ i += rr.rdlength;
+ continue;
+ }
+ if (rr._class != this->_class)
+ {
+ curanswer++;
+ i += rr.rdlength;
+ continue;
+ }
+ break;
+ }
+ if ((unsigned int)curanswer == h.ancount)
+ return NULL;
+ if (i + rr.rdlength > (unsigned int)length)
+ return NULL;
+ if (rr.rdlength > 1023)
+ return NULL;
+
+ switch (rr.type)
+ {
+ case DNS_QRY_PTR:
+ log(DEBUG,"DNS: got a result of type DNS_QRY_PTR");
+ o = 0;
+ q = 0;
+ while (q == 0 && i < length && o + 256 < 1023)
+ {
+ if (h.payload[i] > 63)
+ {
+ log(DEBUG,"DNS: h.payload[i] > 63");
+ memcpy(&p,&h.payload[i],2);
+ i = ntohs(p) - 0xC000 - 12;
+ }
+ else
+ {
+ if (h.payload[i] == 0)
+ {
+ q = 1;
+ }
+ else
+ {
+ res[o] = '\0';
+ if (o != 0)
+ res[o++] = '.';
+ memcpy(&res[o],&h.payload[i + 1],h.payload[i]);
+ o += h.payload[i];
+ i += h.payload[i] + 1;
+ }
+ }
+ }
+ res[o] = '\0';
+ break;
+ case DNS_QRY_A:
+ log(DEBUG,"DNS: got a result of type DNS_QRY_A");
+ if (this->want_list)
+ {
+ dns_ip4list *alist = (dns_ip4list *) res; /* we have to trust that this is aligned */
+ while ((char *)alist - (char *)res < 700)
+ {
+ if (rr.type != DNS_QRY_A)
+ break;
+ if (rr._class != 1)
+ break;
+ if (rr.rdlength != 4)
+ {
+ return NULL;
+ }
+ memcpy(&alist->ip,&h.payload[i],4);
+ if ((unsigned)++curanswer >= h.ancount)
+ break;
+ i += rr.rdlength;
+ q = 0;
+ while (q == 0 && i < length)
+ {
+ if (h.payload[i] > 63)
+ {
+ i += 2;
+ q = 1;
+ }
+ else
+ {
+ if (h.payload[i] == 0)
+ {
+ i++;
+ q = 1;
+ }
+ else i += h.payload[i] + 1;
+ }
+ }
+ if (length - i < 10)
+ {
+ return NULL;
+ }
+ dns_fill_rr(&rr,&h.payload[i]);
+ i += 10;
+ alist->next = (dns_ip4list *) dns_align(((char *) alist) + sizeof(dns_ip4list));
+ alist = alist->next;
+ alist->next = NULL;
+ }
+ alist->next = NULL;
+ break;
+ }
+ memcpy(res,&h.payload[i],rr.rdlength);
+ res[rr.rdlength] = '\0';
+ break;
+ default:
+ memcpy(res,&h.payload[i],rr.rdlength);
+ res[rr.rdlength] = '\0';
+ break;
+ }
+ return res;
}
-std::string DNS::GetResultIP()
+DNS::DNS()
{
- char r[1024];
- log(DEBUG,"DNS: GetResultIP()");
- result = dns_getresult(this->myfd);
- if (this->myfd != -1)
- {
- dns_close(this->myfd);
- this->myfd = -1;
- }
- if (result)
- {
- if (ServerInstance && ServerInstance->stats)
- ServerInstance->stats->statsDnsGood++;
- unsigned char a = (unsigned)result[0];
- unsigned char b = (unsigned)result[1];
- unsigned char c = (unsigned)result[2];
- unsigned char d = (unsigned)result[3];
- snprintf(r,1024,"%u.%u.%u.%u",a,b,c,d);
- return r;
- }
- else
- {
- if (ServerInstance && ServerInstance->stats)
- ServerInstance->stats->statsDnsBad++;
- log(DEBUG,"DANGER WILL ROBINSON! NXDOMAIN for forward lookup, but we got a reverse lookup!");
- return "";
- }
+ log(DEBUG,"Create blank DNS");
}
-
-
-#ifdef THREADED_DNS
-
-/* This function is a thread function which can be thought of as a lightweight process
- * to all you non-threaded people. In actuality its so much more, and pretty damn cool.
- * With threaded dns enabled, each user which connects gets a thread attached to their
- * user record when their DNS lookup starts. This function starts in parallel, and
- * commences a blocking dns lookup. Because its a seperate thread, this occurs without
- * actually blocking the main application. Once the dns lookup is completed, the thread
- * checks if the user is still around by checking their fd against the reference table,
- * and if they are, writes the hostname into the struct and terminates, after setting
- * userrec::dns_done to true. Because this is multi-threaded it can make proper use of
- * SMP setups (like the one i have here *grin*).
- * This is in comparison to the non-threaded dns, which must monitor the thread sockets
- * in a nonblocking fashion, consuming more resources to do so.
- *
- * NB: Yes this does scale, thank you. Even with large numbers of connecting clients
- * in any one timeframe, they wont all connect *at the same time* therefore any argument
- * of "but there will be thousands of threads it'll blow up" is moot, ive tested this and
- * there will only ever be somewhere around the listen backlog in number of pending
- * lookups at any one time. This is significant on any modern SMP system.
- */
-void* dns_task(void* arg)
+DNS::~DNS()
{
- userrec* u = (userrec*)arg;
- int thisfd = u->fd;
-
- log(DEBUG,"DNS thread for user %s on ip %s",u->nick,insp_ntoa(u->ip4));
- DNS dns1(Config->DNSServer);
- DNS dns2(Config->DNSServer);
- std::string host;
- std::string ip;
- int iterations = 0;
-
- if (dns1.ReverseLookup(insp_ntoa(u->ip4),false))
- {
- /* FIX: Dont make these infinite! */
- while ((!dns1.HasResult()) && (++iterations < 20))
- usleep(100);
-
- if (iterations < 20)
- {
- if (dns1.GetFD() != -1)
- {
- host = dns1.GetResult();
- if (host != "")
- {
- if (dns2.ForwardLookup(host, false))
- {
- iterations = 0;
- while ((!dns2.HasResult()) && (++iterations < 20))
- usleep(100);
-
- if (iterations < 20)
- {
- if (dns2.GetFD() != -1)
- {
- ip = dns2.GetResultIP();
- if (ip == std::string(insp_ntoa(u->ip4)))
- {
- if (host.length() < 65)
- {
- if ((fd_ref_table[thisfd] == u) && (fd_ref_table[thisfd]))
- {
- if (!u->dns_done)
- {
- strcpy(u->host,host.c_str());
- if ((fd_ref_table[thisfd] == u) && (fd_ref_table[thisfd]))
- {
- strcpy(u->dhost,host.c_str());
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- if ((fd_ref_table[thisfd] == u) && (fd_ref_table[thisfd]))
- u->dns_done = true;
- log(DEBUG,"THREAD EXIT");
- return NULL;
}
-#endif
Resolver::Resolver(const std::string &source, bool forward, const std::string &dnsserver = "") : input(source), fwd(forward), server(dnsserver)
{
- if (this->server != "")
- Query.SetNS(this->server);
- else
- Query.SetNS(Config->DNSServer);
-
- if (forward)
- {
- Query.ForwardLookup(input.c_str(), false);
- this->fd = Query.GetFD();
- }
- else
- {
- Query.ReverseLookup(input.c_str(), false);
- this->fd = Query.GetFD();
- }
- if (fd < 0)
- {
- log(DEBUG,"Resolver::Resolver: RESOLVER_NSDOWN");
- this->OnError(RESOLVER_NSDOWN);
- ModuleException e("Resolver: Nameserver is down");
- throw e;
- /* We shouldnt get here really */
- return;
- }
+ if (forward)
+ {
+ this->myid = Res->dns_getip4(source.c_str());
+ }
+ else
+ {
+ insp_inaddr binip;
+ if (insp_aton(source.c_str(), &binip) > 0)
+ {
+ /* Valid ip address */
+ this->myid = Res->dns_getname4(&binip);
+ }
+ }
+ if (this->myid == -1)
+ {
+ log(DEBUG,"Resolver::Resolver: Could not get an id!");
+ this->OnError(RESOLVER_NSDOWN);
+ ModuleException e("Resolver: Couldnt get an id to make a request");
+ throw e;
+ /* We shouldnt get here really */
+ return;
+ }
- if (ServerInstance && ServerInstance->SE)
- {
- log(DEBUG,"Resolver::Resolver: this->fd=%d",this->fd);
- ServerInstance->SE->AddFd(this->fd,true,X_ESTAB_CLASSDNS);
- }
- else
- {
- log(DEBUG,"Resolver::Resolver: RESOLVER_NOTREADY");
- this->OnError(RESOLVER_NOTREADY);
- ModuleException e("Resolver: Core not initialized yet");
- throw e;
- /* We shouldnt get here really */
- return;
- }
+ log(DEBUG,"Resolver::Resolver: this->myid=%d",this->myid);
}
Resolver::~Resolver()
{
- log(DEBUG,"Resolver::~Resolver");
- if (ServerInstance && ServerInstance->SE)
- ServerInstance->SE->DelFd(this->fd);
+ log(DEBUG,"Resolver::~Resolver");
}
-int Resolver::GetFd()
+int Resolver::GetId()
{
- return this->fd;
+ return this->myid;
}
bool Resolver::ProcessResult()
{
- log(DEBUG,"Resolver::ProcessResult");
- if (this->fwd)
- result = Query.GetResultIP();
- else
- result = Query.GetResult();
+ log(DEBUG,"Resolver::ProcessResult");
- if (result != "")
- {
- log(DEBUG,"Resolver::OnLookupComplete(%s)",result.c_str());
- this->OnLookupComplete(result);
- return true;
- }
- else
- {
- log(DEBUG,"Resolver::OnError(RESOLVER_NXDOMAIN)");
- this->OnError(RESOLVER_NXDOMAIN);
- return false;
- }
+ std::map<int, std::string>::iterator x = result_list.find(this->myid);
+
+ if (x == result_list.end())
+ {
+ log(DEBUG,"Resolver::OnError(RESOLVER_NXDOMAIN)");
+ this->OnError(RESOLVER_NXDOMAIN);
+ return false;
+ }
+ else
+ {
+
+ log(DEBUG,"Resolver::OnLookupComplete(%s)",x->second.c_str());
+ this->OnLookupComplete(x->second);
+ result_list.erase(x);
+ return true;
+ }
}
void Resolver::OnLookupComplete(const std::string &result)
@@ -1034,43 +702,49 @@ void Resolver::OnError(ResolverError e)
void dns_deal_with_classes(int fd)
{
- log(DEBUG,"dns_deal_with_classes(%d)",fd);
- if ((fd > -1) && (dns_classes[fd]))
- {
- log(DEBUG,"Valid fd %d",fd);
- dns_classes[fd]->ProcessResult();
- delete dns_classes[fd];
- dns_classes[fd] = NULL;
- }
+ log(DEBUG,"dns_deal_with_classes(%d)",fd);
+ if (fd == master_socket)
+ {
+ int id = Res->dns_getresult();
+ if (id != -1)
+ {
+ log(DEBUG,"Result available, id=%d",id);
+ dns_classes[id]->ProcessResult();
+ delete dns_classes[id];
+ dns_classes[id] = NULL;
+ }
+ }
}
bool dns_add_class(Resolver* r)
{
- log(DEBUG,"dns_add_class");
- if ((r) && (r->GetFd() > -1))
- {
- if (!dns_classes[r->GetFd()])
- {
- log(DEBUG,"dns_add_class: added class");
- dns_classes[r->GetFd()] = r;
- return true;
- }
- else
- {
- log(DEBUG,"Space occupied!");
- return false;
- }
- }
- else
- {
- log(DEBUG,"Bad class");
- delete r;
- return true;
- }
+ log(DEBUG,"dns_add_class");
+ if ((r) && (r->GetId() > -1))
+ {
+ if (!dns_classes[r->GetId()])
+ {
+ log(DEBUG,"dns_add_class: added class");
+ dns_classes[r->GetId()] = r;
+ return true;
+ }
+ else
+ {
+ log(DEBUG,"Space occupied!");
+ return false;
+ }
+ }
+ else
+ {
+ log(DEBUG,"Bad class");
+ delete r;
+ return true;
+ }
}
void init_dns()
{
- memset(dns_classes,0,sizeof(dns_classes));
+ Res = new DNS();
+ memset(dns_classes,0,sizeof(dns_classes));
+ create_socket();
}
diff --git a/src/dnsqueue.cpp b/src/dnsqueue.cpp
index e9265fc37..b887ffca5 100644
--- a/src/dnsqueue.cpp
+++ b/src/dnsqueue.cpp
@@ -35,288 +35,15 @@
extern ServerConfig* Config;
extern InspIRCd* ServerInstance;
-class Lookup;
-
-Lookup* dnslist[MAX_DESCRIPTORS];
-Lookup* user_fd_to_dns[MAX_DESCRIPTORS];
-extern userrec* fd_ref_table[MAX_DESCRIPTORS];
-
-//enum LookupState { reverse, forward };
-
-class Lookup {
-private:
- char u[NICKMAX];
- std::string hostname;
-public:
- DNS resolver1;
- DNS resolver2;
-
- Lookup()
- {
- *u = 0;
- hostname = "";
- }
-
- void Reset()
- {
- *u = 0;
- hostname = "";
- }
-
- ~Lookup()
- {
- }
-
- bool DoLookup(std::string nick)
- {
- hostname = "";
- userrec* usr = Find(nick);
- if (usr)
- {
- resolver1.SetNS(std::string(Config->DNSServer));
- if (!resolver1.ReverseLookup(std::string(usr->host), true))
- {
- return false;
- }
- strlcpy(u,nick.c_str(),NICKMAX-1);
-
- /* ASSOCIATE WITH DNS LOOKUP LIST */
- if (resolver1.GetFD() != -1)
- {
- dnslist[resolver1.GetFD()] = this;
- user_fd_to_dns[usr->fd] = this;
- return true;
- }
- }
- return false;
- }
-
- bool Done(int fdcheck)
- {
- if (hostname != "")
- {
- // doing forward lookup
- userrec* usr = NULL;
- if (resolver2.HasResult(fdcheck))
- {
- if (resolver2.GetFD() != -1)
- {
- dnslist[resolver2.GetFD()] = NULL;
- std::string ip = resolver2.GetResultIP();
- usr = Find(u);
- if (usr)
- {
- if (usr->registered > REG_NICKUSER)
- {
- usr->dns_done = true;
- return true;
- }
- if ((hostname != "") && (usr->registered != REG_ALL))
- {
- if ((std::string(insp_ntoa(usr->ip4)) == ip) && (hostname.length() < 65))
- {
- if ((hostname.find_last_of(".in-addr.arpa") == hostname.length() - 1) && (hostname.find_last_of(".in-addr.arpa") != std::string::npos))
- {
- WriteServ(usr->fd,"NOTICE Auth :*** Your ISP are muppets -- reverse resolution resolves back to same reverse .arpa domain (!)");
- }
- else
- {
- strlcpy(usr->host,hostname.c_str(),64);
- strlcpy(usr->dhost,hostname.c_str(),64);
- WriteServ(usr->fd,"NOTICE Auth :*** Found your hostname");
- }
- }
- usr->dns_done = true;
- return true;
- }
- }
- }
- else
- {
- usr = Find(u);
- if (usr)
- {
- usr->dns_done = true;
- }
- return true;
- }
- }
- return false;
- }
- else
- {
- // doing reverse lookup
- userrec* usr = NULL;
- if (resolver1.HasResult(fdcheck))
- {
- usr = Find(u);
- if ((usr) && (usr->dns_done))
- {
- if (resolver1.GetFD() != -1)
- {
- dnslist[resolver1.GetFD()] = NULL;
- user_fd_to_dns[usr->fd] = NULL;
- }
- return true;
- }
- if (resolver1.GetFD() != -1)
- {
- dnslist[resolver1.GetFD()] = NULL;
- hostname = resolver1.GetResult();
- if (usr)
- {
- user_fd_to_dns[usr->fd] = NULL;
- if ((usr->registered > REG_NICKUSER) || (hostname == ""))
- {
- WriteServ(usr->fd,"NOTICE Auth :*** Could not resolve your hostname -- Using your IP address instead");
- usr->dns_done = true;
- return true;
- }
- if (hostname != "")
- {
- resolver2.ForwardLookup(hostname, true);
- if (resolver2.GetFD() != -1)
- {
- dnslist[resolver2.GetFD()] = this;
- if (usr)
- user_fd_to_dns[usr->fd] = this;
- }
- }
- }
- }
- }
- }
- return false;
- }
-
- int GetFD()
- {
- userrec* usr = Find(u);
- if (!usr)
- return 0;
- if (usr->dns_done)
- return 0;
- return usr->fd;
- }
-};
-
bool lookup_dns(const std::string &nick)
{
- /* First attempt to find the nickname */
- userrec* u = Find(nick);
- if (u)
- {
- /* Check the cache */
- /*address_cache::iterator address = addrcache.find(u->ip4);
- if (address != addrcache.end())
- {
- WriteServ(u->fd,"NOTICE Auth :*** Found your hostname (cached)");
- log(DEBUG,"Found cached host");
- strlcpy(u->host,address->second->c_str(),MAXBUF);
- strlcpy(u->dhost,address->second->c_str(),MAXBUF);
- u->dns_done = true;
- return true;
- }*/
- /* If the user exists, create a new
- * lookup object, and associate it
- * with the user. The lookup object
- * will maintain the reference table
- * which we use for quickly finding
- * dns results. Please note that we
- * do not associate a lookup with a
- * userrec* pointer and we use the
- * nickname instead because, by the
- * time the DNS lookup has completed,
- * the nickname could have quit and
- * if we then try and access the
- * pointer we get a nice segfault.
- */
- Lookup* L = new Lookup();
- L->DoLookup(nick);
- return true;
- }
return false;
}
void ZapThisDns(int fd)
{
-#ifdef THREADED_DNS
-/* if (fd_ref_table[fd])
- {
- if (fd_ref_table[fd]->registered >= REG_NICKUSER)
- {
- log(DEBUG,"Joining thread for user %d",fd);
- if (pthread_join(fd_ref_table[fd]->dnsthread, NULL))
- {
- log(DEBUG,"Can't pthread_join(): %s", strerror(errno));
- }
- }
- }*/
-#else
- if ((fd < 0) || (fd > MAX_DESCRIPTORS))
- return;
-
- Lookup *x = user_fd_to_dns[fd];
-
- if (x)
- {
- if (x->resolver1.GetFD() > 0)
- {
- log(DEBUG,"Whacked resolver1");
- dns_close(x->resolver1.GetFD());
- }
-
- if (x->resolver2.GetFD() > 0)
- {
- log(DEBUG,"Whacked resolver2");
- dns_close(x->resolver2.GetFD());
- }
- }
-#endif
}
void dns_poll(int fdcheck)
{
- /* Check the given file descriptor is in valid range */
- if ((fdcheck < 0) || (fdcheck > MAX_DESCRIPTORS))
- return;
-
- /* Try and find the file descriptor in our list of
- * active DNS lookups
- */
- Lookup *x = dnslist[fdcheck];
- if (x)
- {
- /* If it exists check if its a valid fd still */
- if (x->GetFD() != -1)
- {
- /* Check if its done, if it is delete it */
- if (x->Done(fdcheck))
- {
- /* We don't need to delete the file descriptor
- * from the socket engine, as dns.cpp tracks it
- * for us if we are in single-threaded country.
- */
- DELETE(x);
- }
- }
- else
- {
- /* its fd is dodgy, the dns code probably
- * bashed it due to error. Free the class.
- */
- DELETE(x);
- }
- /* If we got down here, the dns lookup was valid, BUT,
- * its still in progress. Be patient, and wait for
- * more socketengine events to complete the lookups.
- */
- return;
- }
- /* This FD doesnt belong here, lets be rid of it,
- * just to be safe so we dont get any more events
- * about it.
- */
- if (ServerInstance && ServerInstance->SE)
- ServerInstance->SE->DelFd(fdcheck);
}
diff --git a/src/inspircd.cpp b/src/inspircd.cpp
index 57c23b328..a72ee2534 100644
--- a/src/inspircd.cpp
+++ b/src/inspircd.cpp
@@ -45,9 +45,6 @@
#include <fstream>
#include <vector>
#include <deque>
-#ifdef THREADED_DNS
-#include <pthread.h>
-#endif
#include "users.h"
#include "ctables.h"
#include "globals.h"
@@ -238,7 +235,6 @@ InspIRCd::InspIRCd(int argc, char** argv)
{
this->Start();
module_sockets.clear();
- init_dns();
this->startup_time = time(NULL);
srand(time(NULL));
log(DEBUG,"*** InspIRCd starting up!");
@@ -336,11 +332,7 @@ InspIRCd::InspIRCd(int argc, char** argv)
std::string InspIRCd::GetVersionString()
{
char versiondata[MAXBUF];
-#ifdef THREADED_DNS
- char dnsengine[] = "multithread";
-#else
- char dnsengine[] = "singlethread";
-#endif
+ char dnsengine[] = "singlethread-object";
if (*Config->CustomVersion)
{
snprintf(versiondata,MAXBUF,"%s %s :%s",VERSION,Config->ServerName,Config->CustomVersion);
@@ -825,20 +817,6 @@ void InspIRCd::DoOneIteration(bool process_module_sockets)
break;
case X_ESTAB_DNS:
- /* When we are using single-threaded dns,
- * the sockets for dns end up in our mainloop.
- * When we are using multi-threaded dns,
- * each thread has its own basic poll() loop
- * within it, making them 'fire and forget'
- * and independent of the mainloop.
- */
-#ifndef THREADED_DNS
- log(DEBUG,"Type: X_ESTAB_DNS: fd=%d",activefds[activefd]);
- dns_poll(activefds[activefd]);
-#endif
- break;
-
- case X_ESTAB_CLASSDNS:
/* Handles instances of the Resolver class,
* a simple class extended by modules for
* nonblocking resolving of addresses.
@@ -918,6 +896,8 @@ int InspIRCd::Run()
{
/* Until THIS point, ServerInstance == NULL */
+ init_dns();
+
LoadAllModules(this);
/* Just in case no modules were loaded - fix for bug #101 */
diff --git a/src/inspsocket.cpp b/src/inspsocket.cpp
index d6b836c4d..99ef731c6 100644
--- a/src/inspsocket.cpp
+++ b/src/inspsocket.cpp
@@ -103,8 +103,9 @@ InspSocket::InspSocket(const std::string &ahost, int aport, bool listening, unsi
{
log(DEBUG,"Attempting to resolve %s",this->host);
/* Its not an ip, spawn the resolver */
- this->dns.SetNS(std::string(Config->DNSServer));
- this->dns.ForwardLookupWithFD(host,fd);
+
+ /* TODO: Implement resolver with new Resolver class */
+
timeout_end = time(NULL) + maxtime;
timeout = false;
this->state = I_RESOLVING;
@@ -149,28 +150,7 @@ void InspSocket::SetQueues(int nfd)
bool InspSocket::DoResolve()
{
log(DEBUG,"In DoResolve(), trying to resolve IP");
- if (this->dns.HasResult())
- {
- log(DEBUG,"Socket has result");
- std::string res_ip = dns.GetResultIP();
- if (res_ip != "")
- {
- log(DEBUG,"Socket result set to %s",res_ip.c_str());
- strlcpy(this->IP,res_ip.c_str(),MAXBUF);
- socket_ref[this->fd] = NULL;
- }
- else
- {
- log(DEBUG,"Socket DNS failure");
- this->Close();
- this->state = I_ERROR;
- this->OnError(I_ERR_RESOLVE);
- this->fd = -1;
- this->ClosePending = true;
- return false;
- }
- return this->DoConnect();
- }
+
log(DEBUG,"No result for socket yet!");
return true;
}
diff --git a/src/message.cpp b/src/message.cpp
index 88ff0ad3d..96b540db4 100644
--- a/src/message.cpp
+++ b/src/message.cpp
@@ -97,24 +97,7 @@ void NonBlocking(int s)
int CleanAndResolve (char *resolvedHost, const char *unresolvedHost, bool forward, unsigned long timeout)
{
- bool ok;
- std::string ipaddr;
-
- DNS d(Config->DNSServer);
- if (forward)
- ok = d.ForwardLookup(unresolvedHost, false);
- else
- ok = d.ReverseLookup(unresolvedHost, false);
- if (!ok)
- return 0;
- time_t T = time(NULL)+timeout;
- while ((!d.HasResult()) && (time(NULL)<T));
- if (forward)
- ipaddr = d.GetResultIP();
- else
- ipaddr = d.GetResult();
- strlcpy(resolvedHost,ipaddr.c_str(),MAXBUF);
- return (ipaddr != "");
+ return 0;
}
int c_count(userrec* u)