- /* Find the server that this command originated from, used in the handlers below */
- TreeServer *ServerSource = Utils->FindServer(prefix);
-
- /* Find the link we just got this from so we don't bounce it back incorrectly */
- std::string sourceserv = this->myhost;
- if (!this->InboundServerName.empty())
- {
- sourceserv = this->InboundServerName;
- }
-
- /*
- * XXX one of these days, this needs to be moved into class Commands.
- */
- if (command == "UID")
- {
- return this->ParseUID(prefix, params);
- }
- else if (command == "FJOIN")
- {
- return this->ForceJoin(prefix,params);
- }
- else if ((command == "NOTICE" || command == "PRIVMSG") && (Utils->IsServer(prefix)))
- {
- return this->ServerMessage(assign(command), prefix, params, sourceserv);
- }
- else if (command == "STATS")
- {
- return this->Stats(prefix, params);
- }
- else if (command == "MOTD")
- {
- return this->Motd(prefix, params);
- }
- else if (command == "KILL" && ServerSource)
- {
- // Kill from a server
- return this->RemoteKill(prefix,params);
- }
- else if (command == "MODULES")
- {
- return this->Modules(prefix, params);
- }
- else if (command == "ADMIN")
- {
- return this->Admin(prefix, params);
- }
- else if (command == "MAP")
- {
- User* user = ServerInstance->FindNick(prefix);
- if (user)
- {
- std::vector<std::string> p(params.begin(), params.end());
- return Utils->Creator->HandleMap(p, user);
- }
- }
- else if (command == "SERVER")
- {
- return this->RemoteServer(prefix,params);
- }
- else if (command == "ERROR")
- {
- return this->Error(params);
- }
- else if (command == "OPERTYPE")
- {
- return this->OperType(prefix,params);
- }
- else if (command == "FMODE")
- {
- return this->ForceMode(prefix,params);
- }
- else if (command == "FTOPIC")
- {
- return this->ForceTopic(prefix,params);
- }
- else if (command == "METADATA")
- {
- return this->MetaData(prefix,params);
- }
- else if (command == "PING")
- {
- return this->LocalPing(prefix,params);
- }
- 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")
- {
- return this->ServerVersion(prefix,params);
- }
- else if (command == "FHOST")
- {
- return this->ChangeHost(prefix,params);
- }
- else if (command == "FNAME")
- {
- return this->ChangeName(prefix,params);
- }
- else if (command == "ADDLINE")
- {
- return this->AddLine(prefix,params);
- }
- else if (command == "DELLINE")
- {
- return this->DelLine(prefix,params);
- }
- else if (command == "SVSNICK")
- {
- return this->ForceNick(prefix,params);
- }
- else if (command == "OPERQUIT")
- {
- return this->OperQuit(prefix,params);
- }
- else if (command == "IDLE")
- {
- return this->Whois(prefix,params);
- }
- else if (command == "PUSH")
- {
- return this->Push(prefix,params);
- }
- else if (command == "TIME")
- {
- 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;
- }
- }
+ // Make sure prefix is still good
+ prefix = who->uuid;
+
+ /*
+ * Check for fake direction here, and drop any instances that are found.
+ * What is fake direction? Imagine the following server setup:
+ * 0AA <-> 0AB <-> 0AC
+ * Fake direction would be 0AC sending a message to 0AB claiming to be from
+ * 0AA, or something similar. Basically, a message taking a path that *cannot*
+ * be correct.
+ *
+ * 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
+ */
+ TreeServer* route_back_again = Utils->BestRouteTo(direction);
+ if ((!route_back_again) || (route_back_again->GetSocket() != this))
+ {
+ if (route_back_again)
+ ServerInstance->Logs->Log("m_spanningtree",DEBUG,"Protocol violation: Fake direction '%s' from connection '%s'",
+ prefix.c_str(),this->GetName().c_str());
+ return;
+ }