summaryrefslogtreecommitdiff
path: root/src/modules
diff options
context:
space:
mode:
Diffstat (limited to 'src/modules')
-rw-r--r--src/modules/extra/m_ssl_gnutls.cpp39
-rw-r--r--src/modules/m_callerid.cpp60
-rw-r--r--src/modules/m_filter.cpp74
-rw-r--r--src/modules/m_ident.cpp1
-rw-r--r--src/modules/m_kicknorejoin.cpp59
-rw-r--r--src/modules/m_nonotice.cpp5
-rw-r--r--src/modules/m_permchannels.cpp40
-rw-r--r--src/modules/m_rline.cpp48
-rw-r--r--src/modules/m_services_account.cpp16
-rw-r--r--src/modules/m_spanningtree/main.cpp2
-rw-r--r--src/modules/m_spanningtree/server.cpp67
-rw-r--r--src/modules/m_spanningtree/treesocket.h11
-rw-r--r--src/modules/m_spanningtree/treesocket2.cpp12
13 files changed, 312 insertions, 122 deletions
diff --git a/src/modules/extra/m_ssl_gnutls.cpp b/src/modules/extra/m_ssl_gnutls.cpp
index 1caacaa0f..00dff68e6 100644
--- a/src/modules/extra/m_ssl_gnutls.cpp
+++ b/src/modules/extra/m_ssl_gnutls.cpp
@@ -86,6 +86,12 @@ static ssize_t gnutls_pull_wrapper(gnutls_transport_ptr_t user_wrap, void* buffe
return -1;
}
int rv = ServerInstance->SE->Recv(user, reinterpret_cast<char *>(buffer), size, 0);
+ if (rv < 0)
+ {
+ /* On Windows we need to set errno for gnutls */
+ if (SocketEngine::IgnoreError())
+ errno = EAGAIN;
+ }
if (rv < (int)size)
ServerInstance->SE->ChangeEventMask(user, FD_READ_WILL_BLOCK);
return rv;
@@ -100,6 +106,12 @@ static ssize_t gnutls_push_wrapper(gnutls_transport_ptr_t user_wrap, const void*
return -1;
}
int rv = ServerInstance->SE->Send(user, reinterpret_cast<const char *>(buffer), size, 0);
+ if (rv < 0)
+ {
+ /* On Windows we need to set errno for gnutls */
+ if (SocketEngine::IgnoreError())
+ errno = EAGAIN;
+ }
if (rv < (int)size)
ServerInstance->SE->ChangeEventMask(user, FD_WRITE_WILL_BLOCK);
return rv;
@@ -322,6 +334,7 @@ class ModuleSSLGnuTLS : public Module
{
gnutls_dh_params_deinit(dh_params);
dh_alloc = false;
+ dh_params = NULL;
}
if (cred_alloc)
@@ -409,10 +422,30 @@ class ModuleSSLGnuTLS : public Module
ret = gnutls_dh_params_init(&dh_params);
dh_alloc = (ret >= 0);
if (!dh_alloc)
- ServerInstance->Logs->Log("m_ssl_gnutls",LOG_DEFAULT, "m_ssl_gnutls.so: Failed to initialise DH parameters: %s", gnutls_strerror(ret));
+ {
+ ServerInstance->Logs->Log("m_ssl_gnutls", LOG_DEFAULT, "m_ssl_gnutls.so: Failed to initialise DH parameters: %s", gnutls_strerror(ret));
+ return;
+ }
- // This may be on a large (once a day or week) timer eventually.
- GenerateDHParams();
+ std::string dhfile = Conf->getString("dhfile");
+ if (!dhfile.empty())
+ {
+ // Try to load DH params from file
+ reader.LoadFile(dhfile);
+ std::string dhstring = reader.Contents();
+ gnutls_datum_t dh_datum = { (unsigned char*)dhstring.data(), static_cast<unsigned int>(dhstring.length()) };
+
+ if ((ret = gnutls_dh_params_import_pkcs3(dh_params, &dh_datum, GNUTLS_X509_FMT_PEM)) < 0)
+ {
+ // File unreadable or GnuTLS was unhappy with the contents, generate the DH primes now
+ ServerInstance->Logs->Log("m_ssl_gnutls", LOG_DEFAULT, "m_ssl_gnutls.so: Generating DH parameters because I failed to load them from file '%s': %s", dhfile.c_str(), gnutls_strerror(ret));
+ GenerateDHParams();
+ }
+ }
+ else
+ {
+ GenerateDHParams();
+ }
}
void GenerateDHParams()
diff --git a/src/modules/m_callerid.cpp b/src/modules/m_callerid.cpp
index e8448bc91..3bc9583cc 100644
--- a/src/modules/m_callerid.cpp
+++ b/src/modules/m_callerid.cpp
@@ -38,26 +38,6 @@ class callerid_data
std::list<callerid_data *> wholistsme;
callerid_data() : lastnotify(0) { }
- callerid_data(const std::string& str)
- {
- irc::commasepstream s(str);
- std::string tok;
- if (s.GetToken(tok))
- {
- lastnotify = ConvToInt(tok);
- }
- while (s.GetToken(tok))
- {
- if (tok.empty())
- {
- continue;
- }
-
- User *u = ServerInstance->FindNick(tok);
- if ((u) && (u->registered == REG_ALL) && (!u->quitting) && (!IS_SERVER(u)))
- accepting.insert(u);
- }
- }
std::string ToString(SerializeFormat format) const
{
@@ -88,8 +68,31 @@ struct CallerIDExtInfo : public ExtensionItem
void unserialize(SerializeFormat format, Extensible* container, const std::string& value)
{
- callerid_data* dat = new callerid_data(value);
- set_raw(container, dat);
+ callerid_data* dat = new callerid_data;
+ irc::commasepstream s(value);
+ std::string tok;
+ if (s.GetToken(tok))
+ dat->lastnotify = ConvToInt(tok);
+
+ while (s.GetToken(tok))
+ {
+ if (tok.empty())
+ continue;
+
+ User *u = ServerInstance->FindNick(tok);
+ if ((u) && (u->registered == REG_ALL) && (!u->quitting) && (!IS_SERVER(u)))
+ {
+ if (dat->accepting.insert(u).second)
+ {
+ callerid_data* other = this->get(u, true);
+ other->wholistsme.push_back(dat);
+ }
+ }
+ }
+
+ void* old = set_raw(container, dat);
+ if (old)
+ this->free(old);
}
callerid_data* get(User* user, bool create)
@@ -113,11 +116,16 @@ struct CallerIDExtInfo : public ExtensionItem
callerid_data *targ = this->get(*it, false);
if (!targ)
+ {
+ ServerInstance->Logs->Log("m_callerid", LOG_DEFAULT, "ERROR: Inconsistency detected in callerid state, please report (1)");
continue; // shouldn't happen, but oh well.
+ }
std::list<callerid_data*>::iterator it2 = std::find(targ->wholistsme.begin(), targ->wholistsme.end(), dat);
if (it2 != targ->wholistsme.end())
targ->wholistsme.erase(it2);
+ else
+ ServerInstance->Logs->Log("m_callerid", LOG_DEFAULT, "ERROR: Inconsistency detected in callerid state, please report (2)");
}
delete dat;
}
@@ -277,6 +285,7 @@ public:
if (!dat2)
{
// How the fuck is this possible.
+ ServerInstance->Logs->Log("m_callerid", LOG_DEFAULT, "ERROR: Inconsistency detected in callerid state, please report (3)");
return false;
}
@@ -284,6 +293,9 @@ public:
if (it != dat2->wholistsme.end())
// Found me!
dat2->wholistsme.erase(it);
+ else
+ ServerInstance->Logs->Log("m_callerid", LOG_DEFAULT, "ERROR: Inconsistency detected in callerid state, please report (4)");
+
user->WriteServ("NOTICE %s :%s is no longer on your accept list", user->nick.c_str(), whotoremove->nick.c_str());
return true;
@@ -320,6 +332,8 @@ class ModuleCallerID : public Module
if (it2 != dat->accepting.end())
dat->accepting.erase(it2);
+ else
+ ServerInstance->Logs->Log("m_callerid", LOG_DEFAULT, "ERROR: Inconsistency detected in callerid state, please report (5)");
}
userdata->wholistsme.clear();
@@ -354,7 +368,7 @@ public:
ModResult PreText(User* user, User* dest, std::string& text)
{
- if (!dest->IsModeSet('g'))
+ if (!dest->IsModeSet('g') || (user == dest))
return MOD_RES_PASSTHRU;
if (operoverride && user->IsOper())
diff --git a/src/modules/m_filter.cpp b/src/modules/m_filter.cpp
index 027222b3a..8bfefd6eb 100644
--- a/src/modules/m_filter.cpp
+++ b/src/modules/m_filter.cpp
@@ -165,19 +165,22 @@ class ImplFilter : public FilterResult
class ModuleFilter : public Module
{
+ bool initing;
+ RegexFactory* factory;
+ void FreeFilters();
+
public:
CommandFilter filtcommand;
dynamic_reference<RegexFactory> RegexEngine;
std::vector<ImplFilter> filters;
- const char *error;
- int erroffset;
int flags;
std::set<std::string> exemptfromfilter; // List of channel names excluded from filtering.
ModuleFilter();
void init();
+ CullResult cull();
ModResult OnUserPreMessage(User* user,void* dest,int target_type, std::string &text, char status, CUList &exempt_list);
FilterResult* FilterMatch(User* user, const std::string &text, int flags);
bool DeleteFilter(const std::string &freeform);
@@ -191,6 +194,7 @@ class ModuleFilter : public Module
void OnDecodeMetaData(Extensible* target, const std::string &extname, const std::string &extdata);
ModResult OnStats(char symbol, User* user, string_list &results);
ModResult OnPreCommand(std::string &command, std::vector<std::string> &parameters, LocalUser *user, bool validated, const std::string &original_line);
+ void OnUnloadModule(Module* mod);
bool AppliesToMe(User* user, FilterResult* filter, int flags);
void ReadFilters();
static bool StringToFilterAction(const std::string& str, FilterAction& fa);
@@ -292,18 +296,33 @@ bool ModuleFilter::AppliesToMe(User* user, FilterResult* filter, int iflags)
return true;
}
-ModuleFilter::ModuleFilter() : filtcommand(this), RegexEngine(this, "regex")
+ModuleFilter::ModuleFilter()
+ : initing(true), filtcommand(this), RegexEngine(this, "regex")
{
}
void ModuleFilter::init()
{
ServerInstance->Modules->AddService(filtcommand);
- Implementation eventlist[] = { I_OnPreCommand, I_OnStats, I_OnSyncNetwork, I_OnDecodeMetaData, I_OnUserPreMessage, I_OnUserPreNotice, I_OnRehash };
+ Implementation eventlist[] = { I_OnPreCommand, I_OnStats, I_OnSyncNetwork, I_OnDecodeMetaData, I_OnUserPreMessage, I_OnUserPreNotice, I_OnRehash, I_OnUnloadModule };
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
OnRehash(NULL);
}
+CullResult ModuleFilter::cull()
+{
+ FreeFilters();
+ return Module::cull();
+}
+
+void ModuleFilter::FreeFilters()
+{
+ for (std::vector<ImplFilter>::const_iterator i = filters.begin(); i != filters.end(); ++i)
+ delete i->regex;
+
+ filters.clear();
+}
+
ModResult ModuleFilter::OnUserPreMessage(User* user,void* dest,int target_type, std::string &text, char status, CUList &exempt_list)
{
if (!IS_LOCAL(user))
@@ -457,20 +476,35 @@ void ModuleFilter::OnRehash(User* user)
if (!chan.empty())
exemptfromfilter.insert(chan);
}
- std::string newrxengine = "regex/" + ServerInstance->Config->ConfValue("filteropts")->getString("engine");
- if (newrxengine == "regex/")
- newrxengine = "regex";
- if (RegexEngine.GetProvider() == newrxengine)
- return;
- //ServerInstance->SNO->WriteGlobalSno('a', "Dumping all filters due to regex engine change (was '%s', now '%s')", RegexEngine.GetProvider().c_str(), newrxengine.c_str());
- //ServerInstance->XLines->DelAll("R");
+ std::string newrxengine = ServerInstance->Config->ConfValue("filteropts")->getString("engine");
+
+ factory = RegexEngine ? (RegexEngine.operator->()) : NULL;
+
+ if (newrxengine.empty())
+ RegexEngine.SetProvider("regex");
+ else
+ RegexEngine.SetProvider("regex/" + newrxengine);
- RegexEngine.SetProvider(newrxengine);
if (!RegexEngine)
{
- ServerInstance->SNO->WriteGlobalSno('a', "WARNING: Regex engine '%s' is not loaded - Filter functionality disabled until this is corrected.", newrxengine.c_str());
+ if (newrxengine.empty())
+ ServerInstance->SNO->WriteGlobalSno('a', "WARNING: No regex engine loaded - Filter functionality disabled until this is corrected.");
+ else
+ ServerInstance->SNO->WriteGlobalSno('a', "WARNING: Regex engine '%s' is not loaded - Filter functionality disabled until this is corrected.", newrxengine.c_str());
+
+ initing = false;
+ FreeFilters();
+ return;
+ }
+
+ if ((!initing) && (RegexEngine.operator->() != factory))
+ {
+ ServerInstance->SNO->WriteGlobalSno('a', "Dumping all filters due to regex engine change");
+ FreeFilters();
}
+
+ initing = false;
ReadFilters();
}
@@ -697,4 +731,18 @@ ModResult ModuleFilter::OnStats(char symbol, User* user, string_list &results)
return MOD_RES_PASSTHRU;
}
+void ModuleFilter::OnUnloadModule(Module* mod)
+{
+ // If the regex engine became unavailable or has changed, remove all filters
+ if (!RegexEngine)
+ {
+ FreeFilters();
+ }
+ else if (RegexEngine.operator->() != factory)
+ {
+ factory = RegexEngine.operator->();
+ FreeFilters();
+ }
+}
+
MODULE_INIT(ModuleFilter)
diff --git a/src/modules/m_ident.cpp b/src/modules/m_ident.cpp
index f38ad2241..2b5a512c9 100644
--- a/src/modules/m_ident.cpp
+++ b/src/modules/m_ident.cpp
@@ -367,6 +367,7 @@ class ModuleIdent : public Module
user->WriteServ("NOTICE Auth :*** Found your ident, '%s'", user->ident.c_str());
}
+ user->InvalidateCache();
isock->Close();
ext.unset(user);
return MOD_RES_PASSTHRU;
diff --git a/src/modules/m_kicknorejoin.cpp b/src/modules/m_kicknorejoin.cpp
index 5f19e5d0c..2f0c15bf3 100644
--- a/src/modules/m_kicknorejoin.cpp
+++ b/src/modules/m_kicknorejoin.cpp
@@ -27,31 +27,46 @@
/* $ModDesc: Provides channel mode +J (delay rejoin after kick) */
-typedef std::map<User*, time_t> delaylist;
+typedef std::map<std::string, time_t> delaylist;
/** Handles channel mode +J
*/
-class KickRejoin : public ParamChannelModeHandler
+class KickRejoin : public ModeHandler
{
+ static const unsigned int max = 60;
public:
SimpleExtItem<delaylist> ext;
- KickRejoin(Module* Creator) : ParamChannelModeHandler(Creator, "kicknorejoin", 'J'), ext("norejoinusers", Creator) { }
-
- bool ParamValidate(std::string& parameter)
+ KickRejoin(Module* Creator)
+ : ModeHandler(Creator, "kicknorejoin", 'J', PARAM_SETONLY, MODETYPE_CHANNEL)
+ , ext("norejoinusers", Creator)
{
- int v = atoi(parameter.c_str());
- if (v <= 0)
- return false;
- parameter = ConvToStr(v);
- return true;
}
- ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string &parameter, bool adding)
+ ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string& parameter, bool adding)
{
- ModeAction rv = ParamChannelModeHandler::OnModeChange(source, dest, channel, parameter, adding);
- if (rv == MODEACTION_ALLOW && !adding)
+ if (adding)
+ {
+ int v = ConvToInt(parameter);
+ if (v <= 0)
+ return MODEACTION_DENY;
+ if (parameter == channel->GetModeParameter(this))
+ return MODEACTION_DENY;
+
+ if ((IS_LOCAL(source) && ((unsigned int)v > max)))
+ v = max;
+
+ parameter = ConvToStr(v);
+ channel->SetModeParam(this, parameter);
+ }
+ else
+ {
+ if (!channel->IsModeSet(this))
+ return MODEACTION_DENY;
+
ext.unset(channel);
- return rv;
+ channel->SetModeParam(this, "");
+ }
+ return MODEACTION_ALLOW;
}
};
@@ -80,30 +95,26 @@ public:
delaylist* dl = kr.ext.get(chan);
if (dl)
{
- std::vector<User*> itemstoremove;
-
- for (delaylist::iterator iter = dl->begin(); iter != dl->end(); iter++)
+ for (delaylist::iterator iter = dl->begin(); iter != dl->end(); )
{
if (iter->second > ServerInstance->Time())
{
- if (iter->first == user)
+ if (iter->first == user->uuid)
{
std::string modeparam = chan->GetModeParameter(&kr);
user->WriteNumeric(ERR_DELAYREJOIN, "%s %s :You must wait %s seconds after being kicked to rejoin (+J)",
user->nick.c_str(), chan->name.c_str(), modeparam.c_str());
return MOD_RES_DENY;
}
+ ++iter;
}
else
{
// Expired record, remove.
- itemstoremove.push_back(iter->first);
+ dl->erase(iter++);
}
}
- for (unsigned int i = 0; i < itemstoremove.size(); i++)
- dl->erase(itemstoremove[i]);
-
if (!dl->size())
kr.ext.unset(chan);
}
@@ -113,7 +124,7 @@ public:
void OnUserKick(User* source, Membership* memb, const std::string &reason, CUList& excepts)
{
- if (memb->chan->IsModeSet(&kr) && (source != memb->user))
+ if (memb->chan->IsModeSet(&kr) && (IS_LOCAL(memb->user)) && (source != memb->user))
{
delaylist* dl = kr.ext.get(memb->chan);
if (!dl)
@@ -121,7 +132,7 @@ public:
dl = new delaylist;
kr.ext.set(memb->chan, dl);
}
- (*dl)[memb->user] = ServerInstance->Time() + ConvToInt(memb->chan->GetModeParameter(&kr));
+ (*dl)[memb->user->uuid] = ServerInstance->Time() + ConvToInt(memb->chan->GetModeParameter(&kr));
}
}
diff --git a/src/modules/m_nonotice.cpp b/src/modules/m_nonotice.cpp
index 89e6be3b7..3a2f0814f 100644
--- a/src/modules/m_nonotice.cpp
+++ b/src/modules/m_nonotice.cpp
@@ -59,11 +59,6 @@ class ModuleNoNotice : public Module
Channel* c = (Channel*)dest;
if (!c->GetExtBanStatus(user, 'T').check(!c->IsModeSet('T')))
{
- if (ServerInstance->ULine(user->server))
- {
- // ulines are exempt.
- return MOD_RES_PASSTHRU;
- }
res = ServerInstance->OnCheckExemption(user,c,"nonotice");
if (res == MOD_RES_ALLOW)
return MOD_RES_PASSTHRU;
diff --git a/src/modules/m_permchannels.cpp b/src/modules/m_permchannels.cpp
index 27026bde9..6a8694a1c 100644
--- a/src/modules/m_permchannels.cpp
+++ b/src/modules/m_permchannels.cpp
@@ -172,14 +172,6 @@ public:
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
OnRehash(NULL);
-
- // Load only when there are no linked servers - we set the TS of the channels we
- // create to the current time, this can lead to desync because spanningtree has
- // no way of knowing what we do
- ProtoServerList serverlist;
- ServerInstance->PI->GetServerList(serverlist);
- if (serverlist.size() < 2)
- LoadDatabase();
}
CullResult cull()
@@ -300,6 +292,38 @@ public:
dirty = false;
}
+ void Prioritize()
+ {
+ // XXX: Load the DB here because the order in which modules are init()ed at boot is
+ // alphabetical, this means we must wait until all modules have done their init()
+ // to be able to set the modes they provide (e.g.: m_stripcolor is inited after us)
+ // Prioritize() is called after all module initialization is complete, consequently
+ // all modes are available now
+
+ static bool loaded = false;
+ if (loaded)
+ return;
+
+ loaded = true;
+
+ // Load only when there are no linked servers - we set the TS of the channels we
+ // create to the current time, this can lead to desync because spanningtree has
+ // no way of knowing what we do
+ ProtoServerList serverlist;
+ ServerInstance->PI->GetServerList(serverlist);
+ if (serverlist.size() < 2)
+ {
+ try
+ {
+ LoadDatabase();
+ }
+ catch (CoreException& e)
+ {
+ ServerInstance->Logs->Log("m_permchannels", LOG_DEFAULT, "Error loading permchannels database: " + std::string(e.GetReason()));
+ }
+ }
+ }
+
virtual Version GetVersion()
{
return Version("Provides support for channel mode +P to provide permanent channels",VF_VENDOR);
diff --git a/src/modules/m_rline.cpp b/src/modules/m_rline.cpp
index c4439cbfb..d164f5fef 100644
--- a/src/modules/m_rline.cpp
+++ b/src/modules/m_rline.cpp
@@ -214,9 +214,13 @@ class ModuleRLine : public Module
RLineFactory f;
CommandRLine r;
bool MatchOnNickChange;
+ bool initing;
+ RegexFactory* factory;
public:
- ModuleRLine() : rxfactory(this, "regex"), f(rxfactory), r(this, f)
+ ModuleRLine()
+ : rxfactory(this, "regex"), f(rxfactory), r(this, f)
+ , initing(true)
{
}
@@ -227,7 +231,7 @@ class ModuleRLine : public Module
ServerInstance->Modules->AddService(r);
ServerInstance->XLines->RegisterFactory(&f);
- Implementation eventlist[] = { I_OnUserConnect, I_OnRehash, I_OnUserPostNick, I_OnStats, I_OnBackgroundTimer };
+ Implementation eventlist[] = { I_OnUserRegister, I_OnRehash, I_OnUserPostNick, I_OnStats, I_OnBackgroundTimer, I_OnUnloadModule };
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
@@ -242,7 +246,7 @@ class ModuleRLine : public Module
return Version("RLINE: Regexp user banning.", VF_COMMON | VF_VENDOR, rxfactory ? rxfactory->name : "");
}
- virtual void OnUserConnect(LocalUser* user)
+ ModResult OnUserRegister(LocalUser* user)
{
// Apply lines on user connect
XLine *rl = ServerInstance->XLines->MatchesLine("R", user);
@@ -251,7 +255,9 @@ class ModuleRLine : public Module
{
// Bang. :P
rl->Apply(user);
+ return MOD_RES_DENY;
}
+ return MOD_RES_PASSTHRU;
}
virtual void OnRehash(User *user)
@@ -262,14 +268,29 @@ class ModuleRLine : public Module
ZlineOnMatch = tag->getBool("zlineonmatch");
std::string newrxengine = tag->getString("engine");
+ factory = rxfactory ? (rxfactory.operator->()) : NULL;
+
if (newrxengine.empty())
rxfactory.SetProvider("regex");
else
rxfactory.SetProvider("regex/" + newrxengine);
+
if (!rxfactory)
{
- ServerInstance->SNO->WriteToSnoMask('a', "WARNING: Regex engine '%s' is not loaded - R-Line functionality disabled until this is corrected.", newrxengine.c_str());
+ if (newrxengine.empty())
+ ServerInstance->SNO->WriteToSnoMask('a', "WARNING: No regex engine loaded - R-Line functionality disabled until this is corrected.");
+ else
+ ServerInstance->SNO->WriteToSnoMask('a', "WARNING: Regex engine '%s' is not loaded - R-Line functionality disabled until this is corrected.", newrxengine.c_str());
+
+ ServerInstance->XLines->DelAll(f.GetType());
}
+ else if ((!initing) && (rxfactory.operator->() != factory))
+ {
+ ServerInstance->SNO->WriteToSnoMask('a', "Regex engine has changed, removing all R-Lines");
+ ServerInstance->XLines->DelAll(f.GetType());
+ }
+
+ initing = false;
}
virtual ModResult OnStats(char symbol, User* user, string_list &results)
@@ -307,6 +328,25 @@ class ModuleRLine : public Module
}
}
+ void OnUnloadModule(Module* mod)
+ {
+ // If the regex engine became unavailable or has changed, remove all rlines
+ if (!rxfactory)
+ {
+ ServerInstance->XLines->DelAll(f.GetType());
+ }
+ else if (rxfactory.operator->() != factory)
+ {
+ factory = rxfactory.operator->();
+ ServerInstance->XLines->DelAll(f.GetType());
+ }
+ }
+
+ void Prioritize()
+ {
+ Module* mod = ServerInstance->Modules->Find("m_cgiirc.so");
+ ServerInstance->Modules->SetPriority(this, I_OnUserRegister, PRIORITY_AFTER, mod);
+ }
};
MODULE_INIT(ModuleRLine)
diff --git a/src/modules/m_services_account.cpp b/src/modules/m_services_account.cpp
index 7c4eb5f0b..81ff3e4c3 100644
--- a/src/modules/m_services_account.cpp
+++ b/src/modules/m_services_account.cpp
@@ -37,7 +37,7 @@ class Channel_r : public ModeHandler
ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string &parameter, bool adding)
{
// only a u-lined server may add or remove the +r mode.
- if (!IS_LOCAL(source) || ServerInstance->ULine(source->server))
+ if (!IS_LOCAL(source))
{
// Only change the mode if it's not redundant
if ((adding != channel->IsModeSet('r')))
@@ -64,7 +64,7 @@ class User_r : public ModeHandler
ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string &parameter, bool adding)
{
- if (!IS_LOCAL(source) || ServerInstance->ULine(source->server))
+ if (!IS_LOCAL(source))
{
if ((adding != dest->IsModeSet('r')))
{
@@ -171,12 +171,6 @@ class ModuleServicesAccount : public Module
std::string *account = accountname.get(user);
bool is_registered = account && !account->empty();
- if ((ServerInstance->ULine(user->nick.c_str())) || (ServerInstance->ULine(user->server)))
- {
- // user is ulined, can speak regardless
- return MOD_RES_PASSTHRU;
- }
-
if (target_type == TYPE_CHANNEL)
{
Channel* c = (Channel*)dest;
@@ -252,12 +246,6 @@ class ModuleServicesAccount : public Module
if (chan)
{
- if ((ServerInstance->ULine(user->nick.c_str())) || (ServerInstance->ULine(user->server)))
- {
- // user is ulined, won't be stopped from joining
- return MOD_RES_PASSTHRU;
- }
-
if (chan->IsModeSet('R'))
{
if (!is_registered)
diff --git a/src/modules/m_spanningtree/main.cpp b/src/modules/m_spanningtree/main.cpp
index 018fcece7..1fa7ef76b 100644
--- a/src/modules/m_spanningtree/main.cpp
+++ b/src/modules/m_spanningtree/main.cpp
@@ -731,7 +731,7 @@ void ModuleSpanningTree::OnRehash(User* user)
std::string msg = "Error in configuration: ";
msg.append(e.GetReason());
ServerInstance->SNO->WriteToSnoMask('l', msg);
- if (!IS_LOCAL(user))
+ if (user && !IS_LOCAL(user))
ServerInstance->PI->SendSNONotice("L", msg);
}
}
diff --git a/src/modules/m_spanningtree/server.cpp b/src/modules/m_spanningtree/server.cpp
index 19e2d53a6..85204ccaa 100644
--- a/src/modules/m_spanningtree/server.cpp
+++ b/src/modules/m_spanningtree/server.cpp
@@ -125,8 +125,9 @@ bool TreeSocket::Outbound_Reply_Server(parameterlist &params)
TreeServer* CheckDupe = Utils->FindServer(sname);
if (CheckDupe)
{
- this->SendError("Server "+sname+" already exists on server "+CheckDupe->GetParent()->GetName()+"!");
- ServerInstance->SNO->WriteToSnoMask('l',"Server connection from \2"+sname+"\2 denied, already exists on server "+CheckDupe->GetParent()->GetName());
+ std::string pname = CheckDupe->GetParent() ? CheckDupe->GetParent()->GetName() : "<ourself>";
+ SendError("Server "+sname+" already exists on server "+pname+"!");
+ ServerInstance->SNO->WriteToSnoMask('l',"Server connection from \2"+sname+"\2 denied, already exists on server "+pname);
return false;
}
CheckDupe = Utils->FindServer(sid);
@@ -168,6 +169,33 @@ bool TreeSocket::Outbound_Reply_Server(parameterlist &params)
return false;
}
+bool TreeSocket::CheckDuplicate(const std::string& sname, const std::string& sid)
+{
+ /* Check for fully initialized instances of the server by name */
+ TreeServer* CheckDupe = Utils->FindServer(sname);
+ if (CheckDupe)
+ {
+ std::string pname = CheckDupe->GetParent() ? CheckDupe->GetParent()->GetName() : "<ourself>";
+ SendError("Server "+sname+" already exists on server "+pname+"!");
+ ServerInstance->SNO->WriteToSnoMask('l',"Server connection from \2"+sname+"\2 denied, already exists on server "+pname);
+ return false;
+ }
+
+ /* Check for fully initialized instances of the server by id */
+ ServerInstance->Logs->Log("m_spanningtree", LOG_DEBUG, "Looking for dupe SID %s", sid.c_str());
+ CheckDupe = Utils->FindServerID(sid);
+
+ if (CheckDupe)
+ {
+ this->SendError("Server ID "+CheckDupe->GetID()+" already exists on server "+CheckDupe->GetName()+"! You may want to specify the server ID for the server manually with <server:id> so they do not conflict.");
+ ServerInstance->SNO->WriteToSnoMask('l',"Server connection from \2"+sname+"\2 denied, server ID '"+CheckDupe->GetID()+
+ "' already exists on server "+CheckDupe->GetName());
+ return false;
+ }
+
+ return true;
+}
+
/*
* Someone else is attempting to connect to us if this is called. Validate their credentials etc.
* -- w
@@ -206,39 +234,24 @@ bool TreeSocket::Inbound_Server(parameterlist &params)
continue;
}
- /* Now check for fully initialized ServerInstances of the server by name */
- TreeServer* CheckDupe = Utils->FindServer(sname);
- if (CheckDupe)
- {
- std::string pname = CheckDupe->GetParent() ? CheckDupe->GetParent()->GetName() : "<ourself>";
- SendError("Server "+sname+" already exists on server "+pname+"!");
- ServerInstance->SNO->WriteToSnoMask('l',"Server connection from \2"+sname+"\2 denied, already exists on server "+pname);
+ if (!CheckDuplicate(sname, sid))
return false;
- }
- /* Check for fully initialized instances of the server by id */
- ServerInstance->Logs->Log("m_spanningtree",LOG_DEBUG,"Looking for dupe SID %s", sid.c_str());
- CheckDupe = Utils->FindServerID(sid);
+ ServerInstance->SNO->WriteToSnoMask('l',"Verified incoming server connection " + linkID + " ("+description+")");
- if (CheckDupe)
- {
- this->SendError("Server ID "+CheckDupe->GetID()+" already exists on server "+CheckDupe->GetName()+"! You may want to specify the server ID for the server manually with <server:id> so they do not conflict.");
- ServerInstance->SNO->WriteToSnoMask('l',"Server connection from \2"+sname+"\2 denied, server ID '"+CheckDupe->GetID()+
- "' already exists on server "+CheckDupe->GetName());
- return false;
- }
+ this->SendCapabilities(2);
- ServerInstance->SNO->WriteToSnoMask('l',"Verified incoming server connection " + linkID + " ("+description+")");
- linkID = sname;
+ // Save these for later, so when they accept our credentials (indicated by BURST) we remember them
+ this->capab->hidden = x->Hidden;
+ this->capab->sid = sid;
+ this->capab->description = description;
+ this->capab->name = sname;
- // this is good. Send our details: Our server name and description and hopcount of 0,
+ // Send our details: Our server name and description and hopcount of 0,
// along with the sendpass from this block.
- this->SendCapabilities(2);
this->WriteLine("SERVER "+ServerInstance->Config->ServerName+" "+this->MakePass(x->SendPass, this->GetTheirChallenge())+" 0 "+ServerInstance->Config->GetSID()+" :"+ServerInstance->Config->ServerDesc);
- // move to the next state, we are now waiting for THEM.
- MyRoot = new TreeServer(Utils, sname, description, sid, Utils->TreeRoot, this, x->Hidden);
- Utils->TreeRoot->AddChild(MyRoot);
+ // move to the next state, we are now waiting for THEM.
this->LinkState = WAIT_AUTH_2;
return true;
}
diff --git a/src/modules/m_spanningtree/treesocket.h b/src/modules/m_spanningtree/treesocket.h
index b6230a6a5..0a519041c 100644
--- a/src/modules/m_spanningtree/treesocket.h
+++ b/src/modules/m_spanningtree/treesocket.h
@@ -75,6 +75,12 @@ struct CapabData
int capab_phase; /* Have sent CAPAB already */
bool auth_fingerprint; /* Did we auth using SSL fingerprint */
bool auth_challenge; /* Did we auth using challenge/response */
+
+ // Data saved from incoming SERVER command, for later use when our credentials have been accepted by the other party
+ std::string description;
+ std::string sid;
+ std::string name;
+ bool hidden;
};
/** Every SERVER connection inbound or outbound is represented by an object of
@@ -92,6 +98,11 @@ class TreeSocket : public BufferedSocket
bool LastPingWasGood; /* Responded to last ping we sent? */
int proto_version; /* Remote protocol version */
bool ConnectionFailureShown; /* Set to true if a connection failure message was shown */
+
+ /** Checks if the given servername and sid are both free
+ */
+ bool CheckDuplicate(const std::string& servername, const std::string& sid);
+
public:
time_t age;
diff --git a/src/modules/m_spanningtree/treesocket2.cpp b/src/modules/m_spanningtree/treesocket2.cpp
index 1504a8807..fdd28a734 100644
--- a/src/modules/m_spanningtree/treesocket2.cpp
+++ b/src/modules/m_spanningtree/treesocket2.cpp
@@ -160,9 +160,21 @@ void TreeSocket::ProcessLine(std::string &line)
ServerInstance->SNO->WriteGlobalSno('l',"\2WARNING\2: Your clocks are out by %d seconds. Please consider synching your clocks.", abs((long)delta));
}
}
+
+ // Check for duplicate server name/sid again, it's possible that a new
+ // server was introduced while we were waiting for them to send BURST.
+ // (we do not reserve their server name/sid when they send SERVER, we do it now)
+ if (!CheckDuplicate(capab->name, capab->sid))
+ return;
+
this->LinkState = CONNECTED;
Utils->timeoutlist.erase(this);
+ linkID = capab->name;
+
+ MyRoot = new TreeServer(Utils, capab->name, capab->description, capab->sid, Utils->TreeRoot, this, capab->hidden);
+ Utils->TreeRoot->AddChild(MyRoot);
+
MyRoot->bursting = true;
this->DoBurst(MyRoot);