The InspIRCd Project
Home | Developers | Wiki | Forums | Bug Tracker | SVN | Download | Blog | Stats
Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

TreeSocket Class Reference

Every SERVER connection inbound or outbound is represented by an object of type TreeSocket. More...

#include <treesocket.h>

Inheritance diagram for TreeSocket:

Inheritance graph
[legend]
Collaboration diagram for TreeSocket:

Collaboration graph
[legend]
List of all members.

Public Member Functions

 TreeSocket (SpanningTreeUtilities *Util, InspIRCd *SI, std::string host, int port, bool listening, unsigned long maxtime, Module *HookMod=NULL)
 Because most of the I/O gubbins are encapsulated within InspSocket, we just call the superclass constructor for most of the action, and append a few of our own values to it.
 TreeSocket (SpanningTreeUtilities *Util, InspIRCd *SI, std::string host, int port, bool listening, unsigned long maxtime, const std::string &ServerName, const std::string &bindto, Module *HookMod=NULL)
 Because most of the I/O gubbins are encapsulated within InspSocket, we just call the superclass constructor for most of the action, and append a few of our own values to it.
 TreeSocket (SpanningTreeUtilities *Util, InspIRCd *SI, int newfd, char *ip, Module *HookMod=NULL)
 When a listening socket gives us a new file descriptor, we must associate it with a socket without creating a new connection.
ServerState GetLinkState ()
 Get link state.
const std::stringGetOurChallenge ()
 Get challenge set in our CAPAB for challenge/response.
void SetOurChallenge (const std::string &c)
 Get challenge set in our CAPAB for challenge/response.
const std::stringGetTheirChallenge ()
 Get challenge set in their CAPAB for challenge/response.
void SetTheirChallenge (const std::string &c)
 Get challenge set in their CAPAB for challenge/response.
bool ComparePass (const std::string &ours, const std::string &theirs)
 Compare two passwords based on authentication scheme.
ModuleGetHook ()
 Return the module which we are hooking to for I/O encapsulation.
 ~TreeSocket ()
 Destructor.
std::string RandString (unsigned int length)
 Generate random string used for challenge-response auth.
std::string MakePass (const std::string &password, const std::string &challenge)
 Construct a password, optionally hashed with the other side's challenge string.
virtual bool OnConnected ()
 When an outbound connection finishes connecting, we receive this event, and must send our SERVER string to the other side.
virtual void OnError (InspSocketError e)
 Handle socket error event.
void SendError (const std::string &errormessage)
 Sends an error to the remote server, and displays it locally to show that it was sent.
virtual int OnDisconnect ()
 Handle socket disconnect event.
void SendServers (TreeServer *Current, TreeServer *s, int hops)
 Recursively send the server tree with distances as hops.
std::string MyCapabilities ()
 Returns my capabilities as a string.
void SendCapabilities ()
 Send my capabilities to the remote side.
bool HasItem (const std::string &list, const std::string &item)
std::string ListDifference (const std::string &one, const std::string &two)
bool Capab (const std::deque< std::string > &params)
void SquitServer (std::string &from, TreeServer *Current)
 This function forces this server to quit, removing this server and any users on it (and servers and users below that, etc etc).
void Squit (TreeServer *Current, const std::string &reason)
 This is a wrapper function for SquitServer above, which does some validation first and passes on the SQUIT to all other remaining servers.
bool ForceMode (const std::string &source, std::deque< std::string > &params)
 FMODE command - server mode with timestamp checks.
bool ForceTopic (const std::string &source, std::deque< std::string > &params)
 FTOPIC command.
bool ForceJoin (const std::string &source, std::deque< std::string > &params)
 FJOIN, similar to TS6 SJOIN, but not quite.
bool IntroduceClient (const std::string &source, std::deque< std::string > &params)
 NICK command.
void SendFJoins (TreeServer *Current, chanrec *c)
 Send one or more FJOINs for a channel of users.
void SendXLines (TreeServer *Current)
 Send G, Q, Z and E lines.
void SendChannelModes (TreeServer *Current)
 Send channel modes and topics.
void SendUsers (TreeServer *Current)
 send all users and their oper state/modes
void DoBurst (TreeServer *s)
 This function is called when we want to send a netburst to a local server.
virtual bool OnDataReady ()
 This function is called when we receive data from a remote server.
void WriteLine (std::string line)
 Send one or more complete lines down the socket.
bool Error (std::deque< std::string > &params)
 Handle ERROR command.
bool Motd (const std::string &prefix, std::deque< std::string > &params)
 remote MOTD.
bool Admin (const std::string &prefix, std::deque< std::string > &params)
 remote ADMIN.
bool Modules (const std::string &prefix, std::deque< std::string > &params)
 Remote MODULES.
bool Stats (const std::string &prefix, std::deque< std::string > &params)
bool OperType (const std::string &prefix, std::deque< std::string > &params)
 Because the core won't let users or even SERVERS set +o, we use the OPERTYPE command to do this.
bool ForceNick (const std::string &prefix, std::deque< std::string > &params)
 Because Andy insists that services-compatible servers must implement SVSNICK and SVSJOIN, that's exactly what we do :p.
bool OperQuit (const std::string &prefix, std::deque< std::string > &params)
bool ServiceJoin (const std::string &prefix, std::deque< std::string > &params)
 SVSJOIN.
bool ServicePart (const std::string &prefix, std::deque< std::string > &params)
 SVSPART.
bool RemoteRehash (const std::string &prefix, std::deque< std::string > &params)
 REHASH.
bool RemoteKill (const std::string &prefix, std::deque< std::string > &params)
 KILL.
bool LocalPong (const std::string &prefix, std::deque< std::string > &params)
 PONG.
bool MetaData (const std::string &prefix, std::deque< std::string > &params)
 METADATA.
bool ServerVersion (const std::string &prefix, std::deque< std::string > &params)
 VERSION.
bool ChangeHost (const std::string &prefix, std::deque< std::string > &params)
 CHGHOST.
bool AddLine (const std::string &prefix, std::deque< std::string > &params)
 ADDLINE.
bool ChangeName (const std::string &prefix, std::deque< std::string > &params)
 CHGNAME.
bool Whois (const std::string &prefix, std::deque< std::string > &params)
 WHOIS.
bool Push (const std::string &prefix, std::deque< std::string > &params)
 PUSH.
bool HandleSetTime (const std::string &prefix, std::deque< std::string > &params)
 SETTIME.
bool Time (const std::string &prefix, std::deque< std::string > &params)
 TIME.
bool LocalPing (const std::string &prefix, std::deque< std::string > &params)
 PING.
bool RemoveStatus (const std::string &prefix, std::deque< std::string > &params)
 Remove all modes from a channel, including statusmodes (+qaovh etc), simplemodes, parameter modes.
bool RemoteServer (const std::string &prefix, std::deque< std::string > &params)
 <- (remote) <- SERVER
bool Outbound_Reply_Server (std::deque< std::string > &params)
 (local) -> SERVER
bool Inbound_Server (std::deque< std::string > &params)
 (local) <- SERVER
void Split (const std::string &line, std::deque< std::string > &n)
 Handle netsplit.
bool ProcessLine (std::string &line)
 Process complete line from buffer.
virtual std::string GetName ()
 Get this server's name.
virtual void OnTimeout ()
 Handle socket timeout from connect().
virtual void OnClose ()
 Handle socket close event.
virtual int OnIncomingConnection (int newsock, char *ip)
 Handle incoming connection event.

Private Attributes

SpanningTreeUtilitiesUtils
std::string myhost
std::string in_buffer
ServerState LinkState
std::string InboundServerName
std::string InboundDescription
int num_lost_users
int num_lost_servers
time_t NextPing
bool LastPingWasGood
bool bursting
unsigned int keylength
std::string ModuleList
std::map< std::string, std::stringCapKeys
ModuleHook
std::string ourchallenge
std::string theirchallenge
std::string OutboundPass
bool sentcapab

Detailed Description

Every SERVER connection inbound or outbound is represented by an object of type TreeSocket.

TreeSockets, being inherited from InspSocket, can be tied into the core socket engine, and we cn therefore receive activity events for them, just like activex objects on speed. (yes really, that is a technical term!) Each of these which relates to a locally connected server is assocated with it, by hooking it onto a TreeSocket class using its constructor. In this way, we can maintain a list of servers, some of which are directly connected, some of which are not.

Definition at line 78 of file treesocket.h.


Constructor & Destructor Documentation

TreeSocket::TreeSocket SpanningTreeUtilities Util,
InspIRCd SI,
std::string  host,
int  port,
bool  listening,
unsigned long  maxtime,
Module HookMod = NULL
 

Because most of the I/O gubbins are encapsulated within InspSocket, we just call the superclass constructor for most of the action, and append a few of our own values to it.

Definition at line 44 of file treesocket1.cpp.

References SpanningTreeUtilities::Creator, Hook, LinkState, LISTENER, myhost, ourchallenge, theirchallenge, and Utils.

Referenced by OnIncomingConnection().

00045         : InspSocket(SI, host, port, listening, maxtime), Utils(Util), Hook(HookMod)
00046 {
00047         myhost = host;
00048         this->LinkState = LISTENER;
00049         theirchallenge.clear();
00050         ourchallenge.clear();
00051         if (listening && Hook)
00052                 InspSocketHookRequest(this, (Module*)Utils->Creator, Hook).Send();
00053 }

TreeSocket::TreeSocket SpanningTreeUtilities Util,
InspIRCd SI,
std::string  host,
int  port,
bool  listening,
unsigned long  maxtime,
const std::string ServerName,
const std::string bindto,
Module HookMod = NULL
 

Because most of the I/O gubbins are encapsulated within InspSocket, we just call the superclass constructor for most of the action, and append a few of our own values to it.

Definition at line 55 of file treesocket1.cpp.

References CONNECTING, SpanningTreeUtilities::Creator, Hook, LinkState, myhost, ourchallenge, theirchallenge, and Utils.

00056         : InspSocket(SI, host, port, listening, maxtime, bindto), Utils(Util), Hook(HookMod)
00057 {
00058         myhost = ServerName;
00059         theirchallenge.clear();
00060         ourchallenge.clear();
00061         this->LinkState = CONNECTING;
00062         if (Hook)
00063                 InspSocketHookRequest(this, (Module*)Utils->Creator, Hook).Send();
00064 }

TreeSocket::TreeSocket SpanningTreeUtilities Util,
InspIRCd SI,
int  newfd,
char *  ip,
Module HookMod = NULL
 

When a listening socket gives us a new file descriptor, we must associate it with a socket without creating a new connection.

This constructor is used for this purpose.

Definition at line 70 of file treesocket1.cpp.

References TimerManager::AddTimer(), SpanningTreeUtilities::Creator, Hook, InspSocket::Instance, SpanningTreeUtilities::LinkBlocks, LinkState, ourchallenge, sentcapab, theirchallenge, InspIRCd::Timers, Utils, and WAIT_AUTH_1.

00071         : InspSocket(SI, newfd, ip), Utils(Util), Hook(HookMod)
00072 {
00073         this->LinkState = WAIT_AUTH_1;
00074         theirchallenge.clear();
00075         ourchallenge.clear();
00076         sentcapab = false;
00077         /* If we have a transport module hooked to the parent, hook the same module to this
00078          * socket, and set a timer waiting for handshake before we send CAPAB etc.
00079          */
00080         if (Hook)
00081                 InspSocketHookRequest(this, (Module*)Utils->Creator, Hook).Send();
00082 
00083         Instance->Timers->AddTimer(new HandshakeTimer(Instance, this, &(Utils->LinkBlocks[0]), this->Utils, 1));
00084 }

TreeSocket::~TreeSocket  ) 
 

Destructor.

Definition at line 96 of file treesocket1.cpp.

References SpanningTreeUtilities::Creator, SpanningTreeUtilities::DelBurstingServer(), Hook, and Utils.

00097 {
00098         if (Hook)
00099                 InspSocketUnhookRequest(this, (Module*)Utils->Creator, Hook).Send();
00100 
00101         Utils->DelBurstingServer(this);
00102 }


Member Function Documentation

bool TreeSocket::AddLine const std::string prefix,
std::deque< std::string > &  params
 

ADDLINE.

Definition at line 503 of file treesocket2.cpp.

References XLineManager::add_eline(), XLineManager::add_gline(), XLineManager::add_kline(), XLineManager::add_qline(), XLineManager::add_zline(), APPLY_GLINES, APPLY_KLINES, XLineManager::apply_lines(), APPLY_QLINES, APPLY_ZLINES, ConvToInt(), SpanningTreeUtilities::DoOneToAllButSender(), XLineManager::eline_set_creation_time(), XLineManager::gline_set_creation_time(), InspSocket::Instance, SpanningTreeUtilities::lines_to_apply, XLineManager::qline_set_creation_time(), InspIRCd::SNO, InspIRCd::Time(), InspIRCd::TimeString(), Utils, SnomaskManager::WriteToSnoMask(), InspIRCd::XLines, and XLineManager::zline_set_creation_time().

Referenced by ProcessLine().

00504 {
00505         if (params.size() < 6)
00506                 return true;
00507         bool propogate = false;
00508         if (!this->bursting)
00509                 Utils->lines_to_apply = 0;
00510         switch (*(params[0].c_str()))
00511         {
00512                 case 'Z':
00513                         propogate = Instance->XLines->add_zline(atoi(params[4].c_str()), params[2].c_str(), params[5].c_str(), params[1].c_str());
00514                         Instance->XLines->zline_set_creation_time(params[1].c_str(), atoi(params[3].c_str()));
00515                         if (propogate)
00516                                 Utils->lines_to_apply |= APPLY_ZLINES;
00517                 break;
00518                 case 'Q':
00519                         propogate = Instance->XLines->add_qline(atoi(params[4].c_str()), params[2].c_str(), params[5].c_str(), params[1].c_str());
00520                         Instance->XLines->qline_set_creation_time(params[1].c_str(), atoi(params[3].c_str()));
00521                         if (propogate)
00522                                 Utils->lines_to_apply |= APPLY_QLINES;
00523                 break;
00524                 case 'E':
00525                         propogate = Instance->XLines->add_eline(atoi(params[4].c_str()), params[2].c_str(), params[5].c_str(), params[1].c_str());
00526                         Instance->XLines->eline_set_creation_time(params[1].c_str(), atoi(params[3].c_str()));
00527                 break;
00528                 case 'G':
00529                         propogate = Instance->XLines->add_gline(atoi(params[4].c_str()), params[2].c_str(), params[5].c_str(), params[1].c_str());
00530                         Instance->XLines->gline_set_creation_time(params[1].c_str(), atoi(params[3].c_str()));
00531                         if (propogate)
00532                                 Utils->lines_to_apply |= APPLY_GLINES;
00533                 break;
00534                 case 'K':
00535                         propogate = Instance->XLines->add_kline(atoi(params[4].c_str()), params[2].c_str(), params[5].c_str(), params[1].c_str());
00536                         if (propogate)
00537                                 Utils->lines_to_apply |= APPLY_KLINES;
00538                 break;
00539                 default:
00540                         /* Just in case... */
00541                         this->Instance->SNO->WriteToSnoMask('x',"\2WARNING\2: Invalid xline type '"+params[0]+"' sent by server "+prefix+", ignored!");
00542                         propogate = false;
00543                 break;
00544         }
00545         /* Send it on its way */
00546         if (propogate)
00547         {
00548                 if (atoi(params[4].c_str()))
00549                 {
00550                         time_t c_requires_crap = ConvToInt(params[4]) + Instance->Time();
00551                         this->Instance->SNO->WriteToSnoMask('x',"%s Added %cLINE on %s to expire on %s (%s).",prefix.c_str(),*(params[0].c_str()),params[1].c_str(),Instance->TimeString(c_requires_crap).c_str(),params[5].c_str());
00552                 }
00553                 else
00554                 {
00555                         this->Instance->SNO->WriteToSnoMask('x',"%s Added permanent %cLINE on %s (%s).",prefix.c_str(),*(params[0].c_str()),params[1].c_str(),params[5].c_str());
00556                 }
00557                 params[5] = ":" + params[5];
00558                 Utils->DoOneToAllButSender(prefix,"ADDLINE",params,prefix);
00559         }
00560         if (!this->bursting)
00561         {
00562                 Instance->XLines->apply_lines(Utils->lines_to_apply);
00563                 Utils->lines_to_apply = 0;
00564         }
00565         return true;
00566 }

