summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbrain <brain@e03df62e-2008-0410-955e-edbf42e46eb7>2006-11-10 20:13:59 +0000
committerbrain <brain@e03df62e-2008-0410-955e-edbf42e46eb7>2006-11-10 20:13:59 +0000
commit25493049050dadfa08527c813f4209a09beab6a7 (patch)
tree65f803c34106dccef63cadbbd8a0f60fdc9fd4f5
parentff7b9e9af0a502989fa88b096b2183590193e2cc (diff)
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
-rw-r--r--include/dns.h28
-rw-r--r--src/dns.cpp23
-rw-r--r--src/inspircd.cpp3
-rw-r--r--src/modules/extra/m_pgsql.cpp2
-rw-r--r--src/modules/m_cgiirc.cpp8
-rw-r--r--src/modules/m_spanningtree.cpp8
-rw-r--r--src/modules/m_testcommand.cpp11
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
};
/**
@@ -147,6 +149,10 @@ class Resolver : public Extensible
*/
InspIRCd* ServerInstance;
/**
+ * Pointer to creator module (if any, or NULL)
+ */
+ Module* Creator;
+ /**
* The input data, either a host or an IP address
*/
std::string input;
@@ -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);
}