* | Inspire Internet Relay Chat Daemon |
* +------------------------------------+
*
- * InspIRCd: (C) 2002-2008 InspIRCd Development Team
- * See: http://www.inspircd.org/wiki/index.php/Credits
+ * InspIRCd: (C) 2002-2009 InspIRCd Development Team
+ * See: http://wiki.inspircd.org/Credits
*
* This program is free but copyrighted software; see
* the file COPYING for details.
#include "commands/cmd_stats.h"
#include "socket.h"
#include "xline.h"
-#include "transport.h"
+#include "../transport.h"
#include "socketengine.h"
-#include "m_spanningtree/main.h"
-#include "m_spanningtree/utils.h"
-#include "m_spanningtree/treeserver.h"
-#include "m_spanningtree/link.h"
-#include "m_spanningtree/treesocket.h"
-#include "m_spanningtree/resolvers.h"
-#include "m_spanningtree/handshaketimer.h"
+#include "main.h"
+#include "utils.h"
+#include "treeserver.h"
+#include "link.h"
+#include "treesocket.h"
+#include "resolvers.h"
+#include "handshaketimer.h"
/* $ModDep: m_spanningtree/resolvers.h m_spanningtree/main.h m_spanningtree/utils.h m_spanningtree/treeserver.h m_spanningtree/link.h m_spanningtree/treesocket.h m_spanningtree/handshaketimer.h */
/* Handle ERROR command */
-bool TreeSocket::Error(std::deque<std::string> ¶ms)
+bool TreeSocket::Error(parameterlist ¶ms)
{
if (params.size() < 1)
return false;
return false;
}
-void TreeSocket::Split(const std::string &line, std::deque<std::string> &n)
+void TreeSocket::Split(const std::string &line, parameterlist &n)
{
n.clear();
irc::tokenstream tokens(line);
bool TreeSocket::ProcessLine(std::string &line)
{
- std::deque<std::string> params;
+ parameterlist params;
irc::string command;
std::string prefix;
if ((params[0][0] == ':') && (params.size() > 1))
{
prefix = params[0].substr(1);
- params.pop_front();
if (prefix.empty())
{
- this->SendError("BUG (?) Empty prefix recieved.");
+ this->SendError("BUG (?) Empty prefix recieved: " + line);
return false;
}
+ command = params[1].c_str();
+ params.erase(params.begin(), params.begin() + 2);
+ }
+ else
+ {
+ command = params[0].c_str();
+ params.erase(params.begin());
}
-
- command = params[0].c_str();
- params.pop_front();
switch (this->LinkState)
{
}
}
this->LinkState = CONNECTED;
- Link* lnk = Utils->FindLink(InboundServerName);
Utils->timeoutlist.erase(this);
- Node = new TreeServer(this->Utils, this->ServerInstance, InboundServerName, InboundDescription, InboundSID, Utils->TreeRoot, this, lnk ? lnk->Hidden : false);
+ Link* lnk = Utils->FindLink(InboundServerName);
- if (Node->DuplicateID())
- {
- this->SendError("Server ID "+InboundSID+" already exists on the network!");
- this->ServerInstance->SNO->WriteToSnoMask('l',"Server \2"+InboundServerName+"\2 being introduced from \2" + prefix + "\2 denied, server ID already exists on the network. Closing link.");
- return false;
- }
+ Node = new TreeServer(this->Utils, this->ServerInstance, InboundServerName, InboundDescription, InboundSID, Utils->TreeRoot, this, lnk ? lnk->Hidden : false);
Utils->TreeRoot->AddChild(Node);
- params.clear();
- params.push_back(InboundServerName);
- params.push_back("*");
- params.push_back("1");
- params.push_back(InboundSID);
- params.push_back(":"+InboundDescription);
- Utils->DoOneToAllButSender(ServerInstance->Config->GetSID(),"SERVER",params,InboundServerName);
+ parameterlist sparams;
+ sparams.push_back(InboundServerName);
+ sparams.push_back("*");
+ sparams.push_back("1");
+ sparams.push_back(InboundSID);
+ sparams.push_back(":"+InboundDescription);
+ Utils->DoOneToAllButSender(ServerInstance->Config->GetSID(),"SERVER",sparams,InboundServerName);
+ Utils->DoOneToAllButSenderRaw(line, InboundServerName, prefix, command, params);
Node->bursting = true;
this->DoBurst(Node);
}
* When would this be seen?
* Well, hopefully never. It could be caused by race conditions, bugs, or
* "miscreant" servers, though, so let's check anyway. -- w
+ *
+ * We also check here for totally invalid prefixes (prefixes that are neither
+ * a valid SID or a valid UUID, so that invalid UUID or SID never makes it
+ * to the higher level functions. -- B
*/
std::string direction = prefix;
User *t = this->ServerInstance->FindUUID(prefix);
if (t)
{
+ /* Find UID */
direction = t->server;
}
+ else if (!this->Utils->FindServer(direction))
+ {
+ /* Find SID */
+ ServerInstance->Logs->Log("m_spanningtree",DEFAULT,"Protocol violation: Invalid prefix '%s' from connection '%s'", direction.c_str(), this->GetName().c_str());
+ return true;
+ }
TreeServer* route_back_again = Utils->BestRouteTo(direction);
if ((!route_back_again) || (route_back_again->GetSocket() != this))
ServerInstance->Logs->Log("m_spanningtree",DEBUG,"Protocol violation: Fake direction in command '%s' from connection '%s'",line.c_str(),this->GetName().c_str());
return true;
}
- /* Fix by brain:
- * When there is activity on the socket, reset the ping counter so
- * that we're not wasting bandwidth pinging an active server.
- */
- route_back_again->SetNextPingTime(ServerInstance->Time() + Utils->PingFreq);
- route_back_again->SetPingFlag();
}
else
{
/* Find the server that this command originated from, used in the handlers below */
TreeServer *ServerSource = Utils->FindServer(prefix);
+ if (ServerSource)
+ {
+ Utils->ServerUser->SetFakeServer(ServerSource->GetName());
+ Utils->ServerUser->uuid = ServerSource->GetID();
+ }
/* Find the link we just got this from so we don't bounce it back incorrectly */
std::string sourceserv = this->myhost;
{
return this->Time(prefix,params);
}
- else if ((command == "KICK") && (Utils->IsServer(prefix)))
- {
- if (params.size() == 3)
- {
- TreeServer* pf = Utils->FindServer(prefix);
- User* user = this->ServerInstance->FindNick(params[1]);
- Channel* chan = this->ServerInstance->FindChan(params[0]);
- if (pf && user && chan)
- {
- if (!chan->ServerKickUser(user, params[2].c_str(), false, pf->GetName().c_str()))
- /* Yikes, the channels gone! */
- delete chan;
- }
- }
-
- return Utils->DoOneToAllButSenderRaw(line,sourceserv,prefix,command,params);
- }
else if (command == "SVSJOIN")
{
return this->ServiceJoin(prefix,params);
{
if (params.size() >= 2)
{
+ std::string oldprefix;
+ if (!ServerSource)
+ {
+ oldprefix = prefix;
+ User *u = ServerInstance->FindNick(prefix);
+ if (!u)
+ return true;
+ prefix = u->nick;
+ }
+
ServerInstance->SNO->WriteToSnoMask(*(params[0].c_str()), "From " + (ServerSource ? ServerSource->GetName().c_str() : prefix) + ": "+ params[1]);
+ prefix = oldprefix;
return Utils->DoOneToAllButSenderRaw(line, sourceserv, prefix, command, params);
}
{
return this->Encap(prefix, params);
}
- else if (command == "MODE" && !this->ServerInstance->FindUUID(prefix)) // XXX we should check for no such serv?
- {
- // Server-prefix MODE.
- std::vector<std::string> modelist(params.begin(), params.end());
-
- /* We don't support this for channel mode changes any more! */
- if (params.size() >= 1)
- {
- if (ServerInstance->FindChan(params[0]))
- {
- this->SendError("Protocol violation by '"+(ServerSource ? ServerSource->GetName().c_str() : prefix)+"'! MODE for channel mode changes is not supported by the InspIRCd 1.2 protocol. You must use FMODE to preserve channel timestamps.");
- return false;
- }
- }
-
- // Insert into the parser
- this->ServerInstance->SendMode(modelist, this->ServerInstance->FakeClient);
-
- // Pass out to the network
- return Utils->DoOneToAllButSenderRaw(line,sourceserv,prefix,command,params);
- }
else
{
/*
* Not a special s2s command. Emulate the user doing it.
* This saves us having a huge ugly command parser again.
*/
- User *who = this->ServerInstance->FindUUID(prefix);
+ User* who = this->ServerInstance->FindUUID(prefix);
- if (!who)
+ if (ServerSource)
{
- // this looks ugly because command is an irc::string
- this->SendError("Command (" + std::string(command.c_str()) + ") from unknown prefix (" + prefix + ")! Dropping link.");
- return false;
+ who = Utils->ServerUser;
+ }
+ else if (!who)
+ {
+ /* this looks ugly because command is an irc::string
+ * It is important that we dont close the link here, unknown prefix can occur
+ * due to various race conditions such as the KILL message for a user somehow
+ * crossing the users QUIT further upstream from the server. Thanks jilles!
+ */
+ ServerInstance->Logs->Log("m_spanningtree", DEBUG, "Command " + std::string(command.c_str()) + " from unknown prefix " + prefix + "! Dropping entire command.");
+ return true;
}
if (command == "NICK")
if (collideret != 1)
{
/*
- * Remote client lost, or both lost, parsing this nickchange would be
- * pointless, as the incoming client's server will soon recieve SVSNICK to
- * change its nick to its UID. :) -- w00t
+ * Remote client lost, or both lost, parsing or passing on this
+ * nickchange would be pointless, as the incoming client's server will
+ * soon recieve SVSNICK to change its nick to its UID. :) -- w00t
*/
return true;
}
}
}
- // its a user
+ // it's a user
std::vector<std::string> strparams(params.begin(), params.end());
switch (this->ServerInstance->CallCommandHandler(command.c_str(), strparams, who))
{
if (this->LinkState == CONNECTING)
{
- Utils->Creator->RemoteMessage(NULL, "CONNECT: Connection to \002%s\002 timed out.", myhost.c_str());
+ this->ServerInstance->SNO->WriteToSnoMask('l', "CONNECT: Connection to \002%s\002 timed out.", myhost.c_str());
Link* MyLink = Utils->FindLink(myhost);
if (MyLink)
Utils->DoFailOver(MyLink);
if (!quitserver.empty())
{
- Utils->Creator->RemoteMessage(NULL,"Connection to '\2%s\2' failed.",quitserver.c_str());
+ this->ServerInstance->SNO->WriteToSnoMask('l', "Connection to '\2%s\2' failed.",quitserver.c_str());
+
time_t server_uptime = ServerInstance->Time() - this->age;
if (server_uptime)
- Utils->Creator->RemoteMessage(NULL,"Connection to '\2%s\2' was established for %s", quitserver.c_str(), Utils->Creator->TimeToStr(server_uptime).c_str());
+ this->ServerInstance->SNO->WriteToSnoMask('l', "Connection to '\2%s\2' was established for %s", quitserver.c_str(), Utils->Creator->TimeToStr(server_uptime).c_str());
}
}
-
-