bool TreeSocket::Admin const std::string prefix,
std::deque< std::string > &  params
 

remote ADMIN.

leet, huh?

Definition at line 161 of file treesocket2.cpp.

References ServerConfig::AdminEmail, ServerConfig::AdminName, ServerConfig::AdminNick, InspIRCd::Config, SpanningTreeUtilities::DoOneToOne(), InspIRCd::FindNick(), InspSocket::Instance, userrec::nick, userrec::server, ServerConfig::ServerName, and Utils.

Referenced by ProcessLine().

00162 {
00163         if (params.size() > 0)
00164         {
00165                 if (this->Instance->MatchText(this->Instance->Config->ServerName, params[0]))
00166                 {
00167                         /* It's for our server */
00168                         string_list results;
00169                         userrec* source = this->Instance->FindNick(prefix);
00170                         if (source)
00171                         {
00172                                 std::deque<std::string> par;
00173                                 par.push_back(prefix);
00174                                 par.push_back("");
00175                                 par[1] = std::string("::")+Instance->Config->ServerName+" 256 "+source->nick+" :Administrative info for "+Instance->Config->ServerName;
00176                                 Utils->DoOneToOne(this->Instance->Config->ServerName, "PUSH",par, source->server);
00177                                 par[1] = std::string("::")+Instance->Config->ServerName+" 257 "+source->nick+" :Name     - "+Instance->Config->AdminName;
00178                                 Utils->DoOneToOne(this->Instance->Config->ServerName, "PUSH",par, source->server);
00179                                 par[1] = std::string("::")+Instance->Config->ServerName+" 258 "+source->nick+" :Nickname - "+Instance->Config->AdminNick;
00180                                 Utils->DoOneToOne(this->Instance->Config->ServerName, "PUSH",par, source->server);
00181                                 par[1] = std::string("::")+Instance->Config->ServerName+" 258 "+source->nick+" :E-Mail   - "+Instance->Config->AdminEmail;
00182                                 Utils->DoOneToOne(this->Instance->Config->ServerName, "PUSH",par, source->server);
00183                         }
00184                 }
00185                 else
00186                 {
00187                         /* Pass it on */
00188                         userrec* source = this->Instance->FindNick(prefix);
00189                         if (source)
00190                                 Utils->DoOneToOne(prefix, "ADMIN", params, params[0]);
00191                 }
00192         }
00193         return true;
00194 }

bool TreeSocket::Capab const std::deque< std::string > &  params  ) 
 

Definition at line 421 of file treesocket1.cpp.

References ServerConfig::AllowHalfop, ModeParser::BuildPrefixes(), CapKeys, SpanningTreeUtilities::ChallengeResponse, CHANMAX, InspIRCd::Config, CONNECTING, ConvToStr(), InspIRCd::FindModule(), irc::tokenstream::GetToken(), IDENTMAX, InspSocket::Instance, cap_validation::key, LinkState, ListDifference(), MAXAWAY, MAXGECOS, MAXKICK, MAXMODES, MAXQUIT, MAXTOPIC, InspIRCd::Modes, ModuleList, NICKMAX, OutboundPass, ProtocolVersion, cap_validation::reason, SendCapabilities(), SendError(), ServerConfig::ServerDesc, SetTheirChallenge(), Utils, and WriteLine().

Referenced by ProcessLine().

00422 {
00423         if (params.size() < 1)
00424         {
00425                 this->SendError("Invalid number of parameters for CAPAB - Mismatched version");
00426                 return false;
00427         }
00428         if (params[0] == "START")
00429         {
00430                 this->ModuleList.clear();
00431                 this->CapKeys.clear();
00432         }
00433         else if (params[0] == "END")
00434         {
00435                 std::string reason;
00436                 int ip6support = 0;
00437 #ifdef SUPPORT_IP6LINKS
00438                 ip6support = 1;
00439 #endif
00440                 /* Compare ModuleList and check CapKeys...
00441                  * Maybe this could be tidier? -- Brain
00442                  */
00443                 if ((this->ModuleList != this->MyCapabilities()) && (this->ModuleList.length()))
00444                 {
00445                         std::string diff = ListDifference(this->ModuleList, this->MyCapabilities());
00446                         if (!diff.length())
00447                         {
00448                                 diff = "your server:" + ListDifference(this->MyCapabilities(), this->ModuleList);
00449                         }
00450                         else
00451                         {
00452                                 diff = "this server:" + diff;
00453                         }
00454                         if (diff.length() == 12)
00455                                 reason = "Module list in CAPAB is not alphabetically ordered, cannot compare lists.";
00456                         else
00457                                 reason = "Modules loaded on these servers are not correctly matched, these modules are not loaded on " + diff;
00458                 }
00459 
00460                 cap_validation valid_capab[] = { 
00461                         {"Maximum nickname lengths differ or remote nickname length not specified", "NICKMAX", NICKMAX},
00462                         {"Maximum ident lengths differ or remote ident length not specified", "IDENTMAX", IDENTMAX},
00463                         {"Maximum channel lengths differ or remote channel length not specified", "CHANMAX", CHANMAX},
00464                         {"Maximum modes per line differ or remote modes per line not specified", "MAXMODES", MAXMODES},
00465                         {"Maximum quit lengths differ or remote quit length not specified", "MAXQUIT", MAXQUIT},
00466                         {"Maximum topic lengths differ or remote topic length not specified", "MAXTOPIC", MAXTOPIC},
00467                         {"Maximum kick lengths differ or remote kick length not specified", "MAXKICK", MAXKICK},
00468                         {"Maximum GECOS (fullname) lengths differ or remote GECOS length not specified", "MAXGECOS", MAXGECOS},
00469                         {"Maximum awaymessage lengths differ or remote awaymessage length not specified", "MAXAWAY", MAXAWAY},
00470                         {"", "", 0}
00471                 };
00472 
00473                 if (((this->CapKeys.find("IP6SUPPORT") == this->CapKeys.end()) && (ip6support)) || ((this->CapKeys.find("IP6SUPPORT") != this->CapKeys.end()) && (this->CapKeys.find("IP6SUPPORT")->second != ConvToStr(ip6support))))
00474                         reason = "We don't both support linking to IPV6 servers";
00475                 if (((this->CapKeys.find("IP6NATIVE") != this->CapKeys.end()) && (this->CapKeys.find("IP6NATIVE")->second == "1")) && (!ip6support))
00476                         reason = "The remote server is IPV6 native, and we don't support linking to IPV6 servers";
00477                 if (((this->CapKeys.find("PROTOCOL") == this->CapKeys.end()) || ((this->CapKeys.find("PROTOCOL") != this->CapKeys.end()) && (this->CapKeys.find("PROTOCOL")->second != ConvToStr(ProtocolVersion)))))
00478                 {
00479                         if (this->CapKeys.find("PROTOCOL") != this->CapKeys.end())
00480                                 reason = "Mismatched protocol versions "+this->CapKeys.find("PROTOCOL")->second+" and "+ConvToStr(ProtocolVersion);
00481                         else
00482                                 reason = "Protocol version not specified";
00483                 }
00484 
00485                 if(this->CapKeys.find("PREFIX") != this->CapKeys.end() && this->CapKeys.find("PREFIX")->second != this->Instance->Modes->BuildPrefixes())
00486                         reason = "One or more of the prefixes on the remote server are invalid on this server.";
00487 
00488                 if (((this->CapKeys.find("HALFOP") == this->CapKeys.end()) && (Instance->Config->AllowHalfop)) || ((this->CapKeys.find("HALFOP") != this->CapKeys.end()) && (this->CapKeys.find("HALFOP")->second != ConvToStr(Instance->Config->AllowHalfop))))
00489                         reason = "We don't both have halfop support enabled/disabled identically";
00490 
00491                 for (int x = 0; valid_capab[x].size; ++x)
00492                 {
00493                         if (((this->CapKeys.find(valid_capab[x].key) == this->CapKeys.end()) || ((this->CapKeys.find(valid_capab[x].key) != this->CapKeys.end()) &&
00494                                                  (this->CapKeys.find(valid_capab[x].key)->second != ConvToStr(valid_capab[x].size)))))
00495                                 reason = valid_capab[x].reason;
00496                 }
00497         
00498                 /* Challenge response, store their challenge for our password */
00499                 std::map<std::string,std::string>::iterator n = this->CapKeys.find("CHALLENGE");
00500                 if (Utils->ChallengeResponse && (n != this->CapKeys.end()) && (Instance->FindModule("m_sha256.so")))
00501                 {
00502                         /* Challenge-response is on now */
00503                         this->SetTheirChallenge(n->second);
00504                         if (!this->GetTheirChallenge().empty() && (this->LinkState == CONNECTING))
00505                         {
00506                                 this->SendCapabilities();
00507                                 this->WriteLine(std::string("SERVER ")+this->Instance->Config->ServerName+" "+this->MakePass(OutboundPass, this->GetTheirChallenge())+" 0 :"+this->Instance->Config->ServerDesc);
00508                         }
00509                 }
00510                 else
00511                 {
00512                         /* They didnt specify a challenge or we don't have m_sha256.so, we use plaintext */
00513                         if (this->LinkState == CONNECTING)
00514                         {
00515                                 this->SendCapabilities();
00516                                 this->WriteLine(std::string("SERVER ")+this->Instance->Config->ServerName+" "+OutboundPass+" 0 :"+this->Instance->Config->ServerDesc);
00517                         }
00518                 }
00519 
00520                 if (reason.length())
00521                 {
00522                         this->SendError("CAPAB negotiation failed: "+reason);
00523                         return false;
00524                 }
00525         }
00526         else if ((params[0] == "MODULES") && (params.size() == 2))
00527         {
00528                 if (!this->ModuleList.length())
00529                 {
00530                         this->ModuleList.append(params[1]);
00531                 }
00532                 else
00533                 {
00534                         this->ModuleList.append(",");
00535                         this->ModuleList.append(params[1]);
00536                 }
00537         }
00538 
00539         else if ((params[0] == "CAPABILITIES") && (params.size() == 2))
00540         {
00541                 irc::tokenstream capabs(params[1]);
00542                 std::string item;
00543                 bool more = true;
00544                 while ((more = capabs.GetToken(item)))
00545                 {
00546                         /* Process each key/value pair */
00547                         std::string::size_type equals = item.rfind('=');
00548                         if (equals != std::string::npos)
00549                         {
00550                                 std::string var = item.substr(0, equals);
00551                                 std::string value = item.substr(equals+1, item.length());
00552                                 CapKeys[var] = value;
00553                         }
00554                 }
00555         }
00556         return true;
00557 }

bool TreeSocket::ChangeHost const std::string prefix,
std::deque< std::string > &  params
 

CHGHOST.

Definition at line 489 of file treesocket2.cpp.

References userrec::ChangeDisplayedHost(), SpanningTreeUtilities::DoOneToAllButSender(), InspIRCd::FindNick(), InspSocket::Instance, userrec::server, and Utils.

Referenced by ProcessLine().

00490 {
00491         if (params.size() < 1)
00492                 return true;
00493         userrec* u = this->Instance->FindNick(prefix);
00494 
00495         if (u)
00496         {
00497                 u->ChangeDisplayedHost(params[0].c_str());
00498                 Utils->DoOneToAllButSender(prefix,"FHOST",params,u->server);
00499         }
00500         return true;
00501 }

bool TreeSocket::ChangeName const std::string prefix,
std::deque< std::string > &  params
 

CHGNAME.

Definition at line 568 of file treesocket2.cpp.

References userrec::ChangeName(), SpanningTreeUtilities::DoOneToAllButSender(), InspIRCd::FindNick(), InspSocket::Instance, userrec::server, and Utils.

Referenced by ProcessLine().

00569 {
00570         if (params.size() < 1)
00571                 return true;
00572         userrec* u = this->Instance->FindNick(prefix);
00573         if (u)
00574         {
00575                 u->ChangeName(params[0].c_str());
00576                 params[0] = ":" + params[0];
00577                 Utils->DoOneToAllButSender(prefix,"FNAME",params,u->server);
00578         }
00579         return true;
00580 }

bool TreeSocket::ComparePass const std::string ours,
const std::string theirs
 

Compare two passwords based on authentication scheme.

Definition at line 813 of file treesocket2.cpp.

References SpanningTreeUtilities::ChallengeResponse, InspIRCd::FindModule(), InspSocket::Instance, and Utils.

Referenced by Inbound_Server(), and Outbound_Reply_Server().

00814 {
00815         if ((!strncmp(ours.c_str(), "HMAC-SHA256:", 12)) || (!strncmp(theirs.c_str(), "HMAC-SHA256:", 12)))
00816         {
00817                 /* One or both of us specified hmac sha256, but we don't have sha256 module loaded!
00818                  * We can't allow this password as valid.
00819                  */
00820                 if (!Instance->FindModule("m_sha256.so") || !Utils->ChallengeResponse)
00821                                 return false;
00822                 else
00823                         /* Straight string compare of hashes */
00824                         return ours == theirs;
00825         }
00826         else
00827                 /* Straight string compare of plaintext */
00828                 return ours == theirs;
00829 }

void TreeSocket::DoBurst TreeServer s  ) 
 

This function is called when we want to send a netburst to a local server.

There is a set order we must do this, because for example users require their servers to exist, and channels require their users to exist. You get the idea.

Definition at line 1233 of file treesocket1.cpp.

References ConvToStr(), SpanningTreeUtilities::Creator, FOREACH_MOD_I, TreeServer::GetName(), GetTheirChallenge(), I_OnSyncOtherMetaData, InspSocket::Instance, SendChannelModes(), SendServers(), SendUsers(), SendXLines(), InspIRCd::SNO, InspIRCd::Time(), SpanningTreeUtilities::TreeRoot, Utils, WriteLine(), and SnomaskManager::WriteToSnoMask().

Referenced by Outbound_Reply_Server(), and ProcessLine().

01234 {
01235         std::string name = s->GetName();
01236         std::string burst = "BURST "+ConvToStr(Instance->Time(true));
01237         std::string endburst = "ENDBURST";
01238         this->Instance->SNO->WriteToSnoMask('l',"Bursting to \2%s\2 (Authentication: %s).", name.c_str(), this->GetTheirChallenge().empty() ? "plaintext password" : "SHA256-HMAC challenge-response");
01239         this->WriteLine(burst);
01240         /* send our version string */
01241         this->WriteLine(std::string(":")+this->Instance->Config->ServerName+" VERSION :"+this->Instance->GetVersionString());
01242         /* Send server tree */
01243         this->SendServers(Utils->TreeRoot,s,1);
01244         /* Send users and their oper status */
01245         this->SendUsers(s);
01246         /* Send everything else (channel modes, xlines etc) */
01247         this->SendChannelModes(s);
01248         this->SendXLines(s);
01249         FOREACH_MOD_I(this->Instance,I_OnSyncOtherMetaData,OnSyncOtherMetaData((Module*)Utils->Creator,(void*)this));
01250         this->WriteLine(endburst);
01251         this->Instance->SNO->WriteToSnoMask('l',"Finished bursting to \2"+name+"\2.");
01252 }

bool TreeSocket::Error std::deque< std::string > &  params  ) 
 

Handle ERROR command.

Definition at line 48 of file treesocket2.cpp.

References InboundServerName, InspSocket::Instance, myhost, InspIRCd::SNO, and SnomaskManager::WriteToSnoMask().

Referenced by ProcessLine().

00049 {
00050         if (params.size() < 1)
00051                 return false;
00052         this->Instance->SNO->WriteToSnoMask('l',"ERROR from %s: %s",(!InboundServerName.empty() ? InboundServerName.c_str() : myhost.c_str()),params[0].c_str());
00053         /* we will return false to cause the socket to close. */
00054         return false;
00055 }

bool TreeSocket::ForceJoin const std::string source,
std::deque< std::string > &  params
 

FJOIN, similar to TS6 SJOIN, but not quite.

Definition at line 776 of file treesocket1.cpp.

