From dac672cf303ce44dc5f877a5f9f7e5aee64b95e1 Mon Sep 17 00:00:00 2001 From: brain Date: Sun, 7 Jan 2007 21:16:03 +0000 Subject: DNS Stuff - this wont work right yet, it will soon (tm) git-svn-id: http://svn.inspircd.org/repository/trunk/inspircd@6250 e03df62e-2008-0410-955e-edbf42e46eb7 --- include/dns.h | 44 ++++++++++++++++-- include/users.h | 2 +- src/dns.cpp | 102 +++++++++++++++++++++++++++++++++++------ src/modules/extra/m_pgsql.cpp | 13 ++++-- src/modules/m_cgiirc.cpp | 20 +++++--- src/modules/m_dnsbl.cpp | 12 +++-- src/modules/m_http_client.cpp | 9 +++- src/modules/m_spanningtree.cpp | 20 +++++--- src/modules/m_testcommand.cpp | 24 ++++++++-- src/users.cpp | 22 ++++++--- 10 files changed, 213 insertions(+), 55 deletions(-) diff --git a/include/dns.h b/include/dns.h index cb7e0549a..83e4ab902 100644 --- a/include/dns.h +++ b/include/dns.h @@ -37,6 +37,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "base.h" #include "socketengine.h" #include "socket.h" +#include "hash_map.h" +#include "hashcomp.h" using namespace std; using irc::sockets::insp_aton; @@ -56,8 +58,9 @@ class DNSResult : public classbase int id; std::string result; unsigned long ttl; + std::string original; - DNSResult(int i, const std::string &res, unsigned long timetolive) : id(i), result(res), ttl(timetolive) { } + DNSResult(int i, const std::string &res, unsigned long timetolive, const std::string &orig) : id(i), result(res), ttl(timetolive), original(orig) { } }; /** @@ -65,6 +68,30 @@ class DNSResult : public classbase */ typedef std::pair DNSInfo; +/** Cached item + */ +class CachedQuery +{ + public: + std::string data; + time_t expires; + + CachedQuery(const std::string &res, unsigned int ttl) : data(res) + { + expires = time(NULL) + ttl; + } + + int CalcTTLRemaining() + { + int n = expires - time(NULL); + return (n < 0 ? 0 : n); + } +}; + +/** DNS cache information + */ +typedef nspace::hash_map > dnscache; + /** * Error types that class Resolver can emit to its error method. */ @@ -201,7 +228,7 @@ class Resolver : public Extensible * whilst lookups are in progress, they can be safely removed and your module will not * crash the server. */ - Resolver(InspIRCd* Instance, const std::string &source, QueryType qt, Module* creator = NULL); + Resolver(InspIRCd* Instance, const std::string &source, QueryType qt, bool &cached, Module* creator = NULL); /** * The default destructor does nothing. @@ -211,7 +238,7 @@ class Resolver : public Extensible * When your lookup completes, this method will be called. * @param result The resulting DNS lookup, either an IP address or a hostname. */ - virtual void OnLookupComplete(const std::string &result, unsigned int ttl) = 0; + virtual void OnLookupComplete(const std::string &result, unsigned int ttl); /** * If an error occurs (such as NXDOMAIN, no domain name found) then this method * will be called. @@ -270,6 +297,11 @@ class DNS : public EventHandler */ bool ip6munge; + /** + * Currently cached items + */ + dnscache* cache; + /** * Build a dns packet payload */ @@ -352,7 +384,7 @@ class DNS : public EventHandler /** * Add a query to the list to be sent */ - DNSRequest* AddQuery(DNSHeader *header, int &id); + DNSRequest* AddQuery(DNSHeader *header, int &id, const char* original); /** * The constructor initialises the dns socket, @@ -388,6 +420,10 @@ class DNS : public EventHandler * are dns requests currently in progress. */ void CleanResolvers(Module* module); + + CachedQuery* GetCache(const std::string &source); + + void DelCache(const std::string &source); }; #endif diff --git a/include/users.h b/include/users.h index 749030894..c26d791fa 100644 --- a/include/users.h +++ b/include/users.h @@ -67,7 +67,7 @@ class UserResolver : public Resolver int bound_fd; bool fwd; public: - UserResolver(InspIRCd* Instance, userrec* user, std::string to_resolve, QueryType qt); + UserResolver(InspIRCd* Instance, userrec* user, std::string to_resolve, QueryType qt, bool &cache); void OnLookupComplete(const std::string &result, unsigned int ttl); void OnError(ResolverError e, const std::string &errormessage); diff --git a/src/dns.cpp b/src/dns.cpp index d2f08a6e0..385f8639e 100644 --- a/src/dns.cpp +++ b/src/dns.cpp @@ -95,8 +95,9 @@ class DNSRequest insp_inaddr myserver; /* DNS server address*/ DNS* dnsobj; /* DNS caller (where we get our FD from) */ unsigned long ttl; /* Time to live */ + std::string orig; /* Original requested name/ip */ - DNSRequest(InspIRCd* Instance, DNS* dns, insp_inaddr server, int id); + DNSRequest(InspIRCd* Instance, DNS* dns, insp_inaddr server, int id, const std::string &original); ~DNSRequest(); DNSInfo ResultIsReady(DNSHeader &h, int length); int SendRequests(const DNSHeader *header, const int length, QueryType qt); @@ -134,11 +135,12 @@ class RequestTimeout : public InspTimer }; /* Allocate the processing buffer */ -DNSRequest::DNSRequest(InspIRCd* Instance, DNS* dns, insp_inaddr server, int id) : dnsobj(dns) +DNSRequest::DNSRequest(InspIRCd* Instance, DNS* dns, insp_inaddr server, int id, const std::string &original) : dnsobj(dns) { res = new unsigned char[512]; *res = 0; memcpy(&myserver, &server, sizeof(insp_inaddr)); + orig = original; 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 */ } @@ -218,7 +220,7 @@ int DNSRequest::SendRequests(const DNSHeader *header, const int length, QueryTyp } /** Add a query with a predefined header, and allocate an ID for it. */ -DNSRequest* DNS::AddQuery(DNSHeader *header, int &id) +DNSRequest* DNS::AddQuery(DNSHeader *header, int &id, const char* original) { /* Is the DNS connection down? */ if (this->GetFd() == -1) @@ -231,7 +233,7 @@ DNSRequest* DNS::AddQuery(DNSHeader *header, int &id) while (requests[id]) id = this->PRNG() & DNS::MAX_REQUEST_ID; - DNSRequest* req = new DNSRequest(ServerInstance, this, this->myserver, id); + DNSRequest* req = new DNSRequest(ServerInstance, this, this->myserver, id, original); header->id[0] = req->id[0] = id >> 8; header->id[1] = req->id[1] = id & 0xFF; @@ -263,6 +265,19 @@ void DNS::Rehash() shutdown(this->GetFd(), 2); close(this->GetFd()); this->SetFd(-1); + + /* Rehash the cache */ + dnscache* newcache = new dnscache(); + for (dnscache::iterator i = this->cache->begin(); i != this->cache->end(); i++) + newcache->insert(*i); + + delete this->cache; + this->cache = newcache; + } + else + { + /* Create initial dns cache */ + this->cache = new dnscache(); } if (insp_aton(ServerInstance->Config->DNSServer,&addr) > 0) @@ -358,9 +373,18 @@ DNS::DNS(InspIRCd* Instance) : ServerInstance(Instance) /* Set the id of the next request to 0 */ currid = 0; + + /* DNS::Rehash() sets this to a valid ptr + */ + this->cache = NULL; + /* Again, DNS::Rehash() sets this to a + * valid value + */ this->SetFd(-1); + /* Actually read the settings + */ this->Rehash(); } @@ -411,7 +435,7 @@ int DNS::GetIP(const char *name) if ((length = this->MakePayload(name, DNS_QUERY_A, 1, (unsigned char*)&h.payload)) == -1) return -1; - DNSRequest* req = this->AddQuery(&h, id); + DNSRequest* req = this->AddQuery(&h, id, name); if ((!req) || (req->SendRequests(&h, length, DNS_QUERY_A) == -1)) return -1; @@ -429,7 +453,7 @@ int DNS::GetIP6(const char *name) if ((length = this->MakePayload(name, DNS_QUERY_AAAA, 1, (unsigned char*)&h.payload)) == -1) return -1; - DNSRequest* req = this->AddQuery(&h, id); + DNSRequest* req = this->AddQuery(&h, id, name); if ((!req) || (req->SendRequests(&h, length, DNS_QUERY_AAAA) == -1)) return -1; @@ -447,7 +471,7 @@ int DNS::GetCName(const char *alias) if ((length = this->MakePayload(alias, DNS_QUERY_CNAME, 1, (unsigned char*)&h.payload)) == -1) return -1; - DNSRequest* req = this->AddQuery(&h, id); + DNSRequest* req = this->AddQuery(&h, id, alias); if ((!req) || (req->SendRequests(&h, length, DNS_QUERY_CNAME) == -1)) return -1; @@ -479,7 +503,7 @@ int DNS::GetName(const insp_inaddr *ip) if ((length = this->MakePayload(query, DNS_QUERY_PTR, 1, (unsigned char*)&h.payload)) == -1) return -1; - DNSRequest* req = this->AddQuery(&h, id); + DNSRequest* req = this->AddQuery(&h, id, insp_ntoa(*ip)); if ((!req) || (req->SendRequests(&h, length, DNS_QUERY_PTR) == -1)) return -1; @@ -525,7 +549,7 @@ int DNS::GetNameForce(const char *ip, ForceProtocol fp) if ((length = this->MakePayload(query, DNS_QUERY_PTR, 1, (unsigned char*)&h.payload)) == -1) return -1; - DNSRequest* req = this->AddQuery(&h, id); + DNSRequest* req = this->AddQuery(&h, id, ip); if ((!req) || (req->SendRequests(&h, length, DNS_QUERY_PTR) == -1)) return -1; @@ -577,7 +601,7 @@ DNSResult DNS::GetResult() { /* Nope - something screwed up. */ ServerInstance->Log(DEBUG,"Whole header not read!"); - return DNSResult(-1,"",0); + return DNSResult(-1,"",0,""); } /* Check wether the reply came from a different DNS @@ -605,7 +629,7 @@ DNSResult DNS::GetResult() if ((port_from != DNS::QUERY_PORT) || (strcasecmp(ipaddr_from, ServerInstance->Config->DNSServer))) { ServerInstance->Log(DEBUG,"port %d is not 53, or %s is not %s",port_from, ipaddr_from, ServerInstance->Config->DNSServer); - return DNSResult(-1,"",0); + return DNSResult(-1,"",0,""); } } @@ -623,7 +647,7 @@ DNSResult DNS::GetResult() { /* 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); - return DNSResult(-1,"",0); + return DNSResult(-1,"",0,""); } else { @@ -648,8 +672,9 @@ DNSResult DNS::GetResult() * an error response and needs to be treated uniquely. * Put the error message in the second field. */ + std::string ro = req->orig; delete req; - return DNSResult(this_id | ERROR_MASK, data.second, 0); + return DNSResult(this_id | ERROR_MASK, data.second, 0, ro); } else { @@ -714,8 +739,9 @@ DNSResult DNS::GetResult() } /* Build the reply with the id and hostname/ip in it */ + std::string ro = req->orig; delete req; - return DNSResult(this_id,resultstr,ttl); + return DNSResult(this_id,resultstr,ttl,ro); } } @@ -871,11 +897,50 @@ DNS::~DNS() close(this->GetFd()); } +CachedQuery* DNS::GetCache(const std::string &source) +{ + dnscache::iterator x = cache->find(source.c_str()); + if (x != cache->end()) + return &(x->second); + else + return NULL; +} + +void DNS::DelCache(const std::string &source) +{ + cache->erase(source.c_str()); +} + +void Resolver::OnLookupComplete(const std::string &result, unsigned int ttl) +{ + throw CoreException("Someone didnt define an OnLookupComplete method for their Resolver class!"); +} + /** High level abstraction of dns used by application at large */ -Resolver::Resolver(InspIRCd* Instance, const std::string &source, QueryType qt, Module* creator) : ServerInstance(Instance), Creator(creator), input(source), querytype(qt) +Resolver::Resolver(InspIRCd* Instance, const std::string &source, QueryType qt, bool &cached, Module* creator) : ServerInstance(Instance), Creator(creator), input(source), querytype(qt) { ServerInstance->Log(DEBUG,"Instance: %08x %08x",Instance, ServerInstance); + cached = false; + + CachedQuery* CQ = ServerInstance->Res->GetCache(source); + if (CQ) + { + int time_left = CQ->CalcTTLRemaining(); + if (!time_left) + { + ServerInstance->Log(DEBUG,"Cached but EXPIRED result: %s", CQ->data.c_str()); + ServerInstance->Res->DelCache(source); + } + else + { + cached = true; + ServerInstance->Log(DEBUG,"Cached result: %s", CQ->data.c_str()); + OnLookupComplete(CQ->data, time_left); + return; + } + } + insp_inaddr binip; switch (querytype) @@ -988,6 +1053,13 @@ void DNS::HandleEvent(EventType et, int errornum) { if (ServerInstance && ServerInstance->stats) ServerInstance->stats->statsDnsGood++; + + if (!this->GetCache(res.original.c_str())) + { + ServerInstance->Log(DEBUG,"Caching result: %s->%s for %lu secs", res.original.c_str(), res.result.c_str(), res.ttl); + this->cache->insert(std::make_pair(res.original.c_str(), CachedQuery(res.result, res.ttl))); + } + Classes[res.id]->OnLookupComplete(res.result, res.ttl); delete Classes[res.id]; Classes[res.id] = NULL; diff --git a/src/modules/extra/m_pgsql.cpp b/src/modules/extra/m_pgsql.cpp index 79630d416..d72256a5f 100644 --- a/src/modules/extra/m_pgsql.cpp +++ b/src/modules/extra/m_pgsql.cpp @@ -90,8 +90,8 @@ class SQLresolver : public Resolver SQLhost host; Module* mod; public: - SQLresolver(Module* m, InspIRCd* Instance, const SQLhost& hi) - : Resolver(Instance, hi.host, DNS_QUERY_FORWARD, (Module*)m), host(hi), mod(m) + SQLresolver(Module* m, InspIRCd* Instance, const SQLhost& hi, bool &cached) + : Resolver(Instance, hi.host, DNS_QUERY_FORWARD, cached, (Module*)m), host(hi), mod(m) { } @@ -1099,9 +1099,12 @@ public: try { - resolver = new SQLresolver(this, ServerInstance, host); - - ServerInstance->AddResolver(resolver); + bool cached; + resolver = new SQLresolver(this, ServerInstance, host, cached); + if (!cached) + ServerInstance->AddResolver(resolver); + else + delete resolver; } catch(...) { diff --git a/src/modules/m_cgiirc.cpp b/src/modules/m_cgiirc.cpp index dc11ccf96..6df039dce 100644 --- a/src/modules/m_cgiirc.cpp +++ b/src/modules/m_cgiirc.cpp @@ -51,8 +51,8 @@ class CGIResolver : public Resolver userrec* them; bool notify; public: - CGIResolver(Module* me, InspIRCd* ServerInstance, bool NotifyOpers, const std::string &source, bool forward, userrec* u, int userfd, const std::string &type) - : Resolver(ServerInstance, source, forward ? DNS_QUERY_FORWARD : DNS_QUERY_REVERSE, me), typ(type), theirfd(userfd), them(u), notify(NotifyOpers) { } + CGIResolver(Module* me, InspIRCd* ServerInstance, bool NotifyOpers, const std::string &source, bool forward, userrec* u, int userfd, const std::string &type, bool &cached) + : Resolver(ServerInstance, source, forward ? DNS_QUERY_FORWARD : DNS_QUERY_REVERSE, cached, me), typ(type), theirfd(userfd), them(u), notify(NotifyOpers) { } virtual void OnLookupComplete(const std::string &result, unsigned int ttl) { @@ -259,8 +259,12 @@ public: try { - CGIResolver* r = new CGIResolver(this, ServerInstance, NotifyOpers, user->password, false, user, user->GetFd(), "PASS"); - ServerInstance->AddResolver(r); + bool cached; + CGIResolver* r = new CGIResolver(this, ServerInstance, NotifyOpers, user->password, false, user, user->GetFd(), "PASS", cached); + if (!cached) + ServerInstance->AddResolver(r); + else + delete r; } catch (ModuleException& e) { @@ -315,8 +319,12 @@ public: try { ServerInstance->Log(DEBUG,"MAKE RESOLVER: %s %d %s",newip, user->GetFd(), "IDENT"); - CGIResolver* r = new CGIResolver(this, ServerInstance, NotifyOpers, newip, false, user, user->GetFd(), "IDENT"); - ServerInstance->AddResolver(r); + bool cached; + CGIResolver* r = new CGIResolver(this, ServerInstance, NotifyOpers, newip, false, user, user->GetFd(), "IDENT", cached); + if (!cached) + ServerInstance->AddResolver(r); + else + delete r; } catch (ModuleException& e) { diff --git a/src/modules/m_dnsbl.cpp b/src/modules/m_dnsbl.cpp index 91bfa5131..d6581a7d1 100644 --- a/src/modules/m_dnsbl.cpp +++ b/src/modules/m_dnsbl.cpp @@ -46,8 +46,8 @@ class DNSBLResolver : public Resolver DNSBLConfEntry *ConfEntry; public: - DNSBLResolver(Module *me, InspIRCd *ServerInstance, const std::string &hostname, userrec* u, int userfd, DNSBLConfEntry *conf) - : Resolver(ServerInstance, hostname, DNS_QUERY_A, me) + DNSBLResolver(Module *me, InspIRCd *ServerInstance, const std::string &hostname, userrec* u, int userfd, DNSBLConfEntry *conf, bool &cached) + : Resolver(ServerInstance, hostname, DNS_QUERY_A, cached, me) { theirfd = userfd; them = u; @@ -307,8 +307,12 @@ class ModuleDNSBL : public Module ServerInstance->Log(DEBUG, "m_dnsbl: sending %s for resolution", hostname.c_str()); /* now we'd need to fire off lookups for `hostname'. */ - DNSBLResolver *r = new DNSBLResolver(this, ServerInstance, hostname, user, user->GetFd(), *i); - ServerInstance->AddResolver(r); + bool cached; + DNSBLResolver *r = new DNSBLResolver(this, ServerInstance, hostname, user, user->GetFd(), *i, cached); + if (!cached) + ServerInstance->AddResolver(r); + else + delete r; } } diff --git a/src/modules/m_http_client.cpp b/src/modules/m_http_client.cpp index 0ca302ef6..92a9aa348 100644 --- a/src/modules/m_http_client.cpp +++ b/src/modules/m_http_client.cpp @@ -56,7 +56,7 @@ class HTTPResolver : public Resolver private: HTTPSocket *socket; public: - HTTPResolver(HTTPSocket *socket, InspIRCd *Instance, const string &hostname) : Resolver(Instance, hostname, DNS_QUERY_FORWARD), socket(socket) + HTTPResolver(HTTPSocket *socket, InspIRCd *Instance, const string &hostname, bool &cached, Module* me) : Resolver(Instance, hostname, DNS_QUERY_FORWARD, cached, me), socket(socket) { } @@ -149,7 +149,12 @@ bool HTTPSocket::DoRequest(HTTPClientRequest *req) if (!inet_aton(this->host, &this->addy)) { - new HTTPResolver(this, Server, url.domain); + bool cached; + HTTPResolver* r = new HTTPResolver(this, Server, url.domain, cached, (Module*)Mod); + if (!cached) + Instance->AddResolver(r); + else + delete r; return true; } else diff --git a/src/modules/m_spanningtree.cpp b/src/modules/m_spanningtree.cpp index 359196990..cbecfa24f 100644 --- a/src/modules/m_spanningtree.cpp +++ b/src/modules/m_spanningtree.cpp @@ -3714,7 +3714,7 @@ class ServernameResolver : public Resolver Link MyLink; SpanningTreeUtilities* Utils; public: - ServernameResolver(Module* me, SpanningTreeUtilities* Util, InspIRCd* Instance, const std::string &hostname, Link x) : Resolver(Instance, hostname, DNS_QUERY_FORWARD, me), MyLink(x), Utils(Util) + ServernameResolver(Module* me, SpanningTreeUtilities* Util, InspIRCd* Instance, const std::string &hostname, Link x, bool &cached) : Resolver(Instance, hostname, DNS_QUERY_FORWARD, cached, me), MyLink(x), Utils(Util) { /* Nothing in here, folks */ } @@ -3764,7 +3764,7 @@ class SecurityIPResolver : public Resolver Link MyLink; SpanningTreeUtilities* Utils; public: - SecurityIPResolver(Module* me, SpanningTreeUtilities* U, InspIRCd* Instance, const std::string &hostname, Link x) : Resolver(Instance, hostname, DNS_QUERY_FORWARD, me), MyLink(x), Utils(U) + SecurityIPResolver(Module* me, SpanningTreeUtilities* U, InspIRCd* Instance, const std::string &hostname, Link x, bool &cached) : Resolver(Instance, hostname, DNS_QUERY_FORWARD, cached, me), MyLink(x), Utils(U) { } @@ -4122,8 +4122,12 @@ void SpanningTreeUtilities::ReadConfiguration(bool rebind) { try { - SecurityIPResolver* sr = new SecurityIPResolver((Module*)this->Creator, this, ServerInstance, L.IPAddr, L); - ServerInstance->AddResolver(sr); + bool cached; + SecurityIPResolver* sr = new SecurityIPResolver((Module*)this->Creator, this, ServerInstance, L.IPAddr, L, cached); + if (!cached) + ServerInstance->AddResolver(sr); + else + delete sr; } catch (ModuleException& e) { @@ -4653,8 +4657,12 @@ class ModuleSpanningTree : public Module { try { - ServernameResolver* snr = new ServernameResolver((Module*)this, Utils, ServerInstance,x->IPAddr, *x); - ServerInstance->AddResolver(snr); + bool cached; + ServernameResolver* snr = new ServernameResolver((Module*)this, Utils, ServerInstance,x->IPAddr, *x, cached); + if (!cached) + ServerInstance->AddResolver(snr); + else + delete snr; } catch (ModuleException& e) { diff --git a/src/modules/m_testcommand.cpp b/src/modules/m_testcommand.cpp index 00988ff96..55632c98e 100644 --- a/src/modules/m_testcommand.cpp +++ b/src/modules/m_testcommand.cpp @@ -26,7 +26,7 @@ class MyV6Resolver : public Resolver { bool fw; public: - MyV6Resolver(InspIRCd* Instance, Module* me, const std::string &source, bool forward) : Resolver(Instance, source, forward ? DNS_QUERY_AAAA : DNS_QUERY_PTR6, me) + MyV6Resolver(InspIRCd* Instance, Module* me, const std::string &source, bool forward, bool &cached) : Resolver(Instance, source, forward ? DNS_QUERY_AAAA : DNS_QUERY_PTR6, cached, me) { fw = forward; } @@ -60,10 +60,24 @@ class cmd_woot : public command_t * do it for us as required.*/ try { - MyV6Resolver* r = new MyV6Resolver(ServerInstance, Creator, "shake.stacken.kth.se", true); - ServerInstance->AddResolver(r); - r = new MyV6Resolver(ServerInstance, Creator, "2001:6b0:1:ea:202:a5ff:fecd:13a6", false); - ServerInstance->AddResolver(r); + bool cached1, cached2; + MyV6Resolver* r = new MyV6Resolver(ServerInstance, Creator, "shake.stacken.kth.se", true, cached1); + if (!cached1) + ServerInstance->AddResolver(r); + else + { + ServerInstance->Log(DEBUG,"Result was cached, delete object"); + delete r; + } + + r = new MyV6Resolver(ServerInstance, Creator, "2001:6b0:1:ea:202:a5ff:fecd:13a6", false, cached2); + if (!cached2) + ServerInstance->AddResolver(r); + else + { + ServerInstance->Log(DEBUG,"Result was cached, delete object"); + delete r; + } } catch (ModuleException& e) { diff --git a/src/users.cpp b/src/users.cpp index 0e25f8e55..37664a629 100644 --- a/src/users.cpp +++ b/src/users.cpp @@ -151,8 +151,12 @@ void userrec::StartDNSLookup() try { ServerInstance->Log(DEBUG,"Passing instance: %08x",this->ServerInstance); - res_reverse = new UserResolver(this->ServerInstance, this, this->GetIPString(), DNS_QUERY_REVERSE); - this->ServerInstance->AddResolver(res_reverse); + bool cached; + res_reverse = new UserResolver(this->ServerInstance, this, this->GetIPString(), DNS_QUERY_REVERSE, cached); + if (!cached) + this->ServerInstance->AddResolver(res_reverse); + else + delete res_reverse; } catch (CoreException& e) { @@ -160,8 +164,8 @@ void userrec::StartDNSLookup() } } -UserResolver::UserResolver(InspIRCd* Instance, userrec* user, std::string to_resolve, QueryType qt) : - Resolver(Instance, to_resolve, qt), bound_user(user) +UserResolver::UserResolver(InspIRCd* Instance, userrec* user, std::string to_resolve, QueryType qt, bool &cache) : + Resolver(Instance, to_resolve, qt, cache), bound_user(user) { this->fwd = (qt == DNS_QUERY_A || qt == DNS_QUERY_AAAA); this->bound_fd = user->GetFd(); @@ -178,13 +182,17 @@ void UserResolver::OnLookupComplete(const std::string &result, unsigned int ttl) /* Check we didnt time out */ if (this->bound_user->registered != REG_ALL) { + bool cached; #ifdef IPV6 const char *ip = this->bound_user->GetIPString(); - bound_user->res_forward = new UserResolver(this->ServerInstance, this->bound_user, result, (strstr(ip,"0::ffff:") == ip ? DNS_QUERY_A : DNS_QUERY_AAAA)); + bound_user->res_forward = new UserResolver(this->ServerInstance, this->bound_user, result, (strstr(ip,"0::ffff:") == ip ? DNS_QUERY_A : DNS_QUERY_AAAA), cached); #else - bound_user->res_forward = new UserResolver(this->ServerInstance, this->bound_user, result, DNS_QUERY_A); + bound_user->res_forward = new UserResolver(this->ServerInstance, this->bound_user, result, DNS_QUERY_A, cached); #endif - this->ServerInstance->AddResolver(bound_user->res_forward); + if (!cached) + this->ServerInstance->AddResolver(bound_user->res_forward); + else + delete bound_user->res_forward; } } catch (CoreException& e) -- cgit v1.2.3