summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam <Adam@anope.org>2012-10-10 23:08:00 -0400
committerAdam <Adam@anope.org>2012-10-10 23:08:00 -0400
commit757ff06011c9b6ac8f66da7a5cac03597194d97a (patch)
tree89553068f751967fe741da50bb835beb589b9552
parent06defe014bf4f74b645429593670fa74803c6758 (diff)
Fix m_ldap to reconnect automatically if the ldap server goes away
-rw-r--r--modules/extra/ldap.h1
-rw-r--r--modules/extra/m_ldap.cpp83
-rw-r--r--modules/extra/m_ldap_authentication.cpp19
3 files changed, 86 insertions, 17 deletions
diff --git a/modules/extra/ldap.h b/modules/extra/ldap.h
index 5d50c89c9..65be27687 100644
--- a/modules/extra/ldap.h
+++ b/modules/extra/ldap.h
@@ -116,6 +116,7 @@ class LDAPInterface
virtual void OnResult(const LDAPResult &r) = 0;
virtual void OnError(const LDAPResult &err) = 0;
+ virtual void OnDelete() { }
};
class LDAPProvider : public Service
diff --git a/modules/extra/m_ldap.cpp b/modules/extra/m_ldap.cpp
index e6e65e85c..d53e04992 100644
--- a/modules/extra/m_ldap.cpp
+++ b/modules/extra/m_ldap.cpp
@@ -15,6 +15,8 @@ class LDAPService : public LDAPProvider, public Thread, public Condition
LDAP *con;
+ time_t last_connect;
+
LDAPMod **BuildMods(const LDAPMods &attributes)
{
LDAPMod **mods = new LDAPMod*[attributes.size() + 1];
@@ -54,19 +56,34 @@ class LDAPService : public LDAPProvider, public Thread, public Condition
delete [] mods;
}
+ void Reconnect()
+ {
+ /* Only try one connect a minute. It is an expensive blocking operation */
+ if (last_connect > Anope::CurTime - 60)
+ throw LDAPException("Unable to connect to LDAP service " + this->name + ": reconnecting too fast");
+ last_connect = Anope::CurTime;
+
+ ldap_unbind_ext(this->con, NULL, NULL);
+ int i = ldap_initialize(&this->con, this->server.c_str());
+ if (i != LDAP_SUCCESS)
+ throw LDAPException("Unable to connect to LDAP service " + this->name + ": " + ldap_err2string(i));
+ }
+
public:
typedef std::map<int, LDAPInterface *> query_queue;
typedef std::vector<std::pair<LDAPInterface *, LDAPResult *> > result_queue;
query_queue queries;
result_queue results;
- LDAPService(Module *o, const Anope::string &n, const Anope::string &s, int po, const Anope::string &b, const Anope::string &p) : LDAPProvider(o, "ldap/" + n), server(s), port(po), admin_binddn(b), admin_pass(p)
+ LDAPService(Module *o, const Anope::string &n, const Anope::string &s, int po, const Anope::string &b, const Anope::string &p) : LDAPProvider(o, "ldap/" + n), server(s), port(po), admin_binddn(b), admin_pass(p), last_connect(0)
{
- if (ldap_initialize(&this->con, this->server.c_str()) != LDAP_SUCCESS)
- throw LDAPException("Unable to connect to LDAP service " + this->name + ": " + Anope::LastError());
+ int i = ldap_initialize(&this->con, this->server.c_str());
+ if (i != LDAP_SUCCESS)
+ throw LDAPException("Unable to connect to LDAP service " + this->name + ": " + ldap_err2string(i));
static const int version = LDAP_VERSION3;
- if (ldap_set_option(this->con, LDAP_OPT_PROTOCOL_VERSION, &version) != LDAP_OPT_SUCCESS)
- throw LDAPException("Unable to set protocol version for " + this->name + ": " + Anope::LastError());
+ i = ldap_set_option(this->con, LDAP_OPT_PROTOCOL_VERSION, &version);
+ if (i != LDAP_OPT_SUCCESS)
+ throw LDAPException("Unable to set protocol version for " + this->name + ": " + ldap_err2string(i));
}
~LDAPService()
@@ -76,7 +93,7 @@ class LDAPService : public LDAPProvider, public Thread, public Condition
for (query_queue::iterator it = this->queries.begin(), it_end = this->queries.end(); it != it_end; ++it)
{
ldap_abandon_ext(this->con, it->first, NULL, NULL);
- delete it->second;
+ it->second->OnDelete();
}
this->queries.clear();
@@ -107,7 +124,15 @@ class LDAPService : public LDAPProvider, public Thread, public Condition
int ret = ldap_sasl_bind(con, who.c_str(), LDAP_SASL_SIMPLE, &cred, NULL, NULL, &msgid);
free(cred.bv_val);
if (ret != LDAP_SUCCESS)
- throw LDAPException(ldap_err2string(ret));
+ {
+ if (ret == LDAP_SERVER_DOWN || ret == LDAP_TIMEOUT)
+ {
+ this->Reconnect();
+ return this->Bind(i, who, pass);
+ }
+ else
+ throw LDAPException(ldap_err2string(ret));
+ }
if (i != NULL)
{
@@ -128,7 +153,15 @@ class LDAPService : public LDAPProvider, public Thread, public Condition
LDAPQuery msgid;
int ret = ldap_search_ext(this->con, base.c_str(), LDAP_SCOPE_SUBTREE, filter.c_str(), NULL, 0, NULL, NULL, NULL, 0, &msgid);
if (ret != LDAP_SUCCESS)
- throw LDAPException(ldap_err2string(ret));
+ {
+ if (ret == LDAP_SERVER_DOWN || ret == LDAP_TIMEOUT)
+ {
+ this->Reconnect();
+ return this->Search(i, base, filter);
+ }
+ else
+ throw LDAPException(ldap_err2string(ret));
+ }
this->Lock();
this->queries[msgid] = i;
@@ -146,7 +179,15 @@ class LDAPService : public LDAPProvider, public Thread, public Condition
this->FreeMods(mods);
if (ret != LDAP_SUCCESS)
- throw LDAPException(ldap_err2string(ret));
+ {
+ if (ret == LDAP_SERVER_DOWN || ret == LDAP_TIMEOUT)
+ {
+ this->Reconnect();
+ return this->Add(i, dn, attributes);
+ }
+ else
+ throw LDAPException(ldap_err2string(ret));
+ }
if (i != NULL)
{
@@ -165,7 +206,15 @@ class LDAPService : public LDAPProvider, public Thread, public Condition
int ret = ldap_delete_ext(this->con, dn.c_str(), NULL, NULL, &msgid);
if (ret != LDAP_SUCCESS)
- throw LDAPException(ldap_err2string(ret));
+ {
+ if (ret == LDAP_SERVER_DOWN || ret == LDAP_TIMEOUT)
+ {
+ this->Reconnect();
+ return this->Del(i, dn);
+ }
+ else
+ throw LDAPException(ldap_err2string(ret));
+ }
if (i != NULL)
{
@@ -186,7 +235,15 @@ class LDAPService : public LDAPProvider, public Thread, public Condition
this->FreeMods(mods);
if (ret != LDAP_SUCCESS)
- throw LDAPException(ldap_err2string(ret));
+ {
+ if (ret == LDAP_SERVER_DOWN || ret == LDAP_TIMEOUT)
+ {
+ this->Reconnect();
+ return this->Modify(i, base, attributes);
+ }
+ else
+ throw LDAPException(ldap_err2string(ret));
+ }
if (i != NULL)
{
@@ -435,8 +492,12 @@ class ModuleLDAP : public Module, public Pipe
int msgid = it2->first;
LDAPInterface *i = it2->second;
++it2;
+
if (i->owner == m)
+ {
+ i->OnDelete();
s->queries.erase(msgid);
+ }
}
for (unsigned i = s->results.size(); i > 0; --i)
{
diff --git a/modules/extra/m_ldap_authentication.cpp b/modules/extra/m_ldap_authentication.cpp
index 2ca08f975..5469713e2 100644
--- a/modules/extra/m_ldap_authentication.cpp
+++ b/modules/extra/m_ldap_authentication.cpp
@@ -85,11 +85,18 @@ class IdentifyInterface : public LDAPInterface
if (ii->admin_bind)
{
Anope::string sf = search_filter.replace_all_cs("%account", ii->req->GetAccount()).replace_all_cs("%object_class", object_class);
- Log(LOG_DEBUG) << "m_ldap_authentication: searching for " << sf;
- LDAPQuery id = ii->lprov->Search(this, basedn, sf);
- this->Add(id, ii);
- ii->admin_bind = false;
- return;
+ try
+ {
+ Log(LOG_DEBUG) << "m_ldap_authentication: searching for " << sf;
+ LDAPQuery id = ii->lprov->Search(this, basedn, sf);
+ this->Add(id, ii);
+ ii->admin_bind = false;
+ return;
+ }
+ catch (const LDAPException &ex)
+ {
+ Log() << "m_ldap_authentication: Unable to search for " << sf << ": " << ex.GetReason();
+ }
}
else
{
@@ -261,7 +268,7 @@ class NSIdentifyLDAP : public Module
catch (const LDAPException &ex)
{
delete ii;
- Log() << "ns_identify_ldap: " << ex.GetReason();
+ Log() << "m_ldap_authentication: " << ex.GetReason();
}
}