References classbase::age, SpanningTreeUtilities::AnnounceTSChange, SpanningTreeUtilities::BestRouteTo(), InspIRCd::Config, DEFAULT, SpanningTreeUtilities::DoOneToAllButSender(), FD_MAGIC_NUMBER, InspIRCd::FindChan(), InspIRCd::FindNick(), ModeParser::FindPrefix(), ModeHandler::GetModeChar(), TreeServer::GetSocket(), irc::modestacker::GetStackedLine(), irc::tokenstream::GetToken(), InspSocket::Instance, chanrec::JoinUser(), InspIRCd::Log(), MAXMODES, InspIRCd::Modes, chanrec::name, userrec::nick, irc::modestacker::Push(), RemoveStatus(), SendError(), InspIRCd::SendMode(), userrec::server, ServerConfig::ServerName, EventHandler::SetFd(), InspIRCd::SNO, SPARSE, InspIRCd::Time(), Utils, chanrec::WriteChannelWithServ(), and SnomaskManager::WriteToSnoMask().

Referenced by ProcessLine().

00777 {
00778         /* 1.1 FJOIN works as follows:
00779          *
00780          * Each FJOIN is sent along with a timestamp, and the side with the lowest
00781          * timestamp 'wins'. From this point on we will refer to this side as the
00782          * winner. The side with the higher timestamp loses, from this point on we
00783          * will call this side the loser or losing side. This should be familiar to
00784          * anyone who's dealt with dreamforge or TS6 before.
00785          *
00786          * When two sides of a split heal and this occurs, the following things
00787          * will happen:
00788          *
00789          * If the timestamps are exactly equal, both sides merge their privilages
00790          * and users, as in InspIRCd 1.0 and ircd2.8. The channels have not been
00791          * re-created during a split, this is safe to do.
00792          *
00793          * If the timestamps are NOT equal, the losing side removes all of its
00794          * modes from the channel, before introducing new users into the channel
00795          * which are listed in the FJOIN command's parameters. The losing side then
00796          * LOWERS its timestamp value of the channel to match that of the winning
00797          * side, and the modes of the users of the winning side are merged in with
00798          * the losing side.
00799          *
00800          * The winning side on the other hand will ignore all user modes from the
00801          * losing side, so only its own modes get applied. Life is simple for those
00802          * who succeed at internets. :-)
00803          *
00804          * NOTE: Unlike TS6 and dreamforge and other protocols which have SJOIN,
00805          * FJOIN does not contain the simple-modes such as +iklmnsp. Why not,
00806          * you ask? Well, quite simply because we don't need to. They'll be sent
00807          * after the FJOIN by FMODE, and FMODE is timestamped, so in the event
00808          * the losing side sends any modes for the channel which shouldnt win,
00809          * they wont as their timestamp will be too high :-)
00810          */
00811 
00812         if (params.size() < 3)
00813                 return true;
00814 
00815         irc::modestacker modestack(true);                               /* Modes to apply from the users in the user list */
00816         userrec* who = NULL;                                            /* User we are currently checking */
00817         std::string channel = params[0];                                /* Channel name, as a string */
00818         time_t TS = atoi(params[1].c_str());                            /* Timestamp given to us for remote side */
00819         irc::tokenstream users(params[2]);                              /* Users from the user list */
00820         bool apply_other_sides_modes = true;                            /* True if we are accepting the other side's modes */
00821         chanrec* chan = this->Instance->FindChan(channel);              /* The channel we're sending joins to */
00822         time_t ourTS = chan ? chan->age : Instance->Time(true)+600;     /* The TS of our side of the link */
00823         bool created = !chan;                                           /* True if the channel doesnt exist here yet */
00824         std::string item;                                               /* One item in the list of nicks */
00825 
00826         params[2] = ":" + params[2];
00827         Utils->DoOneToAllButSender(source,"FJOIN",params,source);
00828 
00829         if (!TS)
00830         {
00831                 Instance->Log(DEFAULT,"*** BUG? *** TS of 0 sent to FJOIN. Are some services authors smoking craq, or is it 1970 again?. Dropped.");
00832                 Instance->SNO->WriteToSnoMask('d', "WARNING: The server %s is sending FJOIN with a TS of zero. Total craq. Command was dropped.", source.c_str());
00833                 return true;
00834         }
00835 
00836         /* If our TS is less than theirs, we dont accept their modes */
00837         if (ourTS < TS)
00838                 apply_other_sides_modes = false;
00839 
00840         /* Our TS greater than theirs, clear all our modes from the channel, accept theirs. */
00841         if (ourTS > TS)
00842         {
00843                 std::deque<std::string> param_list;
00844                 if (Utils->AnnounceTSChange && chan)
00845                         chan->WriteChannelWithServ(Instance->Config->ServerName, "NOTICE %s :TS for %s changed from %lu to %lu", chan->name, chan->name, ourTS, TS);
00846                 ourTS = TS;
00847                 if (!created)
00848                 {
00849                         chan->age = TS;
00850                         param_list.push_back(channel);
00851                         this->RemoveStatus(Instance->Config->ServerName, param_list);
00852                 }
00853         }
00854 
00855         /* Now, process every 'prefixes,nick' pair */
00856         while (users.GetToken(item))
00857         {
00858                 const char* usr = item.c_str();
00859                 if (usr && *usr)
00860                 {
00861                         const char* permissions = usr;
00862                         /* Iterate through all the prefix values, convert them from prefixes to mode letters */
00863                         std::string modes;
00864                         while ((*permissions) && (*permissions != ','))
00865                         {
00866                                 ModeHandler* mh = Instance->Modes->FindPrefix(*permissions);
00867                                 if (mh)
00868                                         modes = modes + mh->GetModeChar();
00869                                 else
00870                                 {
00871                                         this->SendError(std::string("Invalid prefix '")+(*permissions)+"' in FJOIN");
00872                                         return false;
00873                                 }
00874                                 usr++;
00875                                 permissions++;
00876                         }
00877                         /* Advance past the comma, to the nick */
00878                         usr++;
00879                         
00880                         /* Check the user actually exists */
00881                         who = this->Instance->FindNick(usr);
00882                         if (who)
00883                         {
00884                                 /* Check that the user's 'direction' is correct */
00885                                 TreeServer* route_back_again = Utils->BestRouteTo(who->server);
00886                                 if ((!route_back_again) || (route_back_again->GetSocket() != this))
00887                                         continue;
00888 
00889                                 /* Add any permissions this user had to the mode stack */
00890                                 for (std::string::iterator x = modes.begin(); x != modes.end(); ++x)
00891                                         modestack.Push(*x, who->nick);
00892 
00893                                 chanrec::JoinUser(this->Instance, who, channel.c_str(), true, "", TS);
00894                         }
00895                         else
00896                         {
00897                                 Instance->Log(SPARSE,"Warning! Invalid user %s in FJOIN to channel %s IGNORED", usr, channel.c_str());
00898                                 continue;
00899                         }
00900                 }
00901         }
00902 
00903         /* Flush mode stacker if we lost the FJOIN or had equal TS */
00904         if (apply_other_sides_modes)
00905         {
00906                 std::deque<std::string> stackresult;
00907                 const char* mode_junk[MAXMODES+2];
00908                 userrec* n = new userrec(Instance);
00909                 n->SetFd(FD_MAGIC_NUMBER);
00910                 mode_junk[0] = channel.c_str();
00911 
00912                 while (modestack.GetStackedLine(stackresult))
00913                 {
00914                         for (size_t j = 0; j < stackresult.size(); j++)
00915                         {
00916                                 mode_junk[j+1] = stackresult[j].c_str();
00917                         }
00918                         Instance->SendMode(mode_junk, stackresult.size() + 1, n);
00919                 }
00920 
00921                 delete n;
00922         }
00923 
00924         return true;
00925 }

bool TreeSocket::ForceMode const std::string source,
std::deque< std::string > &  params
 

FMODE command - server mode with timestamp checks.

Definition at line 618 of file treesocket1.cpp.

References classbase::age, InspIRCd::CallCommandHandler(), DEFAULT, DELETE(), SpanningTreeUtilities::DoOneToAllButSender(), FD_MAGIC_NUMBER, InspIRCd::FindChan(), InspIRCd::FindNick(), InspSocket::Instance, InspIRCd::Log(), InspIRCd::SendMode(), userrec::server, EventHandler::SetFd(), InspIRCd::SNO, Utils, and SnomaskManager::WriteToSnoMask().

Referenced by ProcessLine().

00619 {
00620         /* Chances are this is a 1.0 FMODE without TS */
00621         if (params.size() < 3)
00622         {
00623                 /* No modes were in the command, probably a channel with no modes set on it */
00624                 return true;
00625         }
00626 
00627         bool smode = false;
00628         std::string sourceserv;
00629         /* Are we dealing with an FMODE from a user, or from a server? */
00630         userrec* who = this->Instance->FindNick(source);
00631         if (who)
00632         {
00633                 /* FMODE from a user, set sourceserv to the users server name */
00634                 sourceserv = who->server;
00635         }
00636         else
00637         {
00638                 /* FMODE from a server, create a fake user to receive mode feedback */
00639                 who = new userrec(this->Instance);
00640                 who->SetFd(FD_MAGIC_NUMBER);
00641                 smode = true;      /* Setting this flag tells us we should free the userrec later */
00642                 sourceserv = source;    /* Set sourceserv to the actual source string */
00643         }
00644         const char* modelist[64];
00645         time_t TS = 0;
00646         int n = 0;
00647         memset(&modelist,0,sizeof(modelist));
00648         for (unsigned int q = 0; (q < params.size()) && (q < 64); q++)
00649         {
00650                 if (q == 1)
00651                 {
00652                         /* The timestamp is in this position.
00653                          * We don't want to pass that up to the
00654                          * server->client protocol!
00655                          */
00656                         TS = atoi(params[q].c_str());
00657                 }
00658                 else
00659                 {
00660                         /* Everything else is fine to append to the modelist */
00661                         modelist[n++] = params[q].c_str();
00662                 }
00663 
00664         }
00665         /* Extract the TS value of the object, either userrec or chanrec */
00666         userrec* dst = this->Instance->FindNick(params[0]);
00667         chanrec* chan = NULL;
00668         time_t ourTS = 0;
00669         if (dst)
00670         {
00671                 ourTS = dst->age;
00672         }
00673         else
00674         {
00675                 chan = this->Instance->FindChan(params[0]);
00676                 if (chan)
00677                 {
00678                         ourTS = chan->age;
00679                 }
00680                 else
00681                         /* Oops, channel doesnt exist! */
00682                         return true;
00683         }
00684 
00685         if (!TS)
00686         {
00687                 Instance->Log(DEFAULT,"*** BUG? *** TS of 0 sent to FMODE. Are some services authors smoking craq, or is it 1970 again?. Dropped.");
00688                 Instance->SNO->WriteToSnoMask('d', "WARNING: The server %s is sending FMODE with a TS of zero. Total craq. Mode was dropped.", sourceserv.c_str());
00689                 return true;
00690         }
00691 
00692         /* TS is equal or less: Merge the mode changes into ours and pass on.
00693          */
00694         if (TS <= ourTS)
00695         {
00696                 if ((TS < ourTS) && (!dst))
00697                         Instance->Log(DEFAULT,"*** BUG *** Channel TS sent in FMODE to %s is %lu which is not equal to %lu!", params[0].c_str(), TS, ourTS);
00698 
00699                 if (smode)
00700                 {
00701                         this->Instance->SendMode(modelist, n, who);
00702                 }
00703                 else
00704                 {
00705                         this->Instance->CallCommandHandler("MODE", modelist, n, who);
00706                 }
00707                 /* HOT POTATO! PASS IT ON! */
00708                 Utils->DoOneToAllButSender(source,"FMODE",params,sourceserv);
00709         }
00710         /* If the TS is greater than ours, we drop the mode and dont pass it anywhere.
00711          */
00712 
00713         if (smode)
00714                 DELETE(who);
00715 
00716         return true;
00717 }

bool TreeSocket::ForceNick const std::string prefix,
std::deque< std::string > &  params
 

Because Andy insists that services-compatible servers must implement SVSNICK and SVSJOIN, that's exactly what we do :p.

Definition at line 257 of file treesocket2.cpp.

References classbase::age, SpanningTreeUtilities::DoOneToAllButSender(), InspIRCd::FindNick(), userrec::ForceNickChange(), InspSocket::Instance, IS_LOCAL, userrec::QuitUser(), and Utils.

Referenced by ProcessLine().

00258 {
00259         if (params.size() < 3)
00260                 return true;
00261 
00262         userrec* u = this->Instance->FindNick(params[0]);
00263 
00264         if (u)
00265         {
00266                 Utils->DoOneToAllButSender(prefix,"SVSNICK",params,prefix);
00267                 if (IS_LOCAL(u))
00268                 {
00269                         std::deque<std::string> par;
00270                         par.push_back(params[1]);
00271                         if (!u->ForceNickChange(params[1].c_str()))
00272                         {
00273                                 userrec::QuitUser(this->Instance, u, "Nickname collision");
00274                                 return true;
00275                         }
00276                         u->age = atoi(params[2].c_str());
00277                 }
00278         }
00279         return true;
00280 }

bool TreeSocket::ForceTopic const std::string source,
std::deque< std::string > &  params
 

FTOPIC command.

Definition at line 720 of file treesocket1.cpp.

References InspIRCd::Config, SpanningTreeUtilities::DoOneToAllButSender(), InspIRCd::FindChan(), InspIRCd::FindNick(), InspSocket::Instance, MAXTOPIC, chanrec::name, userrec::server, ServerConfig::ServerName, chanrec::setby, strlcpy(), chanrec::topic, chanrec::topicset, Utils, chanrec::WriteChannel(), and chanrec::WriteChannelWithServ().

Referenced by ProcessLine().

00721 {
00722         if (params.size() != 4)
00723                 return true;
00724         time_t ts = atoi(params[1].c_str());
00725         std::string nsource = source;
00726         chanrec* c = this->Instance->FindChan(params[0]);
00727         if (c)
00728         {
00729                 if ((ts >= c->topicset) || (!*c->topic))
00730                 {
00731                         userrec* user = this->Instance->FindNick(source);
00732 
00733                         if (c->topic != params[3])
00734                         {
00735                                 // Update topic only when it differs from current topic
00736                                 strlcpy(c->topic, params[3].c_str(), MAXTOPIC);
00737 
00738                                 if (!user)
00739                                 {
00740                                         c->WriteChannelWithServ(Instance->Config->ServerName, "TOPIC %s :%s", c->name, c->topic);
00741                                 }
00742                                 else
00743                                 {
00744                                         c->WriteChannel(user, "TOPIC %s :%s", c->name, c->topic);
00745                                 }
00746                         }
00747 
00748                         // But always update set time and setter
00749                         strlcpy(c->setby, params[2].c_str(), 127);
00750                         c->topicset = ts;
00751 
00752                         /*
00753                          * Take careful note of what happens here;
00754                          * Above, we display the topic change to the server IF the topic incoming is different to the topic already set.
00755                          * HERE, we find the server the user that sent this topic is on, so we *do not* send topics back to the link they just
00756                          * came from. This *cannot* be easily merged with the above check!
00757                          *
00758                          * Thanks to Anope and Namegduf for finally helping me isolate this
00759                          *                      -- w00t (5th/aug/2008)
00760                          */
00761                         if (user)
00762                         {
00763                                 nsource = user->server;
00764                         }
00765 
00766                         /* all done, send it on its way */
00767                         params[3] = ":" + params[3];
00768                         Utils->DoOneToAllButSender(source,"FTOPIC",params,nsource);
00769                 }
00770 
00771         }
00772         return true;
00773 }

Module * TreeSocket::GetHook  ) 
 

Return the module which we are hooking to for I/O encapsulation.

Definition at line 91 of file treesocket1.cpp.

References Hook.

Referenced by HandshakeTimer::Tick().

00092 {
00093         return this->Hook;
00094 }

ServerState TreeSocket::GetLinkState  ) 
 

Get link state.

Definition at line 86 of file treesocket1.cpp.

References LinkState.

00087 {
00088         return this->LinkState;
00089 }

std::string TreeSocket::GetName  )  [virtual]
 

Get this server's name.

Definition at line 1531 of file treesocket2.cpp.

References InboundServerName, and myhost.

Referenced by ProcessLine().

01532 {
01533         std::string sourceserv = this->myhost;
01534         if (!this->InboundServerName.empty())
01535         {
01536                 sourceserv = this->InboundServerName;
01537         }
01538         return sourceserv;
01539 }

