* | Inspire Internet Relay Chat Daemon |
* +------------------------------------+
*
- * InspIRCd: (C) 2002-2008 InspIRCd Development Team
+ * InspIRCd: (C) 2002-2009 InspIRCd Development Team
* See: http://www.inspircd.org/wiki/index.php/Credits
*
* This program is free but copyrighted software; see
void TreeSocket::WriteLine(std::string line)
{
- Instance->Logs->Log("m_spanningtree",DEBUG, "S[%d] O %s", this->GetFd(), line.c_str());
+ ServerInstance->Logs->Log("m_spanningtree",DEBUG, "S[%d] O %s", this->GetFd(), line.c_str());
line.append("\r\n");
this->Write(line);
}
{
if (params.size() < 1)
return false;
- this->Instance->SNO->WriteToSnoMask('l',"ERROR from %s: %s",(!InboundServerName.empty() ? InboundServerName.c_str() : myhost.c_str()),params[0].c_str());
+ this->ServerInstance->SNO->WriteToSnoMask('l',"ERROR from %s: %s",(!InboundServerName.empty() ? InboundServerName.c_str() : myhost.c_str()),params[0].c_str());
/* we will return false to cause the socket to close. */
return false;
}
if (line.empty())
return true;
- Instance->Logs->Log("m_spanningtree",DEBUG, "S[%d] I %s", this->GetFd(), line.c_str());
+ ServerInstance->Logs->Log("m_spanningtree",DEBUG, "S[%d] I %s", this->GetFd(), line.c_str());
this->Split(line.c_str(),params);
if (params.size())
{
time_t them = atoi(params[0].c_str());
- time_t delta = them - Instance->Time();
+ time_t delta = them - ServerInstance->Time();
if ((delta < -600) || (delta > 600))
{
- Instance->SNO->WriteToSnoMask('l',"\2ERROR\2: Your clocks are out by %d seconds (this is more than five minutes). Link aborted, \2PLEASE SYNC YOUR CLOCKS!\2",abs((long)delta));
+ ServerInstance->SNO->WriteToSnoMask('l',"\2ERROR\2: Your clocks are out by %d seconds (this is more than five minutes). Link aborted, \2PLEASE SYNC YOUR CLOCKS!\2",abs((long)delta));
SendError("Your clocks are out by "+ConvToStr(abs((long)delta))+" seconds (this is more than five minutes). Link aborted, PLEASE SYNC YOUR CLOCKS!");
return false;
}
else if ((delta < -30) || (delta > 30))
{
- Instance->SNO->WriteToSnoMask('l',"\2WARNING\2: Your clocks are out by %d seconds. Please consider synching your clocks.", abs((long)delta));
+ ServerInstance->SNO->WriteToSnoMask('l',"\2WARNING\2: Your clocks are out by %d seconds. Please consider synching your clocks.", abs((long)delta));
}
}
this->LinkState = CONNECTED;
+
+ Utils->timeoutlist.erase(this);
+
Link* lnk = Utils->FindLink(InboundServerName);
- Node = new TreeServer(this->Utils, this->Instance, InboundServerName, InboundDescription, InboundSID, Utils->TreeRoot, this, lnk ? lnk->Hidden : false);
+ Node = new TreeServer(this->Utils, this->ServerInstance, InboundServerName, InboundDescription, InboundSID, Utils->TreeRoot, this, lnk ? lnk->Hidden : false);
if (Node->DuplicateID())
{
this->SendError("Server ID "+InboundSID+" already exists on the network!");
- this->Instance->SNO->WriteToSnoMask('l',"Server \2"+InboundServerName+"\2 being introduced from \2" + prefix + "\2 denied, server ID already exists on the network. Closing link.");
+ 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;
}
params.push_back("1");
params.push_back(InboundSID);
params.push_back(":"+InboundDescription);
- Utils->DoOneToAllButSender(Instance->Config->GetSID(),"SERVER",params,InboundServerName);
+ Utils->DoOneToAllButSender(ServerInstance->Config->GetSID(),"SERVER",params,InboundServerName);
Node->bursting = true;
this->DoBurst(Node);
}
}
break;
- case LISTENER:
- /*
- * This really shouldn't happen.
- */
- this->SendError("Internal error -- listening socket accepted its own descriptor!!!");
- return false;
- break;
case CONNECTING:
/*
* State CONNECTING:
* 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->Instance->FindUUID(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))
{
if (route_back_again)
- Instance->Logs->Log("m_spanningtree",DEBUG,"Protocol violation: Fake direction in command '%s' from connection '%s'",line.c_str(),this->GetName().c_str());
+ 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(Instance->Time() + Utils->PingFreq);
+ route_back_again->SetNextPingTime(ServerInstance->Time() + Utils->PingFreq);
route_back_again->SetPingFlag();
}
else
if (command == "SVSMODE") // This isn't in an "else if" so we still force FMODE for changes on channels.
command = "MODE";
- if (command == "MODE")
- {
- if (params.size() >= 2)
- {
- Channel* channel = Instance->FindChan(params[0]);
- if (channel)
- {
- this->SendError("MODE may no longer be used on channels. Please use FMODE, with correct timestamp rules.");
- return false;
- }
- }
- }
-
-
/*
* Now, check for (and parse) commands as appropriate. -- w
*/
}
else if (command == "MAP")
{
- User* user = Instance->FindNick(prefix);
+ User* user = ServerInstance->FindNick(prefix);
if (user)
{
std::vector<std::string> p(params.begin(), params.end());
}
else if (command == "PONG")
{
+ TreeServer *s = Utils->FindServer(prefix);
+ if (s && s->bursting)
+ {
+ ServerInstance->SNO->WriteToSnoMask('l',"Server \002%s\002 has not finished burst, forcing end of burst (send ENDBURST!)", prefix.c_str());
+ s->FinishBurst();
+ }
return this->LocalPong(prefix,params);
}
else if (command == "VERSION")
if (params.size() == 3)
{
TreeServer* pf = Utils->FindServer(prefix);
- User* user = this->Instance->FindNick(params[1]);
- Channel* chan = this->Instance->FindChan(params[0]);
- if (pf && user && chan)
+ if (pf)
{
- if (!chan->ServerKickUser(user, params[2].c_str(), false, pf->GetName().c_str()))
- /* Yikes, the channels gone! */
- delete chan;
+ irc::commasepstream nicks(params[1]);
+ std::string nick;
+ Channel* chan = this->ServerInstance->FindChan(params[0]);
+ if (chan)
+ {
+ while (nicks.GetToken(nick))
+ {
+ User* user = this->ServerInstance->FindNick(nick);
+ if (user)
+ {
+ if (!chan->ServerKickUser(user, params[2].c_str(), false, pf->GetName().c_str()))
+ /* Yikes, the channels gone! */
+ delete chan;
+ }
+ }
+ }
}
}
if (params.size() >= 2)
{
if (ServerSource)
- Instance->Users->WriteMode(params[0].c_str(), WM_AND, "*** From %s: %s", (ServerSource ? ServerSource->GetName().c_str() : prefix.c_str()), params[1].c_str());
+ ServerInstance->Users->WriteMode(params[0].c_str(), WM_AND, "*** From %s: %s", (ServerSource ? ServerSource->GetName().c_str() : prefix.c_str()), params[1].c_str());
}
return Utils->DoOneToAllButSenderRaw(line, sourceserv, prefix, command, params);
}
{
if (params.size() >= 2)
{
- Instance->SNO->WriteToSnoMask(*(params[0].c_str()), "From " + (ServerSource ? ServerSource->GetName().c_str() : prefix) + ": "+ params[1]);
+ 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);
}
// Set prefix server as bursting
if (!ServerSource)
{
- this->Instance->SNO->WriteToSnoMask('l', "WTF: Got BURST from a nonexistant server(?): %s", (ServerSource ? ServerSource->GetName().c_str() : prefix.c_str()));
+ this->ServerInstance->SNO->WriteToSnoMask('l', "WTF: Got BURST from a nonexistant server(?): %s", (ServerSource ? ServerSource->GetName().c_str() : prefix.c_str()));
return false;
}
{
if (!ServerSource)
{
- this->Instance->SNO->WriteToSnoMask('l', "WTF: Got ENDBURST from a nonexistant server(?): %s", (ServerSource ? ServerSource->GetName().c_str() : prefix.c_str()));
+ this->ServerInstance->SNO->WriteToSnoMask('l', "WTF: Got ENDBURST from a nonexistant server(?): %s", (ServerSource ? ServerSource->GetName().c_str() : prefix.c_str()));
return false;
}
{
return this->Encap(prefix, params);
}
- else if (command == "MODE")
+ 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 (Instance->FindChan(params[0]))
+ 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->Instance->SendMode(modelist, this->Instance->FakeClient);
+ this->ServerInstance->SendMode(modelist, this->ServerInstance->FakeClient);
// Pass out to the network
return Utils->DoOneToAllButSenderRaw(line,sourceserv,prefix,command,params);
* Not a special s2s command. Emulate the user doing it.
* This saves us having a huge ugly command parser again.
*/
- User *who = this->Instance->FindUUID(prefix);
+ User* who = this->ServerInstance->FindUUID(prefix);
if (!who)
{
- // 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;
+ /* 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")
* On nick messages, check that the nick doesnt already exist here.
* If it does, perform collision logic.
*/
- User* x = this->Instance->FindNickOnly(params[0]);
+ User* x = this->ServerInstance->FindNickOnly(params[0]);
if ((x) && (x != who))
{
int collideret = 0;
// its a user
std::vector<std::string> strparams(params.begin(), params.end());
- switch (this->Instance->CallCommandHandler(command.c_str(), strparams, who))
+ switch (this->ServerInstance->CallCommandHandler(command.c_str(), strparams, who))
{
case CMD_INVALID:
/*
{
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());
- time_t server_uptime = Instance->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());
- }
-}
-
-int TreeSocket::OnIncomingConnection(int newsock, char* ip)
-{
- bool found = false;
-
- found = (std::find(Utils->ValidIPs.begin(), Utils->ValidIPs.end(), ip) != Utils->ValidIPs.end());
- if (!found)
- {
- for (std::vector<std::string>::iterator i = Utils->ValidIPs.begin(); i != Utils->ValidIPs.end(); i++)
- {
- if (*i == "*" || irc::sockets::MatchCIDR(ip, *i))
- {
- found = true;
- break;
- }
- }
+ this->ServerInstance->SNO->WriteToSnoMask('l', "Connection to '\2%s\2' failed.",quitserver.c_str());
- if (!found)
- {
- Utils->Creator->RemoteMessage(NULL,"Server connection from %s denied (no link blocks with that IP address)", ip);
- Instance->SE->Close(newsock);
- return false;
- }
+ time_t server_uptime = ServerInstance->Time() - this->age;
+ if (server_uptime)
+ this->ServerInstance->SNO->WriteToSnoMask('l', "Connection to '\2%s\2' was established for %s", quitserver.c_str(), Utils->Creator->TimeToStr(server_uptime).c_str());
}
-
- TreeSocket* s = new TreeSocket(this->Utils, this->Instance, newsock, ip, this->Hook);
- s = s; /* Whinge whinge whinge, thats all GCC ever does. */
- return true;
}