diff options
Diffstat (limited to 'src/modules/m_spanningtree')
-rw-r--r-- | src/modules/m_spanningtree/capab.cpp | 8 | ||||
-rw-r--r-- | src/modules/m_spanningtree/commands.h | 2 | ||||
-rw-r--r-- | src/modules/m_spanningtree/fjoin.cpp | 9 | ||||
-rw-r--r-- | src/modules/m_spanningtree/main.cpp | 3 | ||||
-rw-r--r-- | src/modules/m_spanningtree/nick.cpp | 17 | ||||
-rw-r--r-- | src/modules/m_spanningtree/server.cpp | 4 | ||||
-rw-r--r-- | src/modules/m_spanningtree/uid.cpp | 13 |
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 ¶ms) 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 ¶ms) 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. |