const std::string & TreeSocket::GetOurChallenge  ) 
 

Get challenge set in our CAPAB for challenge/response.

Definition at line 104 of file treesocket1.cpp.

References ourchallenge.

Referenced by SendCapabilities().

00105 {
00106         return this->ourchallenge;
00107 }

const std::string & TreeSocket::GetTheirChallenge  ) 
 

Get challenge set in their CAPAB for challenge/response.

Definition at line 114 of file treesocket1.cpp.

References theirchallenge.

Referenced by DoBurst(), Inbound_Server(), and Outbound_Reply_Server().

00115 {
00116         return this->theirchallenge;
00117 }

bool TreeSocket::HandleSetTime const std::string prefix,
std::deque< std::string > &  params
 

SETTIME.

Definition at line 660 of file treesocket2.cpp.

References DEBUG, SpanningTreeUtilities::DoOneToAllButSender(), SpanningTreeUtilities::EnableTimeSync, InspSocket::Instance, InspIRCd::Log(), InspIRCd::SetTimeDelta(), InspIRCd::Time(), and Utils.

Referenced by ProcessLine().

00661 {
00662         if (!params.size() || !Utils->EnableTimeSync)
00663                 return true;
00664 
00665         bool force = false;
00666 
00667         if ((params.size() == 2) && (params[1] == "FORCE"))
00668                 force = true;
00669 
00670         time_t them = atoi(params[0].c_str());
00671         time_t us = Instance->Time(false);
00672 
00673         time_t diff = them - us;
00674 
00675         Utils->DoOneToAllButSender(prefix, "TIMESET", params, prefix);
00676 
00677         if (force || (them != us))
00678         {
00679                 time_t old = Instance->SetTimeDelta(diff);
00680                 Instance->Log(DEBUG, "TS (diff %d) from %s applied (old delta was %d)", diff, prefix.c_str(), old);
00681         }
00682 
00683         return true;
00684 }

bool TreeSocket::HasItem const std::string list,
const std::string item
 

Definition at line 382 of file treesocket1.cpp.

References irc::sepstream::GetToken().

Referenced by ListDifference().

00383 {
00384         irc::commasepstream seplist(list);
00385         std::string item2;
00386 
00387         while (seplist.GetToken(item2))
00388         {
00389                 if (item2 == item)
00390                         return true;
00391         }
00392         return false;
00393 }

bool TreeSocket::Inbound_Server std::deque< std::string > &  params  ) 
 

(local) <- SERVER

Definition at line 888 of file treesocket2.cpp.

References SpanningTreeUtilities::AddBurstingServer(), InspSocket::Close(), ComparePass(), InspIRCd::Config, SpanningTreeUtilities::Creator, SocketEngine::DelFd(), SpanningTreeUtilities::FindBurstingServer(), SpanningTreeUtilities::FindServer(), TreeServer::GetName(), TreeServer::GetParent(), GetTheirChallenge(), InboundDescription, InboundServerName, InspSocket::Instance, SpanningTreeUtilities::LinkBlocks, LinkState, InspIRCd::SE, SendCapabilities(), SendError(), sentcapab, ServerConfig::ServerDesc, InspIRCd::SNO, Utils, WAIT_AUTH_2, WriteLine(), and SnomaskManager::WriteToSnoMask().

Referenced by ProcessLine().

00889 {
00890         if (params.size() < 4)
00891                 return false;
00892         irc::string servername = params[0].c_str();
00893         std::string sname = params[0];
00894         std::string password = params[1];
00895         std::string description = params[3];
00896         int hops = atoi(params[2].c_str());
00897 
00898         this->InboundServerName = sname;
00899         this->InboundDescription = description;
00900 
00901         if (!sentcapab)
00902                 this->SendCapabilities();
00903 
00904         if (hops)
00905         {
00906                 this->SendError("Server too far away for authentication");
00907                 this->Instance->SNO->WriteToSnoMask('l',"Server connection from \2"+sname+"\2 denied, server is too far away for authentication");
00908                 return false;
00909         }
00910 
00911         for (std::vector<Link>::iterator x = Utils->LinkBlocks.begin(); x < Utils->LinkBlocks.end(); x++)
00912         {
00913                 if ((x->Name == servername) && ((ComparePass(this->MakePass(x->RecvPass,this->GetOurChallenge()),password) || x->RecvPass == password && (this->GetTheirChallenge().empty()))))
00914                 {
00915                         /* First check for instances of the server that are waiting between the inbound and outbound SERVER command */
00916                         TreeSocket* CheckDupeSocket = Utils->FindBurstingServer(sname);
00917                         if (CheckDupeSocket)
00918                         {
00919                                 /* If we find one, we abort the link to prevent a race condition */
00920                                 this->SendError("Negotiation collision");
00921                                 this->Instance->SNO->WriteToSnoMask('l',"Server connection from \2"+sname+"\2 denied, already exists in a negotiating state.");
00922                                 CheckDupeSocket->SendError("Negotiation collision");
00923                                 Instance->SE->DelFd(CheckDupeSocket);
00924                                 CheckDupeSocket->Close();
00925                                 return false;
00926                         }
00927                         /* Now check for fully initialized instances of the server */
00928                         TreeServer* CheckDupe = Utils->FindServer(sname);
00929                         if (CheckDupe)
00930                         {
00931                                 this->SendError("Server "+sname+" already exists on server "+CheckDupe->GetParent()->GetName()+"!");
00932                                 this->Instance->SNO->WriteToSnoMask('l',"Server connection from \2"+sname+"\2 denied, already exists on server "+CheckDupe->GetParent()->GetName());
00933                                 return false;
00934                         }
00935                         this->Instance->SNO->WriteToSnoMask('l',"Verified incoming server connection from \002"+sname+"\002["+(x->HiddenFromStats ? "<hidden>" : this->GetIP())+"] ("+description+")");
00936                         if (this->Hook)
00937                         {
00938                                 std::string name = InspSocketNameRequest((Module*)Utils->Creator, this->Hook).Send();
00939                                 this->Instance->SNO->WriteToSnoMask('l',"Connection from \2"+sname+"\2["+(x->HiddenFromStats ? "<hidden>" : this->GetIP())+"] using transport \2"+name+"\2");
00940                         }
00941 
00942                         Utils->AddBurstingServer(sname,this);
00943 
00944                         // this is good. Send our details: Our server name and description and hopcount of 0,
00945                         // along with the sendpass from this block.
00946                         this->SendCapabilities();
00947                         this->WriteLine(std::string("SERVER ")+this->Instance->Config->ServerName+" "+this->MakePass(x->SendPass, this->GetTheirChallenge())+" 0 :"+this->Instance->Config->ServerDesc);
00948                         // move to the next state, we are now waiting for THEM.
00949                         this->LinkState = WAIT_AUTH_2;
00950                         return true;
00951                 }
00952         }
00953         this->SendError("Invalid credentials");
00954         this->Instance->SNO->WriteToSnoMask('l',"Server connection from \2"+sname+"\2 denied, invalid link credentials");
00955         return false;
00956 }

bool TreeSocket::IntroduceClient const std::string source,
std::deque< std::string > &  params
 

NICK command.

Do we have enough parameters: NICK age nick host dhost ident +modes ip :gecos

Our client looks ok, lets introduce it now

Definition at line 928 of file treesocket1.cpp.

References InspIRCd::AddGlobalClone(), TreeServer::AddUserCount(), classbase::age, bursting, ModeHandler::ChangeCount(), InspIRCd::clientlist, ConvToInt(), ConvToStr(), DEBUG, userrec::dhost, SpanningTreeUtilities::DoOneToAllButSender(), FD_MAGIC_NUMBER, ModeParser::FindMode(), SpanningTreeUtilities::FindRemoteBurstServer(), SpanningTreeUtilities::FindServer(), InspIRCd::FindServerNamePtr(), FOREACH_MOD_I, userrec::fullname, userrec::GetIPString(), connection::host, I_OnPostConnect, userrec::ident, IDENTMAX, InspSocket::Instance, cmd_validation::item, InspSocket::length, InspIRCd::Log(), MAXGECOS, InspIRCd::Modes, MODETYPE_USER, userrec::nick, NICKMAX, ModeHandler::OnModeChange(), SpanningTreeUtilities::quiet_bursts, userrec::QuitUser(), REG_ALL, connection::registered, userrec::server, EventHandler::SetFd(), userrec::SetSockAddr(), connection::signon, InspIRCd::SilentULine(), InspIRCd::SNO, strlcpy(), Utils, WriteLine(), and SnomaskManager::WriteToSnoMask().

Referenced by ProcessLine().

00929 {
00933         if (params.size() != 8)
00934         {
00935                 if (params.size() >= 2)
00936                         this->WriteLine(std::string(":")+this->Instance->Config->ServerName+" KILL "+params[1]+" :Invalid client introduction ("+params[1]+"?)");
00937                                 return true;
00938         }
00939 
00940         time_t age = ConvToInt(params[0]);
00941         const char* tempnick = params[1].c_str();
00942         std::string empty;
00943 
00944         cmd_validation valid[] = { {"Nickname", 1, NICKMAX}, {"Hostname", 2, 64}, {"Displayed hostname", 3, 64}, {"Ident", 4, IDENTMAX+1}, {"GECOS", 7, MAXGECOS}, {"", 0, 0} };
00945 
00946         TreeServer* remoteserver = Utils->FindServer(source);
00947         if (!remoteserver)
00948         {
00949                 this->WriteLine(std::string(":")+this->Instance->Config->ServerName+" KILL "+params[1]+" :Invalid client introduction (Unknown server "+source+")");
00950                 return true;
00951         }
00952 
00953         /* Check parameters for validity before introducing the client, discovered by dmb */
00954         if (!age)
00955         {
00956                 this->WriteLine(std::string(":")+this->Instance->Config->ServerName+" KILL "+params[1]+" :Invalid client introduction (Invalid TS?)");
00957                 return true;
00958         }
00959         for (size_t x = 0; valid[x].length; ++x)
00960         {
00961                 if (params[valid[x].param].length() > valid[x].length)
00962                 {
00963                         this->WriteLine(std::string(":")+this->Instance->Config->ServerName+" KILL "+params[1]+" :Invalid client introduction (" + valid[x].item + " > " + ConvToStr(valid[x].length) + ")");
00964                         return true;
00965                 }
00966         }
00967 
00970         Instance->Log(DEBUG,"New remote client %s",tempnick);
00971         user_hash::iterator iter = this->Instance->clientlist->find(tempnick);
00972 
00973         if (iter != this->Instance->clientlist->end())
00974         {
00975                 /* nick collision */
00976                 this->WriteLine(std::string(":")+this->Instance->Config->ServerName+" KILL "+tempnick+" :Nickname collision");
00977                 userrec::QuitUser(this->Instance, iter->second, "Nickname collision");
00978                 return true;
00979         }
00980 
00981         userrec* _new = new userrec(this->Instance);
00982         (*(this->Instance->clientlist))[tempnick] = _new;
00983         _new->SetFd(FD_MAGIC_NUMBER);
00984         strlcpy(_new->nick, tempnick,NICKMAX-1);
00985         strlcpy(_new->host, params[2].c_str(),64);
00986         strlcpy(_new->dhost, params[3].c_str(),64);
00987         _new->server = this->Instance->FindServerNamePtr(source.c_str());
00988         strlcpy(_new->ident, params[4].c_str(),IDENTMAX+1);
00989         strlcpy(_new->fullname, params[7].c_str(),MAXGECOS);
00990         _new->registered = REG_ALL;
00991         _new->signon = age;
00992 
00993         /* we need to remove the + from the modestring, so we can do our stuff */
00994         std::string::size_type pos_after_plus = params[5].find_first_not_of('+');
00995         if (pos_after_plus != std::string::npos)
00996         params[5] = params[5].substr(pos_after_plus);
00997 
00998         for (std::string::iterator v = params[5].begin(); v != params[5].end(); v++)
00999         {
01000                 /* For each mode thats set, increase counter */
01001                 ModeHandler* mh = Instance->Modes->FindMode(*v, MODETYPE_USER);
01002                 if (mh)
01003                 {
01004                         mh->OnModeChange(_new, _new, NULL, empty, true);
01005                         _new->SetMode(*v, true);
01006                         mh->ChangeCount(1);
01007                 }
01008         }
01009 
01010         /* now we've done with modes processing, put the + back for remote servers */
01011         params[5] = "+" + params[5];
01012 
01013 #ifdef SUPPORT_IP6LINKS
01014         if (params[6].find_first_of(":") != std::string::npos)
01015                 _new->SetSockAddr(AF_INET6, params[6].c_str(), 0);
01016         else
01017 #endif
01018                 _new->SetSockAddr(AF_INET, params[6].c_str(), 0);
01019 
01020         Instance->AddGlobalClone(_new);
01021 
01022         bool dosend = !(((this->Utils->quiet_bursts) && (this->bursting || Utils->FindRemoteBurstServer(remoteserver))) || (this->Instance->SilentULine(_new->server)));
01023         
01024         if (dosend)
01025                 this->Instance->SNO->WriteToSnoMask('C',"Client connecting at %s: %s!%s@%s [%s] [%s]",_new->server,_new->nick,_new->ident,_new->host, _new->GetIPString(), _new->fullname);
01026 
01027         params[7] = ":" + params[7];
01028         Utils->DoOneToAllButSender(source,"NICK", params, source);
01029 
01030         // Increment the Source Servers User Count..
01031         TreeServer* SourceServer = Utils->FindServer(source);
01032         if (SourceServer)
01033         {
01034                 SourceServer->AddUserCount();
01035         }
01036 
01037         FOREACH_MOD_I(Instance,I_OnPostConnect,OnPostConnect(_new));
01038 
01039         return true;
01040 }

std::string TreeSocket::ListDifference const std::string one,
const std::string two
 

Definition at line 396 of file treesocket1.cpp.

References irc::sepstream::GetToken(), and HasItem().

Referenced by Capab().

00397 {
00398         irc::commasepstream list_one(one);
00399         std::string item;
00400         std::string result;
00401         while (list_one.GetToken(item))
00402         {
00403                 if (!HasItem(two, item))
00404                 {
00405                         result.append(" ");
00406                         result.append(item);
00407                 }
00408         }
00409         return result;
00410 }

bool TreeSocket::LocalPing const std::string prefix,
std::deque< std::string > &  params
 

PING.

Definition at line 734 of file treesocket2.cpp.

References SpanningTreeUtilities::DoOneToOne(), Utils, and WriteLine().

Referenced by ProcessLine().

00735 {
00736         if (params.size() < 1)
00737                 return true;
00738         if (params.size() == 1)
00739         {
00740                 std::string stufftobounce = params[0];
00741                 this->WriteLine(std::string(":")+this->Instance->Config->ServerName+" PONG "+stufftobounce);
00742                 return true;
00743         }
00744         else
00745         {
00746                 std::string forwardto = params[1];
00747                 if (forwardto == this->Instance->Config->ServerName)
00748                 {
00749                         // this is a ping for us, send back PONG to the requesting server
00750                         params[1] = params[0];
00751                         params[0] = forwardto;
00752                         Utils->DoOneToOne(forwardto,"PONG",params,params[1]);
00753                 }
00754                 else
00755                 {
00756                         // not for us, pass it on :)
00757                         Utils->DoOneToOne(prefix,"PING",params,forwardto);
00758                 }
00759                 return true;
00760         }
00761 }

bool TreeSocket::LocalPong const std::string prefix,
std::deque< std::string > &  params
 

PONG.

Definition at line 391 of file treesocket2.cpp.

References SpanningTreeUtilities::DoOneToOne(), InspIRCd::FindNick(), SpanningTreeUtilities::FindServer(), InspSocket::Instance, TreeServer::LastPingMsec, TreeServer::rtt, TreeServer::SetPingFlag(), Utils, and userrec::WriteServ().

Referenced by ProcessLine().

