|
|||
|
|||
|
#include <treesocket.h>
Inheritance diagram for TreeSocket:


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::string & | GetOurChallenge () |
| 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::string & | GetTheirChallenge () |
| 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. | |
| Module * | GetHook () |
| 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 > ¶ms) |
| 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 > ¶ms) |
| FMODE command - server mode with timestamp checks. | |
| bool | ForceTopic (const std::string &source, std::deque< std::string > ¶ms) |
| FTOPIC command. | |
| bool | ForceJoin (const std::string &source, std::deque< std::string > ¶ms) |
| FJOIN, similar to TS6 SJOIN, but not quite. | |
| bool | IntroduceClient (const std::string &source, std::deque< std::string > ¶ms) |
| 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 > ¶ms) |
| Handle ERROR command. | |
| bool | Motd (const std::string &prefix, std::deque< std::string > ¶ms) |
| remote MOTD. | |
| bool | Admin (const std::string &prefix, std::deque< std::string > ¶ms) |
| remote ADMIN. | |
| bool | Modules (const std::string &prefix, std::deque< std::string > ¶ms) |
| Remote MODULES. | |
| bool | Stats (const std::string &prefix, std::deque< std::string > ¶ms) |
| bool | OperType (const std::string &prefix, std::deque< std::string > ¶ms) |
| 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 > ¶ms) |
| 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 > ¶ms) |
| bool | ServiceJoin (const std::string &prefix, std::deque< std::string > ¶ms) |
| SVSJOIN. | |
| bool | ServicePart (const std::string &prefix, std::deque< std::string > ¶ms) |
| SVSPART. | |
| bool | RemoteRehash (const std::string &prefix, std::deque< std::string > ¶ms) |
| REHASH. | |
| bool | RemoteKill (const std::string &prefix, std::deque< std::string > ¶ms) |
| KILL. | |
| bool | LocalPong (const std::string &prefix, std::deque< std::string > ¶ms) |
| PONG. | |
| bool | MetaData (const std::string &prefix, std::deque< std::string > ¶ms) |
| METADATA. | |
| bool | ServerVersion (const std::string &prefix, std::deque< std::string > ¶ms) |
| VERSION. | |
| bool | ChangeHost (const std::string &prefix, std::deque< std::string > ¶ms) |
| CHGHOST. | |
| bool | AddLine (const std::string &prefix, std::deque< std::string > ¶ms) |
| ADDLINE. | |
| bool | ChangeName (const std::string &prefix, std::deque< std::string > ¶ms) |
| CHGNAME. | |
| bool | Whois (const std::string &prefix, std::deque< std::string > ¶ms) |
| WHOIS. | |
| bool | Push (const std::string &prefix, std::deque< std::string > ¶ms) |
| PUSH. | |
| bool | HandleSetTime (const std::string &prefix, std::deque< std::string > ¶ms) |
| SETTIME. | |
| bool | Time (const std::string &prefix, std::deque< std::string > ¶ms) |
| TIME. | |
| bool | LocalPing (const std::string &prefix, std::deque< std::string > ¶ms) |
| PING. | |
| bool | RemoveStatus (const std::string &prefix, std::deque< std::string > ¶ms) |
| Remove all modes from a channel, including statusmodes (+qaovh etc), simplemodes, parameter modes. | |
| bool | RemoteServer (const std::string &prefix, std::deque< std::string > ¶ms) |
| <- (remote) <- SERVER | |
| bool | Outbound_Reply_Server (std::deque< std::string > ¶ms) |
| (local) -> SERVER | |
| bool | Inbound_Server (std::deque< std::string > ¶ms) |
| (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 | |
| SpanningTreeUtilities * | Utils |
| 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::string > | CapKeys |
| Module * | Hook |
| std::string | ourchallenge |
| std::string | theirchallenge |
| std::string | OutboundPass |
| bool | sentcapab |
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.
|
||||||||||||||||||||||||||||||||
|
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 }
|
|
||||||||||||||||||||||||||||||||||||||||
|
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 }
|
|
||||||||||||||||||||||||
|
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 }
|
|
|
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 }
|
|
||||||||||||
|
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 }
|
|
||||||||||||
|
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 }
|
|
|
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 }
|
|
||||||||||||
|
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 }
|
|
||||||||||||
|
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 }
|
|
||||||||||||
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
||||||||||||
|
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 }
|
|
||||||||||||
|
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 }
|
|
||||||||||||
|
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 }
|
|
||||||||||||
|
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 }
|
|
|
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 }
|
|
|
Get link state.
Definition at line 86 of file treesocket1.cpp. References LinkState. 00087 { 00088 return this->LinkState; 00089 }
|
|
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
||||||||||||
|
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 }
|
|
||||||||||||
|
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 }
|
|
|
(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 }
|
|
||||||||||||
|
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 }
|
|
||||||||||||
|
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 }
|
|
||||||||||||
|
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 }
|
|
||||||||||||
|
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 }
|
|
||||||||||||
|
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 }
|
|
||||||||||||
|
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 }
|
|
||||||||||||
|
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 }
|
|
||||||||||||
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
||||||||||||
|
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 }
|
|
|
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 }
|
|
||||||||||||
|
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 }
|
|
||||||||||||
|
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 }
|
|
|
(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 }
|
|
|
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 }
|
|
||||||||||||
|
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 }
|
|
|
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 }
|
|
||||||||||||
|
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 }
|
|
||||||||||||
|
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 }
|
|
||||||||||||
|
<- (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 }
|
|
||||||||||||
|
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 }
|
|
|
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 }
|
|
|
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 |