summaryrefslogtreecommitdiff
path: root/src/modules/m_spanningtree
diff options
context:
space:
mode:
Diffstat (limited to 'src/modules/m_spanningtree')
-rw-r--r--src/modules/m_spanningtree/capab.cpp8
-rw-r--r--src/modules/m_spanningtree/commands.h2
-rw-r--r--src/modules/m_spanningtree/fjoin.cpp9
-rw-r--r--src/modules/m_spanningtree/main.cpp3
-rw-r--r--src/modules/m_spanningtree/nick.cpp17
-rw-r--r--src/modules/m_spanningtree/server.cpp4
-rw-r--r--src/modules/m_spanningtree/uid.cpp13
7 files changed, 39 insertions, 17 deletions
diff --git a/src/modules/m_spanningtree/capab.cpp b/src/modules/m_spanningtree/capab.cpp
index e242bcd4a..f27fe8889 100644
--- a/src/modules/m_spanningtree/capab.cpp
+++ b/src/modules/m_spanningtree/capab.cpp
@@ -153,7 +153,13 @@ void TreeSocket::SendCapabilities(int phase)
extra+
" PREFIX="+ServerInstance->Modes->BuildPrefixes()+
" CHANMODES="+ServerInstance->Modes->GiveModeList(MODETYPE_CHANNEL)+
- " USERMODES="+ServerInstance->Modes->GiveModeList(MODETYPE_USER)
+ " USERMODES="+ServerInstance->Modes->GiveModeList(MODETYPE_USER)+
+ // XXX: Advertise the presence or absence of m_globops in CAPAB CAPABILITIES.
+ // Services want to know about it, and since m_globops was not marked as VF_(OPT)COMMON
+ // in 2.0, we advertise it here to not break linking to previous versions.
+ // Protocol version 1201 (1.2) does not have this issue because we advertise m_globops
+ // to 1201 protocol servers irrespectively of its module flags.
+ (ServerInstance->Modules->Find("m_globops.so") != NULL ? " GLOBOPS=1" : " GLOBOPS=0")
);
this->WriteLine("CAPAB END");
diff --git a/src/modules/m_spanningtree/commands.h b/src/modules/m_spanningtree/commands.h
index 67e2d43d6..3047e7e60 100644
--- a/src/modules/m_spanningtree/commands.h
+++ b/src/modules/m_spanningtree/commands.h
@@ -130,7 +130,7 @@ class CommandFJoin : public ServerCommand
* @param newname The new name of the channel; must be the same or a case change of the current name
*/
static void LowerTS(Channel* chan, time_t TS, const std::string& newname);
- void ProcessModeUUIDPair(const std::string& item, TreeSocket* src_socket, Channel* chan, irc::modestacker* modestack);
+ void ProcessModeUUIDPair(const std::string& item, TreeServer* sourceserver, Channel* chan, irc::modestacker* modestack);
public:
CommandFJoin(Module* Creator) : ServerCommand(Creator, "FJOIN", 3) { }
CmdResult Handle(User* user, std::vector<std::string>& params);
diff --git a/src/modules/m_spanningtree/fjoin.cpp b/src/modules/m_spanningtree/fjoin.cpp
index d8027628f..d5b80fcb1 100644
--- a/src/modules/m_spanningtree/fjoin.cpp
+++ b/src/modules/m_spanningtree/fjoin.cpp
@@ -148,7 +148,7 @@ CmdResult CommandFJoin::Handle(User* srcuser, std::vector<std::string>& params)
}
irc::modestacker modestack(true);
- TreeSocket* src_socket = TreeServer::Get(srcuser)->GetSocket();
+ TreeServer* const sourceserver = TreeServer::Get(srcuser);
/* Now, process every 'modes,uuid' pair */
irc::tokenstream users(params.back());
@@ -156,7 +156,7 @@ CmdResult CommandFJoin::Handle(User* srcuser, std::vector<std::string>& params)
irc::modestacker* modestackptr = (apply_other_sides_modes ? &modestack : NULL);
while (users.GetToken(item))
{
- ProcessModeUUIDPair(item, src_socket, chan, modestackptr);
+ ProcessModeUUIDPair(item, sourceserver, chan, modestackptr);
}
/* Flush mode stacker if we lost the FJOIN or had equal TS */
@@ -166,7 +166,7 @@ CmdResult CommandFJoin::Handle(User* srcuser, std::vector<std::string>& params)
return CMD_SUCCESS;
}
-void CommandFJoin::ProcessModeUUIDPair(const std::string& item, TreeSocket* src_socket, Channel* chan, irc::modestacker* modestack)
+void CommandFJoin::ProcessModeUUIDPair(const std::string& item, TreeServer* sourceserver, Channel* chan, irc::modestacker* modestack)
{
std::string::size_type comma = item.find(',');
@@ -180,6 +180,7 @@ void CommandFJoin::ProcessModeUUIDPair(const std::string& item, TreeSocket* src_
return;
}
+ TreeSocket* src_socket = sourceserver->GetSocket();
/* Check that the user's 'direction' is correct */
TreeServer* route_back_again = TreeServer::Get(who);
if (route_back_again->GetSocket() != src_socket)
@@ -202,7 +203,7 @@ void CommandFJoin::ProcessModeUUIDPair(const std::string& item, TreeSocket* src_
}
}
- Membership* memb = chan->ForceJoin(who, NULL, route_back_again->bursting);
+ Membership* memb = chan->ForceJoin(who, NULL, sourceserver->bursting);
if (!memb)
return;
diff --git a/src/modules/m_spanningtree/main.cpp b/src/modules/m_spanningtree/main.cpp
index a17fb203c..ee4c4bdd8 100644
--- a/src/modules/m_spanningtree/main.cpp
+++ b/src/modules/m_spanningtree/main.cpp
@@ -694,6 +694,7 @@ void ModuleSpanningTree::OnUnloadModule(Module* mod)
return;
ServerInstance->PI->SendMetaData("modules", "-" + mod->ModuleSourceFile);
+restart:
// Close all connections which use an IO hook provided by this module
const TreeServer::ChildServers& list = Utils->TreeRoot->GetChildren();
for (TreeServer::ChildServers::const_iterator i = list.begin(); i != list.end(); ++i)
@@ -703,6 +704,8 @@ void ModuleSpanningTree::OnUnloadModule(Module* mod)
{
sock->SendError("SSL module unloaded");
sock->Close();
+ // XXX: The list we're iterating is modified by TreeSocket::Squit() which is called by Close()
+ goto restart;
}
}
diff --git a/src/modules/m_spanningtree/nick.cpp b/src/modules/m_spanningtree/nick.cpp
index ecec849ee..686a2cc4c 100644
--- a/src/modules/m_spanningtree/nick.cpp
+++ b/src/modules/m_spanningtree/nick.cpp
@@ -42,21 +42,22 @@ CmdResult CommandNick::HandleRemote(RemoteUser* user, std::vector<std::string>&
* On nick messages, check that the nick doesn't already exist here.
* If it does, perform collision logic.
*/
+ bool callfnc = true;
User* x = ServerInstance->FindNickOnly(params[0]);
- if ((x) && (x != user))
+ if ((x) && (x != user) && (x->registered == REG_ALL))
{
/* x is local, who is remote */
int collideret = Utils->DoCollision(x, TreeServer::Get(user), newts, user->ident, user->GetIPString(), user->uuid);
if (collideret != 1)
{
- /*
- * Remote client lost, or both lost, parsing or passing on this
- * nickchange would be pointless, as the incoming client's server will
- * soon receive SAVE to change its nick to its UID. :) -- w00t
- */
- return CMD_FAILURE;
+ // Remote client lost, or both lost, rewrite this nick change as a change to uuid before
+ // forwarding and don't call ChangeNick() because DoCollision() has done it already
+ params[0] = user->uuid;
+ callfnc = false;
}
}
- user->ChangeNick(params[0], newts);
+ if (callfnc)
+ user->ChangeNick(params[0], newts);
+
return CMD_SUCCESS;
}
diff --git a/src/modules/m_spanningtree/server.cpp b/src/modules/m_spanningtree/server.cpp
index 69cae001c..f232d57d6 100644
--- a/src/modules/m_spanningtree/server.cpp
+++ b/src/modules/m_spanningtree/server.cpp
@@ -148,7 +148,7 @@ bool TreeSocket::Outbound_Reply_Server(parameterlist &params)
return true;
}
- this->SendError("Invalid credentials (check the other server's linking snomask for more information)");
+ this->SendError("Mismatched server name or password (check the other server's snomask output for details - e.g. umode +s +Ll)");
ServerInstance->SNO->WriteToSnoMask('l',"Server connection from \2"+sname+"\2 denied, invalid link credentials");
return false;
}
@@ -240,7 +240,7 @@ bool TreeSocket::Inbound_Server(parameterlist &params)
return true;
}
- this->SendError("Invalid credentials");
+ this->SendError("Mismatched server name or password (check the other server's snomask output for details - e.g. umode +s +Ll)");
ServerInstance->SNO->WriteToSnoMask('l',"Server connection from \2"+sname+"\2 denied, invalid link credentials");
return false;
}
diff --git a/src/modules/m_spanningtree/uid.cpp b/src/modules/m_spanningtree/uid.cpp
index 1b17ca6e7..ac9041ecc 100644
--- a/src/modules/m_spanningtree/uid.cpp
+++ b/src/modules/m_spanningtree/uid.cpp
@@ -45,7 +45,18 @@ CmdResult CommandUID::HandleServer(TreeServer* remoteserver, std::vector<std::st
/* check for collision */
User* collideswith = ServerInstance->FindNickOnly(params[2]);
- if (collideswith)
+ if ((collideswith) && (collideswith->registered != REG_ALL))
+ {
+ // User that the incoming user is colliding with is not fully registered, we force nick change the
+ // unregistered user to their uuid and tell them what happened
+ collideswith->WriteFrom(collideswith, "NICK %s", collideswith->uuid.c_str());
+ collideswith->WriteNumeric(433, "%s %s :Nickname overruled.", collideswith->nick.c_str(), collideswith->nick.c_str());
+
+ // Clear the bit before calling User::ChangeNick() to make it NOT run the OnUserPostNick() hook
+ collideswith->registered &= ~REG_NICK;
+ collideswith->ChangeNick(collideswith->uuid, true);
+ }
+ else if (collideswith)
{
/*
* Nick collision.