00392 {
00393         if (params.size() < 1)
00394                 return true;
00395 
00396         if (params.size() == 1)
00397         {
00398                 TreeServer* ServerSource = Utils->FindServer(prefix);
00399                 if (ServerSource)
00400                 {
00401                         ServerSource->SetPingFlag();
00402                         timeval t;
00403                         gettimeofday(&t, NULL);
00404                         long ts = (t.tv_sec * 1000) + (t.tv_usec / 1000);
00405                         ServerSource->rtt = ts - ServerSource->LastPingMsec;
00406                 }
00407         }
00408         else
00409         {
00410                 std::string forwardto = params[1];
00411                 if (forwardto == this->Instance->Config->ServerName)
00412                 {
00413                         /*
00414                          * this is a PONG for us
00415                          * if the prefix is a user, check theyre local, and if they are,
00416                          * dump the PONG reply back to their fd. If its a server, do nowt.
00417                          * Services might want to send these s->s, but we dont need to yet.
00418                          */
00419                         userrec* u = this->Instance->FindNick(prefix);
00420                         if (u)
00421                         {
00422                                 u->WriteServ("PONG %s %s",params[0].c_str(),params[1].c_str());
00423                         }
00424                 }
00425                 else
00426                 {
00427                         // not for us, pass it on :)
00428                         Utils->DoOneToOne(prefix,"PONG",params,forwardto);
00429                 }
00430         }
00431 
00432         return true;
00433 }

std::string TreeSocket::MakePass const std::string password,
const std::string challenge
 

Construct a password, optionally hashed with the other side's challenge string.

Definition at line 124 of file treesocket1.cpp.

References SpanningTreeUtilities::ChallengeResponse, SpanningTreeUtilities::Creator, DEFAULT, InspIRCd::FindModule(), InspSocket::Instance, InspIRCd::Log(), and Utils.

00125 {
00126         /* This is a simple (maybe a bit hacky?) HMAC algorithm, thanks to jilles for
00127          * suggesting the use of HMAC to secure the password against various attacks.
00128          *
00129          * Note: If m_sha256.so is not loaded, we MUST fall back to plaintext with no
00130          *       HMAC challenge/response.
00131          */
00132         Module* sha256 = Instance->FindModule("m_sha256.so");
00133         if (Utils->ChallengeResponse && sha256 && !challenge.empty())
00134         {
00135                 /* XXX: This is how HMAC is supposed to be done:
00136                  *
00137                  * sha256( (pass xor 0x5c) + sha256((pass xor 0x36) + m) )
00138                  *
00139                  * Note that we are encoding the hex hash, not the binary
00140                  * output of the hash which is slightly different to standard.
00141                  *
00142                  * Don't ask me why its always 0x5c and 0x36... it just is.
00143                  */
00144                 std::string hmac1, hmac2;
00145 
00146                 for (size_t n = 0; n < password.length(); n++)
00147                 {
00148                         hmac1 += static_cast<char>(password[n] ^ 0x5C);
00149                         hmac2 += static_cast<char>(password[n] ^ 0x36);
00150                 }
00151 
00152                 hmac2 += challenge;
00153                 HashResetRequest(Utils->Creator, sha256).Send();
00154                 hmac2 = HashSumRequest(Utils->Creator, sha256, hmac2).Send();
00155 
00156                 HashResetRequest(Utils->Creator, sha256).Send();
00157                 std::string hmac = hmac1 + hmac2;
00158                 hmac = HashSumRequest(Utils->Creator, sha256, hmac).Send();
00159 
00160                 return "HMAC-SHA256:"+ hmac;
00161         }
00162         else if (!challenge.empty() && !sha256)
00163                 Instance->Log(DEFAULT,"Not authenticating to server using SHA256/HMAC because we don't have m_sha256 loaded!");
00164 
00165         return password;
00166 }

bool TreeSocket::MetaData const std::string prefix,
std::deque< std::string > &  params
 

METADATA.

Definition at line 435 of file treesocket2.cpp.

References SpanningTreeUtilities::DoOneToAllButSender(), InspIRCd::FindChan(), InspIRCd::FindNick(), SpanningTreeUtilities::FindServer(), FOREACH_MOD_I, I_OnDecodeMetaData, InspSocket::Instance, SpanningTreeUtilities::SetRemoteBursting(), TYPE_CHANNEL, TYPE_OTHER, TYPE_USER, and Utils.

Referenced by ProcessLine().

00436 {
00437         if (params.size() < 2)
00438                 return true;
00439         else if (params.size() < 3)
00440                 params.push_back("");
00441         TreeServer* ServerSource = Utils->FindServer(prefix);
00442         if (ServerSource)
00443         {
00444                 Utils->SetRemoteBursting(ServerSource, false);
00445 
00446                 if (params[0] == "*")
00447                 {
00448                         FOREACH_MOD_I(this->Instance,I_OnDecodeMetaData,OnDecodeMetaData(TYPE_OTHER,NULL,params[1],params[2]));
00449                 }
00450                 else if (*(params[0].c_str()) == '#')
00451                 {
00452                         chanrec* c = this->Instance->FindChan(params[0]);
00453                         if (c)
00454                         {
00455                                 FOREACH_MOD_I(this->Instance,I_OnDecodeMetaData,OnDecodeMetaData(TYPE_CHANNEL,c,params[1],params[2]));
00456                         }
00457                 }
00458                 else if (*(params[0].c_str()) != '#')
00459                 {
00460                         userrec* u = this->Instance->FindNick(params[0]);
00461                         if (u)
00462                         {
00463                                 FOREACH_MOD_I(this->Instance,I_OnDecodeMetaData,OnDecodeMetaData(TYPE_USER,u,params[1],params[2]));
00464                         }
00465                 }
00466         }
00467 
00468         params[2] = ":" + params[2];
00469         Utils->DoOneToAllButSender(prefix,"METADATA",params,prefix);
00470         return true;
00471 }

bool TreeSocket::Modules const std::string prefix,
std::deque< std::string > &  params
 

Remote MODULES.

Definition at line 57 of file treesocket2.cpp.

References Version::Build, ServerConfig::CleanFilename(), InspIRCd::Config, SpanningTreeUtilities::DoOneToOne(), InspIRCd::FindNick(), Version::Flags, InspSocket::Instance, Version::Major, MAXBUF, Version::Minor, ServerConfig::module_names, InspIRCd::modules, userrec::nick, userrec::oper, Version::Revision, userrec::server, ServerConfig::ServerName, strlcat(), strlcpy(), Utils, VF_COMMON, VF_SERVICEPROVIDER, VF_STATIC, and VF_VENDOR.

Referenced by ProcessLine().

00058 {
00059         if (params.empty())
00060                 return true;
00061 
00062         if (!this->Instance->MatchText(this->Instance->Config->ServerName, params[0]))
00063         {
00064                 /* Pass it on, not for us */
00065                 Utils->DoOneToOne(prefix, "MODULES", params, params[0]);
00066                 return true;
00067         }
00068 
00069         char strbuf[MAXBUF];
00070         std::deque<std::string> par;
00071         par.push_back(prefix);
00072         par.push_back("");
00073 
00074         userrec* source = this->Instance->FindNick(prefix);
00075         if (!source)
00076                 return true;
00077 
00078         for (unsigned int i = 0; i < Instance->Config->module_names.size(); i++)
00079         {
00080                 Version V = Instance->modules[i]->GetVersion();
00081                 char modulename[MAXBUF];
00082                 char flagstate[MAXBUF];
00083                 *flagstate = 0;
00084                 if (V.Flags & VF_STATIC)
00085                         strlcat(flagstate,", static",MAXBUF);
00086                 if (V.Flags & VF_VENDOR)
00087                         strlcat(flagstate,", vendor",MAXBUF);
00088                 if (V.Flags & VF_COMMON)
00089                         strlcat(flagstate,", common",MAXBUF);
00090                 if (V.Flags & VF_SERVICEPROVIDER)
00091                         strlcat(flagstate,", service provider",MAXBUF);
00092                 if (!flagstate[0])
00093                         strcpy(flagstate,"  <no flags>");
00094                 strlcpy(modulename,Instance->Config->module_names[i].c_str(),256);
00095                 if (*source->oper)
00096                 {
00097                         snprintf(strbuf, MAXBUF, "::%s 702 %s :0x%08lx %d.%d.%d.%d %s (%s)",Instance->Config->ServerName,source->nick,(long unsigned int)Instance->modules[i],V.Major,V.Minor,V.Revision,V.Build,ServerConfig::CleanFilename(modulename),flagstate+2);
00098                 }
00099                 else
00100                 {
00101                         snprintf(strbuf, MAXBUF, "::%s 702 %s :%s",Instance->Config->ServerName,source->nick,ServerConfig::CleanFilename(modulename));
00102                 }
00103                 par[1] = strbuf;
00104                 Utils->DoOneToOne(Instance->Config->ServerName, "PUSH", par, source->server);
00105         }
00106         snprintf(strbuf, MAXBUF, "::%s 703 %s :End of MODULES list", Instance->Config->ServerName, source->nick);
00107         par[1] = strbuf;
00108         Utils->DoOneToOne(Instance->Config->ServerName, "PUSH", par, source->server);
00109         return true;
00110 }

bool TreeSocket::Motd const std::string prefix,
std::deque< std::string > &  params
 

remote MOTD.

leet, huh?

Definition at line 113 of file treesocket2.cpp.

References InspIRCd::Config, SpanningTreeUtilities::DoOneToOne(), InspIRCd::FindNick(), InspSocket::Instance, ServerConfig::MOTD, userrec::nick, userrec::server, ServerConfig::ServerName, and Utils.

Referenced by ProcessLine().

00114 {
00115         if (params.size() > 0)
00116         {
00117                 if (this->Instance->MatchText(this->Instance->Config->ServerName, params[0]))
00118                 {
00119                         /* It's for our server */
00120                         string_list results;
00121                         userrec* source = this->Instance->FindNick(prefix);
00122 
00123                         if (source)
00124                         {
00125                                 std::deque<std::string> par;
00126                                 par.push_back(prefix);
00127                                 par.push_back("");
00128 
00129                                 if (!Instance->Config->MOTD.size())
00130                                 {
00131                                         par[1] = std::string("::")+Instance->Config->ServerName+" 422 "+source->nick+" :Message of the day file is missing.";
00132                                         Utils->DoOneToOne(this->Instance->Config->ServerName, "PUSH",par, source->server);
00133                                         return true;
00134                                 }
00135 
00136                                 par[1] = std::string("::")+Instance->Config->ServerName+" 375 "+source->nick+" :"+Instance->Config->ServerName+" message of the day";
00137                                 Utils->DoOneToOne(this->Instance->Config->ServerName, "PUSH",par, source->server);
00138 
00139                                 for (unsigned int i = 0; i < Instance->Config->MOTD.size(); i++)
00140                                 {
00141                                         par[1] = std::string("::")+Instance->Config->ServerName+" 372 "+source->nick+" :- "+Instance->Config->MOTD[i];
00142                                         Utils->DoOneToOne(this->Instance->Config->ServerName, "PUSH",par, source->server);
00143                                 }
00144 
00145                                 par[1] = std::string("::")+Instance->Config->ServerName+" 376 "+source->nick+" :End of message of the day.";
00146                                 Utils->DoOneToOne(this->Instance->Config->ServerName, "PUSH",par, source->server);
00147                         }
00148                 }
00149                 else
00150                 {
00151                         /* Pass it on */
00152                         userrec* source = this->Instance->FindNick(prefix);
00153                         if (source)
00154                                 Utils->DoOneToOne(prefix, "MOTD", params, params[0]);
00155                 }
00156         }
00157         return true;
00158 }

std::string TreeSocket::MyCapabilities  ) 
 

Returns my capabilities as a string.

Definition at line 280 of file treesocket1.cpp.

References InspIRCd::GetModuleCount(), InspSocket::Instance, and VF_COMMON.

Referenced by SendCapabilities().

00281 {
00282         std::vector<std::string> modlist;
00283         std::string capabilities;
00284         for (int i = 0; i <= this->Instance->GetModuleCount(); i++)
00285         {
00286                 if (this->Instance->modules[i]->GetVersion().Flags & VF_COMMON)
00287                         modlist.push_back(this->Instance->Config->module_names[i]);
00288         }
00289         sort(modlist.begin(),modlist.end());
00290         for (unsigned int i = 0; i < modlist.size(); i++)
00291         {
00292                 if (i)
00293                         capabilities = capabilities + ",";
00294                 capabilities = capabilities + modlist[i];
00295         }
00296         return capabilities;
00297 }

void TreeSocket::OnClose  )  [virtual]
 

Handle socket close event.

Reimplemented from InspSocket.

Definition at line 1552 of file treesocket2.cpp.

References classbase::age, CONNECTED, SpanningTreeUtilities::Creator, SpanningTreeUtilities::FindServer(), InboundServerName, InspSocket::Instance, myhost, ModuleSpanningTree::RemoteMessage(), Squit(), InspIRCd::Time(), ModuleSpanningTree::TimeToStr(), and Utils.

01553 {
01554         // Test fix for big fuckup
01555         if (this->LinkState != CONNECTED)
01556                 return;
01557 
01558         // Connection closed.
01559         // If the connection is fully up (state CONNECTED)
01560         // then propogate a netsplit to all peers.
01561         std::string quitserver = this->myhost;
01562         if (!this->InboundServerName.empty())
01563         {
01564                 quitserver = this->InboundServerName;
01565         }
01566         TreeServer* s = Utils->FindServer(quitserver);
01567         if (s)
01568         {
01569                 Squit(s,"Remote host closed the connection");
01570         }
01571 
01572         if (!quitserver.empty())
01573         {
01574                 Utils->Creator->RemoteMessage(NULL,"Connection to '\2%s\2' failed.",quitserver.c_str());
01575                 time_t server_uptime = Instance->Time() - this->age;    
01576                 if (server_uptime)
01577                         Utils->Creator->RemoteMessage(NULL,"Connection to '\2%s\2' was established for %s", quitserver.c_str(), Utils->Creator->TimeToStr(server_uptime).c_str());
01578         }
01579 }

bool TreeSocket::OnConnected  )  [virtual]
 

When an outbound connection finishes connecting, we receive this event, and must send our SERVER string to the other side.

If the other side is happy, as outlined in the server to server docs on the inspircd.org site, the other side will then send back its own server string.

Reimplemented from InspSocket.

Definition at line 174 of file treesocket1.cpp.

References TimerManager::AddTimer(), CONNECTING, SpanningTreeUtilities::Creator, InspSocket::GetIP(), Hook, InspSocket::Instance, SpanningTreeUtilities::LinkBlocks, myhost, OutboundPass, ModuleSpanningTree::RemoteMessage(), SendCapabilities(), sentcapab, InspIRCd::Timers, and Utils.

00175 {
00176         if (this->LinkState == CONNECTING)
00177         {
00178                 /* we do not need to change state here. */
00179                 for (std::vector<Link>::iterator x = Utils->LinkBlocks.begin(); x < Utils->LinkBlocks.end(); x++)
00180                 {
00181                         if (x->Name == this->myhost)
00182                         {
00183                                 Utils->Creator->RemoteMessage(NULL,"Connection to \2%s\2[%s] started.", myhost.c_str(), (x->HiddenFromStats ? "<hidden>" : this->GetIP().c_str()));
00184                                 if (Hook)
00185                                 {
00186                                         InspSocketHookRequest(this, (Module*)Utils->Creator, Hook).Send();
00187                                         Utils->Creator->RemoteMessage(NULL,"Connection to \2%s\2[%s] using transport \2%s\2", myhost.c_str(), (x->HiddenFromStats ? "<hidden>" : this->GetIP().c_str()),
00188                                                         x->Hook.c_str());
00189                                 }
00190                                 this->OutboundPass = x->SendPass;
00191                                 sentcapab = false;
00192 
00193                                 /* found who we're supposed to be connecting to, send the neccessary gubbins. */
00194                                 if (this->GetHook())
00195                                         Instance->Timers->AddTimer(new HandshakeTimer(Instance, this, &(*x), this->Utils, 1));
00196                                 else
00197                                         this->SendCapabilities();
00198 
00199                                 return true;
00200                         }
00201                 }
00202         }
00203         /* There is a (remote) chance that between the /CONNECT and the connection
00204          * being accepted, some muppet has removed the <link> block and rehashed.
00205          * If that happens the connection hangs here until it's closed. Unlikely
00206          * and rather harmless.
00207          */
00208         this->Utils->Creator->RemoteMessage(NULL,"Connection to \2%s\2 lost link tag(!)", myhost.c_str());
00209         return true;
00210 }

