From 25493049050dadfa08527c813f4209a09beab6a7 Mon Sep 17 00:00:00 2001 From: brain Date: Fri, 10 Nov 2006 20:13:59 +0000 Subject: Add fix for patch #166 (this is a reasonably big one) git-svn-id: http://svn.inspircd.org/repository/trunk/inspircd@5679 e03df62e-2008-0410-955e-edbf42e46eb7 --- include/dns.h | 28 ++++++++++++++++++++++++++-- src/dns.cpp | 23 ++++++++++++++++++++++- src/inspircd.cpp | 3 +++ src/modules/extra/m_pgsql.cpp | 2 +- src/modules/m_cgiirc.cpp | 8 ++++---- src/modules/m_spanningtree.cpp | 8 ++++---- src/modules/m_testcommand.cpp | 11 ++++++----- 7 files changed, 66 insertions(+), 17 deletions(-) diff --git a/include/dns.h b/include/dns.h index 79b286233..4a1335cc7 100644 --- a/include/dns.h +++ b/include/dns.h @@ -48,6 +48,7 @@ using irc::sockets::insp_sockaddr; using irc::sockets::insp_inaddr; class InspIRCd; +class Module; /** * Result status, used internally @@ -69,7 +70,8 @@ enum ResolverError RESOLVER_NXDOMAIN = 2, RESOLVER_NOTREADY = 3, RESOLVER_BADIP = 4, - RESOLVER_TIMEOUT = 5 + RESOLVER_TIMEOUT = 5, + RESLOVER_FORCEUNLOAD = 6 }; /** @@ -146,6 +148,10 @@ class Resolver : public Extensible * Pointer to creator */ InspIRCd* ServerInstance; + /** + * Pointer to creator module (if any, or NULL) + */ + Module* Creator; /** * The input data, either a host or an IP address */ @@ -193,8 +199,14 @@ class Resolver : public Extensible * event a lookup could not be allocated, or a similar hard error occurs such as * the network being down. This will also be thrown if an invalid IP address is * passed when resolving a 'PTR' record. + * + * NOTE: If you are instantiating your DNS lookup from a module, you should set the + * value of creator to point at your Module class. This way if your module is unloaded + * 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); + Resolver(InspIRCd* Instance, const std::string &source, QueryType qt, Module* creator = NULL); + /** * The default destructor does nothing. */ @@ -220,6 +232,11 @@ class Resolver : public Extensible * this method will return -1. */ int GetId(); + + /** + * Returns the creator module, or NULL + */ + Module* GetCreator(); }; /** DNS is a singleton class used by the core to dispatch dns @@ -364,6 +381,13 @@ class DNS : public EventHandler * Turn an in6_addr into a .ip6.arpa domain */ static void MakeIP6Int(char* query, const in6_addr *ip); + + /** + * Clean out all dns resolvers owned by a particular + * module, to make unloading a module safe if there + * are dns requests currently in progress. + */ + void CleanResolvers(Module* module); }; #endif diff --git a/src/dns.cpp b/src/dns.cpp index 3381c18fa..23e1dfcab 100644 --- a/src/dns.cpp +++ b/src/dns.cpp @@ -870,7 +870,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); @@ -948,6 +948,11 @@ int Resolver::GetId() return this->myid; } +Module* Resolver::GetCreator() +{ + return this->Creator; +} + /** Process a socket read event */ void DNS::HandleEvent(EventType et, int errornum) { @@ -1025,6 +1030,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() { diff --git a/src/inspircd.cpp b/src/inspircd.cpp index 1b636bc87..9521f1b22 100644 --- a/src/inspircd.cpp +++ b/src/inspircd.cpp @@ -508,6 +508,9 @@ bool InspIRCd::UnloadModule(const char* filename) modules[j]->OnCleanup(TYPE_USER,u->second); } + /* Tidy up any dangling resolvers */ + this->Res->CleanResolvers(modules[j]); + FOREACH_MOD_I(this,I_OnUnloadModule,OnUnloadModule(modules[j],Config->module_names[j])); for(int t = 0; t < 255; t++) diff --git a/src/modules/extra/m_pgsql.cpp b/src/modules/extra/m_pgsql.cpp index 1bd19e964..f4392a4ed 100644 --- a/src/modules/extra/m_pgsql.cpp +++ b/src/modules/extra/m_pgsql.cpp @@ -96,7 +96,7 @@ class SQLresolver : public Resolver ModulePgSQL* mod; public: SQLresolver(ModulePgSQL* m, InspIRCd* Instance, const SQLhost& hi) - : Resolver(Instance, hi.host, DNS_QUERY_FORWARD), host(hi), mod(m) + : Resolver(Instance, hi.host, DNS_QUERY_FORWARD, (Module*)m), host(hi), mod(m) { } diff --git a/src/modules/m_cgiirc.cpp b/src/modules/m_cgiirc.cpp index a8d071e31..ec2ac6129 100644 --- a/src/modules/m_cgiirc.cpp +++ b/src/modules/m_cgiirc.cpp @@ -55,8 +55,8 @@ class CGIResolver : public Resolver userrec* them; bool notify; public: - CGIResolver(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), 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) + : Resolver(ServerInstance, source, forward ? DNS_QUERY_FORWARD : DNS_QUERY_REVERSE, me), typ(type), theirfd(userfd), them(u), notify(NotifyOpers) { } virtual void OnLookupComplete(const std::string &result) { @@ -263,7 +263,7 @@ public: try { - CGIResolver* r = new CGIResolver(ServerInstance, NotifyOpers, user->password, false, user, user->GetFd(), "PASS"); + CGIResolver* r = new CGIResolver(this, ServerInstance, NotifyOpers, user->password, false, user, user->GetFd(), "PASS"); ServerInstance->AddResolver(r); } catch (ModuleException& e) @@ -319,7 +319,7 @@ public: try { ServerInstance->Log(DEBUG,"MAKE RESOLVER: %s %d %s",newip, user->GetFd(), "IDENT"); - CGIResolver* r = new CGIResolver(ServerInstance, NotifyOpers, newip, false, user, user->GetFd(), "IDENT"); + CGIResolver* r = new CGIResolver(this, ServerInstance, NotifyOpers, newip, false, user, user->GetFd(), "IDENT"); ServerInstance->AddResolver(r); } catch (ModuleException& e) diff --git a/src/modules/m_spanningtree.cpp b/src/modules/m_spanningtree.cpp index d9bb93e3e..92c95c525 100644 --- a/src/modules/m_spanningtree.cpp +++ b/src/modules/m_spanningtree.cpp @@ -3585,7 +3585,7 @@ class ServernameResolver : public Resolver Link MyLink; SpanningTreeUtilities* Utils; public: - ServernameResolver(SpanningTreeUtilities* Util, InspIRCd* Instance, const std::string &hostname, Link x) : Resolver(Instance, hostname, DNS_QUERY_FORWARD), MyLink(x), Utils(Util) + ServernameResolver(Module* me, SpanningTreeUtilities* Util, InspIRCd* Instance, const std::string &hostname, Link x) : Resolver(Instance, hostname, DNS_QUERY_FORWARD, me), MyLink(x), Utils(Util) { /* Nothing in here, folks */ } @@ -3630,7 +3630,7 @@ class SecurityIPResolver : public Resolver Link MyLink; SpanningTreeUtilities* Utils; public: - SecurityIPResolver(SpanningTreeUtilities* U, InspIRCd* Instance, const std::string &hostname, Link x) : Resolver(Instance, hostname, DNS_QUERY_FORWARD), MyLink(x), Utils(U) + SecurityIPResolver(Module* me, SpanningTreeUtilities* U, InspIRCd* Instance, const std::string &hostname, Link x) : Resolver(Instance, hostname, DNS_QUERY_FORWARD, me), MyLink(x), Utils(U) { } @@ -3932,7 +3932,7 @@ void SpanningTreeUtilities::ReadConfiguration(bool rebind) { try { - SecurityIPResolver* sr = new SecurityIPResolver(this, ServerInstance, L.IPAddr, L); + SecurityIPResolver* sr = new SecurityIPResolver((Module*)this->Creator, this, ServerInstance, L.IPAddr, L); ServerInstance->AddResolver(sr); } catch (ModuleException& e) @@ -4408,7 +4408,7 @@ class ModuleSpanningTree : public Module { try { - ServernameResolver* snr = new ServernameResolver(Utils, ServerInstance,x->IPAddr, *x); + ServernameResolver* snr = new ServernameResolver((Module*)this, Utils, ServerInstance,x->IPAddr, *x); ServerInstance->AddResolver(snr); } catch (ModuleException& e) diff --git a/src/modules/m_testcommand.cpp b/src/modules/m_testcommand.cpp index 9da6788cd..50853d4b3 100644 --- a/src/modules/m_testcommand.cpp +++ b/src/modules/m_testcommand.cpp @@ -31,7 +31,7 @@ class MyV6Resolver : public Resolver { bool fw; public: - MyV6Resolver(const std::string &source, bool forward) : Resolver(ServerInstance, source, forward ? DNS_QUERY_AAAA : DNS_QUERY_PTR6) + MyV6Resolver(Module* me, const std::string &source, bool forward) : Resolver(ServerInstance, source, forward ? DNS_QUERY_AAAA : DNS_QUERY_PTR6, me) { fw = forward; } @@ -51,9 +51,10 @@ class MyV6Resolver : public Resolver */ class cmd_woot : public command_t { + Module* Creator; public: /* Command 'woot', takes no parameters and needs no special modes */ - cmd_woot (InspIRCd* Instance) : command_t(Instance,"WOOT", 0, 0) + cmd_woot (InspIRCd* Instance, Module* maker) : command_t(Instance,"WOOT", 0, 0), Creator(maker) { this->source = "m_testcommand.so"; } @@ -64,9 +65,9 @@ class cmd_woot : public command_t * do it for us as required.*/ try { - MyV6Resolver* r = new MyV6Resolver("shake.stacken.kth.se", true); + MyV6Resolver* r = new MyV6Resolver(Creator, "shake.stacken.kth.se", true); ServerInstance->AddResolver(r); - r = new MyV6Resolver("2001:6b0:1:ea:202:a5ff:fecd:13a6", false); + r = new MyV6Resolver(Creator, "2001:6b0:1:ea:202:a5ff:fecd:13a6", false); ServerInstance->AddResolver(r); } catch (ModuleException& e) @@ -87,7 +88,7 @@ class ModuleTestCommand : public Module { // Create a new command - newcommand = new cmd_woot(ServerInstance); + newcommand = new cmd_woot(ServerInstance, this); ServerInstance->AddCommand(newcommand); } -- cgit v1.2.3