bool TreeSocket::OnDataReady  )  [virtual]
 

This function is called when we receive data from a remote server.

We buffer the data in a std::string (it doesnt stay there for long), reading using InspSocket::Read() which can read up to 16 kilobytes in one operation.

IF THIS FUNCTION RETURNS FALSE, THE CORE CLOSES AND DELETES THE SOCKET OBJECT FOR US.

Reimplemented from InspSocket.

Definition at line 1262 of file treesocket1.cpp.

References in_buffer, and InspSocket::Read().

01263 {
01264         char* data = this->Read();
01265         /* Check that the data read is a valid pointer and it has some content */
01266         if (data && *data)
01267         {
01268                 this->in_buffer.append(data);
01269                 /* While there is at least one new line in the buffer,
01270                  * do something useful (we hope!) with it.
01271                  */
01272                 while (in_buffer.find("\n") != std::string::npos)
01273                 {
01274                         std::string ret = in_buffer.substr(0,in_buffer.find("\n")-1);
01275                         in_buffer = in_buffer.substr(in_buffer.find("\n")+1,in_buffer.length()-in_buffer.find("\n"));
01276                         /* Use rfind here not find, as theres more
01277                          * chance of the \r being near the end of the
01278                          * string, not the start.
01279                          */
01280                         if (ret.find("\r") != std::string::npos)
01281                                 ret = in_buffer.substr(0,in_buffer.find("\r")-1);
01282                         /* Process this one, abort if it
01283                          * didnt return true.
01284                          */
01285                         if (!this->ProcessLine(ret))
01286                         {
01287                                 return false;
01288                         }
01289                 }
01290                 return true;
01291         }
01292         /* EAGAIN returns an empty but non-NULL string, so this
01293          * evaluates to TRUE for EAGAIN but to FALSE for EOF.
01294          */
01295         return (data && !*data);
01296 }

int TreeSocket::OnDisconnect  )  [virtual]
 

Handle socket disconnect event.

Reimplemented from InspSocket.

Definition at line 246 of file treesocket1.cpp.

00247 {
00248         /* For the same reason as above, we don't
00249          * handle OnDisconnect()
00250          */
00251         return true;
00252 }

void TreeSocket::OnError InspSocketError  e  )  [virtual]
 

Handle socket error event.

Reimplemented from InspSocket.

Definition at line 212 of file treesocket1.cpp.

References SpanningTreeUtilities::Creator, SpanningTreeUtilities::DoFailOver(), SpanningTreeUtilities::FindLink(), I_ERR_BIND, I_ERR_CONNECT, I_ERR_NOMOREFDS, I_ERR_SOCKET, I_ERR_WRITE, LISTENER, myhost, ModuleSpanningTree::RemoteMessage(), and Utils.

00213 {
00214         Link* MyLink;
00215 
00216         if (this->LinkState == LISTENER)
00217                 return;
00218 
00219         switch (e)
00220         {
00221                 case I_ERR_CONNECT:
00222                         Utils->Creator->RemoteMessage(NULL,"Connection failed: Connection to \002%s\002 refused", myhost.c_str());
00223                         MyLink = Utils->FindLink(myhost);
00224                         if (MyLink)
00225                                 Utils->DoFailOver(MyLink);
00226                 break;
00227                 case I_ERR_SOCKET:
00228                         Utils->Creator->RemoteMessage(NULL,"Connection failed: Could not create socket (%s)", strerror(errno));
00229                 break;
00230                 case I_ERR_BIND:
00231                         Utils->Creator->RemoteMessage(NULL,"Connection failed: Error binding socket to address or port (%s)", strerror(errno));
00232                 break;
00233                 case I_ERR_WRITE:
00234                         Utils->Creator->RemoteMessage(NULL,"Connection failed: I/O error on connection (%s)", strerror(errno));
00235                 break;
00236                 case I_ERR_NOMOREFDS:
00237                         Utils->Creator->RemoteMessage(NULL,"Connection failed: Operating system is out of file descriptors!");
00238                 break;
00239                 default:
00240                         if ((errno) && (errno != EINPROGRESS) && (errno != EAGAIN))
00241                                 Utils->Creator->RemoteMessage(NULL,"Connection to \002%s\002 failed with OS error: %s", myhost.c_str(), strerror(errno));
00242                 break;
00243         }
00244 }

int TreeSocket::OnIncomingConnection int  newsock,
char *  ip
[virtual]
 

Handle incoming connection event.

Reimplemented from InspSocket.

Definition at line 1581 of file treesocket2.cpp.

References InspSocket::Instance, irc::sockets::MatchCIDR(), InspIRCd::SNO, TreeSocket(), Utils, SpanningTreeUtilities::ValidIPs, and SnomaskManager::WriteToSnoMask().

01582 {
01583         /* To prevent anyone from attempting to flood opers/DDoS by connecting to the server port,
01584          * or discovering if this port is the server port, we don't allow connections from any
01585          * IPs for which we don't have a link block.
01586          */
01587         bool found = false;
01588 
01589         found = (std::find(Utils->ValidIPs.begin(), Utils->ValidIPs.end(), ip) != Utils->ValidIPs.end());
01590         if (!found)
01591         {
01592                 for (vector<std::string>::iterator i = Utils->ValidIPs.begin(); i != Utils->ValidIPs.end(); i++)
01593                         if (irc::sockets::MatchCIDR(ip, (*i).c_str()))
01594                                 found = true;
01595 
01596                 if (!found)
01597                 {
01598                         this->Instance->SNO->WriteToSnoMask('d',"Server connection from %s denied (no link blocks with that IP address", ip);
01599                         close(newsock);
01600                         return false;
01601                 }
01602         }
01603 
01604         TreeSocket* s = new TreeSocket(this->Utils, this->Instance, newsock, ip, this->Hook);
01605         s = s; /* Whinge whinge whinge, thats all GCC ever does. */
01606         return true;
01607 }

void TreeSocket::OnTimeout  )  [virtual]
 

Handle socket timeout from connect().

Reimplemented from InspSocket.

Definition at line 1541 of file treesocket2.cpp.

References CONNECTING, SpanningTreeUtilities::Creator, SpanningTreeUtilities::DoFailOver(), SpanningTreeUtilities::FindLink(), myhost, ModuleSpanningTree::RemoteMessage(), and Utils.

01542 {
01543         if (this->LinkState == CONNECTING)
01544         {
01545                 Utils->Creator->RemoteMessage(NULL, "CONNECT: Connection to \002%s\002 timed out.", myhost.c_str());
01546                 Link* MyLink = Utils->FindLink(myhost);
01547                 if (MyLink)
01548                         Utils->DoFailOver(MyLink);
01549         }
01550 }

bool TreeSocket::OperQuit const std::string prefix,
std::deque< std::string > &  params
 

Definition at line 282 of file treesocket2.cpp.

References SpanningTreeUtilities::DoOneToAllButSender(), InspIRCd::FindNick(), InspSocket::Instance, userrec::SetOperQuit(), and Utils.

Referenced by ProcessLine().

00283 {
00284         if (params.size() < 1)
00285                 return true;
00286 
00287         userrec* u = this->Instance->FindNick(prefix);
00288 
00289         if (u)
00290         {
00291                 u->SetOperQuit(params[0]);
00292                 params[0] = ":" + params[0];
00293                 Utils->DoOneToAllButSender(prefix,"OPERQUIT",params,prefix);
00294         }
00295         return true;
00296 }

bool TreeSocket::OperType const std::string prefix,
std::deque< std::string > &  params
 

Because the core won't let users or even SERVERS set +o, we use the OPERTYPE command to do this.

Definition at line 236 of file treesocket2.cpp.

References InspIRCd::all_opers, SpanningTreeUtilities::DoOneToAllButSender(), InspIRCd::FindNick(), InspSocket::Instance, IS_OPER, NICKMAX, InspIRCd::SNO, irc::Spacify(), strlcpy(), UM_OPERATOR, Utils, and SnomaskManager::WriteToSnoMask().

Referenced by ProcessLine().

00237 {
00238         if (params.size() != 1)
00239                 return true;
00240         std::string opertype = params[0];
00241         userrec* u = this->Instance->FindNick(prefix);
00242         if (u)
00243         {
00244                 if (!IS_OPER(u))
00245                         this->Instance->all_opers.push_back(u);
00246                 u->modes[UM_OPERATOR] = 1;
00247                 strlcpy(u->oper,opertype.c_str(),NICKMAX-1);
00248                 Utils->DoOneToAllButSender(u->nick,"OPERTYPE",params,u->server);
00249                 this->Instance->SNO->WriteToSnoMask('o',"From %s: User %s (%s@%s) is now an IRC operator of type %s",u->server, u->nick,u->ident,u->host,irc::Spacify(opertype.c_str()));
00250         }
00251         return true;
00252 }

bool TreeSocket::Outbound_Reply_Server std::deque< std::string > &  params  ) 
 

(local) -> SERVER

Definition at line 831 of file treesocket2.cpp.

References TreeServer::AddChild(), bursting, ComparePass(), CONNECTED, DoBurst(), SpanningTreeUtilities::DoOneToAllButSender(), SpanningTreeUtilities::FindServer(), TreeServer::GetName(), TreeServer::GetParent(), GetTheirChallenge(), TreeServer::Hidden, InboundDescription, InboundServerName, InspSocket::Instance, SpanningTreeUtilities::LinkBlocks, LinkState, SendCapabilities(), SendError(), sentcapab, InspIRCd::SNO, SpanningTreeUtilities::TreeRoot, Utils, and SnomaskManager::WriteToSnoMask().

Referenced by ProcessLine().

00832 {
00833         if (params.size() < 4)
00834                 return false;
00835 
00836         irc::string servername = params[0].c_str();
00837         std::string sname = params[0];
00838         std::string password = params[1];
00839         std::string description = params[3];
00840         int hops = atoi(params[2].c_str());
00841 
00842         this->InboundServerName = sname;
00843         this->InboundDescription = description;
00844 
00845         if (!sentcapab)
00846                 this->SendCapabilities();
00847 
00848         if (hops)
00849         {
00850                 this->SendError("Server too far away for authentication");
00851                 this->Instance->SNO->WriteToSnoMask('l',"Server connection from \2"+sname+"\2 denied, server is too far away for authentication");
00852                 return false;
00853         }
00854 
00855         for (std::vector<Link>::iterator x = Utils->LinkBlocks.begin(); x < Utils->LinkBlocks.end(); x++)
00856         {
00857                 if ((x->Name == servername) && ((ComparePass(this->MakePass(x->RecvPass,this->GetOurChallenge()),password)) || (x->RecvPass == password && (this->GetTheirChallenge().empty()))))
00858                 {
00859                         TreeServer* CheckDupe = Utils->FindServer(sname);
00860                         if (CheckDupe)
00861                         {
00862                                 this->SendError("Server "+sname+" already exists on server "+CheckDupe->GetParent()->GetName()+"!");
00863                                 this->Instance->SNO->WriteToSnoMask('l',"Server connection from \2"+sname+"\2 denied, already exists on server "+CheckDupe->GetParent()->GetName());
00864                                 return false;
00865                         }
00866                         // Begin the sync here. this kickstarts the
00867                         // other side, waiting in WAIT_AUTH_2 state,
00868                         // into starting their burst, as it shows
00869                         // that we're happy.
00870                         this->LinkState = CONNECTED;
00871                         // we should add the details of this server now
00872                         // to the servers tree, as a child of the root
00873                         // node.
00874                         TreeServer* Node = new TreeServer(this->Utils,this->Instance,sname,description,Utils->TreeRoot,this,x->Hidden);
00875                         Utils->TreeRoot->AddChild(Node);
00876                         params[3] = ":" + params[3];
00877                         Utils->DoOneToAllButSender(Utils->TreeRoot->GetName(),"SERVER",params,sname);
00878                         this->bursting = true;
00879                         this->DoBurst(Node);
00880                         return true;
00881                 }
00882         }
00883         this->SendError("Invalid credentials");
00884         this->Instance->SNO->WriteToSnoMask('l',"Server connection from \2"+sname+"\2 denied, invalid link credentials");
00885         return false;
00886 }

bool TreeSocket::ProcessLine std::string line  ) 
 

Process complete line from buffer.

Definition at line 970 of file treesocket2.cpp.

References TreeServer::AddChild(), AddLine(), Admin(), XLineManager::apply_lines(), assign(), SpanningTreeUtilities::BestRouteTo(), bursting, Capab(), ChangeHost(), ChangeName(), CMD_FAILURE, CMD_INVALID, InspIRCd::Config, CONNECTED, CONNECTING, ConvToStr(), SpanningTreeUtilities::Creator, DEBUG, DEFAULT, SpanningTreeUtilities::DelBurstingServer(), DoBurst(), SpanningTreeUtilities::DoOneToAllButSender(), SpanningTreeUtilities::DoOneToAllButSenderRaw(), SpanningTreeUtilities::DoOneToMany(), SpanningTreeUtilities::EnableTimeSync, Error(), FD_MAGIC_NUMBER, InspIRCd::FindChan(), SpanningTreeUtilities::FindLink(), InspIRCd::FindNick(), SpanningTreeUtilities::FindServer(), ForceJoin(), ForceMode(), ForceNick(), ForceTopic(), GetName(), TreeServer::GetName(), TreeServer::GetSocket(), HandleSetTime(), Link::Hidden, Inbound_Server(), InboundDescription, InboundServerName, InspSocket::Instance, IntroduceClient(), SpanningTreeUtilities::IsServer(), SpanningTreeUtilities::lines_to_apply, LinkState, LISTENER, LocalPing(), LocalPong(), InspIRCd::Log(), SpanningTreeUtilities::MasterTime, MetaData(), Modules(), Motd(), myhost, userrec::nick, OperQuit(), OperType(), Outbound_Reply_Server(), SpanningTreeUtilities::PingFreq, prefix, Push(), userrec::QuitUser(), RemoteKill(), RemoteRehash(), RemoteServer(), RemoveStatus(), Event::Send(), SendError(), InspIRCd::SendMode(), userrec::server, chanrec::ServerKickUser(), ServerConfig::ServerName, ServerVersion(), ServiceJoin(), ServicePart(), EventHandler::SetFd(), TreeServer::SetNextPingTime(), TreeServer::SetPingFlag(), SpanningTreeUtilities::SetRemoteBursting(), InspIRCd::SetTimeDelta(), InspIRCd::SNO, Split(), Squit(), Stats(), Time(), InspIRCd::Time(), SpanningTreeUtilities::TreeRoot, Utils, WAIT_AUTH_1, WAIT_AUTH_2, warned, Whois(), WM_AND, InspIRCd::WriteMode(), InspIRCd::WriteOpers(), SnomaskManager::WriteToSnoMask(), and InspIRCd::XLines.

00971 {
00972         std::deque<std::string> params;
00973         irc::string command;
00974         std::string prefix;
00975 
00976         line = line.substr(0, line.find_first_of("\r\n"));
00977 
00978         if (line.empty())
00979                 return true;
00980 
00981         Instance->Log(DEBUG, "S[%d] <- %s", this->GetFd(), line.c_str());
00982 
00983         this->Split(line.c_str(),params);
00984         
00985         if (params.empty())
00986                 return true;
00987         
00988         if ((params[0][0] == ':') && (params.size() > 1))
00989         {
00990                 prefix = params[0].substr(1);
00991                 params.pop_front();
00992         }
00993         command = params[0].c_str();
00994         params.pop_front();
00995         switch (this->LinkState)
00996         {
00997                 TreeServer* Node;
00998 
00999                 case WAIT_AUTH_1:
01000                         // Waiting for SERVER command from remote server. Server initiating
01001                         // the connection sends the first SERVER command, listening server
01002                         // replies with theirs if its happy, then if the initiator is happy,
01003                         // it starts to send its net sync, which starts the merge, otherwise
01004                         // it sends an ERROR.
01005                         if (command == "PASS")
01006                         {
01007                                 /* Silently ignored */
01008                         }
01009                         else if (command == "SERVER")
01010                         {
01011                                 return this->Inbound_Server(params);
01012                         }
01013                         else if (command == "ERROR")
01014                         {
01015                                 return this->Error(params);
01016                         }
01017                         else if (command == "USER")
01018                         {
01019                                 this->SendError("Client connections to this port are prohibited.");
01020                                 return false;
01021                         }
01022                         else if (command == "CAPAB")
01023                         {
01024                                 return this->Capab(params);
01025                         }
01026                         else if ((command == "U") || (command == "S"))
01027                         {
01028                                 this->SendError("Cannot use the old-style mesh linking protocol with m_spanningtree.so!");
01029                                 return false;
01030                         }
01031                         else
01032                         {
01033                                 irc::string error = "Invalid command in negotiation phase: " + command;
01034                                 this->SendError(assign(error));
01035                                 return false;
01036                         }
01037                 break;
01038                 case WAIT_AUTH_2:
01039                         // Waiting for start of other side's netmerge to say they liked our
01040                         // password.
01041                         if (command == "SERVER")
01042                         {
01043                                 // cant do this, they sent it to us in the WAIT_AUTH_1 state!
01044                                 // silently ignore.
01045                                 return true;
01046                         }
01047                         else if ((command == "U") || (command == "S"))
01048                         {
01049                                 this->SendError("Cannot use the old-style mesh linking protocol with m_spanningtree.so!");
01050                                 return false;
01051                         }
01052                         else if (command == "BURST")
01053                         {
01054                                 if (params.size() && Utils->EnableTimeSync)
01055                                 {
01056                                         bool we_have_delta = (Instance->Time(false) != Instance->Time(true));
01057                                         time_t them = atoi(params[0].c_str());
01058                                         time_t delta = them - Instance->Time(false);
01059                                         if ((delta < -300) || (delta > 300))
01060                                         {
01061                                                 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(delta));
01062                                                 SendError("Your clocks are out by "+ConvToStr(abs(delta))+" seconds (this is more than five minutes). Link aborted, PLEASE SYNC YOUR CLOCKS!");
01063                                                 return false;
01064                                         }
01065                                         else if ((delta < -30) || (delta > 30))
01066                                         {
01067                                                 Instance->SNO->WriteToSnoMask('l',"\2WARNING\2: Your clocks are out by %d seconds. Please consider synching your clocks.", abs(delta));
01068                                         }
01069 
01070                                         if (!Utils->MasterTime && !we_have_delta)
01071                                         {
01072                                                 this->Instance->SetTimeDelta(delta);
01073                                                 // Send this new timestamp to any other servers
01074                                                 Utils->DoOneToMany(Utils->TreeRoot->GetName(), "TIMESET", params);
01075                                         }
01076                                 }
01077                                 this->LinkState = CONNECTED;
01078                                 TreeServer* CheckDupe = Utils->FindServer(InboundServerName);
01079                                 if (CheckDupe)
01080                                 {
01081                                         this->SendError("Server "+InboundServerName+" already exists!");
01082                                         this->Instance->SNO->WriteToSnoMask('l',"Server \2"+InboundServerName+"\2 being introduced from \2" + prefix + "\2 denied, already exists. Closing link with " + prefix);
01083                                         return false;
01084                                 }
01085                                 Link* lnk = Utils->FindLink(InboundServerName);
01086                                 Node = new TreeServer(this->Utils,this->Instance, InboundServerName, InboundDescription, Utils->TreeRoot, this, lnk ? lnk->Hidden : false);
01087                                 Utils->DelBurstingServer(this);
01088                                 Utils->TreeRoot->AddChild(Node);
01089                                 params.clear();
01090                                 params.push_back(InboundServerName);
01091                                 params.push_back("*");
01092                                 params.push_back("1");
01093                                 params.push_back(":"+InboundDescription);
01094                                 Utils->DoOneToAllButSender(Utils->TreeRoot->GetName(),"SERVER",params,InboundServerName);
01095                                 this->bursting = true;
01096                                 this->DoBurst(Node);
01097                         }
01098                         else if (command == "ERROR")
01099                         {
01100                                 return this->Error(params);
01101                         }
01102                         else if (command == "CAPAB")
01103                         {
01104                                 return this->Capab(params);
01105                         }
01106 
01107                 break;
01108                 case LISTENER:
01109                         this->SendError("Internal error -- listening socket accepted its own descriptor!!!");
01110                         return false;
01111                 break;
01112                 case CONNECTING:
01113                         if (command == "SERVER")
01114                         {
01115                                 // another server we connected to, which was in WAIT_AUTH_1 state,
01116                                 // has just sent us their credentials. If we get this far, theyre
01117                                 // happy with OUR credentials, and they are now in WAIT_AUTH_2 state.
01118                                 // if we're happy with this, we should send our netburst which
01119                                 // kickstarts the merge.
01120                                 return this->Outbound_Reply_Server(params);
01121                         }
01122                         else if (command == "ERROR")
01123                         {
01124                                 return this->Error(params);
01125                         }
01126                         else if (command == "CAPAB")
01127                         {
01128                                 return this->Capab(params);
01129                         }
01130                 break;
01131                 case CONNECTED:
01132                         // This is the 'authenticated' state, when all passwords
01133                         // have been exchanged and anything past this point is taken
01134                         // as gospel.
01135 
01136                         if (!prefix.empty())
01137                         {
01138                                 std::string direction = prefix;
01139                                 userrec* t = this->Instance->FindNick(prefix);
01140                                 if (t)
01141                                 {
01142                                         direction = t->server;
01143                                 }
01144                                 TreeServer* route_back_again = Utils->BestRouteTo(direction);
01145                                 if ((!route_back_again) || (route_back_again->GetSocket() != this))
01146                                 {
01147                                         if (route_back_again)
01148                                                 Instance->Log(DEBUG,"Protocol violation: Fake direction in command '%s' from connection '%s'",line.c_str(),this->GetName().c_str());
01149                                         return true;
01150                                 }
01151                                 /* Fix by brain:
01152                                  * When there is activity on the socket, reset the ping counter so
01153                                  * that we're not wasting bandwidth pinging an active server.
01154                                  */
01155                                 route_back_again->SetNextPingTime(time(NULL) + Utils->PingFreq);
01156                                 route_back_again->SetPingFlag();
01157                         }
01158                         else
01159                         {
01160                                 prefix = this->GetName();
01161                         }
01162 
01163                         if ((command == "MODE") && (params.size() >= 2))
01164                         {
01165                                 chanrec* channel = Instance->FindChan(params[0]);
01166                                 if (channel)
01167                                 {
01168                                         userrec* x = Instance->FindNick(prefix);
01169                                         if (x)
01170                                         {
01171                                                 if (warned.find(x->server) == warned.end())
01172                                                 {
01173                                                         Instance->Log(DEFAULT,"WARNING: I revceived modes '%s' from another server '%s'. This is not compliant with InspIRCd. Please check that server for bugs.", params[1].c_str(), x->server);
01174                                                         Instance->SNO->WriteToSnoMask('d', "WARNING: The server %s is sending nonstandard modes: '%s MODE %s' where FMODE should be used, and may cause desyncs.", x->server, x->nick, params[1].c_str());
01175                                                         warned[x->server] = x->nick;
01176                                                 }
01177                                         }
01178                                 }
01179                         }
01180 
01181                         if (command == "SVSMODE")
01182                         {
01183                                 /* Services expects us to implement
01184                                  * SVSMODE. In inspircd its the same as
01185                                  * MODE anyway.
01186                                  */
01187                                 command = "MODE";
01188                         }
01189                         std::string target;
01190                         /* Yes, know, this is a mess. Its reasonably fast though as we're
01191                          * working with std::string here.
01192                          */
01193                         if ((command == "NICK") && (params.size() >= 8))
01194                         {
01195                                 return this->IntroduceClient(prefix,params);
01196                         }
01197                         else if (command == "FJOIN")
01198                         {
01199                                 TreeServer* ServerSource = Utils->FindServer(prefix);
01200                                 if (ServerSource)
01201                                         Utils->SetRemoteBursting(ServerSource, false);
01202                                 return this->ForceJoin(prefix,params);
01203                         }
01204                         else if (command == "STATS")
01205                         {
01206                                 return this->Stats(prefix, params);
01207                         }
01208                         else if (command == "MOTD")
01209                         {
01210                                 return this->Motd(prefix, params);
01211                         }
01212                         else if (command == "KILL" && Utils->IsServer(prefix))
01213                         {
01214                                 return this->RemoteKill(prefix,params);
01215                         }
01216                         else if (command == "MODULES")
01217                         {
01218                                 return this->Modules(prefix, params);
01219                         }
01220                         else if (command == "ADMIN")
01221                         {
01222                                 return this->Admin(prefix, params);
01223                         }
01224                         else if (command == "SERVER")
01225                         {
01226                                 return this->RemoteServer(prefix,params);
01227                         }
01228                         else if (command == "ERROR")
01229                         {
01230                                 return this->Error(params);
01231                         }
01232                         else if (command == "OPERTYPE")
01233                         {
01234                                 return this->OperType(prefix,params);
01235                         }
01236                         else if (command == "FMODE")
01237                         {
01238                                 TreeServer* ServerSource = Utils->FindServer(prefix);
01239                                 if (ServerSource)
01240                                         Utils->SetRemoteBursting(ServerSource, false);
01241                                 return this->ForceMode(prefix,params);
01242                         }
01243                         else if (command == "FTOPIC")
01244                         {
01245                                 return this->ForceTopic(prefix,params);
01246                         }
01247                         else if (command == "REHASH")
01248                         {
01249                                 return this->RemoteRehash(prefix,params);
01250                         }
01251                         else if (command == "METADATA")
01252                         {
01253                                 return this->MetaData(prefix,params);
01254                         }
01255                         else if (command == "REMSTATUS")
01256                         {
01257                                 return this->RemoveStatus(prefix,params);
01258                         }
01259                         else if (command == "PING")
01260                         {
01261                                 if (prefix.empty())
01262                                         prefix = this->GetName();
01263                                 /*
01264                                  * We just got a ping from a server that's bursting.
01265                                  * This can't be right, so set them to not bursting, and
01266                                  * apply their lines.
01267                                  */
01268                                 TreeServer* ServerSource = Utils->FindServer(prefix);
01269                                 if (ServerSource)
01270                                         Utils->SetRemoteBursting(ServerSource, false);
01271 
01272                                 if (this->bursting)
01273                                 {
01274                                         this->bursting = false;
01275                                         Instance->XLines->apply_lines(Utils->lines_to_apply);
01276                                         Utils->lines_to_apply = 0;
01277                                 }
01278 
01279                                 return this->LocalPing(prefix,params);
01280                         }
01281                         else if (command == "PONG")
01282                         {
01283                                 if (prefix.empty())
01284                                         prefix = this->GetName();
01285                                 /*
01286                                  * We just got a pong from a server that's bursting.
01287                                  * This can't be right, so set them to not bursting, and
01288                                  * apply their lines.
01289                                  */
01290                                 TreeServer* ServerSource = Utils->FindServer(prefix);
01291                                 if (ServerSource)
01292                                         Utils->SetRemoteBursting(ServerSource, false);
01293 
01294                                 if (this->bursting)
01295                                 {
01296                                         this->bursting = false;
01297                                         Instance->XLines->apply_lines(Utils->lines_to_apply);
01298                                         Utils->lines_to_apply = 0;
01299                                 }
01300 
01301                                 return this->LocalPong(prefix,params);
01302                         }
01303                         else if (command == "VERSION")
01304                         {
01305                                 return this->ServerVersion(prefix,params);
01306                         }
01307                         else if (command == "FHOST")
01308                         {
01309                                 return this->ChangeHost(prefix,params);
01310                         }
01311                         else if (command == "FNAME")
01312                         {
01313                                 return this->ChangeName(prefix,params);
01314                         }
01315                         else if (command == "ADDLINE")
01316                         {
01317                                 TreeServer* ServerSource = Utils->FindServer(prefix);
01318                                 if (ServerSource)
01319                                         Utils->SetRemoteBursting(ServerSource, false);
01320                                 return this->AddLine(prefix,params);
01321                         }
01322                         else if (command == "SVSNICK")
01323                         {
01324                                 if (prefix.empty())
01325                                 {
01326                                         prefix = this->GetName();
01327                                 }
01328                                 return this->ForceNick(prefix,params);
01329                         }
01330                         else if (command == "OPERQUIT")
01331                         {
01332                                 return this->OperQuit(prefix,params);
01333                         }
01334                         else if (command == "IDLE")
01335                         {
01336                                 return this->Whois(prefix,params);
01337                         }
01338                         else if (command == "PUSH")
01339                         {
01340                                 return this->Push(prefix,params);
01341                         }
01342                         else if (command == "TIMESET")
01343                         {
01344                                 return this->HandleSetTime(prefix, params);
01345                         }
01346                         else if (command == "TIME")
01347                         {
01348                                 return this->Time(prefix,params);
01349                         }
01350                         else if ((command == "KICK") && (Utils->IsServer(prefix)))
01351                         {
01352                                 std::string sourceserv = this->myhost;
01353                                 if (params.size() == 3)
01354                                 {
01355                                         userrec* user = this->Instance->FindNick(params[1]);
01356                                         chanrec* chan = this->Instance->FindChan(params[0]);
01357                                         if (user && chan)
01358                                         {
01359                                                 if (!chan->ServerKickUser(user, params[2].c_str(), false))
01360                                                         /* Yikes, the channels gone! */
01361                                                         delete chan;
01362                                         }
01363                                 }
01364                                 if (!this->InboundServerName.empty())
01365                                 {
01366                                         sourceserv = this->InboundServerName;
01367                                 }
01368                                 return Utils->DoOneToAllButSenderRaw(line,sourceserv,prefix,command,params);
01369                         }
01370                         else if (command == "SVSJOIN")
01371                         {
01372                                 if (prefix.empty())
01373                                 {
01374                                         prefix = this->GetName();
01375                                 }
01376                                 return this->ServiceJoin(prefix,params);
01377                         }
01378                         else if (command == "SVSPART")
01379                         {
01380                                 if (prefix.empty())
01381                                         prefix = this->GetName();
01382                                 return this->ServicePart(prefix,params);
01383                         }
01384                         else if (command == "SQUIT")
01385                         {
01386                                 if (params.size() == 2)
01387                                 {
01388                                         this->Squit(Utils->FindServer(params[0]),params[1]);
01389                                 }
01390                                 return true;
01391                         }
01392                         else if (command == "OPERNOTICE")
01393                         {
01394                                 std::string sourceserv = this->myhost;
01395                                 if (!this->InboundServerName.empty())
01396                                         sourceserv = this->InboundServerName;
01397                                 if (params.size() >= 1)
01398                                         Instance->WriteOpers("*** From " + prefix + ": " + params[0]);
01399                                 return Utils->DoOneToAllButSenderRaw(line, sourceserv, prefix, command, params);
01400                         }
01401                         else if (command == "MODENOTICE")
01402                         {
01403                                 std::string sourceserv = this->myhost;
01404                                 if (!this->InboundServerName.empty())
01405                                         sourceserv = this->InboundServerName;
01406                                 if (params.size() >= 2)
01407                                 {
01408                                         Instance->WriteMode(params[0].c_str(), WM_AND, "*** From %s: %s", prefix.c_str(), params[1].c_str());
01409                                 }
01410                                 return Utils->DoOneToAllButSenderRaw(line, sourceserv, prefix, command, params);
01411                         }
01412                         else if (command == "SNONOTICE")
01413                         {
01414                                 std::string sourceserv = this->myhost;
01415                                 if (!this->InboundServerName.empty())
01416                                         sourceserv = this->InboundServerName;
01417                                 if (params.size() >= 2)
01418                                 {
01419                                         Instance->SNO->WriteToSnoMask(*(params[0].c_str()), "From " + prefix + ": "+ params[1]);
01420                                 }
01421                                 return Utils->DoOneToAllButSenderRaw(line, sourceserv, prefix, command, params);
01422                         }
01423                         else if (command == "ENDBURST")
01424                         {
01425                                 this->bursting = false;
01426                                 Instance->XLines->apply_lines(Utils->lines_to_apply);
01427                                 Utils->lines_to_apply = 0;
01428                                 std::string sourceserv = this->myhost;
01429                                 if (!this->InboundServerName.empty())
01430                                         sourceserv = this->InboundServerName;
01431                                 this->Instance->SNO->WriteToSnoMask('l',"Received end of netburst from \2%s\2",sourceserv.c_str());
01432 
01433                                 Event rmode((char*)sourceserv.c_str(), (Module*)Utils->Creator, "new_server");
01434                                 rmode.Send(Instance);
01435 
01436                                 return true;
01437                         }
01438                         else
01439                         {
01440                                 // not a special inter-server command.
01441                                 // Emulate the actual user doing the command,
01442                                 // this saves us having a huge ugly parser.
01443                                 userrec* who = this->Instance->FindNick(prefix);
01444                                 std::string sourceserv = this->myhost;
01445                                 if (!this->InboundServerName.empty())
01446                                 {
01447                                         sourceserv = this->InboundServerName;
01448                                 }
01449                                 if ((!who) && (command == "MODE"))
01450                                 {
01451                                         if (Utils->IsServer(prefix))
01452                                         {
01453                                                 const char* modelist[127];
01454                                                 for (size_t i = 0; i < params.size(); i++)
01455                                                         modelist[i] = params[i].c_str();
01456                                                 userrec* fake = new userrec(Instance);
01457                                                 fake->SetFd(FD_MAGIC_NUMBER);
01458                                                 this->Instance->SendMode(modelist, params.size(), fake);
01459 
01460                                                 delete fake;
01461                                                 /* Hot potato! pass it on! */
01462                                                 return Utils->DoOneToAllButSenderRaw(line,sourceserv,prefix,command,params);
01463                                         }
01464                                 }
01465                                 if (who)
01466                                 {
01467                                         if ((command == "NICK") && (params.size() > 0))
01468                                         {
01469                                                 /* On nick messages, check that the nick doesnt
01470                                                  * already exist here. If it does, kill their copy,
01471                                                  * and our copy.
01472                                                  */
01473                                                 userrec* x = this->Instance->FindNick(params[0]);
01474                                                 if ((x) && (x != who))
01475                                                 {
01476                                                         std::deque<std::string> p;
01477                                                         p.push_back(params[0]);
01478                                                         p.push_back(":Nickname collision ("+prefix+" -> "+params[0]+")");
01479                                                         Utils->DoOneToMany(this->Instance->Config->ServerName,"KILL",p);
01480                                                         p.clear();
01481                                                         p.push_back(prefix);
01482                                                         p.push_back(":Nickname collision");
01483                                                         Utils->DoOneToMany(this->Instance->Config->ServerName,"KILL",p);
01484                                                         userrec::QuitUser(this->Instance,x,"Nickname collision ("+prefix+" -> "+params[0]+")");
01485                                                         userrec* y = this->Instance->FindNick(prefix);
01486                                                         if (y)
01487                                                         {
01488                                                                 userrec::QuitUser(this->Instance,y,"Nickname collision");
01489                                                         }
01490                                                         return Utils->DoOneToAllButSenderRaw(line,sourceserv,prefix,command,params);
01491                                                 }
01492                                         }
01493                                         // its a user
01494                                         target = who->server;
01495                                         const char* strparams[127];
01496                                         for (unsigned int q = 0; q < params.size(); q++)
01497                                         {
01498                                                 strparams[q] = params[q].c_str();
01499                                         }
01500                                         switch (this->Instance->CallCommandHandler(command.c_str(), strparams, params.size(), who))
01501                                         {
01502                                                 case CMD_INVALID:
01503                                                         this->SendError("Unrecognised or malformed command '"+std::string(command.c_str())+"' -- possibly loaded mismatched modules");
01504                                                         return false;
01505                                                 break;
01506                                                 case CMD_FAILURE:
01507                                                         return true;
01508                                                 break;
01509                                                 default:
01510                                                         /* CMD_SUCCESS and CMD_USER_DELETED fall through here */
01511                                                 break;
01512                                         }
01513                                 }
01514                                 else
01515                                 {
01516                                         // its not a user. Its either a server, or somethings screwed up.
01517                                         if (Utils->IsServer(prefix))
01518                                                 target = this->Instance->Config->ServerName;
01519                                         else
01520                                                 return true;
01521                                 }
01522                                 return Utils->DoOneToAllButSenderRaw(line,sourceserv,prefix,command,params);
01523 
01524                         }
01525                         return true;
01526                 break;
01527         }
01528         return true;
01529 }

bool TreeSocket::Push const std::string prefix,
std::deque< std::string > &  params
 

PUSH.

Definition at line 640 of file treesocket2.cpp.

References SpanningTreeUtilities::DoOneToOne(), InspIRCd::FindNick(), InspSocket::Instance, IS_LOCAL, userrec::server, Utils, and userrec::Write().

Referenced by ProcessLine().

00641 {
00642         if (params.size() < 2)
00643                 return true;
00644         userrec* u = this->Instance->FindNick(params[0]);
00645         if (!u)
00646                 return true;
00647         if (IS_LOCAL(u))
00648         {
00649                 u->Write(params[1]);
00650         }
00651         else
00652         {
00653                 // continue the raw onwards
00654                 params[1] = ":" + params[1];
00655                 Utils->DoOneToOne(prefix,"PUSH",params,u->server);
00656         }
00657         return true;
00658 }

std::string TreeSocket::RandString unsigned int  length  ) 
 

Generate random string used for challenge-response auth.

Definition at line 299 of file treesocket1.cpp.

References EventHandler::fd.

Referenced by SendCapabilities().

00300 {
00301         char* randombuf = new char[length+1];
00302         std::string out;
00303 #ifdef WINDOWS
00304         int fd = -1;
00305 #else
00306         int fd = open("/dev/urandom", O_RDONLY, 0);
00307 #endif
00308 
00309         if (fd >= 0)
00310         {
00311 #ifndef WINDOWS
00312                 read(fd, randombuf, length);
00313                 close(fd);
00314 #endif
00315         }
00316         else
00317         {
00318                 for (unsigned int i = 0; i < length; i++)
00319                         randombuf[i] = rand();
00320         }
00321 
00322         for (unsigned int i = 0; i < length; i++)
00323         {
00324                 char randchar = static_cast<char>((randombuf[i] & 0x7F) | 0x21);
00325                 out += (randchar == '=' ? '_' : randchar);
00326         }
00327 
00328         delete[] randombuf;
00329         return out;
00330 }

bool TreeSocket::RemoteKill const std::string prefix,
std::deque< std::string > &  params
 

KILL.

Definition at line 366 of file treesocket2.cpp.

References SpanningTreeUtilities::DoOneToAllButSender(), InspIRCd::FindNick(), InspSocket::Instance, userrec::nick, userrec::QuitUser(), Utils, and userrec::Write().

Referenced by ProcessLine().

00367 {        
00368         if (params.size() != 2)
00369                 return true;
00370 
00371         userrec* who = this->Instance->FindNick(params[0]);
00372 
00373         if (who)
00374         {
00375                 /* Prepend kill source, if we don't have one -- '[' is check for older 1.1 servers, and services, that prefix reason with servername. */
00376                 if ((*(params[1].c_str()) != 'K') && (*(params[1].c_str()) != '['))
00377                 {
00378                         params[1] = "Killed (" + params[1] +")";
00379                 }
00380                 std::string reason = params[1];
00381                 params[1] = ":" + params[1];
00382                 Utils->DoOneToAllButSender(prefix,"KILL",params,prefix);
00383                 // NOTE: This is safe with kill hiding on, as RemoteKill is only reached if we have a server prefix.
00384                 // in short this is not executed for USERS.
00385                 who->Write(":%s KILL %s :%s (%s)", prefix.c_str(), who->nick, prefix.c_str(), reason.c_str());
00386                 userrec::QuitUser(this->Instance,who,reason);
00387         }
00388         return true;
00389 }

bool TreeSocket::RemoteRehash const std::string prefix,
std::deque< std::string > &  params
 

REHASH.

Definition at line 341 of file treesocket2.cpp.

References InspIRCd::Config, ServerConfig::DisabledCommands, SpanningTreeUtilities::DoOneToAllButSender(), FOREACH_MOD_I, I_OnRehash, InitializeDisabledCommands(), InspSocket::Instance, SpanningTreeUtilities::ReadConfiguration(), InspIRCd::RehashServer(), InspIRCd::SNO, Utils, and SnomaskManager::WriteToSnoMask().

Referenced by ProcessLine().

00342 {
00343         if (params.size() < 1)
00344                 return false;
00345 
00346         std::string servermask = params[0];
00347         std::string parameter;
00348 
00349         if (params.size() > 1)
00350         {
00351                 parameter = params[1];
00352         }
00353 
00354         if (this->Instance->MatchText(this->Instance->Config->ServerName,servermask))
00355         {
00356                 this->Instance->SNO->WriteToSnoMask('l',"Remote rehash initiated by \002"+prefix+"\002.");
00357                 this->Instance->RehashServer();
00358                 Utils->ReadConfiguration(true);
00359                 FOREACH_MOD_I(this->Instance, I_OnRehash, OnRehash(NULL, parameter));
00360                 InitializeDisabledCommands(Instance->Config->DisabledCommands, Instance);
00361         }
00362         Utils->DoOneToAllButSender(prefix,"REHASH",params,prefix);
00363         return true;
00364 }

bool TreeSocket::RemoteServer const std::string prefix,
std::deque< std::string > &  params
 

<- (remote) <- SERVER

Definition at line 782 of file treesocket2.cpp.

References TreeServer::AddChild(), SpanningTreeUtilities::DoOneToAllButSender(), SpanningTreeUtilities::FindLink(), SpanningTreeUtilities::FindServer(), Link::Hidden, InspSocket::Instance, SendError(), SpanningTreeUtilities::SetRemoteBursting(), InspIRCd::SNO, Utils, and SnomaskManager::WriteToSnoMask().

Referenced by ProcessLine().

00783 {
00784         if (params.size() < 4)
00785                 return false;
00786         std::string servername = params[0];
00787         std::string password = params[1];
00788         // hopcount is not used for a remote server, we calculate this ourselves
00789         std::string description = params[3];
00790         TreeServer* ParentOfThis = Utils->FindServer(prefix);
00791         if (!ParentOfThis)
00792         {
00793                 this->SendError("Protocol error - Introduced remote server from unknown server "+prefix);
00794                 return false;
00795         }
00796         TreeServer* CheckDupe = Utils->FindServer(servername);
00797         if (CheckDupe)
00798         {
00799                 this->SendError("Server "+servername+" already exists!");
00800                 this->Instance->SNO->WriteToSnoMask('l',"Server \2"+servername+"\2 being introduced from \2" + prefix + "\2 denied, already exists. Closing link with " + prefix);
00801                 return false;
00802         }
00803         Link* lnk = Utils->FindLink(servername);
00804         TreeServer* Node = new TreeServer(this->Utils,this->Instance,servername,description,ParentOfThis,NULL, lnk ? lnk->Hidden : false);
00805         ParentOfThis->AddChild(Node);
00806         params[3] = ":" + params[3];
00807         Utils->SetRemoteBursting(Node, true);
00808         Utils->DoOneToAllButSender(prefix,"SERVER",params,prefix);
00809         this->Instance->SNO->WriteToSnoMask('l',"Server \002"+prefix+"\002 introduced server \002"+servername+"\002 ("+description+")");
00810         return true;
00811 }

bool TreeSocket::RemoveStatus const std::string prefix,
std::deque< std::string > &  params
 

Remove all modes from a channel, including statusmodes (+qaovh etc), simplemodes, parameter modes.

This does not update the timestamp of the target channel, this must be done seperately.

Definition at line 765 of file treesocket2.cpp.

References InspIRCd::FindChan(), ModeParser::FindMode(), InspSocket::Instance, InspIRCd::Modes, MODETYPE_CHANNEL, and ModeHandler::RemoveMode().

Referenced by ForceJoin(), and ProcessLine().

00766 {
00767         if (params.size() < 1)
00768                 return true;
00769         chanrec* c = Instance->FindChan(params[0]);
00770         if (c)
00771         {
00772                 for (char modeletter = 'A'; modeletter <= 'z'; modeletter++)
00773                 {
00774                         ModeHandler* mh = Instance->Modes->FindMode(modeletter, MODETYPE_CHANNEL);
00775                         if (mh)
00776                                 mh->RemoveMode(c);
00777                 }
00778         }
00779         return true;
00780 }

void TreeSocket::SendCapabilities  ) 
 

Send my capabilities to the remote side.

Definition at line 332 of file treesocket1.cpp.

References ModeParser::BuildPrefixes(), SpanningTreeUtilities::ChallengeResponse, CHANMAX, ModeParser::ChanModes(), ConvToStr(), InspIRCd::FindModule(), GetOurChallenge(), irc::sepstream::GetToken(), IDENTMAX, InspSocket::Instance, MAXAWAY, MAXGECOS, MAXKICK, MAXMODES, MAXQUIT, MAXTOPIC, InspIRCd::Modes, MyCapabilities(), NICKMAX, ProtocolVersion, RandString(), sentcapab, SetOurChallenge(), Utils, and WriteLine().

Referenced by Capab(), Inbound_Server(), OnConnected(), Outbound_Reply_Server(), and HandshakeTimer::Tick().

00333 {
00334         if (sentcapab)
00335                 return;
00336 
00337         sentcapab = true;
00338         irc::commasepstream modulelist(MyCapabilities());
00339         this->WriteLine("CAPAB START");
00340 
00341         /* Send module names, split at 509 length */
00342         std::string item;
00343         std::string line = "CAPAB MODULES ";
00344         while (modulelist.GetToken(item))
00345         {
00346                 if (line.length() + item.length() + 1 > 509)
00347                 {
00348                         this->WriteLine(line);
00349                         line = "CAPAB MODULES ";
00350                 }
00351 
00352                 if (line != "CAPAB MODULES ")
00353                         line.append(",");
00354 
00355                 line.append(item);
00356         }
00357         if (line != "CAPAB MODULES ")
00358                 this->WriteLine(line);
00359 
00360         int ip6 = 0;
00361         int ip6support = 0;
00362 #ifdef IPV6
00363         ip6 = 1;
00364 #endif
00365 #ifdef SUPPORT_IP6LINKS
00366         ip6support = 1;
00367 #endif
00368         std::string extra;
00369         /* Do we have sha256 available? If so, we send a challenge */
00370         if (Utils->ChallengeResponse && (Instance->FindModule("m_sha256.so")))
00371         {
00372                 this->SetOurChallenge(RandString(20));
00373                 extra = " CHALLENGE=" + this->GetOurChallenge();
00374         }
00375 
00376         this->WriteLine("CAPAB CAPABILITIES :NICKMAX="+ConvToStr(NICKMAX)+" HALFOP="+ConvToStr(this->Instance->Config->AllowHalfop)+" CHANMAX="+ConvToStr(CHANMAX)+" MAXMODES="+ConvToStr(MAXMODES)+" IDENTMAX="+ConvToStr(IDENTMAX)+" MAXQUIT="+ConvToStr(MAXQUIT)+" MAXTOPIC="+ConvToStr(MAXTOPIC)+" MAXKICK="+ConvToStr(MAXKICK)+" MAXGECOS="+ConvToStr(MAXGECOS)+" MAXAWAY="+ConvToStr(MAXAWAY)+" IP6NATIVE="+ConvToStr(ip6)+" IP6SUPPORT="+ConvToStr(ip6support)+" PROTOCOL="+ConvToStr(ProtocolVersion)+extra+" PREFIX="+Instance->Modes->BuildPrefixes()+" CHANMODES="+Instance->Modes->ChanModes()+" SVSPART=1");
00377 
00378         this->WriteLine("CAPAB END");
00379 }

void TreeSocket::SendChannelModes TreeServer Current  ) 
 

Send channel modes and topics.

Definition at line 1167 of file treesocket1.cpp.

References InspIRCd::chanlist, InspIRCd::Config, SpanningTreeUtilities::Creator, DEBUG, FOREACH_MOD_I, I_OnSyncChannel, I_OnSyncChannelMetaData, InspSocket::Instance, InspIRCd::Log(), MAXBUF, SendFJoins(), ServerConfig::ServerName, Utils, and WriteLine().

Referenced by DoBurst().

01168 {
01169         char data[MAXBUF];
01170         std::deque<std::string> list;
01171         std::string n = this->Instance->Config->ServerName;
01172         const char* sn = n.c_str();
01173         Instance->Log(DEBUG,"Sending channels and modes, %d to send", this->Instance->c